Linux

ACL 可以覆蓋 Linux 上的文件權限嗎?

  • February 2, 2015

我最近在 FreeBSD 上遇到了這個問題,但感謝上帝 ZFS 在那里為我解決了這個問題。但是我在 CentOS 中再次使用 ext4 並且不知道是否有一種簡單的方法(或任何方法)。我想要的是一個目錄,在這個目錄中,某個組中的任何使用者都保證了對文件的讀/寫訪問權限,而不管使用者的無能umask、糟糕的 FTP 客戶端上傳決定等。我認為這是不可能的,但我’想錯了。看起來不可能的原因是 ext4 ACL 不能覆蓋文件權限,只能與它們相交。例如:

# mkdir bar
# chmod 700 bar
# getfacl bar
# file: bar
# owner: root
# group: mygroup
# flags: -s-
user::rwx
group::rwx                      #effective:---
group:mygroup:rwx              #effective:---
mask::---
other::---
default:user::rwx
default:group::rwx
default:group:mygroup:rwx
default:mask::rwx
default:other::---

您可以看到預設的 ACL遮罩都指定rwx為,mygroup但文件權限勝過它並導致---. 不幸的是,這意味著如果使用者的 FTP 客戶端(例如)將文件上傳為 640,組中的其他人將無法處理它。有沒有解決的辦法?

ACL 授予的權限附加的,但也許您希望它們是遞歸的?(他們不是)

您幾乎可以使用 ACL 獲得所需的內容。您需要首先在樹中的每個文件和目錄上**遞歸地設置 ACL,就像上面一樣。**請務必default:group:mygroup:rwx在目錄中包含設置。現在,任何新目錄都將自動應用這些設置,並且這些目錄中的新文件也是如此。

有兩次仍然失敗:

  • 當有人從樹外移動文件或目錄時。由於 inode 已經存在,它不會獲得其上設置的預設值。
  • 當有人使用覆蓋預設值的 ACL 感知程序從存檔中提取文件時。

除了編寫一個 cron 作業來定期執行之外,我不知道有什麼方法可以處理這兩個chgrp -R mygroup DIRECTORY; chmod g+rwx -R DIRECTORY。根據共享目錄中的文件數量,這可能可行,也可能不可行。

這是我用來修復文件樹上的 ACL 的腳本的略微修改版本。它使用特定的讀寫組和只讀組列表完全覆蓋樹中任何內容上的任何 ACL。

#! /usr/bin/env perl
use strict;
use warnings;
use String::ShellQuote;
use Cwd 'abs_path';

# Usage: fix-permissions.pl DIRECTORY RW_GROUP1,RW_GROUP2... RO_GROUP1,RO_GROUP2...

my $dir= $ARGV[0];
my @rw_groups= split ',', $ARGV[1] if $ARGV[1];
my @ro_groups= split ',', $ARGV[2] if $ARGV[2];
-d $dir or die "No such directory'$dir'\n";
$dir= abs_path($dir);
$dir =~ m|/[^/]+/| or die "Cowardly refusing to run on a top-level directory: $dir\n";

# Give all files rw-r----- and all directories rwxr-x---
# then give each rw_group read/write access, then each ro_group
# read-only access to the whole tree
my $dir_perm= join(',',
 'u::rwx',
 'g::r-x',
 'o::---',
 'd:u::rwx',
 'd:g::r-x',
 'd:o::---',
 ( map { "g:$_:rwx" } @rw_groups ),
 ( map { "d:g:$_:rwx" } @rw_groups ),
 ( map { "g:$_:r-x" } @ro_groups ),
 ( map { "d:g:$_:r-x" } @ro_groups )
);
my $file_perm= join(',',
 'u::rwx',
 'g::r-x',
 'o::---',
 ( map { "g:$_:rw-" } @rw_groups ),
 ( map { "g:$_:r--" } @ro_groups )
);

for (
 "find ".shell_quote($dir)." -type d -print0 | xargs -0 -r setfacl --set ".shell_quote($dir_perm),
 "find ".shell_quote($dir)." ! -type d -print0 | xargs -0 -r setfacl --set ".shell_quote($file_perm)
) {
 0 == system($_) or die "command failed: $_\n";
}

引用自:https://unix.stackexchange.com/questions/182368