Apa yang terjadi dalam kedua kasus adalah sama:untuk mengeksekusi file secara langsung, bit eksekusi perlu disetel, dan sistem file tidak dapat dipasang noexec. Namun hal ini tidak menghentikan apa pun untuk membaca file-file itu.
Saat skrip bash dijalankan sebagai ./hello_world
dan file tersebut tidak dapat dieksekusi (baik tanpa izin exec, atau noexec pada sistem file), #!
baris bahkan tidak dicentang , karena sistem bahkan tidak memuat file. Skrip tidak pernah "dieksekusi" dalam pengertian yang relevan.
Dalam kasus bash ./hello_world
, yah, opsi sistem file noexec tidak sepintar yang Anda inginkan. bash
perintah yang dijalankan adalah /bin/bash
, dan /bin
tidak berada di sistem file dengan noexec
. Jadi, tidak ada masalah. Sistem tidak peduli bahwa bash (atau python atau perl atau apa pun) adalah seorang juru bahasa. Itu hanya menjalankan perintah yang Anda berikan (/bin/bash
) dengan argumen yang merupakan file. Dalam kasus bash atau shell lain, file itu berisi daftar perintah untuk dieksekusi, tetapi sekarang kita "melewati" apa pun yang akan memeriksa bit eksekusi file. Pemeriksaan itu tidak bertanggung jawab atas apa yang terjadi nanti.
Pertimbangkan kasus ini:
$ cat hello_world | /bin/bash
… atau bagi mereka yang tidak suka Penggunaan Kucing yang Tidak Berguna:
$ /bin/bash < hello_world
"Shbang" #!
urutan di awal file hanyalah keajaiban yang bagus untuk melakukan hal yang sama secara efektif saat Anda mencoba mengeksekusi file sebagai perintah. Anda mungkin menemukan artikel LWN.net ini bermanfaat:Bagaimana program dijalankan.
Jawaban sebelumnya menjelaskan mengapa noexec
pengaturan tidak mencegah skrip dijalankan saat juru bahasa (dalam kasus Anda /bin/bash
) secara eksplisit dipanggil dari baris perintah. Tetapi jika hanya itu saja, perintah ini juga akan berfungsi:
/lib64/ld-linux-x86-64.so.2 hello_world
Dan seperti yang Anda catat itu tidak berhasil. Itu karena noexec
memiliki efek lain juga. Kernel tidak akan mengizinkan file yang dipetakan memori dari sistem file itu dengan PROT_EXEC
diaktifkan.
File yang dipetakan memori digunakan dalam beberapa skenario. Dua skenario yang paling umum adalah untuk file yang dapat dieksekusi dan pustaka. Ketika sebuah program dimulai menggunakan execve
system call, kernel secara internal akan membuat pemetaan memori untuk linker dan dapat dieksekusi. Pustaka lain yang diperlukan adalah memori yang dipetakan oleh linker melalui mmap
panggilan sistem dengan PROT_EXEC
diaktifkan. Jika Anda mencoba menggunakan perpustakaan dari sistem file dengan noexec
kernel akan menolak untuk melakukan mmap
panggilan.
Saat Anda memanggil /lib64/ld-linux-x86-64.so.2 hello_world
execve
system call hanya akan membuat pemetaan memori untuk linker dan linker akan membuka hello_world
dapat dieksekusi dan berupaya membuat pemetaan memori dengan cara yang hampir sama seperti yang akan dilakukan untuk perpustakaan. Dan ini adalah titik dimana kernel menolak untuk menjalankan mmap
panggilan dan Anda mendapatkan kesalahan:
./hello_world: error while loading shared libraries: ./hello_world: failed to map segment from shared object: Operation not permitted
noexec
pengaturan masih memungkinkan pemetaan memori tanpa izin eksekusi (seperti yang kadang-kadang digunakan untuk file data) dan juga memungkinkan pembacaan file secara normal, itulah sebabnya bash hello_world
bekerja untuk Anda.
Menjalankan perintah dengan cara ini:
bash hello_world
Anda membuat bash
baca dari file hello_world
(yang tidak dilarang).
Dalam kasus lain OS coba jalankan file ini hello_world
dan gagal karena noexec
bendera