Dự án chuyển cơ chế cách ly cam kết sang Linux

Tác giả của thư viện C tiêu chuẩn Cosmopolitan và nền tảng Redbean đã công bố triển khai cơ chế cách ly commit() cho Linux. Cam kết ban đầu được phát triển bởi dự án OpenBSD và cho phép bạn cấm có chọn lọc các ứng dụng truy cập vào các lệnh gọi hệ thống không được sử dụng (một loại danh sách trắng các lệnh gọi hệ thống được hình thành cho ứng dụng và các lệnh gọi khác đều bị cấm). Không giống như các cơ chế hạn chế cuộc gọi hệ thống có sẵn trong Linux, chẳng hạn như seccomp, cơ chế cam kết ban đầu được thiết kế đơn giản nhất có thể.

Sáng kiến ​​thất bại trong việc cách ly các ứng dụng trong môi trường cơ sở OpenBSD bằng cơ chế systrace cho thấy việc cách ly ở cấp độ các lệnh gọi hệ thống riêng lẻ là quá phức tạp và tốn thời gian. Thay vào đó, một cam kết đã được đề xuất, cho phép tạo ra các quy tắc cách ly mà không cần đi sâu vào chi tiết và thao túng các lớp truy cập được tạo sẵn. Ví dụ: các lớp được cung cấp là stdio (đầu vào/đầu ra), rpath (tệp chỉ đọc), wpath (ghi tệp), cpath (tạo tệp), tmppath (làm việc với các tệp tạm thời), inet (ổ cắm mạng), unix ( unix sockets), dns (độ phân giải DNS), getpw (quyền truy cập đọc vào cơ sở dữ liệu người dùng), ioctl (cuộc gọi ioctl), proc (quản lý quy trình), exec (khởi chạy quy trình) và id (quản lý quyền truy cập).

Các quy tắc làm việc với lệnh gọi hệ thống được chỉ định dưới dạng chú thích, bao gồm danh sách các lớp lệnh gọi hệ thống được phép và một loạt đường dẫn tệp được phép truy cập. Sau khi xây dựng và khởi chạy ứng dụng đã sửa đổi, kernel sẽ đảm nhận công việc giám sát việc tuân thủ các quy tắc đã chỉ định.

Một triển khai cam kết riêng biệt đang được phát triển cho FreeBSD, được phân biệt bằng khả năng cách ly các ứng dụng mà không thực hiện thay đổi mã của chúng, trong khi ở OpenBSD, lệnh gọi cam kết nhằm mục đích tích hợp chặt chẽ với môi trường cơ sở và thêm chú thích vào mã của từng ứng dụng. ứng dụng.

Các nhà phát triển cổng cam kết cho Linux đã lấy ví dụ về FreeBSD và thay vì thực hiện các thay đổi đối với mã, họ đã chuẩn bị một tiện ích bổ sung commit.com cho phép bạn áp dụng các hạn chế mà không cần thay đổi mã ứng dụng. Ví dụ: để chạy tiện ích Curl chỉ có quyền truy cập vào các lớp gọi hệ thống stdio, rpath, inet và threadstdio, chỉ cần chạy “./pledge.com -p ‘stdio rpath inet thread’ Curl http://example.com”.

Tiện ích cam kết hoạt động trên tất cả các bản phân phối Linux bắt đầu bằng RHEL6 và không yêu cầu quyền truy cập root. Ngoài ra, dựa trên thư viện quốc tế, một API được cung cấp để quản lý các hạn chế về mã chương trình bằng ngôn ngữ C, cho phép, cùng với những tính năng khác, tạo ra các vùng để hạn chế có chọn lọc quyền truy cập liên quan đến các chức năng ứng dụng nhất định.

Việc triển khai không yêu cầu thay đổi kernel - các hạn chế cam kết được dịch sang các quy tắc SECCOMP BPF và được xử lý bằng cơ chế cách ly cuộc gọi hệ thống Linux gốc. Ví dụ: cam kết cuộc gọi("stdio rpath", 0) sẽ được chuyển đổi thành bộ lọc BPF static const struct sock_filter kFilter[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall, 0, 14 - 1 ), / * L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])), /* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 4 - 3, 0), /* L3* / BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 10, 0, 13 - 4), /* L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])), /* L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~0x80800), /* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 8 - 7, 0), /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 0, 13 - 8) , /* L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), /* L9*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 12 - 10, 0), /*L10*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 12 - 11, 0), /*L11*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 17, 0, 13 - 11), /*L12*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), /*L13*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L14*/ /* bộ lọc tiếp theo */ };

Nguồn: opennet.ru

Thêm một lời nhận xét