drwxr-xr-x là gì? Giải thích permission Linux
Đọc drwxr-xr-x từng ký tự để hiểu mode 755, quyền x trên thư mục là đi qua, và vì sao chmod 777 không phải cách sửa permission đúng.
Ý nghĩa của drwxr-xr-x
drwxr-xr-x mô tả một thư mục mà owner có thể thay đổi nội dung, còn mọi user khác có thể đọc và đi qua thư mục đó nhưng không thể thay đổi gì. Ở dạng octal, mode này là 755. Linux in 10 ký tự này ở đầu mỗi dòng output của ls -l. Chúng luôn có cùng ý nghĩa và cùng thứ tự, nên chỉ cần hiểu một chuỗi là bạn có thể hiểu tất cả chuỗi tương tự.
Có một quy tắc cần biết trước, vì nó quyết định việc tự kiểm tra của bạn có cho kết quả đúng hay không. User root bỏ qua các permission bit. Kernel cấp cho root capability CAP_DAC_OVERRIDE (discretionary access control override), nên root có thể mở các file có mode không cho phép việc đó. Mọi ví dụ trên trang này đều thành công khi chạy bằng root, bất kể các bit ghi gì. Hãy đăng nhập bằng user thông thường khi muốn quan sát các quy tắc này hoạt động.
Mười ký tự, đọc từng ký tự
Tạo một thư mục và một file để kiểm tra. Không có lệnh nào ở đây tác động ra ngoài thư mục mới.
mkdir -p ~/permdemo/inner
printf 'hello\n' > ~/permdemo/inner/notes.txt
ls -ld ~/permdemo ~/permdemo/inner ~/permdemo/inner/notes.txtVới umask mặc định phổ biến là 022, hai dòng thư mục bắt đầu bằng drwxr-xr-x và dòng file bắt đầu bằng -rw-r--r--.
Ký tự 1 cho biết loại file, không phải permission. d là thư mục. - là file thông thường. l là symbolic link. c và b lần lượt là device node dạng character và block. s là socket, còn p là named pipe. Ký tự này nằm ngoài giá trị octal, nên drwxr-xr-x trở thành 755 thay vì bắt đầu bằng d.
Chín ký tự phía sau được chia thành ba nhóm, mỗi nhóm ba ký tự, và thứ tự của chúng không bao giờ thay đổi.
- Ký tự 2 đến 4 là bộ ba owner, gồm các bit áp dụng cho user sở hữu file.
- Ký tự 5 đến 7 là bộ ba group, gồm các bit áp dụng cho group của file.
- Ký tự 8 đến 10 là bộ ba other, gồm các bit áp dụng cho tất cả user khác.
Trong một bộ ba, các vị trí luôn là r, sau đó w, rồi x; dấu gạch ngang nghĩa là bit đó đang tắt. Các chữ cái không đổi vị trí. r-x nghĩa là có quyền đọc nhưng không có quyền ghi. -w- nghĩa là có quyền ghi nhưng không có quyền đọc; trường hợp này hợp lệ nhưng hiếm gặp.
Vì vậy drwxr-xr-x được tách như sau: d cho thư mục, tiếp theo rwx cho owner, r-x cho group và r-x cho other.
Một số hệ thống in thêm ký tự thứ 11. Dấu chấm ở cuối, drwxr-xr-x., nghĩa là file có SELinux (security enhanced Linux) context. Các bản phân phối dùng SELinux như Fedora và Rocky mặc định in ký tự này. Dấu cộng ở cuối, drwxr-xr-x+, nghĩa là file có POSIX ACL (access control list), tức một tập rule bổ sung ngoài chín bit này. Dùng getfacl <path> để đọc các rule bổ sung đó.
r, w và x có tác dụng khác nhau trên thư mục
Đây là quy tắc đầu tiên mà người mới thường hiểu sai. Các chữ cái trên file và thư mục giống nhau. Nhưng quyền mà chúng cấp thì không giống nhau.
rtrên file cho phép đọc nội dung.rtrên thư mục liệt kê tên bên trong thư mục, đây là việc màlskhông có tùy chọn cần.wtrên file cho phép thay đổi nội dung.wtrên thư mục cho phép thêm và xóa entry trong thư mục. Xóa một file là thay đổi đối với thư mục, nên quyền write trên thư mục mới quyết định việc này; mode của chính file không có tác dụng.xtrên file cho phép chạy file như một chương trình.xtrên thư mục cho phép traverse, tức là kernel có thể resolve một tên bên trong thư mục trong quá trình tra cứu path.
Traverse là phần khiến nhiều người bất ngờ. x trên thư mục không chạy gì cả. Để mở /srv/site/index.html, cần x trên /, rồi x trên /srv, tiếp theo x trên /srv/site, và cuối cùng r trên file. Nếu một thư mục trong chuỗi đó không có x cấp cho bạn, quá trình tra cứu dừng tại đó, và caller nhận được Permission denied cho toàn bộ path, ngay cả khi file ở cuối có quyền đọc cho mọi người. namei -l /srv/site/index.html in từng bước trong chuỗi cùng mode và owner, để bạn thấy link nào làm quá trình bị dừng.
Một thư mục có r nhưng không có x là trạng thái nửa vời khá lạ mà bạn cần nhận biết. User thông thường có thể liệt kê tên, vì đó là quyền mà r cấp, nhưng không thể stat bất kỳ entry nào. Vì vậy ls -l điền dấu hỏi vào các cột size và mode, đồng thời in ls: cannot access ...: Permission denied cho từng entry.
Chuyển các ký tự thành 755
Mỗi bộ ba là một số ba bit. r có giá trị 4, w có giá trị 2, x có giá trị 1. Cộng các bit đang bật.
rwxlà 4 + 2 + 1 = 7rw-là 4 + 2 = 6r-xlà 4 + 1 = 5r--là 4---là 0
drwxr-xr-x vì vậy là 7 cho owner, 5 cho group và 5 cho other: 755. -rw-r--r-- là 6, 4, 4: 644. drwxrwxr-x là 7, 7, 5: 775, tức 755 với quyền ghi được thêm cho group. Bạn không cần tự đếm ký tự, vì stat in cả hai dạng cùng lúc.
stat -c '%A %a %U %G %n' ~/permdemo ~/permdemo/inner/notes.txt%A là dạng ký tự, %a là dạng bát phân, còn %U và %G cho biết user sở hữu và group sở hữu.
Các chuỗi quyền mà mọi người thường tìm kiếm
Đây là những mode thường gặp trên một server thực tế, kèm giá trị octal và vị trí thường xuất hiện.
-rw-r--r--là 644. File thông thường mà service chỉ đọc, chẳng hạn file cấu hình hoặc trang HTML.-rw-------là 600. Dữ liệu bí mật: private key SSH hoặc file.envcủa ứng dụng.-rw-rw-r--là 664. File trong một thư mục được chia sẻ cho một group, nơi các thành viên cần quyền ghi.-rwxr-xr-xlà 755. Script và binary, chẳng hạn/usr/local/bin/backup.shvà hầu hết/usr/bin.-rwx------là 700. Script riêng tư mà chỉ owner mới được chạy.drwxr-xr-xlà 755. Gần như mọi thư mục hệ thống và document root của website.drwx------là 700.~/.sshvà các thư mục home trên một máy được khóa chặt.drwxrwxr-xlà 775. Thư mục mà group của owner có thể ghi vào.drwxrwsr-xlà 2775. Tương tự, nhưng có thêm bit setgid, nên các file mới bên trong sẽ kế thừa group của thư mục.drwxrwxrwtlà 1777./tmp.tở cuối là sticky bit, nên user chỉ có thể xóa file của chính mình.-rwsr-xr-xlà 4755. Binary setuid chạy với quyền của owner, chẳng hạn/usr/bin/passwdvà/usr/bin/sudo.-rw-rw-rw-là 666, còndrwxrwxrwxlà 777. Cho phép mọi user ghi, và trên server điều này gần như luôn là một lỗi.lrwxrwxrwxlà chuỗi mà mọi symbolic link đều hiển thị. Linux bỏ qua các bit mode trên link và kiểm tra target thay vào đó, nên chuỗi này hoàn toàn không có ý nghĩa.
Bạn thuộc bộ quyền nào
Đây là quy tắc thứ hai mà người mới thường hiểu sai. Kernel chỉ chọn đúng một bộ quyền rồi dừng lại.
Nếu user ID của bạn trùng với owner của file, bạn nhận bộ quyền owner. Các bit group và other không được xét đến. Nếu không, kernel kiểm tra group của file có nằm trong một group của bạn hay không. Nếu có, bạn nhận bộ quyền group. Nếu không, bạn nhận bộ quyền other.
Có 2 hệ quả. Bộ quyền owner vẫn được áp dụng dù đây là bộ quyền hạn chế nhất. File có mode 0466, hiển thị là -r--rw-rw-, chỉ cho owner quyền đọc nhưng cho mọi người khác quyền ghi, vì điều kiện owner được khớp trước và kernel không đọc các bộ quyền phía sau. Đây là hành vi hợp lệ và thường gây khó hiểu khi mới gặp.
Bộ quyền group được chọn theo group của file, không phải theo danh sách group mà bạn thuộc về. ls -l in 2 tên trên mỗi dòng: owner trước, group sau. Chỉ group thứ hai đó mới có quyền quyết định trên file. Thuộc 20 group chỉ có ích khi file có một trong các group đó.
id
stat -c '%U %G %A %n' ~/permdemo/inner/notes.txtid in user của bạn và toàn bộ group mà bạn thuộc về. stat in owner và group của file. So sánh 2 kết quả này để biết kernel sẽ dùng bộ quyền nào cho bạn.
Đây là lý do một shared directory thường được gán một group và bật bit setgid. sudo chmod 2775 /srv/shared hiển thị là drwxrwsr-x. Các file được tạo bên trong sẽ kế thừa group của directory thay vì group cá nhân của người tạo. Các subdirectory mới cũng được bật bit setgid. Setgid đặt group, không đặt mode. Với umask mặc định là 022, file mới bên trong vẫn có mode 644. Thành viên trong group có thể đọc nhưng không thể ghi. Muốn cho group quyền ghi, mọi người làm việc trong đó phải dùng umask 002, hoặc phải cấu hình default ACL trên directory. Default ACL này thay thế umask cho các file được tạo bên trong. Mỗi service dùng một account riêng là phần còn lại của vấn đề này. Nội dung đó được trình bày trong mỗi Linux user một service trên VPS.
umask quyết định mode của mọi file mới
File mới không tự lấy mode từ bạn. Mode của nó do program tạo file quyết định, sau đó bị trừ đi các bit mà umask xóa. umask là một mask dùng để xóa bit, vì vậy umask càng lớn thì file càng private.
Phần lớn distribution phát hành với giá trị 022. Program tạo regular file thường yêu cầu 0666. Program tạo directory thường yêu cầu 0777. umask xóa 022 khỏi cả hai yêu cầu, nên file có mode 644 và directory có mode 755. Đây chính là cặp giá trị thường thấy trên một VPS mới.
umask
umask -S
touch ~/permdemo/new.txt && mkdir -p ~/permdemo/newdir
ls -ld ~/permdemo/new.txt ~/permdemo/newdirumask -S in ra cùng giá trị dưới dạng chữ cái, dễ đọc hơn 0022. Đặt umask 027 trong ~/.profile để dùng default chặt hơn: file có mode 640 và directory có mode 750, nhờ đó group của bạn có thể đọc file bạn làm, còn những người khác thì không. Các kết quả này giả định request thông thường là 0666 và 0777.
Có hai giới hạn cần nhớ. umask chỉ có thể xóa bit, không thể thêm bit. File được yêu cầu với mode 0666, là mode mà touch yêu cầu, sẽ không bao giờ có quyền execute dù bạn đặt umask thế nào. Program yêu cầu chỉ cho owner truy cập vẫn giữ nguyên quyền đó: mktemp tạo file với mode 600 và directory với mode 700 khi dùng umask 022 hoặc 027. Ngoài ra, systemd service không đọc shell profile của bạn, nên hãy đặt giá trị này trong unit file.
[Service]
UMask=0027Có một trường hợp không dùng umask. Khi parent directory có default ACL, umask bị bỏ qua và các permission bit của file mới được lấy từ ACL kế thừa.
Vì sao file web dùng quyền 644 và thư mục web dùng quyền 755
Web server chạy dưới một account riêng: www-data trên Debian và Ubuntu, nginx trên Rocky và Alma. Process đó cần quyền đọc trên các file được phân phối và quyền traverse trên các thư mục cha. Nó không có lý do để ghi vào các file này, và static site không bao giờ nên cho phép việc đó.
Quyền 644 trên file cho owner quyền ghi và mọi user quyền đọc, nên deploy user có thể publish còn web user có thể phục vụ file. Quyền 755 trên thư mục cho owner quyền ghi và mọi user quyền traverse, nên web user có thể đi qua path nhưng không thể thêm hoặc xóa bất cứ thứ gì. Khi application có bug, nó cũng không thể ghi đè các page đang được phục vụ.
Quy tắc traverse gây lỗi ngay tại đây. Nếu site nằm trong /home/deploy/site, /home/deploy là 750, và web user không thuộc group của thư mục, web user hoàn toàn không thể đi vào home directory. Request sẽ kết thúc bằng HTTP 403 và một dòng như sau trong /var/log/nginx/error.log:
open() "/home/deploy/site/index.html" failed (13: Permission denied), client: 203.0.113.5Số 13 là EACCES, tức kernel từ chối quyền truy cập. Network không có vấn đề: port vẫn listening và request đã đến nơi. Vì vậy lỗi này dễ gây nhầm lẫn khi bạn vẫn đang học cách port listening hoạt động trên Linux. Chạy namei -l /home/deploy/site/index.html rồi đọc theo chuỗi path để tìm directory đầu tiên không có x cho other.
Directory mà application cần ghi vào, chẳng hạn upload path, là ngoại lệ. Cấp quyền bằng ownership thay vì dùng mode rộng hơn: sudo chown -R www-data:www-data /srv/site/uploads và giữ mode ở 755. Chỉ cho phép ghi tại directory duy nhất thực sự cần quyền đó.
chmod mà không làm phẳng toàn bộ cây thư mục
chmod có cả hai dạng. Dạng bát phân đặt cả 9 bit cùng lúc: chmod 644 notes.txt. Dạng symbolic chỉ thay đổi phần bạn chỉ định và giữ nguyên phần còn lại: chmod u+x deploy.sh thêm quyền execute cho owner, còn chmod go-w notes.txt xóa quyền write của group và other.
Đệ quy là chỗ dễ làm hỏng cây thư mục. chmod -R 755 . đánh dấu mọi file ảnh và mọi file cấu hình là executable, vì chmod không thể phân biệt script với JPEG. Hãy dùng chữ hoa X thay thế.
chmod -R u=rwX,go=rX ~/permdemo
stat -c '%a %n' ~/permdemo ~/permdemo/inner/notes.txtX chữ hoa áp dụng quyền execute cho directory và cho các file vốn đã có một execute bit ở đâu đó. Directory sẽ có quyền 755, file thông thường sẽ có quyền 644, còn các script vốn đã executable vẫn giữ nguyên trạng thái đó. Khi một file đã có mode mà bạn tin cậy, chmod --reference=good.sh other.sh sẽ sao chép mode đó sang các file khác.
Thông báo bạn thấy khi sai một bit
bash: ./deploy.sh: Permission denied nghĩa là script không có bit x trong bộ quyền áp dụng cho bạn, hoặc một thư mục trên đường dẫn của nó không có x. chmod u+x deploy.sh sửa được trường hợp đầu tiên.
bash: ./deploy.sh: cannot execute: required file not found là một lỗi khác có tên dễ gây nhầm lẫn. Bit x không có vấn đề, nhưng interpreter được ghi ở dòng đầu tiên lại không tồn tại. Nguyên nhân thường gặp là line ending của Windows, khiến kernel tìm một interpreter có tên /bin/bash\r. Sửa bằng sed -i 's/\r$//' deploy.sh.
Permissions 0644 for '/home/deploy/.ssh/id_ed25519' are too open. xuất phát từ SSH client, vì client từ chối dùng private key mà các account khác có thể đọc. Key cần quyền 600 và ~/.ssh cần quyền 700. Hướng dẫn đầy đủ về quản lý key và quyền file SSH có trong quản lý key SSH và quyền file của chúng.
Authentication refused: bad ownership or modes for directory /home/deploy/.ssh xuất hiện trong journal của server khi home directory hoặc .ssh của nó cho phép group ghi. Thiết lập StrictModes của sshd từ chối key, còn từ phía client, lỗi này chỉ hiện thành một prompt yêu cầu password bất ngờ mà không có giải thích.
sudo: /etc/sudoers is world writable, theo sau là sudo: no valid sudoers sources found, quitting, nghĩa là sudo đã kiểm tra mode của file cấu hình riêng và từ chối chạy. File đó phải có quyền 0440 và tuyệt đối không được cho phép mọi user ghi. Đây là hậu quả thường gặp của một lệnh chmod đệ quy trên phạm vi rộng. Lỗi này có thể xuất hiện cùng thông báo của sshd ở trên, khiến console của provider trở thành cách duy nhất để truy cập lại server.
Vì sao 777 không phải là cách khắc phục
777 cấp quyền ghi cho mọi account trên máy và cho mọi process chạy dưới các account đó. Server chạy các service bằng user riêng, nên “mọi người” trên VPS bao gồm nhiều đối tượng hơn đáng kể so với laptop. Một service bị breach có thể ghi vào mọi nơi mà 777 cho phép.
Trong web root, tác hại xảy ra trực tiếp. Một directory cho phép mọi người ghi và đồng thời được server phục vụ sẽ biến lỗ hổng upload file thành cách đặt một script lên máy rồi request lại script đó.
777 gần như luôn là câu trả lời sai cho vấn đề ownership. Triệu chứng là “app không thể ghi vào directory này”. Nguyên nhân là directory thuộc về sai user. sudo chown -R appuser:appuser /srv/app/storage với mode 755 giải quyết vấn đề này: application có thể ghi vào đó, còn mọi account khác vẫn có thể list và truy cập directory nhưng không thể ghi vào đó. Việc tạo các account này trước khi deploy bất kỳ thứ gì thuộc về 10 phút đầu tiên trên một VPS mới.
Quyền ghi cho mọi người hợp lệ ở một nơi quen thuộc là /tmp, và nó được viết là drwxrwxrwt. t ở cuối là sticky bit: directory cho phép mọi người ghi, nhưng mỗi user chỉ có thể xóa các file do chính user đó sở hữu. Nếu không có bit này, bất kỳ account nào cũng có thể xóa file tạm của account khác.
Đọc mode trước khi thay đổi
Các lệnh này chỉ đọc trạng thái, nên an toàn khi chạy ở bất kỳ đâu.
id
umask
stat -c '%A %a %U %G %n' ~/permdemo ~/permdemo/inner/notes.txt
namei -l ~/permdemo/inner/notes.txt
find ~/permdemo -perm -0002find <path> -perm -0002 liệt kê mọi thứ bên dưới một đường dẫn có bật bit ghi cho mọi người. Đây là cách nhanh nhất để audit một máy chủ sau khi ai đó đã sửa chữa bằng chmod 777.
Để kiểm tra một service account cụ thể có thể truy cập vào một thư mục hay không, hãy thực hiện kiểm tra với account đó. sudo -u www-data test -x /srv/site && echo yes || echo no in yes khi user đó có quyền traverse trên thư mục và in no khi không có quyền này. Kiểm tra với root không chứng minh được điều gì, vì root bỏ qua bước kiểm tra nên kết quả luôn là yes.
FAQ
drwxr-xr-x trong Linux có nghĩa là gì?
Đây là một directory, được biểu thị bằng ký tự đầu d, với mode 755. Bộ 3 quyền của owner là rwx, nên owner có đầy đủ mọi quyền trên directory này. Bộ 3 quyền của group là r-x và bộ 3 quyền của other là r-x, nên mọi account khác đều có thể liệt kê tên bên trong và đi qua directory, nhưng chỉ owner mới có thể thêm hoặc xóa nội dung. Xác nhận bất kỳ path nào bằng stat -c '%A %a %U %G %n' <path>. Lệnh này in dạng ký tự và dạng octal cạnh nhau.
Vì sao web file có mode 644 còn web directory có mode 755?
Web server chạy dưới một account khác, là www-data trên Ubuntu. Nó cần quyền đọc trên các file được serve và quyền traverse trên mọi directory nằm phía trên các file đó. Nó không cần quyền ghi vào file hoặc directory. Mode 644 cho owner quyền ghi và mọi account khác quyền đọc. Mode 755 cho owner quyền ghi và mọi account khác quyền traverse. Directory mà application thực sự cần ghi vào nên được chuyển quyền sở hữu bằng chown cho user của application đó, thay vì mở rộng mode cho mọi account.
Bit x có nghĩa là tôi có thể execute một directory không?
Không. Trên directory, x có nghĩa là traverse. Đây là quyền resolve một name bên trong directory khi kernel duyệt một path. cd cần quyền này, và mọi lần mở một file bên dưới directory đó cũng vậy. Mỗi directory trên path đều cần x. Vì vậy, file có mode 644 vẫn không thể truy cập nếu một directory phía trên thiếu x đối với bạn. namei -l /path/to/file in mode của mọi directory trong chain, cho biết quá trình lookup dừng ở đâu.
chmod 777 có khi nào là cách sửa đúng không?
Gần như không bao giờ trên server. Mode này cấp quyền ghi cho mọi account trên máy, bao gồm cả các account mà service sử dụng. Vì vậy, một service bị breach có thể rewrite file. Khi application không thể ghi vào một directory, vấn đề thực sự thường là ownership: sudo chown -R appuser:appuser /srv/app/storage với mode 755 cấp quyền ghi cho application, còn các account khác vẫn có thể đọc directory nhưng không thể ghi vào đó. Ngoại lệ quen thuộc là /tmp với mode 1777. Cách này chỉ an toàn vì sticky bit ngăn user xóa file của user khác.
Vì sao ls in dấu chấm hoặc dấu cộng sau phần permission?
Ký tự thứ 11 mô tả các rule nằm ngoài 9 bit permission. Dấu chấm, như trong drwxr-xr-x., có nghĩa là một SELinux security context được gắn vào. Đây là trạng thái bình thường trên Fedora và Rocky. Dấu cộng, như trong drwxr-xr-x+, có nghĩa là một POSIX ACL (access control list) đã được thiết lập. Khi đó, một user hoặc group có thể có các quyền không hiển thị trong 3 bộ quyền. Chạy getfacl <path> để liệt kê các entry bổ sung đó.