ACL 可以覆盖 Linux 上的文件权限吗?

ACL 可以覆盖 Linux 上的文件权限吗?

我最近在 FreeBSD 上遇到了这个问题,但感谢上帝 ZFS 帮我解决了这个问题。然而,我在带有 ext4 的 CentOS 中再次遇到了它,不知道是否有一个简单的方法可以绕过它(或任何绕过它的方法)。我想要的是一个目录,其中某个组中的任何用户都可以保证对文件的读/写访问权限,无论用户无能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::---

可以看到默认的ACLmask 都指定rwxformygroup但文件权限胜过它并导致---.不幸的是,这意味着如果用户的 FTP 客户端(例如)将文件上传为 640,组中的其他人将无法干扰它。有没有解决的办法?

答案1

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";
}

相关内容