Daemon ghi nhận một lần chroot thất bại và hồ sơ trông đã rộng rãi, nên cách sửa hấp dẫn là mở rộng một quy tắc đường dẫn rồi khởi động lại. Điều đó thường không thay đổi gì, vì chroot bị chặn bởi một đặc quyền mà hồ sơ chưa từng có thể trao. Quyết định chạm vào lớp nào cần ba bước kiểm tra, và chúng đều rẻ: tiến trình được phép giữ gì, chính sách cho phép gì, và trình khởi chạy đã gỡ bỏ gì trước khi một trong hai điều kia có ý nghĩa.

Hai cổng tách biệt, và chỉ một thuộc về AppArmor

chroot cần CAP_SYS_CHROOT trong không gian tên người dùng mà tiến trình đang chạy. Đó là đặc quyền thông thường của Linux, được nhân kiểm tra trước khi lời gọi làm bất cứ điều gì với đường dẫn. Riêng ra, một hồ sơ AppArmor ở chế độ enforcing vẫn có thể từ chối capability ngay cả khi tiến trình đang giữ nó, bởi chính sách bắt buộc được xem xét thêm vào thông tin xác thực chứ không thay thế chúng. Sự phân biệt này quan trọng trong thực tế: hai lớp nằm trong các tệp khác nhau và thường do những người khác nhau bảo trì.

Hai cổng đó thất bại với cùng một errno. Cả hai đều tạo EPERM, và cả hai đều hiện ra như một phàn nàn chung về quyền trong nhật ký của daemon, đó là lý do việc đoán nội dung hồ sơ tiêu tốn nhiều thời gian đến vậy. Quy tắc đường dẫn bạn sắp thêm kiểm soát truy cập tệp sau khi chroot thành công; nó không liên quan tới việc thao tác có được phép hay không.

Cổng thứ ba nằm ở thượng nguồn của cả hai. Nếu trình quản lý dịch vụ hoặc một lớp bọc khởi chạy tiến trình mà không có capability đó trong tập giới hạn của nó, không thay đổi AppArmor nào có thể đưa nó trở lại, và việc thêm capability vào hồ sơ chỉ ghi lại một ý định mà nhân sẽ không thực hiện.

Đọc trạng thái đặc quyền trước khi sửa chính sách

Hãy bắt đầu từ tiến trình đang chạy, chứ không phải từ cấu hình mà bạn tin là đang hoạt động. Tệp trạng thái phơi ra năm mặt nạ capability và cờ no-new-privileges, và chúng trả lời những câu hỏi khác nhau:

grep -E '^(CapInh|CapPrm|CapEff|CapBnd|CapAmb|NoNewPrivs):' /proc/$(pidof openvpn)/status
sudo aa-status | grep -i openvpn

CapEff là tập quan trọng cho lời gọi: một capability có trong CapBnd nhưng vắng trong CapEff thì được trần cho phép và hiện không được giữ. CapAmb quan trọng khi tệp nhị phân không có đặc quyền theo nghĩa setuid thông thường, vì capability môi trường là cách một dịch vụ giữ đặc quyền qua exec mà không cần capability tệp. CapInh giữ các bit có thể được kế thừa qua exec, nhưng chỉ khi tập kế thừa của tệp được thực thi cho phép, nên một bit ở đó tự nó không cấp gì.

Sau đó xác nhận hồ sơ nào thực sự được gắn. Một tiến trình có thể bị hạn chế bởi tên hồ sơ bạn không ngờ tới, nhất là khi một bản phân phối cung cấp unit và hồ sơ của riêng nó cùng nhau, và đọc /proc/PID/attr/current giải quyết việc đó trong một dòng. So sánh tệp bạn đã sửa với hồ sơ mà nhân báo cáo chính là khác biệt giữa sửa nguyên nhân và sửa một tệp mà không ai nạp.

Chỉ thêm quy tắc capability khi dấu vết kiểm toán nói vậy

Bản ghi của nhân và kiểm toán nêu tên lớp đã từ chối. Hãy tìm một lần từ chối mang thao tác capable và tên sys_chroot, cùng với hồ sơ đã tạo ra nó. Nếu bản ghi đó tồn tại, tiến trình đã giữ capability và AppArmor đã từ chối, và thay đổi đúng đích là một quy tắc capability bên trong hồ sơ thật:

capability sys_chroot,

Giữ nó như một mảnh trong hồ sơ thực sự được gắn, và đối chiếu từ khóa với tài liệu tham chiếu hồ sơ apparmor.d thay vì sao chép một quy tắc từ bài hướng dẫn không liên quan. Đặt nó vào một include dùng chung sẽ cấp quyền đó cho mọi chương trình bị hạn chế nạp tệp ấy, và chuyển hồ sơ sang chế độ complain sẽ giấu lần từ chối tiếp theo thay vì giải quyết lần này. Quy tắc trong hồ sơ gỡ bỏ một lần từ chối chính sách; nó không tạo ra đặc quyền, nên một tiến trình chưa từng có CAP_SYS_CHROOT trong tập hiệu lực vẫn sẽ thất bại dù quy tắc đã có.

Nếu bản ghi kiểm toán không cho thấy lần từ chối AppArmor nào, hãy ngừng sửa hồ sơ. Bạn đang đối mặt với vấn đề thông tin xác thực, và phần việc còn lại nằm ở unit hoặc ở tiến trình cha, không phải ở ngôn ngữ chính sách.

Trình quản lý dịch vụ giữ trần riêng của nó

systemd đặt một tập giới hạn capability cho mỗi dịch vụ, và mặc định tập đó hẹp. Bất cứ thứ gì bị loại ở đó đều không dùng được cho tiến trình dù hồ sơ nói gì, đó là lý do các unit đã gia cố có thể thất bại ở một thao tác vốn chạy được khi daemon được khởi chạy bằng tay. Các chỉ thị liên quan dễ đọc trong unit và dễ bị bỏ qua khi chính ứng dụng báo lỗi. Các drop-in do gói phân phối cung cấp là nguồn thường gặp của một trần mà không ai nhớ đã cấu hình.

Nâng trần và cấp capability là hai thay đổi, không phải một. Một mục trong tập giới hạn nói rằng tiến trình được phép giữ capability; nó không thêm capability vào tập hiệu lực, và NoNewPrivs có thể ngăn một lần nâng cấp về sau thành công ngay cả khi mọi thứ khác khớp. Chỉ thêm những gì thao tác cần, giữ nguyên phần gia cố còn lại, và chống lại lối tắt cấp mọi capability để một lời gọi đi qua.

Thứ tự cũng quan trọng ở đây. Đổi trần của unit trước, xác minh CapEff giờ đã chứa bit đó, và chỉ sau đó mới quyết định AppArmor còn từ chối hay không. Làm cả hai thay đổi cùng lúc sẽ khiến bạn lại phải đoán nếu lỗi vẫn tiếp diễn.

Khi lần từ chối biến mất, hãy kiểm tra chính nhà tù

Một chroot thành công sẽ dời gốc, nên mọi đường dẫn daemon chạm tới sau đó đều được phân giải bên trong cây mới. Cấu hình thiếu, một nút thiết bị không có hoặc một thư mục chứng chỉ chưa được sao chép vào giờ sẽ hiện ra như lỗi tệp, và lỗi đó là vấn đề bố cục chứ không phải capability. Hãy đọc sự kiện tiếp theo thay vì thêm một quyền rộng khác. Việc dời gốc cũng thay đổi ý nghĩa của một đường dẫn tương đối, đó là lý do các hướng dẫn gia cố nhấn mạnh đường dẫn tuyệt đối trong cấu hình daemon.

Cũng hữu ích khi nhớ chroot không làm gì. Nó là một ranh giới đường dẫn, không phải sandbox: một tiến trình giữ đặc quyền có thể thoát ra, đó là lý do capability thường bị bỏ sau lời gọi và vì sao việc hạn chế nên tiếp tục bao quanh daemon. Giữ hồ sơ AppArmor, tập giới hạn capability và các hạn chế hệ thống tệp lại với nhau chính là mục đích của bài tập, không phải phần dư cần gỡ sau khi dịch vụ khởi động.

Quy tắc quyết định rất ngắn. Nếu bản ghi kiểm toán nêu AppArmor, hãy thêm một quy tắc capability vào hồ sơ đang gắn. Nếu tập hiệu lực rỗng, sửa trần của unit và thứ tự hạ đặc quyền. Nếu hồ sơ không phải cái bạn đã sửa, hãy ngừng sửa và tìm ra cái thật.

Bài viết liên quan