POSIX ACLs on XFS are exposed as system.posix_acl_* as well as trusted.SGI_ACL_*. Setting the system attributes updates inode->i_mode, inode->i_acl, and inode->i_default_acl as it should, but setting the trusted attributes does not do that. Fix that by adding xattr handlers for the two trusted.SGI_ACL_* attributes. The handlers must be installed before the trusted.* xattr handler in xfs_xattr_handlers to take effect. Other than before, trusted.SGI_ACL_* attribute values are now verified and cannot be set to invalid values anymore. Access to those attributes is still limited to users capable of CAP_SYS_ADMIN, while the system.posix_acl_* attributes can be read by anyone and set by the file owner. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> --- fs/xfs/xfs_acl.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_acl.h | 3 +++ fs/xfs/xfs_xattr.c | 4 ++- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 763e365..0eea7ee 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -305,3 +305,79 @@ xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) set_acl: return __xfs_set_acl(inode, type, acl); } + +static int +xfs_xattr_acl_get(struct dentry *dentry, const char *name, + void *value, size_t size, int type) +{ + struct inode *inode = d_inode(dentry); + struct posix_acl *acl; + int error; + + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + + acl = get_acl(inode, type); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl == NULL) + return -ENODATA; + + error = XFS_ACL_SIZE(acl->a_count); + if (value) { + if (error > size) + error = -ERANGE; + else + xfs_acl_to_disk(value, acl); + } + + posix_acl_release(acl); + return error; +} + +static int +xfs_xattr_acl_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + struct inode *inode = d_inode(dentry); + struct xfs_inode *ip = XFS_I(inode); + struct posix_acl *acl = NULL; + int error; + + if (!inode->i_op->set_acl) + return -EOPNOTSUPP; + + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) + return value ? -EACCES : 0; + + if (value) { + acl = xfs_acl_from_disk(value, size, XFS_ACL_MAX_ENTRIES(ip->i_mount)); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + if (acl) { + error = posix_acl_valid(acl); + if (error) + goto out; + } + } + + error = inode->i_op->set_acl(inode, acl, type); +out: + posix_acl_release(acl); + return error; +} + +const struct xattr_handler xfs_xattr_sgi_acl_file = { + .prefix = XATTR_TRUSTED_PREFIX SGI_ACL_FILE, + .flags = ACL_TYPE_ACCESS, + .get = xfs_xattr_acl_get, + .set = xfs_xattr_acl_set, +}; + +const struct xattr_handler xfs_xattr_sgi_acl_default = { + .prefix = XATTR_TRUSTED_PREFIX SGI_ACL_DEFAULT, + .flags = ACL_TYPE_DEFAULT, + .get = xfs_xattr_acl_get, + .set = xfs_xattr_acl_set, +}; diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 3841b07..461dea6 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -27,6 +27,9 @@ extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); extern int posix_acl_access_exists(struct inode *inode); extern int posix_acl_default_exists(struct inode *inode); + +extern const struct xattr_handler xfs_xattr_sgi_acl_file; +extern const struct xattr_handler xfs_xattr_sgi_acl_default; #else static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) { diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index c0368151..7534cb5 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -97,12 +97,14 @@ static const struct xattr_handler xfs_xattr_security_handler = { const struct xattr_handler *xfs_xattr_handlers[] = { &xfs_xattr_user_handler, - &xfs_xattr_trusted_handler, &xfs_xattr_security_handler, #ifdef CONFIG_XFS_POSIX_ACL &posix_acl_access_xattr_handler, &posix_acl_default_xattr_handler, + &xfs_xattr_sgi_acl_file, + &xfs_xattr_sgi_acl_default, #endif + &xfs_xattr_trusted_handler, NULL }; -- 2.5.0 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs