diff options
author | Andreas Gruenbacher | 2015-12-02 14:44:40 +0100 |
---|---|---|
committer | Al Viro | 2015-12-06 21:34:16 -0500 |
commit | 5d92b75c753ae27578ee764df3be650c67fa5877 (patch) | |
tree | 360e7bbd6446de9e9b59ab33515274cb5561ec4b /fs | |
parent | 786534b92f3ce68f4afc8a761c80b76887797b0a (diff) |
xfs: Change how listxattr generates synthetic attributes
Instead of adding the synthesized POSIX ACL attribute names after listing all
non-synthesized attributes, generate them immediately when listing the
non-synthesized attributes.
In addition, merge xfs_xattr_put_listent and xfs_xattr_put_listent_sizes to
ensure that the list size is computed correctly; the split version was
overestimating the list size for non-root users.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: xfs@oss.sgi.com
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_acl.c | 23 | ||||
-rw-r--r-- | fs/xfs/xfs_acl.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_xattr.c | 137 |
3 files changed, 59 insertions, 105 deletions
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 6bb470fbb8e8..2d5df1f23bbc 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -252,29 +252,6 @@ xfs_set_mode(struct inode *inode, umode_t mode) return error; } -static int -xfs_acl_exists(struct inode *inode, unsigned char *name) -{ - int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb)); - - return (xfs_attr_get(XFS_I(inode), name, NULL, &len, - ATTR_ROOT|ATTR_KERNOVAL) == 0); -} - -int -posix_acl_access_exists(struct inode *inode) -{ - return xfs_acl_exists(inode, SGI_ACL_FILE); -} - -int -posix_acl_default_exists(struct inode *inode) -{ - if (!S_ISDIR(inode->i_mode)) - return 0; - return xfs_acl_exists(inode, SGI_ACL_DEFAULT); -} - int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) { diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 52f8255d6bdf..286fa89217f5 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -24,16 +24,12 @@ struct posix_acl; #ifdef CONFIG_XFS_POSIX_ACL 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); #else static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) { return NULL; } # define xfs_set_acl NULL -# define posix_acl_access_exists(inode) 0 -# define posix_acl_default_exists(inode) 0 #endif /* CONFIG_XFS_POSIX_ACL */ extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c index 36a43851aac0..110f1d7d86b0 100644 --- a/fs/xfs/xfs_xattr.c +++ b/fs/xfs/xfs_xattr.c @@ -129,47 +129,19 @@ const struct xattr_handler *xfs_xattr_handlers[] = { NULL }; -static unsigned int xfs_xattr_prefix_len(int flags) -{ - if (flags & XFS_ATTR_SECURE) - return sizeof("security"); - else if (flags & XFS_ATTR_ROOT) - return sizeof("trusted"); - else - return sizeof("user"); -} - -static const char *xfs_xattr_prefix(int flags) -{ - if (flags & XFS_ATTR_SECURE) - return xfs_xattr_security_handler.prefix; - else if (flags & XFS_ATTR_ROOT) - return xfs_xattr_trusted_handler.prefix; - else - return xfs_xattr_user_handler.prefix; -} - static int -xfs_xattr_put_listent( +__xfs_xattr_put_listent( struct xfs_attr_list_context *context, - int flags, - unsigned char *name, - int namelen, - int valuelen, - unsigned char *value) + char *prefix, + int prefix_len, + unsigned char *name, + int namelen) { - unsigned int prefix_len = xfs_xattr_prefix_len(flags); char *offset; int arraytop; - ASSERT(context->count >= 0); - - /* - * Only show root namespace entries if we are actually allowed to - * see them. - */ - if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN)) - return 0; + if (!context->alist) + goto compute_size; arraytop = context->count + prefix_len + namelen + 1; if (arraytop > context->firstu) { @@ -177,17 +149,19 @@ xfs_xattr_put_listent( return 1; } offset = (char *)context->alist + context->count; - strncpy(offset, xfs_xattr_prefix(flags), prefix_len); + strncpy(offset, prefix, prefix_len); offset += prefix_len; strncpy(offset, (char *)name, namelen); /* real name */ offset += namelen; *offset = '\0'; + +compute_size: context->count += prefix_len + namelen + 1; return 0; } static int -xfs_xattr_put_listent_sizes( +xfs_xattr_put_listent( struct xfs_attr_list_context *context, int flags, unsigned char *name, @@ -195,24 +169,55 @@ xfs_xattr_put_listent_sizes( int valuelen, unsigned char *value) { - context->count += xfs_xattr_prefix_len(flags) + namelen + 1; - return 0; -} + char *prefix; + int prefix_len; -static int -list_one_attr(const char *name, const size_t len, void *data, - size_t size, ssize_t *result) -{ - char *p = data + *result; + ASSERT(context->count >= 0); - *result += len; - if (!size) - return 0; - if (*result > size) - return -ERANGE; + if (flags & XFS_ATTR_ROOT) { +#ifdef CONFIG_XFS_POSIX_ACL + if (namelen == SGI_ACL_FILE_SIZE && + strncmp(name, SGI_ACL_FILE, + SGI_ACL_FILE_SIZE) == 0) { + int ret = __xfs_xattr_put_listent( + context, XATTR_SYSTEM_PREFIX, + XATTR_SYSTEM_PREFIX_LEN, + XATTR_POSIX_ACL_ACCESS, + strlen(XATTR_POSIX_ACL_ACCESS)); + if (ret) + return ret; + } else if (namelen == SGI_ACL_DEFAULT_SIZE && + strncmp(name, SGI_ACL_DEFAULT, + SGI_ACL_DEFAULT_SIZE) == 0) { + int ret = __xfs_xattr_put_listent( + context, XATTR_SYSTEM_PREFIX, + XATTR_SYSTEM_PREFIX_LEN, + XATTR_POSIX_ACL_DEFAULT, + strlen(XATTR_POSIX_ACL_DEFAULT)); + if (ret) + return ret; + } +#endif - strcpy(p, name); - return 0; + /* + * Only show root namespace entries if we are actually allowed to + * see them. + */ + if (!capable(CAP_SYS_ADMIN)) + return 0; + + prefix = XATTR_TRUSTED_PREFIX; + prefix_len = XATTR_TRUSTED_PREFIX_LEN; + } else if (flags & XFS_ATTR_SECURE) { + prefix = XATTR_SECURITY_PREFIX; + prefix_len = XATTR_SECURITY_PREFIX_LEN; + } else { + prefix = XATTR_USER_PREFIX; + prefix_len = XATTR_USER_PREFIX_LEN; + } + + return __xfs_xattr_put_listent(context, prefix, prefix_len, name, + namelen); } ssize_t @@ -221,7 +226,6 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) struct xfs_attr_list_context context; struct attrlist_cursor_kern cursor = { 0 }; struct inode *inode = d_inode(dentry); - int error; /* * First read the regular on-disk attributes. @@ -230,37 +234,14 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size) context.dp = XFS_I(inode); context.cursor = &cursor; context.resynch = 1; - context.alist = data; + context.alist = size ? data : NULL; context.bufsize = size; context.firstu = context.bufsize; - - if (size) - context.put_listent = xfs_xattr_put_listent; - else - context.put_listent = xfs_xattr_put_listent_sizes; + context.put_listent = xfs_xattr_put_listent; xfs_attr_list_int(&context); if (context.count < 0) return -ERANGE; - /* - * Then add the two synthetic ACL attributes. - */ - if (posix_acl_access_exists(inode)) { - error = list_one_attr(XATTR_NAME_POSIX_ACL_ACCESS, - strlen(XATTR_NAME_POSIX_ACL_ACCESS) + 1, - data, size, &context.count); - if (error) - return error; - } - - if (posix_acl_default_exists(inode)) { - error = list_one_attr(XATTR_NAME_POSIX_ACL_DEFAULT, - strlen(XATTR_NAME_POSIX_ACL_DEFAULT) + 1, - data, size, &context.count); - if (error) - return error; - } - return context.count; } |