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>
This commit is contained in:
parent
786534b92f
commit
5d92b75c75
3 changed files with 72 additions and 118 deletions
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -129,24 +129,35 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static unsigned int xfs_xattr_prefix_len(int flags)
|
||||
static int
|
||||
__xfs_xattr_put_listent(
|
||||
struct xfs_attr_list_context *context,
|
||||
char *prefix,
|
||||
int prefix_len,
|
||||
unsigned char *name,
|
||||
int namelen)
|
||||
{
|
||||
if (flags & XFS_ATTR_SECURE)
|
||||
return sizeof("security");
|
||||
else if (flags & XFS_ATTR_ROOT)
|
||||
return sizeof("trusted");
|
||||
else
|
||||
return sizeof("user");
|
||||
}
|
||||
char *offset;
|
||||
int arraytop;
|
||||
|
||||
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;
|
||||
if (!context->alist)
|
||||
goto compute_size;
|
||||
|
||||
arraytop = context->count + prefix_len + namelen + 1;
|
||||
if (arraytop > context->firstu) {
|
||||
context->count = -1; /* insufficient space */
|
||||
return 1;
|
||||
}
|
||||
offset = (char *)context->alist + context->count;
|
||||
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
|
||||
|
@ -158,61 +169,55 @@ xfs_xattr_put_listent(
|
|||
int valuelen,
|
||||
unsigned char *value)
|
||||
{
|
||||
unsigned int prefix_len = xfs_xattr_prefix_len(flags);
|
||||
char *offset;
|
||||
int arraytop;
|
||||
char *prefix;
|
||||
int prefix_len;
|
||||
|
||||
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 (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
|
||||
|
||||
arraytop = context->count + prefix_len + namelen + 1;
|
||||
if (arraytop > context->firstu) {
|
||||
context->count = -1; /* insufficient space */
|
||||
return 1;
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
offset = (char *)context->alist + context->count;
|
||||
strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
|
||||
offset += prefix_len;
|
||||
strncpy(offset, (char *)name, namelen); /* real name */
|
||||
offset += namelen;
|
||||
*offset = '\0';
|
||||
context->count += prefix_len + namelen + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_xattr_put_listent_sizes(
|
||||
struct xfs_attr_list_context *context,
|
||||
int flags,
|
||||
unsigned char *name,
|
||||
int namelen,
|
||||
int valuelen,
|
||||
unsigned char *value)
|
||||
{
|
||||
context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
list_one_attr(const char *name, const size_t len, void *data,
|
||||
size_t size, ssize_t *result)
|
||||
{
|
||||
char *p = data + *result;
|
||||
|
||||
*result += len;
|
||||
if (!size)
|
||||
return 0;
|
||||
if (*result > size)
|
||||
return -ERANGE;
|
||||
|
||||
strcpy(p, name);
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue