Standar WASI: Luncurkan WebAssembly Beyond the Web

Pada tanggal 27 Maret, kami di Mozilla mengumumkan standarisasi WASI, antarmuka sistem WebAssembly (antarmuka sistem WebAssembly).

Mengapa: pengembang mulai menggunakan WebAssembly di luar browser, karena WASM menyediakan cara yang cepat, terukur, dan aman untuk menjalankan kode yang sama di semua mesin. Tetapi kami belum memiliki dasar yang kuat untuk perkembangan semacam itu. Di luar browser, Anda perlu beberapa cara untuk berkomunikasi dengan sistem, yaitu antarmuka sistem. Tetapi platform WebAssembly belum memilikinya.

Apa: WebAssembly adalah assembler untuk mesin konseptual dan bukan fisik. Ini bekerja pada berbagai arsitektur, oleh karena itu, antarmuka sistem diperlukan untuk OS konseptual untuk bekerja pada sistem operasi yang berbeda.

Inilah yang WASI adalah: itu adalah antarmuka sistem untuk platform WebAssembly.

Kami berusaha keras untuk menciptakan antarmuka sistem yang akan menjadi pendamping sejati untuk WebAssembly dengan portabilitas dan keamanan maksimum.

Siapa: Sebagai bagian dari tim pengembangan WebAssembly, kami mengorganisir subkelompok yang akan distandarisasi pada WASI . Kami telah mengumpulkan mitra yang tertarik dan mencari yang baru.

Berikut adalah beberapa alasan mengapa kami, mitra, dan pendukung kami menganggap ini penting:

Sean White, Direktur R&D Mozilla:
"WebAssembly telah mengubah cara orang mengirimkan jenis konten menarik yang baru. Ini membantu pengembang dan pembuat konten. Sejauh ini, semuanya telah bekerja melalui peramban, tetapi dengan WASI, lebih banyak pengguna dan lebih banyak perangkat di berbagai tempat akan mendapat manfaat dari WebAssembly. "

Tyler McMullen, CTO Dengan Cepat:
“Kami melihat WebAssembly sebagai platform untuk mengeksekusi kode dengan cepat dan aman di cloud tepi. Terlepas dari lingkungan yang berbeda (tepi dan browser), terima kasih kepada WASI, Anda tidak perlu mem-port-kan kode ke setiap platform. "

Miles Borins, CTO dari Komite Pengarah Node:
“WebAssembly dapat memecahkan salah satu masalah terbesar Node: bagaimana mencapai kecepatan hampir asli dan menggunakan kembali kode yang ditulis dalam bahasa lain seperti C dan C ++, sambil tetap menjaga portabilitas dan keamanan. Standarisasi WASI adalah langkah pertama menuju ini. "

Lori Voss, salah satu pendiri npm:
“Npm sangat bersemangat tentang kemampuan WebAssembly potensial dari ekosistem npm karena membuatnya lebih mudah untuk mendapatkan kode asli untuk dijalankan di aplikasi JavaScript sisi-server. Kami menantikan hasil dari proses ini. "

Jadi ini acara besar!

Saat ini ada tiga implementasi WASI:


Demonstrasi WASI dalam aksi:


Selanjutnya, kita akan berbicara tentang proposal Mozilla tentang bagaimana antarmuka sistem ini seharusnya bekerja.

Apa itu antarmuka sistem?


Banyak yang mengatakan bahasa seperti C menyediakan akses langsung ke sumber daya sistem. Tetapi ini tidak sepenuhnya benar. Pada kebanyakan sistem, bahasa-bahasa ini tidak memiliki akses langsung ke hal-hal seperti membuka atau membuat file. Kenapa tidak

Karena sumber daya sistem ini - file, memori, dan koneksi jaringan - terlalu penting untuk stabilitas dan keamanan.

Jika satu program secara tidak sengaja merusak sumber daya yang lain, itu dapat menyebabkan crash. Lebih buruk lagi, jika suatu program (atau pengguna) secara khusus menyerang sumber daya orang lain, ia dapat mencuri data sensitif.



Oleh karena itu, Anda memerlukan cara untuk mengontrol program dan pengguna mana yang dapat mengakses sumber daya. Untuk waktu yang lama, pengembang sistem menemukan cara untuk menyediakan kontrol seperti itu: cincin perlindungan.

Dengan cincin perlindungan, OS pada dasarnya mengatur penghalang pelindung di sekitar sumber daya sistem. Inilah intinya. Hanya itu yang dapat melakukan operasi seperti membuat file, membuka file, atau membuka koneksi jaringan.

Program pengguna dijalankan di luar kernel dalam apa yang disebut ruang pengguna. Jika program ingin membuka file, ia harus meminta kernel.



Di sinilah konsep panggilan sistem muncul. Ketika suatu program perlu meminta kernel untuk beberapa operasi, itu mengirimkan panggilan sistem. Kernel memeriksa pengguna yang menghubungi dan melihat apakah ia memiliki izin untuk mengakses file ini.

Pada sebagian besar perangkat, satu-satunya cara untuk mengakses sumber daya sistem adalah melalui panggilan sistem.



Sistem operasi menyediakan akses ke panggilan sistem. Tetapi jika setiap OS memiliki panggilan sistemnya sendiri, tidakkah mereka perlu menulis versi kode yang berbeda? Untungnya tidak. Masalahnya diselesaikan dengan menggunakan abstraksi.

Sebagian besar bahasa memiliki perpustakaan standar. Saat coding, programmer tidak perlu tahu sistem apa yang dia tulis. Itu hanya menggunakan antarmuka. Kemudian, saat mengkompilasi, rantai alat Anda memilih implementasi antarmuka mana yang akan digunakan untuk sistem mana. Implementasi ini menggunakan fungsi dari API sistem operasi, jadi khusus untuk itu.

Di sinilah konsep antarmuka sistem muncul. Misalnya, jika Anda mengkompilasi printf untuk mesin Windows, itu akan menggunakan Windows API. Jika dikompilasi untuk Mac atau Linux, ia menggunakan POSIX.



Namun, ini menimbulkan masalah untuk WebAssembly. Di sini kita tidak tahu OS mana yang mengoptimalkan program bahkan saat kompilasi. Dengan demikian, Anda tidak dapat menggunakan antarmuka sistem dari salah satu OS di dalam penerapan pustaka standar di WebAssembly.



Saya sudah mengatakan bahwa WebAssembly adalah assembler untuk mesin konseptual , bukan mesin nyata. Demikian pula, WebAssembly membutuhkan antarmuka sistem untuk OS konseptual daripada nyata.

Tetapi sudah ada runtime yang dapat menjalankan WebAssembly di luar browser, bahkan tanpa antarmuka sistem ini. Bagaimana mereka melakukannya? Ayo lihat.

Bagaimana cara kerja WebAssembly di luar browser?


Alat pertama untuk menghasilkan kode WebAssembly adalah Emscripten. Ini mengemulasi di web antarmuka sistem OS tertentu - POSIX. Ini berarti bahwa programmer dapat menggunakan fungsi-fungsi dari library C standar (libc).

Untuk ini, Emscripten menggunakan implementasi libc-nya sendiri. Ini dibagi menjadi dua bagian: yang pertama dikompilasi menjadi modul WebAssembly, dan yang lainnya diimplementasikan dalam kode JS-lem. Lem JS ini mengirimkan panggilan ke browser yang berbicara dengan OS.



Sebagian besar kode WebAssembly awal dikompilasi dengan Emscripten. Karenanya, ketika orang mulai ingin menjalankan WebAssembly tanpa browser, mereka mulai menjalankan kode Emscripten.

Jadi dalam runtimes ini Anda harus membuat implementasi Anda sendiri untuk semua fungsi yang ada di kode JS-lem.

Tapi ada masalah. Antarmuka yang disediakan oleh kode lem JS belum dirancang sebagai antarmuka standar atau bahkan publik. Misalnya, untuk memanggil suka read di API normal, kode lem JS menggunakan _system3(which, varargs) .



Parameter pertama which merupakan bilangan bulat yang selalu cocok dengan angka dalam nama (dalam kasus kami 3).

Parameter kedua, varargs mencantumkan argumen. Ini disebut varargs karena kita dapat memiliki jumlah argumen yang berbeda. Tapi WebAssembly tidak memungkinkan untuk meneruskan sejumlah variabel argumen ke suatu fungsi. Oleh karena itu, mereka ditransmisikan melalui memori linier, yang tidak aman dan lebih lambat daripada melalui register.

Untuk Emscripten di browser, ini normal. Tapi sekarang runtimes melihat ini sebagai standar de facto, menerapkan versi JS lem mereka sendiri. Mereka mengemulasi detail internal dari lapisan emulasi POSIX.

Ini berarti bahwa mereka menerapkan kembali kode (misalnya, meneruskan argumen sebagai nilai tumpukan), yang masuk akal mengingat kendala Emscripten, tetapi tidak ada kendala seperti itu di lingkungan runtime ini.



Jika kita telah membangun ekosistem WebAssembly selama beberapa dekade yang akan datang, itu membutuhkan fondasi yang kuat, bukan kruk. Ini berarti bahwa standar kami yang sebenarnya tidak bisa menjadi emulasi emulasi.

Tetapi prinsip apa yang berlaku dalam kasus ini?

Prinsip apa yang harus dipatuhi oleh antarmuka sistem WebAssembly?


Dua prinsip dasar WebAssembly:

  • portabilitas
  • keamanan

Kami melampaui browser, tetapi mempertahankan prinsip-prinsip utama ini.

Namun, pendekatan POSIX dan sistem kontrol akses Unix tidak memberi kami hasil yang diinginkan. Mari kita lihat apa masalahnya.

Portabilitas


POSIX menyediakan portabilitas kode sumber. Anda dapat mengkompilasi kode sumber yang sama dengan versi libc yang berbeda untuk komputer yang berbeda.



Tapi WebAssembly harus melampaui itu. Kita perlu mengkompilasi sekali untuk berjalan pada sejumlah sistem yang berbeda. Kami membutuhkan binari portabel.



Ini menyederhanakan distribusi kode.

Misalnya, jika modul Node asli ditulis dalam WebAssembly, maka pengguna tidak perlu menjalankan node-gyp saat memasang aplikasi dengan modul asli, dan pengembang tidak perlu mengonfigurasi dan mendistribusikan puluhan file biner.

Keamanan


Ketika kode meminta sistem operasi untuk membuat input atau output, OS harus mengevaluasi keamanan operasi ini, biasanya menggunakan sistem kontrol akses berdasarkan kepemilikan dan grup.

Misalnya, sebuah program meminta untuk membuka file. Pengguna memiliki serangkaian file tertentu yang dapat diaksesnya.

Ketika seorang pengguna memulai suatu program, program itu dimulai atas nama pengguna itu. Jika pengguna memiliki akses ke file - apakah ia adalah pemiliknya, atau merupakan bagian dari grup yang memiliki akses ke file - maka program memiliki akses yang sama.



Ini melindungi pengguna dari satu sama lain, yang masuk akal di masa lalu, ketika banyak orang bekerja pada satu komputer dan administrator mengendalikan perangkat lunak. Kemudian ancaman utama adalah pengguna lain melihat file Anda.

Segalanya telah berubah. Saat ini, sistem biasanya merupakan pengguna tunggal, tetapi menggunakan kode pihak ketiga yang keandalannya tidak diketahui. Sekarang ancaman utama berasal dari kode yang Anda jalankan sendiri.

Misalnya, untuk perpustakaan di aplikasi Anda, pengelola baru telah dimulai (seperti yang sering terjadi pada open source). Dia mungkin seorang aktivis yang tulus ... atau pengganggu. Dan jika ia memiliki akses ke sistem Anda - misalnya, kemampuan untuk membuka file apa pun dan mengirimkannya melalui jaringan - maka kode ini dapat menyebabkan kerusakan besar.


Aplikasi yang mencurigakan : Saya bekerja untuk pengguna Bob. Bolehkah saya membuka dompet Bitcoin-nya?
Inti : Untuk Bob? Tentu saja!
Aplikasi yang mencurigakan : Hebat! Bagaimana dengan konektivitas jaringan?

Inilah sebabnya mengapa menggunakan perpustakaan pihak ketiga berbahaya. WebAssembly memberikan keamanan dengan cara yang berbeda - melalui kotak pasir. Di sini, kode tidak dapat berbicara langsung ke OS. Tetapi bagaimana cara mengakses sumber daya sistem? Host (browser atau runtime wasm) berfungsi sebagai kode yang dapat digunakan oleh kode.

Ini berarti bahwa host secara fungsional membatasi fungsionalitas program, tidak memungkinkan Anda untuk bertindak atas nama pengguna, menyebabkan panggilan sistem apa pun dengan hak pengguna penuh.

Memiliki kotak pasir itu sendiri tidak membuat sistem aman - tuan rumah masih dapat mentransfer fungsionalitas penuh ke kotak pasir, dalam hal ini tidak memberikan perlindungan apa pun. Tapi kotak pasir setidaknya memberikan peluang teoretis bagi penghuni untuk membangun sistem yang lebih aman.


WA : Tolong, berikut adalah beberapa mainan yang aman untuk berinteraksi dengan OS (safe_write, safe_read).
Aplikasi mencurigakan : Oh sial ... di mana akses saya ke jaringan?

Dalam antarmuka sistem apa pun, Anda harus mematuhi kedua prinsip ini. Portabilitas membuat pengembangan dan distribusi perangkat lunak lebih mudah, dan alat untuk melindungi tuan rumah dan pengguna mutlak diperlukan.

Seperti apa tampilan antarmuka sistem itu?


Dengan dua prinsip utama ini, apa yang seharusnya menjadi antarmuka sistem WebAssembly?

Ini akan kita temukan dalam proses standardisasi. Namun, kami memiliki saran untuk memulai:

  • Membuat seperangkat antarmuka standar modular
  • Mari kita mulai dengan standarisasi modul inti wasi-core.




Apa yang akan ada di wasi-core? Ini adalah dasar-dasar yang dibutuhkan oleh semua program. Modul ini akan mencakup sebagian besar fungsi POSIX, termasuk file, koneksi jaringan, jam dan angka acak.

Banyak fungsi dasar akan membutuhkan pendekatan yang sangat mirip. Misalnya, pendekatan berorientasi file POSIX disediakan dengan panggilan sistem buka, tutup, baca, dan tulis, dan yang lainnya adalah add-on dari atas.

Tetapi wasi-core tidak mencakup semua fungsi POSIX. Misalnya, konsep suatu proses tidak jelas masuk ke dalam WebAssembly. Selain itu, jelas bahwa setiap engine WebAssembly harus mendukung operasi proses seperti fork . Tetapi kami juga ingin membuat standardisasi fork mungkin.



Bahasa seperti Rust akan menggunakan wasi-core secara langsung di perpustakaan standar mereka. Misalnya, open dari Rust diterapkan ketika dikompilasi ke dalam WebAssembly dengan memanggil __wasi_path_open .

Untuk C dan C ++, kami menciptakan wasi-sysroot , yang mengimplementasikan libc dalam hal fungsi wasi-core.



Kami berharap kompiler seperti Dentang dapat berinteraksi dengan WASI API, dan rantai alat lengkap seperti Rust compiler dan Emscripten akan menggunakan WASI sebagai bagian dari implementasi sistem mereka.

Bagaimana kode khusus menjalankan fungsi WASI ini?

Runtime di mana kode dieksekusi melewati fungsi wasi-core, menempatkan objek di kotak pasir.



Ini memberikan portabilitas, karena setiap host dapat memiliki implementasi wasi-core sendiri khusus untuk platformnya: dari runtime WebAssembly seperti Mozilla Wasmtime dan Fastly Lucet, ke Node atau bahkan browser.

Ini juga menyediakan isolasi yang dapat diandalkan, karena host memilih berdasarkan perangkat lunak yang berfungsi untuk mentransfer ke kotak pasir, yaitu sistem yang harus diizinkan oleh panggilan sistem. Ini keamanan.



WASI meningkatkan dan memperluas keamanan dengan memperkenalkan konsep keamanan berbasis otorisasi ke dalam sistem.

Biasanya, jika kode perlu membuka file, itu panggilan open dengan nama jalur di baris. Kemudian, OS memeriksa apakah kode tersebut memiliki hak untuk tindakan semacam itu (berdasarkan hak pengguna yang meluncurkan program).

Dalam kasus WASI, saat memanggil suatu fungsi untuk mengakses file, Anda harus memberikan deskripsi file yang izinnya dilampirkan untuk file itu sendiri atau untuk direktori yang berisi file.

Dengan demikian, Anda tidak dapat memiliki kode yang secara tidak sengaja meminta Anda untuk membuka /etc/passwd . Sebaliknya, kode hanya dapat bekerja dengan direktori sendiri.



Ini memungkinkan berbagai panggilan sistem untuk diselesaikan dengan aman ke kode yang terisolasi karena kemampuan panggilan sistem ini terbatas.

Demikian juga di setiap modul. Secara default, modul tidak memiliki akses ke deskriptor file. Tetapi jika kode dalam satu modul memiliki deskriptor file, itu dapat meneruskannya ke fungsi yang disebut dalam modul lain. Atau buat versi yang lebih terbatas dari deskriptor file untuk diteruskan ke fungsi lain.

Dengan demikian, runtime meneruskan deskriptor file yang dapat digunakan aplikasi dalam kode tingkat atas, dan kemudian deskriptor file didistribusikan ke seluruh sistem sebagaimana diperlukan.



Ini membawa WebAssembly lebih dekat ke prinsip privilege paling rendah, di mana modul hanya mendapatkan akses ke set minimum sumber daya yang diperlukan untuk melakukan tugasnya.

Konsep ini didasarkan pada keamanan berbasis hak istimewa, seperti di CloudABI dan Capsicum. Salah satu masalah dengan sistem ini adalah portabilitas kode yang sulit. Tetapi kami percaya bahwa masalah ini dapat diselesaikan.

Jika kode sudah menggunakan openat dengan jalur file relatif, kompilasi kode hanya akan berfungsi.

Jika kode menggunakan migrasi open dan gaya- open terlalu drastis, WASI akan memberikan solusi tambahan. Menggunakan libpreopen, Anda membuat daftar path file yang aplikasi memiliki akses hukum. Kemudian gunakan open , tetapi hanya dengan jalur ini.

Apa selanjutnya


Kami percaya wasi-core adalah awal yang baik. Ini mempertahankan portabilitas dan keamanan WebAssembly, memberikan dasar yang kuat untuk ekosistem.

Tetapi setelah standarisasi penuh wasi-core, masalah lain perlu diselesaikan, termasuk:

  • input-output tidak sinkron
  • pemantauan file
  • kunci file

Ini baru permulaan, jadi jika Anda punya ide, libatkan !

Source: https://habr.com/ru/post/id446764/


All Articles