2010-12-11 30 views
5

Tôi muốn triển khai hộp cát bằng cách ptrace() nhập một quy trình tôi bắt đầu và tất cả các con của nó sẽ tạo (bao gồm cả cháu, v.v.). Quy trình cha mẹ ptrace(), tức là người giám sát. sẽ là một chương trình C hoặc Python đơn giản, và về khái niệm nó sẽ giới hạn truy cập hệ thống tập tin (dựa trên tên đường dẫn và hướng truy cập (đọc hoặc ghi) và truy cập ổ cắm (ví dụ như không cho phép tạo socket). sao cho quy trình ptrace() d và con của nó (đệ quy) sẽ không thể bỏ qua hộp cát? Có điều gì đặc biệt mà người giám sát nên làm tại thời điểm fork() để tránh điều kiện chủng tộc? Có thể đọc các đối số tên tệp của ví dụ rename() từ quá trình con không có tình trạng đua xe?Làm cách nào để ptrace của Linux không an toàn hoặc chứa điều kiện chủng tộc?

Đây là những gì tôi đã lên kế hoạch để làm:

  • PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE để tránh (một số) coditions chủng tộc khi fork() ing
  • disallow tất cả các hệ thống gọi theo mặc định, và soạn một danh sách trắng của hệ thống cho phép gọi
  • chắc chắn rằng *at() biến thể hệ thống cuộc gọi (như openat) là đúng được bảo vệ

Tôi nên chú ý đến điều gì khác?

+0

Vì vậy, về cơ bản bạn đang cố gắng sao chép phụ trợ dựa trên ptrace của Systrace (http://www.systrace.org/)? – thkala

+0

Vâng, người giám sát của tôi sẽ làm việc tương tự như systrace. Thật không may, systrace dường như không được duy trì, nó không biên dịch rõ ràng, và nó cũng có vẻ là lỗi (nó treo cứng vô thời hạn khi tôi sandboxed GCC chạy GNU như). – pts

Trả lời

11

Vấn đề chính là nhiều đối số syscall, như tên tệp, được chuyển đến hạt nhân dưới dạng con trỏ của người dùng. Bất kỳ tác vụ nào được phép chạy đồng thời và có quyền ghi vào bộ nhớ mà con trỏ trỏ tới có thể sửa đổi hiệu quả các đối số này sau khi chúng được giám sát của bạn kiểm tra và trước khi hạt nhân hoạt động trên chúng. Vào thời điểm hạt nhân đi theo con trỏ, nội dung được trỏ tới có thể đã được thay đổi một cách có chủ ý bởi một tác vụ có thể lập lịch trình (quy trình hoặc luồng) khác có quyền truy cập vào bộ nhớ đó. Ví dụ:

Thread 1       Supervisor    Thread 2 
----------------------------------------------------------------------------------------------------- 
strcpy(filename, "/dev/null"); 
open(filename, O_RDONLY); 
            Check filename - OK 
                  strcpy(filename, "/home/user/.ssh/id_rsa"); 
(in kernel) opens "/home/user/.ssh/id_rsa" 

Một cách để ngăn chặn điều này là để không cho phép gọi clone() với CLONE_VM cờ, và ngoài ra ngăn chặn bất kỳ sự sáng tạo của thể ghi MAP_SHARED ánh xạ bộ nhớ (hoặc ít nhất là theo dõi chúng như vậy mà bạn từ chối bất kỳ syscall cố gắng tham chiếu trực tiếp dữ liệu từ một ánh xạ như vậy). Bạn cũng có thể sao chép bất kỳ đối số nào như vậy vào bộ đệm không bị chia sẻ trước khi cho phép syscall tiếp tục. Điều này sẽ ngăn chặn hiệu quả bất kỳ ứng dụng luồng nào đang chạy trong hộp cát.

Phương án thay thế là SIGSTOP mọi tiến trình khác trong nhóm truy tìm xung quanh mọi syscall nguy hiểm tiềm ẩn, chờ chúng thực sự dừng lại, sau đó cho phép syscall tiến hành. Sau khi nó trở về, bạn sau đó SIGCONT chúng (trừ khi chúng đã bị dừng). Không cần phải nói, điều này có thể có tác động hiệu suất đáng kể.

(Cũng có các vấn đề tương tự với các đối số syscall được truyền trên ngăn xếp và với các bảng tệp mở được chia sẻ).

+0

Được chấp nhận, rất sâu sắc, cảm ơn! – pts

+0

tại sao giải pháp sao chép ngăn chặn các ứng dụng luồng? không phải là ứng dụng mong đợi hệ thống gọi là "kinda" nguyên tử, anyways? – keppla

+1

@keppla: Bởi vì bạn không thể tạo vùng bộ nhớ không chia sẻ trong một ứng dụng luồng, vì tất cả các chủ đề chia sẻ cùng một máy ảo. Giải pháp sao chép không chia sẻ là dành cho các đối số syscall trong vùng bộ nhớ được chia sẻ với các quy trình khác. – caf

3

Không ptrace chỉ nhận được thông báo sau khi thực tế? Tôi không nghĩ rằng bạn có một cơ hội để thực sự ngăn chặn các syscall xảy ra, chỉ để giết nó nhanh như bạn có thể một khi bạn nhìn thấy một cái gì đó "ác".

Dường như bạn đang tìm kiếm nhiều thứ như SELinux hoặc AppArmor, nơi bạn có thể đảm bảo rằng thậm chí không có một cuộc gọi bất hợp pháp nào được thực hiện.

+0

Trên Linux, có PTRACE_SYSEMU, có thể chặn syscall. Cũng cảm ơn bạn đã đề cập đến các lựa chọn thay thế. Tuy nhiên, tôi không hiểu tại sao SELinux hoặc AppArmor sẽ an toàn hơn - miễn là không có lỗi và điều kiện chủng tộc. Nó là một giả định hợp lý? – pts

+1

Một cách phổ biến để vô hiệu hóa một syscall là thay đổi nó thành getpid (2). – maat

Các vấn đề liên quan