在 Linux 上使用 NFSv4 ACL

在 Linux 上使用 NFSv4 ACL

我已经成功设置了 NFSv4 客户端和服务器,大致遵循以下指南:设置 NFS 指南。两者都运行 Ubuntu Linux 14.04。这是一个小型测试环境,没有复杂的身份验证;两台服务器只使用相同的密码文件。一切似乎都正常工作;文件在客户端上可见,权限/用户 ID 正确。

现在我想使用 NFSv4 ACL 来控制对 NFSv4 服务器上文件的访问。我在客户端上安装了必要的命令行工具,并且能够看到类似于 NFSv4 ACL 的内容:

$ nfs4_getfacl .
A::OWNER@:rwaDxtTcCy
A::GROUP@:rxtcy
A::EVERYONE@:rxtcy

但是,虽然我可以顺利获取 ACL 列表,但我无法设置任何 ACL。每次尝试都会导致Invalid argument错误setxattr

$ nfs4_setfacl -a A::OWNER@:rxtncy .
Failed setxattr operation: Invalid argument

我使用 strace 查看发生了什么。根据我能找到的稀疏文档,NFSv4 ACL 作为二进制 XDR 数据存储在system.nfs4_acl文件上调用的扩展属性中。果然,这就是正在发生的事情;setxatt正在返回EINVAL

getxattr("/primary/home/rstudiouser", "system.nfs4_acl", 0x0, 0) = 80
getxattr("/primary/home/rstudiouser", "system.nfs4_acl", "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x01\xe7\x00\x00\x00\x06OWNER@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\xa1\x00\x00\x00\x06GROUP@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\xa1\x00\x00\x00\x09EVERYONE@\x00\x00", 80) = 80
setxattr("/primary/home/rstudiouser", "system.nfs4_acl", "\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\xa9\x00\x00\x00\x06OWNER@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x01\xe7\x00\x00\x00\x06OWNER@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\xa1\x00\x00\x00\x06GROUP@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\xa1\x00\x00\x00\x09EVERYONE@\x00\x00", 104, XATTR_REPLACE) = -1 EINVAL (Invalid argument)

那么,为什么会setxattr失败呢? NFSv4 服务器上启用了扩展属性:

$ sudo tune2fs -l /dev/sda1
tune2fs 1.42.9 (4-Feb-2014)
...
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file 
uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash
Default mount options:    user_xattr acl
...

并且客户端肯定使用 NFSv4 协议;用来mount显示已安装的驱动器:

$ mount
...
192.168.55.103:/primary/home on /primary/home type nfs4 (rw,rsize=8192,wsize=8192,timeo=14,intr,nfsvers=4,acl,addr=192.168.55.103,client
addr=192.168.55.101)
...

我尝试翻转 nfsd 上的所有调试标志,看看是否会产生有用的日志。

$ sudo rpcdebug -m nfsd -s all

它确实确认服务器正在接收设置属性的请求。

Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567892] nfsd_dispatch: vers 4 proc 1
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567909] nfsv4 compound op #1/2: 22 (OP_PUTFH)
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567915] nfsd: fh_verify(36: 01070001 001c0002 00000000 acf697e6 a847b405 c98a638b)
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567929] nfsv4 compound op ffff88003c2f6080 opcnt 2 #1: 22: status 0
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567932] nfsv4 compound op #2/2: 34 (OP_SETATTR)
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567938] nfsd: fh_verify(36: 01070001 001c0002 00000000 acf697e6 a847b405 c98a638b)
Apr  7 20:21:49 vagrant-ubuntu-trusty-64 kernel: [73465.567978] nfsv4 compound op ffff88003c2f6080 opcnt 2 #2: 34: status 22

“状态 22”是什么?为什么,22 = EINVAL,无效参数,这是setxattr客户端返回的内容。不幸的是,它似乎没有透露任何有关为什么该论点被视为无效。

我还尝试过其他一些方法:

  1. 一种可能性是服务器认为 ACL 格式不正确。为了检查这一点,我使用了nfs4_setfacl -e .,这会打开现存的Invalid argument文本编辑器中的 ACL 进行操作。保存文件而不进行任何更改仍会生成应用时产生的 ACL 。

  2. 用户 ID 映射是 NFSv4 的另一个常见问题。我已验证用户 ID 是否排列正确,并且从 NFSv4 客户端的角度来看文件所有权/模式位是否正确。我还尝试通过在两台服务器上进行设置来为 NFSv4 创建域Domain = localdomain/etc/idmapd.conf但毫无效果。

如果您在基于 Linux 的 NFS 服务器上使用 NFSv4 ACL,我很想听听您的意见;我发现了很多关于设置 NFSv4 本身的教程(请参阅此篇幅顶部的链接),但几乎没有提到 ACL 的使用。

答案1

不管怎样,在经过几次尝试之后,我最终放弃了这种努力,其中大部分是尝试使用带有 ZFS 的 Ubuntu 主机。

由于我的测试环境只需要一个可以公开带有 ACL 的 NFSv4 服务器的 VM,因此我最终放弃了运行 Linux 服务器的努力,而是使用 FreeBSD 10.3 映像。尝试让它与 NFSv4 一起工作是很难,但至少是可能的。有一个相当不错的指南FreeBSD nfsv4(4) 手册页

答案2

NFSv4 ACL 类似于 RichACL。问题是 RichACL 未在除 ZFS 之外的任何底层 Linux 文件系统中实现。Ext4、XFS 等仅支持 POSIX ACL,这是前者的有限子集。文件的实际权限将降低到底层文件系统支持的权限。底线是 ACL 在 Linux 上是一团糟(2019 年 3 月仍然如此),需要修复。

相关内容