Chuyển đến nội dung
MINH VO Ghi chép từ công việc
của một kỹ sư tại Việt Nam
Cơ bản10 phút đọc

Quyền trên thư mục Linux giải thích lỗi Permission denied dễ gây hiểu nhầm

Chẩn đoán lỗi truy cập bằng quyền tra cứu trên từng thư mục cha, phân biệt liệt kê tên, mở tệp đã biết và thay đổi mục trong thư mục.

Mô hình dây chuyền băng tải với ba trạm và một nhánh vòng bên cạnh

Để đọc tệp trên Linux, tiến trình cần nhiều hơn quyền đọc trên chính tệp đó. Nó còn phải có quyền tra cứu, được biểu diễn bằng bit thực thi, trên từng thư mục dùng để đi tới tệp. Vì vậy, report.txt có quyền đọc vẫn có thể gây lỗi Permission denied khi một thư mục cha chặn quá trình đi qua đường dẫn.

Phân biệt này hữu ích khi bạn chẩn đoán một tài khoản dịch vụ không mở được tệp cấu hình dù kết quả ls -l trông có vẻ cho phép đọc. Quyền trên thư mục mô tả các thao tác với những mục bên trong thư mục. Ý nghĩa của chúng khác với cùng các chữ cái quyền trên một tệp thông thường.

Xét từng thành phần của đường dẫn

Giả sử dịch vụ mở /srv/reports/daily/report.txt. Quá trình tìm đường dẫn bắt đầu từ thư mục gốc, lần lượt tra cứu srv, reports và daily trước khi tới tệp. Thiếu quyền tra cứu ở bất kỳ thư mục nào trong số đó sẽ chặn thao tác, dù tệp cuối cho phép mọi người đọc.

Nhân hệ điều hành chọn nhóm quyền chủ sở hữu, nhóm hay người khác dựa trên thông tin định danh của tiến trình. Các nhóm bổ sung cũng có thể ảnh hưởng. Danh sách kiểm soát truy cập, gọi là ACL, và cơ chế như SELinux hay AppArmor có thể bổ sung quy tắc ngoài các bit quyền đơn giản. Vì vậy, giải thích bằng bit quyền là điểm bắt đầu, chưa phải toàn bộ mô hình cấp quyền.

Đường dẫn đi qua srv và reports nhưng dừng ở daily vì thư mục này thiếu quyền tra cứu.Mở ảnh kích thước đầy đủ ↗

Thư mục daily bị chặn khiến quá trình tra cứu chưa tới được tệp có quyền đọc. Bit đọc của tệp không thể cấp quyền đi qua một thành phần nằm trước nó trong đường dẫn.

Tạo thư mục thử nghiệm có thể bỏ đi

Chạy ví dụ bằng tài khoản người dùng thông thường trong shell bạn kiểm soát. Nó chỉ thay đổi thư mục tạm mới tạo. Người dùng có đặc quyền có thể vượt qua các phép kiểm tra quyền tùy nghi thông thường, nên root không phù hợp để minh họa hành vi này.

lab=$(mktemp -d)
mkdir "$lab/daily"
printf '%s\n' 'example report' > "$lab/daily/report.txt"
chmod 644 "$lab/daily/report.txt"
chmod 600 "$lab/daily"
cat "$lab/daily/report.txt"
chmod 700 "$lab/daily"
cat "$lab/daily/report.txt"

Lệnh cat đầu dự kiến thất bại với chủ sở hữu thư mục vì thiếu bit thực thi dành cho chủ sở hữu. Lệnh thứ hai thành công sau khi khôi phục quyền tra cứu. Nội dung và quyền của tệp không thay đổi. Nếu quan sát khác, kiểm tra người dùng hiệu lực, ACL và đặc quyền trước khi thay đổi lời giải thích.

Thư mục cha tạm do mktemp -d tạo thường chỉ dành cho chủ sở hữu. Điều đó tiện cho thử nghiệm cục bộ, nhưng tài khoản khác cũng cần quyền đi qua thư mục cha nếu muốn kiểm tra thư mục bên trong. Nhiều thử nghiệm quyền trở nên khó hiểu vì chính cách dựng dữ liệu thử đã thêm một thành phần bị chặn.

Liệt kê tên và tra cứu là hai thao tác khác nhau

Quyền đọc trên thư mục cho phép đọc danh sách tên mục. Quyền tra cứu cho phép tìm một mục đã biết và truy cập siêu dữ liệu hoặc nội dung của nó, còn tùy quyền của chính mục đó. Thư mục có quyền tra cứu nhưng không có quyền đọc có thể cho mở một tên tệp đã biết, đồng thời ngăn việc liệt kê thông thường toàn bộ tên.

Quyền ghi trên thư mục điều khiển thay đổi các mục bên trong. Tạo hoặc xóa một mục thường cũng cần quyền tra cứu trên thư mục đó. Xóa tệp chủ yếu là thao tác trên thư mục chứa tên tệp; bit ghi của bản thân tệp không bảo vệ chắc chắn trước việc bị người có quyền thay đổi thư mục gỡ bỏ. Thư mục có sticky bit, chẳng hạn cấu hình /tmp thông dụng, bổ sung quy tắc về quyền sở hữu.

Những khác biệt này giải thích vì sao đổi tệp sang quyền 777 thường không giải quyết đúng vấn đề. Thư mục cha bị chặn vẫn có thể giữ nguyên, còn tệp lại được cấp thêm quyền ghi và thực thi không cần thiết. Hãy bắt đầu từ thao tác bị từ chối và tài khoản thực hiện thao tác.

Kiểm tra đúng danh tính dịch vụ đang dùng

Tài khoản shell chạy lệnh chẩn đoán có thể khác tài khoản dịch vụ mở tệp. Kiểm tra người dùng và các nhóm bổ sung trong cấu hình dịch vụ, sau đó kiểm tra thông tin định danh hiệu lực của tiến trình. Quản trị viên đọc thủ công thành công không chứng minh dịch vụ cũng đọc được.

Khi có sẵn, công cụ như namei -l /srv/reports/daily/report.txt có thể hiển thị quyền và chủ sở hữu của từng thành phần. Cũng cần xem liên kết tượng trưng có dẫn sang cây thư mục khác hay không. Đích tương đối của symlink được diễn giải từ thư mục chứa liên kết, và đường dẫn đích cuối có các yêu cầu tra cứu riêng.

Nếu các bit quyền có vẻ đúng, chuyển sang bằng chứng cho giả thuyết tiếp theo. ACL có thể thay đổi kết quả cấp quyền hiệu lực. Container có thể nhìn thấy một điểm gắn khác hoặc dùng mã người dùng dạng số khác. Cơ chế cô lập dịch vụ có thể làm đường dẫn không truy cập được dù shell trên máy chủ nhìn thấy nó. Nhật ký kiểm toán có thể ghi nhận từ chối từ chính sách bảo mật. Giữ các giả thuyết tách biệt để mỗi quan sát kiểm tra một lời giải thích cụ thể.

Cấp đúng thao tác mà dịch vụ cần

Đường dẫn cấu hình chỉ đọc thường cần quyền tra cứu trên các thư mục cha và quyền đọc trên tệp cuối. Không cần biến thư mục thành nơi mọi người đều có quyền ghi. Nhóm sở hữu hoặc ACL được giới hạn phù hợp có thể cấp quyền cho dịch vụ mà vẫn giữ phạm vi truy cập hẹp với người dùng khác.

Sau khi thay đổi quyền, lặp lại đúng thao tác bằng danh tính và đường dẫn mà dịch vụ dùng. Ghi cả quyền trước và sau trong bản mô tả thay đổi. Tài liệu phân giải đường dẫn Linux mô tả thứ tự tra cứu và phép kiểm tra quyền; thứ tự đó tạo ra trình tự cụ thể để điều tra lỗi tiếp theo.

So sánh quyền chỉ tra cứu và quyền chỉ đọc thư mục

Ví dụ đầu đổi một bit. Hai chế độ đối lập sẽ làm rõ hơn vì sao không nên gộp quyền đọc và quyền tra cứu thành một khái niệm truy cập chung. Dùng tài khoản thường, thư mục tạm đã tạo và shell tiếp tục chạy sau một lệnh thất bại dự kiến:

chmod 100 "$lab/daily"
cat "$lab/daily/report.txt"
ls -- "$lab/daily"
chmod 400 "$lab/daily"
ls -1 -- "$lab/daily"
cat "$lab/daily/report.txt"
chmod 700 "$lab/daily"

Với mode 100, chủ sở hữu có quyền tra cứu nhưng không có quyền đọc thư mục. Mở tệp có tên đã biết thành công, còn liệt kê tên thất bại. Với mode 400, chủ sở hữu đọc được các tên mục, nên lệnh liệt kê đơn giản có thể hiện tên tệp. Tuy nhiên, mở tên đó lại thất bại vì cần quyền tra cứu. Các tùy chọn liệt kê phức tạp hơn có thể tra cứu thêm siêu dữ liệu và báo lỗi bổ sung; ví dụ cố ý dùng dạng chỉ liệt kê tên.

Bảng so sánh mode 100 chỉ tra cứu, mode 400 chỉ đọc và mode 700 đủ quyền riêng cho chủ sở hữu khi liệt kê tên hoặc mở tệp đã biết.Mở ảnh kích thước đầy đủ ↗

Bảng giữ nguyên quyền đọc của tệp. Kết quả thay đổi do thư mục chứa tệp. Mô hình giả định quyền tùy nghi thông thường, chủ sở hữu không có đặc quyền vượt kiểm tra và các thư mục bên ngoài đều đi qua được. Cơ chế cô lập dịch vụ hoặc chính sách bảo mật có thể áp thêm giới hạn ngoài mô hình này.

Vì sao vẫn xóa được tệp chỉ đọc

Thư mục chứa các tên tham chiếu tới đối tượng trong hệ thống tệp. Gỡ một tên là cập nhật thư mục đó, không phải ghi nội dung qua bộ mô tả của tệp. Bởi vậy, mode cấm ghi nội dung không tự cấm thao tác unlink đối với mục thư mục. Tài liệu unlink của Linux mô tả quyền trên thư mục và những điều kiện lỗi bổ sung liên quan.

Ví dụ cục bộ sau chỉ xóa một tệp đánh dấu vừa tạo trong thư mục thử, không xóa báo cáo dùng ở các bước trước:

printf '%s\n' 'disposable marker' > "$lab/daily/remove-me.txt"
chmod 400 "$lab/daily/remove-me.txt"
rm -f -- "$lab/daily/remove-me.txt"
test ! -e "$lab/daily/remove-me.txt"

Chủ sở hữu xóa được mục này vì thư mục chứa nó có quyền ghi và tra cứu sau khi khối trước khôi phục mode. Cờ force chỉ bỏ qua câu hỏi xác nhận đối với tệp đánh dấu chỉ đọc; nó không cấp thêm quyền của hệ thống tệp. Quan sát này không có nghĩa mọi tệp chỉ đọc đều xóa được. Sticky bit, thuộc tính immutable, hệ thống tệp gắn chỉ đọc, ACL hoặc chính sách bảo mật có thể đổi kết quả. Ví dụ tách riêng các phép kiểm tra quyền thư mục thông thường để làm rõ sự phụ thuộc thường bị bỏ sót.

Tài liệu chmod còn giúp phân biệt thay đổi quyền với thực hiện thao tác được bảo vệ. Chủ sở hữu thường có thể đổi mode của tệp, với các giới hạn được tài liệu mô tả; tài khoản dịch vụ muốn đọc tệp có thể không sở hữu nó. Sửa quyền bằng tài khoản quản trị và xác minh truy cập bằng tài khoản dịch vụ là hai bước sử dụng thông tin định danh khác nhau.

Biến thông báo lỗi thành yêu cầu truy cập cụ thể

Ghi đường dẫn chính xác, người dùng hiệu lực và các nhóm, thao tác, cùng kết quả mong đợi. Chẳng hạn, dịch vụ đọc báo cáo cần đi qua các thư mục cha và mở tệp đã biết để đọc. Nó có thể không cần liệt kê những tệp bên cạnh hoặc tạo báo cáo mới. Khi ấy, chỉ kiểm tra liệt kê thư mục sẽ chưa kiểm tra đúng yêu cầu của ứng dụng.

Để tự tái hiện, dự đoán kết quả mở một tệp đã biết khi chỉ một thư mục bên ngoài mất quyền tra cứu. Trước hết khôi phục quyền thư mục bên trong để mỗi lần chỉ đổi một nguyên nhân. Sau đó thử lại khi khôi phục quyền bên ngoài. Đây cũng là cách chẩn đoán thực tế: xác định thao tác đầu tiên thất bại, đổi điều kiện nhỏ nhất có liên quan rồi lặp lại thao tác gốc bằng danh tính gốc.

Nguồn tham khảo & đọc thêm

  1. Linux path resolution manual
  2. Linux unlink reference
  3. Linux chmod reference
← Về trang bài viết

Hình minh họa

100%