Trong một từ, "không".
Linux không thực sự phân biệt giữa các tập tin thực thi và tập lệnh; những #!
lúc đầu là một cách để nói với kernel những gì chương trình để chạy để đánh giá đầu vào, nhưng nó không phải là cách duy nhất một kịch bản có thể được thực thi.
Vì vậy, ví dụ, nếu tôi có một kịch bản
$ cat x
#!/bin/sh
echo hello
Sau đó tôi có thể chạy nó với lệnh
$ ./x
Điều đó sẽ khiến kernel thử và thực thi nó, phát hiện ra #!
và sau đó chạy một cách hiệu quả /bin/sh x
.
Tuy nhiên tôi cũng có thể chạy bất kỳ biến thể nào trong số này:
$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x
hoặc thậm chí
. ./x
Vì vậy, ngay cả khi kernel đã cố thực thi việc ký ở exec
lớp, chúng ta có thể bỏ qua điều này bằng cách chỉ chạy trình thông dịch với tập lệnh làm tham số.
Điều này có nghĩa là việc ký mã sẽ phải nằm trong chính trình thông dịch. Và điều gì sẽ ngăn người dùng biên dịch bản sao của chính họ mà không cần mã thực thi ký?
Giải pháp tiêu chuẩn cho vấn đề này không phải là sử dụng ký, mà là sử dụng Kiểm soát truy cập bắt buộc (MAC), chẳng hạn như SELinux
. Với các hệ thống MAC, bạn có thể chỉ định chính xác những gì mỗi người dùng được phép chạy và chuyển tiếp các lớp. Vì vậy, ví dụ, bạn có thể nói "người dùng bình thường có thể chạy bất cứ thứ gì ngoại trừ máy chủ web và quy trình CGI chỉ có thể truy cập nội dung từ /var/httpd
thư mục; mọi thứ khác đều bị từ chối".