Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs xattr updates from Al Viro: "Andreas' xattr cleanup series. It's a followup to his xattr work that went in last cycle; -0.5KLoC" * 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: xattr handlers: Simplify list operation ocfs2: Replace list xattr handler operations nfs: Move call to security_inode_listsecurity into nfs_listxattr xfs: Change how listxattr generates synthetic attributes tmpfs: listxattr should include POSIX ACL xattrs tmpfs: Use xattr handler infrastructure btrfs: Use xattr handler infrastructure vfs: Distinguish between full xattr names and proper prefixes posix acls: Remove duplicate xattr name definitions gfs2: Remove gfs2_xattr_acl_chmod vfs: Remove vfs_xattr_cmp
This commit is contained in:
commit
ddf1d6238d
49 changed files with 538 additions and 1076 deletions
|
@ -60,10 +60,10 @@
|
|||
static
|
||||
int get_xattr_type(const char *name)
|
||||
{
|
||||
if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
|
||||
if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS))
|
||||
return XATTR_ACL_ACCESS_T;
|
||||
|
||||
if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
|
||||
if (!strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT))
|
||||
return XATTR_ACL_DEFAULT_T;
|
||||
|
||||
if (!strncmp(name, XATTR_USER_PREFIX,
|
||||
|
|
24
fs/9p/acl.c
24
fs/9p/acl.c
|
@ -67,8 +67,8 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
|
|||
return 0;
|
||||
}
|
||||
/* get the default/access acl values and cache them */
|
||||
dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT);
|
||||
pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS);
|
||||
dacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_DEFAULT);
|
||||
pacl = __v9fs_get_acl(fid, XATTR_NAME_POSIX_ACL_ACCESS);
|
||||
|
||||
if (!IS_ERR(dacl) && !IS_ERR(pacl)) {
|
||||
set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);
|
||||
|
@ -133,10 +133,10 @@ static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl)
|
|||
goto err_free_out;
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
@ -220,15 +220,12 @@ static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
|
|||
struct posix_acl *acl;
|
||||
int error;
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
v9ses = v9fs_dentry2v9ses(dentry);
|
||||
/*
|
||||
* We allow set/get/list of acl when access=client is not specified
|
||||
*/
|
||||
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
|
||||
return v9fs_xattr_get(dentry, handler->prefix, buffer, size);
|
||||
return v9fs_xattr_get(dentry, handler->name, buffer, size);
|
||||
|
||||
acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags);
|
||||
if (IS_ERR(acl))
|
||||
|
@ -250,16 +247,13 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
|
|||
struct v9fs_session_info *v9ses;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
v9ses = v9fs_dentry2v9ses(dentry);
|
||||
/*
|
||||
* set the attribute on the remote. Without even looking at the
|
||||
* xattr value. We leave it to the server to validate
|
||||
*/
|
||||
if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
|
||||
return v9fs_xattr_set(dentry, handler->prefix, value, size,
|
||||
return v9fs_xattr_set(dentry, handler->name, value, size,
|
||||
flags);
|
||||
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
|
@ -319,7 +313,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
|
|||
default:
|
||||
BUG();
|
||||
}
|
||||
retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags);
|
||||
retval = v9fs_xattr_set(dentry, handler->name, value, size, flags);
|
||||
if (!retval)
|
||||
set_cached_acl(inode, handler->flags, acl);
|
||||
err_out:
|
||||
|
@ -328,14 +322,14 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
|
|||
}
|
||||
|
||||
const struct xattr_handler v9fs_xattr_acl_access_handler = {
|
||||
.prefix = POSIX_ACL_XATTR_ACCESS,
|
||||
.name = XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
.flags = ACL_TYPE_ACCESS,
|
||||
.get = v9fs_xattr_get_acl,
|
||||
.set = v9fs_xattr_set_acl,
|
||||
};
|
||||
|
||||
const struct xattr_handler v9fs_xattr_acl_default_handler = {
|
||||
.prefix = POSIX_ACL_XATTR_DEFAULT,
|
||||
.name = XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
.flags = ACL_TYPE_DEFAULT,
|
||||
.get = v9fs_xattr_get_acl,
|
||||
.set = v9fs_xattr_set_acl,
|
||||
|
|
|
@ -143,8 +143,6 @@ static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
|
|||
{
|
||||
const char *full_name = xattr_full_name(handler, name);
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return v9fs_xattr_get(dentry, full_name, buffer, size);
|
||||
}
|
||||
|
||||
|
@ -154,8 +152,6 @@ static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
|
|||
{
|
||||
const char *full_name = xattr_full_name(handler, name);
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return v9fs_xattr_set(dentry, full_name, value, size, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
@ -81,7 +81,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
ret = posix_acl_equiv_mode(acl, &inode->i_mode);
|
||||
if (ret < 0)
|
||||
|
@ -94,7 +94,7 @@ static int __btrfs_set_acl(struct btrfs_trans_handle *trans,
|
|||
case ACL_TYPE_DEFAULT:
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
return acl ? -EINVAL : 0;
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -3550,10 +3550,10 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
|
|||
int scanned = 0;
|
||||
|
||||
if (!xattr_access) {
|
||||
xattr_access = btrfs_name_hash(POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS));
|
||||
xattr_default = btrfs_name_hash(POSIX_ACL_XATTR_DEFAULT,
|
||||
strlen(POSIX_ACL_XATTR_DEFAULT));
|
||||
xattr_access = btrfs_name_hash(XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
strlen(XATTR_NAME_POSIX_ACL_ACCESS));
|
||||
xattr_default = btrfs_name_hash(XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
strlen(XATTR_NAME_POSIX_ACL_DEFAULT));
|
||||
}
|
||||
|
||||
slot++;
|
||||
|
@ -9996,7 +9996,7 @@ static const struct inode_operations btrfs_dir_inode_operations = {
|
|||
.setattr = btrfs_setattr,
|
||||
.mknod = btrfs_mknod,
|
||||
.setxattr = btrfs_setxattr,
|
||||
.getxattr = btrfs_getxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = btrfs_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
|
@ -10073,7 +10073,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
|
|||
.getattr = btrfs_getattr,
|
||||
.setattr = btrfs_setattr,
|
||||
.setxattr = btrfs_setxattr,
|
||||
.getxattr = btrfs_getxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = btrfs_removexattr,
|
||||
.permission = btrfs_permission,
|
||||
|
@ -10087,7 +10087,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
|
|||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = btrfs_setxattr,
|
||||
.getxattr = btrfs_getxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = btrfs_removexattr,
|
||||
.get_acl = btrfs_get_acl,
|
||||
|
@ -10101,7 +10101,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
|
|||
.setattr = btrfs_setattr,
|
||||
.permission = btrfs_permission,
|
||||
.setxattr = btrfs_setxattr,
|
||||
.getxattr = btrfs_getxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = btrfs_listxattr,
|
||||
.removexattr = btrfs_removexattr,
|
||||
.update_time = btrfs_update_time,
|
||||
|
|
168
fs/btrfs/xattr.c
168
fs/btrfs/xattr.c
|
@ -351,137 +351,89 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* List of handlers for synthetic system.* attributes. All real ondisk
|
||||
* attributes are handled directly.
|
||||
*/
|
||||
static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return __btrfs_getxattr(inode, name, buffer, size);
|
||||
}
|
||||
|
||||
static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
const void *buffer, size_t size,
|
||||
int flags)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return __btrfs_setxattr(NULL, inode, name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
|
||||
struct dentry *dentry,
|
||||
const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
name = xattr_full_name(handler, name);
|
||||
return btrfs_set_prop(d_inode(dentry), name, value, size, flags);
|
||||
}
|
||||
|
||||
static const struct xattr_handler btrfs_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = btrfs_xattr_handler_get,
|
||||
.set = btrfs_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler btrfs_trusted_xattr_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = btrfs_xattr_handler_get,
|
||||
.set = btrfs_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler btrfs_user_xattr_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.get = btrfs_xattr_handler_get,
|
||||
.set = btrfs_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler btrfs_btrfs_xattr_handler = {
|
||||
.prefix = XATTR_BTRFS_PREFIX,
|
||||
.get = btrfs_xattr_handler_get,
|
||||
.set = btrfs_xattr_handler_set_prop,
|
||||
};
|
||||
|
||||
const struct xattr_handler *btrfs_xattr_handlers[] = {
|
||||
&btrfs_security_xattr_handler,
|
||||
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&btrfs_trusted_xattr_handler,
|
||||
&btrfs_user_xattr_handler,
|
||||
&btrfs_btrfs_xattr_handler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the attribute is in a supported namespace.
|
||||
*
|
||||
* This is applied after the check for the synthetic attributes in the system
|
||||
* namespace.
|
||||
*/
|
||||
static int btrfs_is_valid_xattr(const char *name)
|
||||
{
|
||||
int len = strlen(name);
|
||||
int prefixlen = 0;
|
||||
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
XATTR_SECURITY_PREFIX_LEN))
|
||||
prefixlen = XATTR_SECURITY_PREFIX_LEN;
|
||||
else if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
prefixlen = XATTR_SYSTEM_PREFIX_LEN;
|
||||
else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
|
||||
prefixlen = XATTR_TRUSTED_PREFIX_LEN;
|
||||
else if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
|
||||
prefixlen = XATTR_USER_PREFIX_LEN;
|
||||
else if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
||||
prefixlen = XATTR_BTRFS_PREFIX_LEN;
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* The name cannot consist of just prefix
|
||||
*/
|
||||
if (len <= prefixlen)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_getxattr(dentry, name, buffer, size);
|
||||
|
||||
ret = btrfs_is_valid_xattr(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
return __btrfs_getxattr(d_inode(dentry), name, buffer, size);
|
||||
}
|
||||
|
||||
int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
|
||||
size_t size, int flags)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The permission on security.* and system.* is not checked
|
||||
* in permission().
|
||||
*/
|
||||
if (btrfs_root_readonly(root))
|
||||
return -EROFS;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_setxattr(dentry, name, value, size, flags);
|
||||
|
||||
ret = btrfs_is_valid_xattr(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
||||
return btrfs_set_prop(d_inode(dentry), name,
|
||||
value, size, flags);
|
||||
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
|
||||
return __btrfs_setxattr(NULL, d_inode(dentry), name, value, size,
|
||||
flags);
|
||||
return generic_setxattr(dentry, name, value, size, flags);
|
||||
}
|
||||
|
||||
int btrfs_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct btrfs_root *root = BTRFS_I(d_inode(dentry))->root;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The permission on security.* and system.* is not checked
|
||||
* in permission().
|
||||
*/
|
||||
if (btrfs_root_readonly(root))
|
||||
return -EROFS;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_removexattr(dentry, name);
|
||||
|
||||
ret = btrfs_is_valid_xattr(name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
|
||||
return btrfs_set_prop(d_inode(dentry), name,
|
||||
NULL, 0, XATTR_REPLACE);
|
||||
|
||||
return __btrfs_setxattr(NULL, d_inode(dentry), name, NULL, 0,
|
||||
XATTR_REPLACE);
|
||||
return generic_removexattr(dentry, name);
|
||||
}
|
||||
|
||||
static int btrfs_initxattrs(struct inode *inode,
|
||||
|
|
|
@ -28,8 +28,6 @@ extern ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
|
|||
extern int __btrfs_setxattr(struct btrfs_trans_handle *trans,
|
||||
struct inode *inode, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
extern ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size);
|
||||
extern int btrfs_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
extern int btrfs_removexattr(struct dentry *dentry, const char *name);
|
||||
|
|
|
@ -49,10 +49,10 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
@ -92,7 +92,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
ret = posix_acl_equiv_mode(acl, &new_mode);
|
||||
if (ret < 0)
|
||||
|
@ -106,7 +106,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
|||
ret = acl ? -EINVAL : 0;
|
||||
goto out;
|
||||
}
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -202,11 +202,11 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
|
|||
ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1);
|
||||
|
||||
if (acl) {
|
||||
size_t len = strlen(POSIX_ACL_XATTR_ACCESS);
|
||||
size_t len = strlen(XATTR_NAME_POSIX_ACL_ACCESS);
|
||||
err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8);
|
||||
if (err)
|
||||
goto out_err;
|
||||
ceph_pagelist_encode_string(pagelist, POSIX_ACL_XATTR_ACCESS,
|
||||
ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
len);
|
||||
err = posix_acl_to_xattr(&init_user_ns, acl,
|
||||
tmp_buf, val_size1);
|
||||
|
@ -216,12 +216,12 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
|
|||
ceph_pagelist_append(pagelist, tmp_buf, val_size1);
|
||||
}
|
||||
if (default_acl) {
|
||||
size_t len = strlen(POSIX_ACL_XATTR_DEFAULT);
|
||||
size_t len = strlen(XATTR_NAME_POSIX_ACL_DEFAULT);
|
||||
err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8);
|
||||
if (err)
|
||||
goto out_err;
|
||||
err = ceph_pagelist_encode_string(pagelist,
|
||||
POSIX_ACL_XATTR_DEFAULT, len);
|
||||
XATTR_NAME_POSIX_ACL_DEFAULT, len);
|
||||
err = posix_acl_to_xattr(&init_user_ns, default_acl,
|
||||
tmp_buf, val_size2);
|
||||
if (err < 0)
|
||||
|
|
|
@ -190,8 +190,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
|||
#endif /* CONFIG_CIFS_ACL */
|
||||
} else {
|
||||
int temp;
|
||||
temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS));
|
||||
temp = strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
strlen(XATTR_NAME_POSIX_ACL_ACCESS));
|
||||
if (temp == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
|
@ -203,8 +203,8 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
|
|||
#else
|
||||
cifs_dbg(FYI, "set POSIX ACL not supported\n");
|
||||
#endif
|
||||
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||
} else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
|
||||
|
@ -292,8 +292,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
|||
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
|
||||
full_path, ea_name, ea_value, buf_size,
|
||||
cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||
} else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
|
||||
} else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
strlen(XATTR_NAME_POSIX_ACL_ACCESS)) == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||
|
@ -303,8 +303,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
|
|||
#else
|
||||
cifs_dbg(FYI, "Query POSIX ACL not supported yet\n");
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
} else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT,
|
||||
strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
|
||||
} else if (strncmp(ea_name, XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
strlen(XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) {
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
if (sb->s_flags & MS_POSIXACL)
|
||||
rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
|
||||
|
|
|
@ -292,16 +292,21 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
|
|||
const struct xattr_handler *handler =
|
||||
ext2_xattr_handler(entry->e_name_index);
|
||||
|
||||
if (handler) {
|
||||
size_t size = handler->list(handler, dentry, buffer,
|
||||
rest, entry->e_name,
|
||||
entry->e_name_len);
|
||||
if (handler && (!handler->list || handler->list(dentry))) {
|
||||
const char *prefix = handler->prefix ?: handler->name;
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t size = prefix_len + entry->e_name_len + 1;
|
||||
|
||||
if (buffer) {
|
||||
if (size > rest) {
|
||||
error = -ERANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
buffer += size;
|
||||
memcpy(buffer, prefix, prefix_len);
|
||||
buffer += prefix_len;
|
||||
memcpy(buffer, entry->e_name, entry->e_name_len);
|
||||
buffer += entry->e_name_len;
|
||||
*buffer++ = 0;
|
||||
}
|
||||
rest -= size;
|
||||
}
|
||||
|
|
|
@ -7,29 +7,11 @@
|
|||
#include <linux/security.h>
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext2_xattr_security_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
{
|
||||
const int prefix_len = XATTR_SECURITY_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int
|
||||
ext2_xattr_security_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
|
||||
buffer, size);
|
||||
}
|
||||
|
@ -39,8 +21,6 @@ ext2_xattr_security_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_SECURITY, name,
|
||||
value, size, flags);
|
||||
}
|
||||
|
@ -71,7 +51,6 @@ ext2_init_security(struct inode *inode, struct inode *dir,
|
|||
|
||||
const struct xattr_handler ext2_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.list = ext2_xattr_security_list,
|
||||
.get = ext2_xattr_security_get,
|
||||
.set = ext2_xattr_security_set,
|
||||
};
|
||||
|
|
|
@ -8,23 +8,10 @@
|
|||
#include "ext2.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext2_xattr_trusted_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool
|
||||
ext2_xattr_trusted_list(struct dentry *dentry)
|
||||
{
|
||||
const int prefix_len = XATTR_TRUSTED_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
return capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -32,8 +19,6 @@ ext2_xattr_trusted_get(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
|
||||
buffer, size);
|
||||
}
|
||||
|
@ -43,8 +28,6 @@ ext2_xattr_trusted_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext2_xattr_set(d_inode(dentry), EXT2_XATTR_INDEX_TRUSTED, name,
|
||||
value, size, flags);
|
||||
}
|
||||
|
|
|
@ -10,23 +10,10 @@
|
|||
#include "ext2.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext2_xattr_user_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool
|
||||
ext2_xattr_user_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_USER_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
return test_opt(dentry->d_sb, XATTR_USER);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -34,8 +21,6 @@ ext2_xattr_user_get(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
return ext2_xattr_get(d_inode(dentry), EXT2_XATTR_INDEX_USER,
|
||||
|
@ -47,8 +32,6 @@ ext2_xattr_user_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
|
|
@ -404,19 +404,24 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
|
|||
const struct xattr_handler *handler =
|
||||
ext4_xattr_handler(entry->e_name_index);
|
||||
|
||||
if (handler) {
|
||||
size_t size = handler->list(handler, dentry, buffer,
|
||||
rest, entry->e_name,
|
||||
entry->e_name_len);
|
||||
if (handler && (!handler->list || handler->list(dentry))) {
|
||||
const char *prefix = handler->prefix ?: handler->name;
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t size = prefix_len + entry->e_name_len + 1;
|
||||
|
||||
if (buffer) {
|
||||
if (size > rest)
|
||||
return -ERANGE;
|
||||
buffer += size;
|
||||
memcpy(buffer, prefix, prefix_len);
|
||||
buffer += prefix_len;
|
||||
memcpy(buffer, entry->e_name, entry->e_name_len);
|
||||
buffer += entry->e_name_len;
|
||||
*buffer++ = 0;
|
||||
}
|
||||
rest -= size;
|
||||
}
|
||||
}
|
||||
return buffer_size - rest;
|
||||
return buffer_size - rest; /* total size */
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -11,30 +11,11 @@
|
|||
#include "ext4.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext4_xattr_security_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
{
|
||||
const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int
|
||||
ext4_xattr_security_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -44,8 +25,6 @@ ext4_xattr_security_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_SECURITY,
|
||||
name, value, size, flags);
|
||||
}
|
||||
|
@ -79,7 +58,6 @@ ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
|
|||
|
||||
const struct xattr_handler ext4_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.list = ext4_xattr_security_list,
|
||||
.get = ext4_xattr_security_get,
|
||||
.set = ext4_xattr_security_set,
|
||||
};
|
||||
|
|
|
@ -12,23 +12,10 @@
|
|||
#include "ext4.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext4_xattr_trusted_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool
|
||||
ext4_xattr_trusted_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
return capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -36,8 +23,6 @@ ext4_xattr_trusted_get(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name, void *buffer,
|
||||
size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -47,8 +32,6 @@ ext4_xattr_trusted_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_TRUSTED,
|
||||
name, value, size, flags);
|
||||
}
|
||||
|
|
|
@ -11,23 +11,10 @@
|
|||
#include "ext4.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t
|
||||
ext4_xattr_user_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool
|
||||
ext4_xattr_user_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_USER_PREFIX, prefix_len);
|
||||
memcpy(list+prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
return test_opt(dentry->d_sb, XATTR_USER);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -35,8 +22,6 @@ ext4_xattr_user_get(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
return ext4_xattr_get(d_inode(dentry), EXT4_XATTR_INDEX_USER,
|
||||
|
@ -48,8 +33,6 @@ ext4_xattr_user_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (!test_opt(dentry->d_sb, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
return ext4_xattr_set(d_inode(dentry), EXT4_XATTR_INDEX_USER,
|
||||
|
|
|
@ -25,38 +25,6 @@
|
|||
#include "f2fs.h"
|
||||
#include "xattr.h"
|
||||
|
||||
static size_t f2fs_xattr_generic_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t len)
|
||||
{
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
|
||||
int total_len, prefix_len;
|
||||
|
||||
switch (handler->flags) {
|
||||
case F2FS_XATTR_INDEX_USER:
|
||||
if (!test_opt(sbi, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
break;
|
||||
case F2FS_XATTR_INDEX_TRUSTED:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
break;
|
||||
case F2FS_XATTR_INDEX_SECURITY:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prefix_len = strlen(handler->prefix);
|
||||
total_len = prefix_len + len + 1;
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, handler->prefix, prefix_len);
|
||||
memcpy(list + prefix_len, name, len);
|
||||
list[prefix_len + len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name, void *buffer,
|
||||
size_t size)
|
||||
|
@ -77,8 +45,6 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return f2fs_getxattr(d_inode(dentry), handler->flags, name,
|
||||
buffer, size, NULL);
|
||||
}
|
||||
|
@ -103,24 +69,20 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
|
|||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return f2fs_setxattr(d_inode(dentry), handler->flags, name,
|
||||
value, size, NULL, flags);
|
||||
}
|
||||
|
||||
static size_t f2fs_xattr_advise_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t len)
|
||||
static bool f2fs_xattr_user_list(struct dentry *dentry)
|
||||
{
|
||||
const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
|
||||
size_t size;
|
||||
struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
|
||||
|
||||
size = strlen(xname) + 1;
|
||||
if (list && size <= list_size)
|
||||
memcpy(list, xname, size);
|
||||
return size;
|
||||
return test_opt(sbi, XATTR_USER);
|
||||
}
|
||||
|
||||
static bool f2fs_xattr_trusted_list(struct dentry *dentry)
|
||||
{
|
||||
return capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
|
||||
|
@ -129,9 +91,6 @@ static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
|
|||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (buffer)
|
||||
*((char *)buffer) = F2FS_I(inode)->i_advise;
|
||||
return sizeof(char);
|
||||
|
@ -143,8 +102,6 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
|
|||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
if (!inode_owner_or_capable(inode))
|
||||
return -EPERM;
|
||||
if (value == NULL)
|
||||
|
@ -183,7 +140,7 @@ int f2fs_init_security(struct inode *inode, struct inode *dir,
|
|||
const struct xattr_handler f2fs_xattr_user_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.flags = F2FS_XATTR_INDEX_USER,
|
||||
.list = f2fs_xattr_generic_list,
|
||||
.list = f2fs_xattr_user_list,
|
||||
.get = f2fs_xattr_generic_get,
|
||||
.set = f2fs_xattr_generic_set,
|
||||
};
|
||||
|
@ -191,15 +148,14 @@ const struct xattr_handler f2fs_xattr_user_handler = {
|
|||
const struct xattr_handler f2fs_xattr_trusted_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.flags = F2FS_XATTR_INDEX_TRUSTED,
|
||||
.list = f2fs_xattr_generic_list,
|
||||
.list = f2fs_xattr_trusted_list,
|
||||
.get = f2fs_xattr_generic_get,
|
||||
.set = f2fs_xattr_generic_set,
|
||||
};
|
||||
|
||||
const struct xattr_handler f2fs_xattr_advise_handler = {
|
||||
.prefix = F2FS_SYSTEM_ADVISE_PREFIX,
|
||||
.name = F2FS_SYSTEM_ADVISE_NAME,
|
||||
.flags = F2FS_XATTR_INDEX_ADVISE,
|
||||
.list = f2fs_xattr_advise_list,
|
||||
.get = f2fs_xattr_advise_get,
|
||||
.set = f2fs_xattr_advise_set,
|
||||
};
|
||||
|
@ -207,7 +163,6 @@ const struct xattr_handler f2fs_xattr_advise_handler = {
|
|||
const struct xattr_handler f2fs_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.flags = F2FS_XATTR_INDEX_SECURITY,
|
||||
.list = f2fs_xattr_generic_list,
|
||||
.get = f2fs_xattr_generic_get,
|
||||
.set = f2fs_xattr_generic_set,
|
||||
};
|
||||
|
@ -455,20 +410,27 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
|||
list_for_each_xattr(entry, base_addr) {
|
||||
const struct xattr_handler *handler =
|
||||
f2fs_xattr_handler(entry->e_name_index);
|
||||
const char *prefix;
|
||||
size_t prefix_len;
|
||||
size_t size;
|
||||
|
||||
if (!handler)
|
||||
if (!handler || (handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
|
||||
size = handler->list(handler, dentry, buffer, rest,
|
||||
entry->e_name, entry->e_name_len);
|
||||
if (buffer && size > rest) {
|
||||
error = -ERANGE;
|
||||
goto cleanup;
|
||||
prefix = handler->prefix ?: handler->name;
|
||||
prefix_len = strlen(prefix);
|
||||
size = prefix_len + entry->e_name_len + 1;
|
||||
if (buffer) {
|
||||
if (size > rest) {
|
||||
error = -ERANGE;
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(buffer, prefix, prefix_len);
|
||||
buffer += prefix_len;
|
||||
memcpy(buffer, entry->e_name, entry->e_name_len);
|
||||
buffer += entry->e_name_len;
|
||||
*buffer++ = 0;
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
buffer += size;
|
||||
rest -= size;
|
||||
}
|
||||
error = buffer_size - rest;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define F2FS_XATTR_REFCOUNT_MAX 1024
|
||||
|
||||
/* Name indexes */
|
||||
#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise"
|
||||
#define F2FS_SYSTEM_ADVISE_NAME "system.advise"
|
||||
#define F2FS_XATTR_INDEX_USER 1
|
||||
#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2
|
||||
#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3
|
||||
|
|
|
@ -31,9 +31,9 @@ static const char *gfs2_acl_name(int type)
|
|||
{
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
return GFS2_POSIX_ACL_ACCESS;
|
||||
return XATTR_POSIX_ACL_ACCESS;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
return GFS2_POSIX_ACL_DEFAULT;
|
||||
return XATTR_POSIX_ACL_DEFAULT;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#include "incore.h"
|
||||
|
||||
#define GFS2_POSIX_ACL_ACCESS "posix_acl_access"
|
||||
#define GFS2_POSIX_ACL_DEFAULT "posix_acl_default"
|
||||
#define GFS2_ACL_MAX_ENTRIES(sdp) ((300 << (sdp)->sd_sb.sb_bsize_shift) >> 12)
|
||||
|
||||
extern struct posix_acl *gfs2_get_acl(struct inode *inode, int type);
|
||||
|
|
|
@ -1237,56 +1237,6 @@ static int gfs2_xattr_set(const struct xattr_handler *handler,
|
|||
size, flags, handler->flags);
|
||||
}
|
||||
|
||||
|
||||
static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
|
||||
struct gfs2_ea_header *ea, char *data)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
unsigned int amount = GFS2_EA_DATA_LEN(ea);
|
||||
unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
|
||||
int ret;
|
||||
|
||||
ret = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gfs2_iter_unstuffed(ip, ea, data, NULL);
|
||||
gfs2_trans_end(sdp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
struct gfs2_sbd *sdp = GFS2_SB(inode);
|
||||
struct gfs2_ea_location el;
|
||||
int error;
|
||||
|
||||
error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (GFS2_EA_IS_STUFFED(el.el_ea)) {
|
||||
error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0);
|
||||
if (error == 0) {
|
||||
gfs2_trans_add_meta(ip->i_gl, el.el_bh);
|
||||
memcpy(GFS2_EA2DATA(el.el_ea), data,
|
||||
GFS2_EA_DATA_LEN(el.el_ea));
|
||||
}
|
||||
} else {
|
||||
error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);
|
||||
}
|
||||
|
||||
brelse(el.el_bh);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = gfs2_setattr_simple(inode, attr);
|
||||
gfs2_trans_end(sdp);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ea_dealloc_indirect(struct gfs2_inode *ip)
|
||||
{
|
||||
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
|
||||
|
|
|
@ -62,6 +62,5 @@ extern int gfs2_ea_dealloc(struct gfs2_inode *ip);
|
|||
/* Exported to acl.c */
|
||||
|
||||
extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data);
|
||||
extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data);
|
||||
|
||||
#endif /* __EATTR_DOT_H__ */
|
||||
|
|
|
@ -21,10 +21,10 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
xattr_name = POSIX_ACL_XATTR_ACCESS;
|
||||
xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
xattr_name = POSIX_ACL_XATTR_DEFAULT;
|
||||
xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
@ -66,7 +66,7 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
xattr_name = POSIX_ACL_XATTR_ACCESS;
|
||||
xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
err = posix_acl_equiv_mode(acl, &inode->i_mode);
|
||||
if (err < 0)
|
||||
|
@ -76,7 +76,7 @@ int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
|
|||
break;
|
||||
|
||||
case ACL_TYPE_DEFAULT:
|
||||
xattr_name = POSIX_ACL_XATTR_DEFAULT;
|
||||
xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
return acl ? -EACCES : 0;
|
||||
break;
|
||||
|
|
|
@ -431,9 +431,6 @@ int hfsplus_setxattr(struct dentry *dentry, const char *name,
|
|||
char *xattr_name;
|
||||
int res;
|
||||
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
|
||||
GFP_KERNEL);
|
||||
if (!xattr_name)
|
||||
|
@ -589,9 +586,6 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
|
|||
int res;
|
||||
char *xattr_name;
|
||||
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
xattr_name = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + 1,
|
||||
GFP_KERNEL);
|
||||
if (!xattr_name)
|
||||
|
@ -853,9 +847,6 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Don't allow retrieving properly prefixed attributes
|
||||
* by prepending them with "osx."
|
||||
|
@ -876,9 +867,6 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *buffer, size_t size, int flags)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Don't allow setting properly prefixed attributes
|
||||
* by prepending them with "osx."
|
||||
|
|
|
@ -52,9 +52,6 @@ static int jffs2_security_getxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -63,31 +60,12 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *buffer, size_t size, int flags)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
|
||||
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_SECURITY,
|
||||
name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t jffs2_security_listxattr(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
|
||||
|
||||
if (list && retlen <= list_size) {
|
||||
strcpy(list, XATTR_SECURITY_PREFIX);
|
||||
strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
|
||||
}
|
||||
|
||||
return retlen;
|
||||
}
|
||||
|
||||
const struct xattr_handler jffs2_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.list = jffs2_security_listxattr,
|
||||
.set = jffs2_security_setxattr,
|
||||
.get = jffs2_security_getxattr
|
||||
};
|
||||
|
|
|
@ -967,7 +967,8 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
struct jffs2_xattr_ref *ref, **pref;
|
||||
struct jffs2_xattr_datum *xd;
|
||||
const struct xattr_handler *xhandle;
|
||||
ssize_t len, rc;
|
||||
const char *prefix;
|
||||
ssize_t prefix_len, len, rc;
|
||||
int retry = 0;
|
||||
|
||||
rc = check_xattr_ref_inode(c, ic);
|
||||
|
@ -998,18 +999,23 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
|||
}
|
||||
}
|
||||
xhandle = xprefix_to_handler(xd->xprefix);
|
||||
if (!xhandle)
|
||||
if (!xhandle || (xhandle->list && !xhandle->list(dentry)))
|
||||
continue;
|
||||
prefix = xhandle->prefix ?: xhandle->name;
|
||||
prefix_len = strlen(prefix);
|
||||
rc = prefix_len + xd->name_len + 1;
|
||||
|
||||
if (buffer) {
|
||||
rc = xhandle->list(xhandle, dentry, buffer + len,
|
||||
size - len, xd->xname,
|
||||
xd->name_len);
|
||||
} else {
|
||||
rc = xhandle->list(xhandle, dentry, NULL, 0,
|
||||
xd->xname, xd->name_len);
|
||||
if (rc > size - len) {
|
||||
rc = -ERANGE;
|
||||
goto out;
|
||||
}
|
||||
memcpy(buffer, prefix, prefix_len);
|
||||
buffer += prefix_len;
|
||||
memcpy(buffer, xd->xname, xd->name_len);
|
||||
buffer += xd->name_len;
|
||||
*buffer++ = 0;
|
||||
}
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
len += rc;
|
||||
}
|
||||
rc = len;
|
||||
|
|
|
@ -20,8 +20,6 @@ static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -30,28 +28,13 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *buffer, size_t size, int flags)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_TRUSTED,
|
||||
name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t jffs2_trusted_listxattr(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
static bool jffs2_trusted_listxattr(struct dentry *dentry)
|
||||
{
|
||||
size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
|
||||
if (list && retlen<=list_size) {
|
||||
strcpy(list, XATTR_TRUSTED_PREFIX);
|
||||
strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
|
||||
}
|
||||
|
||||
return retlen;
|
||||
return capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
const struct xattr_handler jffs2_trusted_xattr_handler = {
|
||||
|
|
|
@ -20,8 +20,6 @@ static int jffs2_user_getxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
return do_jffs2_getxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -30,30 +28,12 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *buffer, size_t size, int flags)
|
||||
{
|
||||
if (!strcmp(name, ""))
|
||||
return -EINVAL;
|
||||
return do_jffs2_setxattr(d_inode(dentry), JFFS2_XPREFIX_USER,
|
||||
name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t jffs2_user_listxattr(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
|
||||
|
||||
if (list && retlen <= list_size) {
|
||||
strcpy(list, XATTR_USER_PREFIX);
|
||||
strcpy(list + XATTR_USER_PREFIX_LEN, name);
|
||||
}
|
||||
|
||||
return retlen;
|
||||
}
|
||||
|
||||
const struct xattr_handler jffs2_user_xattr_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.list = jffs2_user_listxattr,
|
||||
.set = jffs2_user_setxattr,
|
||||
.get = jffs2_user_getxattr
|
||||
};
|
||||
|
|
|
@ -40,10 +40,10 @@ struct posix_acl *jfs_get_acl(struct inode *inode, int type)
|
|||
|
||||
switch(type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
ea_name = POSIX_ACL_XATTR_ACCESS;
|
||||
ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
ea_name = POSIX_ACL_XATTR_DEFAULT;
|
||||
ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
@ -82,7 +82,7 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
ea_name = POSIX_ACL_XATTR_ACCESS;
|
||||
ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
rc = posix_acl_equiv_mode(acl, &inode->i_mode);
|
||||
if (rc < 0)
|
||||
|
@ -94,7 +94,7 @@ static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
|
|||
}
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
ea_name = POSIX_ACL_XATTR_DEFAULT;
|
||||
ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -205,7 +205,7 @@ int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
|
|||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_remove(&attrs->xattrs, name);
|
||||
return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
ssize_t kernfs_iop_getxattr(struct dentry *dentry, const char *name, void *buf,
|
||||
|
@ -230,7 +230,7 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
|||
if (!attrs)
|
||||
return -ENOMEM;
|
||||
|
||||
return simple_xattr_list(&attrs->xattrs, buf, size);
|
||||
return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size);
|
||||
}
|
||||
|
||||
static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
|
||||
|
|
|
@ -284,12 +284,12 @@ nfs3_listxattr(struct dentry *dentry, char *data, size_t size)
|
|||
int error;
|
||||
|
||||
error = nfs3_list_one_acl(inode, ACL_TYPE_ACCESS,
|
||||
POSIX_ACL_XATTR_ACCESS, data, size, &result);
|
||||
XATTR_NAME_POSIX_ACL_ACCESS, data, size, &result);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = nfs3_list_one_acl(inode, ACL_TYPE_DEFAULT,
|
||||
POSIX_ACL_XATTR_DEFAULT, data, size, &result);
|
||||
XATTR_NAME_POSIX_ACL_DEFAULT, data, size, &result);
|
||||
if (error)
|
||||
return error;
|
||||
return result;
|
||||
|
|
|
@ -6253,9 +6253,6 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
|
|||
const void *buf, size_t buflen,
|
||||
int flags)
|
||||
{
|
||||
if (strcmp(key, "") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return nfs4_proc_set_acl(d_inode(dentry), buf, buflen);
|
||||
}
|
||||
|
||||
|
@ -6263,32 +6260,15 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *key,
|
||||
void *buf, size_t buflen)
|
||||
{
|
||||
if (strcmp(key, "") != 0)
|
||||
return -EINVAL;
|
||||
|
||||
return nfs4_proc_get_acl(d_inode(dentry), buf, buflen);
|
||||
}
|
||||
|
||||
static size_t nfs4_xattr_list_nfs4_acl(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_len, const char *name,
|
||||
size_t name_len)
|
||||
static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
|
||||
{
|
||||
size_t len = sizeof(XATTR_NAME_NFSV4_ACL);
|
||||
|
||||
if (!nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry))))
|
||||
return 0;
|
||||
|
||||
if (list && len <= list_len)
|
||||
memcpy(list, XATTR_NAME_NFSV4_ACL, len);
|
||||
return len;
|
||||
return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
||||
static inline int nfs4_server_supports_labels(struct nfs_server *server)
|
||||
{
|
||||
return server->caps & NFS_CAP_SECURITY_LABEL;
|
||||
}
|
||||
|
||||
static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *key,
|
||||
|
@ -6310,29 +6290,34 @@ static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static size_t nfs4_xattr_list_nfs4_label(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_len, const char *name,
|
||||
size_t name_len)
|
||||
static ssize_t
|
||||
nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
int len = 0;
|
||||
|
||||
if (nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) {
|
||||
len = security_inode_listsecurity(d_inode(dentry), NULL, 0);
|
||||
if (list && len <= list_len)
|
||||
security_inode_listsecurity(d_inode(dentry), list, len);
|
||||
if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) {
|
||||
len = security_inode_listsecurity(inode, list, list_len);
|
||||
if (list_len && len > list_len)
|
||||
return -ERANGE;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct xattr_handler nfs4_xattr_nfs4_label_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.list = nfs4_xattr_list_nfs4_label,
|
||||
.get = nfs4_xattr_get_nfs4_label,
|
||||
.set = nfs4_xattr_set_nfs4_label,
|
||||
};
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
static ssize_t
|
||||
nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* nfs_fhget will use either the mounted_on_fileid or the fileid
|
||||
|
@ -8749,6 +8734,24 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
ssize_t error, error2;
|
||||
|
||||
error = generic_listxattr(dentry, list, size);
|
||||
if (error < 0)
|
||||
return error;
|
||||
if (list) {
|
||||
list += error;
|
||||
size -= error;
|
||||
}
|
||||
|
||||
error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size);
|
||||
if (error2 < 0)
|
||||
return error2;
|
||||
return error + error2;
|
||||
}
|
||||
|
||||
static const struct inode_operations nfs4_dir_inode_operations = {
|
||||
.create = nfs_create,
|
||||
.lookup = nfs_lookup,
|
||||
|
@ -8765,7 +8768,7 @@ static const struct inode_operations nfs4_dir_inode_operations = {
|
|||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = generic_listxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
|
@ -8775,7 +8778,7 @@ static const struct inode_operations nfs4_file_inode_operations = {
|
|||
.setattr = nfs_setattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.listxattr = generic_listxattr,
|
||||
.listxattr = nfs4_listxattr,
|
||||
.removexattr = generic_removexattr,
|
||||
};
|
||||
|
||||
|
@ -8834,7 +8837,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
|||
};
|
||||
|
||||
static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
|
||||
.prefix = XATTR_NAME_NFSV4_ACL,
|
||||
.name = XATTR_NAME_NFSV4_ACL,
|
||||
.list = nfs4_xattr_list_nfs4_acl,
|
||||
.get = nfs4_xattr_get_nfs4_acl,
|
||||
.set = nfs4_xattr_set_nfs4_acl,
|
||||
|
|
168
fs/ocfs2/xattr.c
168
fs/ocfs2/xattr.c
|
@ -544,8 +544,7 @@ static inline const char *ocfs2_xattr_prefix(int name_index)
|
|||
|
||||
if (name_index > 0 && name_index < OCFS2_XATTR_MAX)
|
||||
handler = ocfs2_xattr_handler_map[name_index];
|
||||
|
||||
return handler ? handler->prefix : NULL;
|
||||
return handler ? xattr_prefix(handler) : NULL;
|
||||
}
|
||||
|
||||
static u32 ocfs2_xattr_name_hash(struct inode *inode,
|
||||
|
@ -884,14 +883,39 @@ static int ocfs2_xattr_value_truncate(struct inode *inode,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ocfs2_xattr_list_entry(char *buffer, size_t size,
|
||||
size_t *result, const char *prefix,
|
||||
static int ocfs2_xattr_list_entry(struct super_block *sb,
|
||||
char *buffer, size_t size,
|
||||
size_t *result, int type,
|
||||
const char *name, int name_len)
|
||||
{
|
||||
char *p = buffer + *result;
|
||||
int prefix_len = strlen(prefix);
|
||||
int total_len = prefix_len + name_len + 1;
|
||||
const char *prefix;
|
||||
int prefix_len;
|
||||
int total_len;
|
||||
|
||||
switch(type) {
|
||||
case OCFS2_XATTR_INDEX_USER:
|
||||
if (OCFS2_SB(sb)->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS:
|
||||
case OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT:
|
||||
if (!(sb->s_flags & MS_POSIXACL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case OCFS2_XATTR_INDEX_TRUSTED:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
prefix = ocfs2_xattr_prefix(type);
|
||||
if (!prefix)
|
||||
return 0;
|
||||
prefix_len = strlen(prefix);
|
||||
total_len = prefix_len + name_len + 1;
|
||||
*result += total_len;
|
||||
|
||||
/* we are just looking for how big our buffer needs to be */
|
||||
|
@ -914,23 +938,20 @@ static int ocfs2_xattr_list_entries(struct inode *inode,
|
|||
{
|
||||
size_t result = 0;
|
||||
int i, type, ret;
|
||||
const char *prefix, *name;
|
||||
const char *name;
|
||||
|
||||
for (i = 0 ; i < le16_to_cpu(header->xh_count); i++) {
|
||||
struct ocfs2_xattr_entry *entry = &header->xh_entries[i];
|
||||
type = ocfs2_xattr_get_type(entry);
|
||||
prefix = ocfs2_xattr_prefix(type);
|
||||
name = (const char *)header +
|
||||
le16_to_cpu(entry->xe_name_offset);
|
||||
|
||||
if (prefix) {
|
||||
name = (const char *)header +
|
||||
le16_to_cpu(entry->xe_name_offset);
|
||||
|
||||
ret = ocfs2_xattr_list_entry(buffer, buffer_size,
|
||||
&result, prefix, name,
|
||||
entry->xe_name_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = ocfs2_xattr_list_entry(inode->i_sb,
|
||||
buffer, buffer_size,
|
||||
&result, type, name,
|
||||
entry->xe_name_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -4033,32 +4054,30 @@ static int ocfs2_list_xattr_bucket(struct inode *inode,
|
|||
int ret = 0, type;
|
||||
struct ocfs2_xattr_tree_list *xl = (struct ocfs2_xattr_tree_list *)para;
|
||||
int i, block_off, new_offset;
|
||||
const char *prefix, *name;
|
||||
const char *name;
|
||||
|
||||
for (i = 0 ; i < le16_to_cpu(bucket_xh(bucket)->xh_count); i++) {
|
||||
struct ocfs2_xattr_entry *entry = &bucket_xh(bucket)->xh_entries[i];
|
||||
type = ocfs2_xattr_get_type(entry);
|
||||
prefix = ocfs2_xattr_prefix(type);
|
||||
|
||||
if (prefix) {
|
||||
ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb,
|
||||
bucket_xh(bucket),
|
||||
i,
|
||||
&block_off,
|
||||
&new_offset);
|
||||
if (ret)
|
||||
break;
|
||||
ret = ocfs2_xattr_bucket_get_name_value(inode->i_sb,
|
||||
bucket_xh(bucket),
|
||||
i,
|
||||
&block_off,
|
||||
&new_offset);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
name = (const char *)bucket_block(bucket, block_off) +
|
||||
new_offset;
|
||||
ret = ocfs2_xattr_list_entry(xl->buffer,
|
||||
xl->buffer_size,
|
||||
&xl->result,
|
||||
prefix, name,
|
||||
entry->xe_name_len);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
name = (const char *)bucket_block(bucket, block_off) +
|
||||
new_offset;
|
||||
ret = ocfs2_xattr_list_entry(inode->i_sb,
|
||||
xl->buffer,
|
||||
xl->buffer_size,
|
||||
&xl->result,
|
||||
type, name,
|
||||
entry->xe_name_len);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -7226,31 +7245,14 @@ int ocfs2_init_security_and_acl(struct inode *dir,
|
|||
leave:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'security' attributes support
|
||||
*/
|
||||
static size_t ocfs2_xattr_security_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
const size_t prefix_len = XATTR_SECURITY_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
|
||||
memcpy(list + prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int ocfs2_xattr_security_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -7259,9 +7261,6 @@ static int ocfs2_xattr_security_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_SECURITY,
|
||||
name, value, size, flags);
|
||||
}
|
||||
|
@ -7314,7 +7313,6 @@ int ocfs2_init_security_set(handle_t *handle,
|
|||
|
||||
const struct xattr_handler ocfs2_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.list = ocfs2_xattr_security_list,
|
||||
.get = ocfs2_xattr_security_get,
|
||||
.set = ocfs2_xattr_security_set,
|
||||
};
|
||||
|
@ -7322,31 +7320,10 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
|
|||
/*
|
||||
* 'trusted' attributes support
|
||||
*/
|
||||
static size_t ocfs2_xattr_trusted_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
const size_t prefix_len = XATTR_TRUSTED_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
|
||||
memcpy(list + prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
|
||||
name, buffer, size);
|
||||
}
|
||||
|
@ -7355,16 +7332,12 @@ static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler,
|
|||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return ocfs2_xattr_set(d_inode(dentry), OCFS2_XATTR_INDEX_TRUSTED,
|
||||
name, value, size, flags);
|
||||
}
|
||||
|
||||
const struct xattr_handler ocfs2_xattr_trusted_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.list = ocfs2_xattr_trusted_list,
|
||||
.get = ocfs2_xattr_trusted_get,
|
||||
.set = ocfs2_xattr_trusted_set,
|
||||
};
|
||||
|
@ -7372,34 +7345,12 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
|
|||
/*
|
||||
* 'user' attributes support
|
||||
*/
|
||||
static size_t ocfs2_xattr_user_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
const size_t prefix_len = XATTR_USER_PREFIX_LEN;
|
||||
const size_t total_len = prefix_len + name_len + 1;
|
||||
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
|
||||
|
||||
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
|
||||
return 0;
|
||||
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, XATTR_USER_PREFIX, prefix_len);
|
||||
memcpy(list + prefix_len, name, name_len);
|
||||
list[prefix_len + name_len] = '\0';
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int ocfs2_xattr_user_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
|
||||
return -EOPNOTSUPP;
|
||||
return ocfs2_xattr_get(d_inode(dentry), OCFS2_XATTR_INDEX_USER, name,
|
||||
|
@ -7412,8 +7363,6 @@ static int ocfs2_xattr_user_set(const struct xattr_handler *handler,
|
|||
{
|
||||
struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
@ -7423,7 +7372,6 @@ static int ocfs2_xattr_user_set(const struct xattr_handler *handler,
|
|||
|
||||
const struct xattr_handler ocfs2_xattr_user_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.list = ocfs2_xattr_user_list,
|
||||
.get = ocfs2_xattr_user_get,
|
||||
.set = ocfs2_xattr_user_set,
|
||||
};
|
||||
|
|
|
@ -769,8 +769,6 @@ posix_acl_xattr_get(const struct xattr_handler *handler,
|
|||
struct posix_acl *acl;
|
||||
int error;
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
if (!IS_POSIXACL(d_backing_inode(dentry)))
|
||||
return -EOPNOTSUPP;
|
||||
if (d_is_symlink(dentry))
|
||||
|
@ -797,8 +795,6 @@ posix_acl_xattr_set(const struct xattr_handler *handler,
|
|||
struct posix_acl *acl = NULL;
|
||||
int ret;
|
||||
|
||||
if (strcmp(name, "") != 0)
|
||||
return -EINVAL;
|
||||
if (!IS_POSIXACL(inode))
|
||||
return -EOPNOTSUPP;
|
||||
if (!inode->i_op->set_acl)
|
||||
|
@ -827,25 +823,14 @@ posix_acl_xattr_set(const struct xattr_handler *handler,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static size_t
|
||||
posix_acl_xattr_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool
|
||||
posix_acl_xattr_list(struct dentry *dentry)
|
||||
{
|
||||
const char *xname = handler->prefix;
|
||||
size_t size;
|
||||
|
||||
if (!IS_POSIXACL(d_backing_inode(dentry)))
|
||||
return 0;
|
||||
|
||||
size = strlen(xname) + 1;
|
||||
if (list && size <= list_size)
|
||||
memcpy(list, xname, size);
|
||||
return size;
|
||||
return IS_POSIXACL(d_backing_inode(dentry));
|
||||
}
|
||||
|
||||
const struct xattr_handler posix_acl_access_xattr_handler = {
|
||||
.prefix = POSIX_ACL_XATTR_ACCESS,
|
||||
.name = XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
.flags = ACL_TYPE_ACCESS,
|
||||
.list = posix_acl_xattr_list,
|
||||
.get = posix_acl_xattr_get,
|
||||
|
@ -854,7 +839,7 @@ const struct xattr_handler posix_acl_access_xattr_handler = {
|
|||
EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
|
||||
|
||||
const struct xattr_handler posix_acl_default_xattr_handler = {
|
||||
.prefix = POSIX_ACL_XATTR_DEFAULT,
|
||||
.name = XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
.flags = ACL_TYPE_DEFAULT,
|
||||
.list = posix_acl_xattr_list,
|
||||
.get = posix_acl_xattr_get,
|
||||
|
|
|
@ -756,7 +756,8 @@ find_xattr_handler_prefix(const struct xattr_handler **handlers,
|
|||
return NULL;
|
||||
|
||||
for_each_xattr_handler(handlers, xah) {
|
||||
if (strncmp(xah->prefix, name, strlen(xah->prefix)) == 0)
|
||||
const char *prefix = xattr_prefix(xah);
|
||||
if (strncmp(prefix, name, strlen(prefix)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -839,19 +840,16 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
|
|||
|
||||
handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
|
||||
name);
|
||||
if (!handler) /* Unsupported xattr name */
|
||||
if (!handler /* Unsupported xattr name */ ||
|
||||
(handler->list && !handler->list(b->dentry)))
|
||||
return 0;
|
||||
size = namelen + 1;
|
||||
if (b->buf) {
|
||||
size = handler->list(handler, b->dentry,
|
||||
b->buf + b->pos, b->size, name,
|
||||
namelen);
|
||||
if (size > b->size)
|
||||
return -ERANGE;
|
||||
} else {
|
||||
size = handler->list(handler, b->dentry,
|
||||
NULL, 0, name, namelen);
|
||||
memcpy(b->buf + b->pos, name, namelen);
|
||||
b->buf[b->pos + namelen] = 0;
|
||||
}
|
||||
|
||||
b->pos += size;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -186,10 +186,10 @@ struct posix_acl *reiserfs_get_acl(struct inode *inode, int type)
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
|
@ -244,7 +244,7 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = POSIX_ACL_XATTR_ACCESS;
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
if (acl) {
|
||||
error = posix_acl_equiv_mode(acl, &inode->i_mode);
|
||||
if (error < 0)
|
||||
|
@ -256,7 +256,7 @@ __reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
|
|||
}
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = POSIX_ACL_XATTR_DEFAULT;
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
return acl ? -EACCES : 0;
|
||||
break;
|
||||
|
|
|
@ -34,21 +34,9 @@ security_set(const struct xattr_handler *handler, struct dentry *dentry,
|
|||
return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t security_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_len,
|
||||
const char *name, size_t namelen)
|
||||
static bool security_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t len = namelen + 1;
|
||||
|
||||
if (IS_PRIVATE(d_inode(dentry)))
|
||||
return 0;
|
||||
|
||||
if (list && len <= list_len) {
|
||||
memcpy(list, name, namelen);
|
||||
list[namelen] = '\0';
|
||||
}
|
||||
|
||||
return len;
|
||||
return !IS_PRIVATE(d_inode(dentry));
|
||||
}
|
||||
|
||||
/* Initializes the security context for a new inode and returns the number
|
||||
|
|
|
@ -33,20 +33,9 @@ trusted_set(const struct xattr_handler *handler, struct dentry *dentry,
|
|||
return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t trusted_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool trusted_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t len = name_len + 1;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(d_inode(dentry)))
|
||||
return 0;
|
||||
|
||||
if (list && len <= list_size) {
|
||||
memcpy(list, name, name_len);
|
||||
list[name_len] = '\0';
|
||||
}
|
||||
return len;
|
||||
return capable(CAP_SYS_ADMIN) && !IS_PRIVATE(d_inode(dentry));
|
||||
}
|
||||
|
||||
const struct xattr_handler reiserfs_xattr_trusted_handler = {
|
||||
|
|
|
@ -30,19 +30,9 @@ user_set(const struct xattr_handler *handler, struct dentry *dentry,
|
|||
return reiserfs_xattr_set(d_inode(dentry), name, buffer, size, flags);
|
||||
}
|
||||
|
||||
static size_t user_list(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, char *list, size_t list_size,
|
||||
const char *name, size_t name_len)
|
||||
static bool user_list(struct dentry *dentry)
|
||||
{
|
||||
const size_t len = name_len + 1;
|
||||
|
||||
if (!reiserfs_xattrs_user(dentry->d_sb))
|
||||
return 0;
|
||||
if (list && len <= list_size) {
|
||||
memcpy(list, name, name_len);
|
||||
list[name_len] = '\0';
|
||||
}
|
||||
return len;
|
||||
return reiserfs_xattrs_user(dentry->d_sb);
|
||||
}
|
||||
|
||||
const struct xattr_handler reiserfs_xattr_user_handler = {
|
||||
|
|
|
@ -58,7 +58,7 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
|
|||
struct squashfs_xattr_entry entry;
|
||||
struct squashfs_xattr_val val;
|
||||
const struct xattr_handler *handler;
|
||||
int name_size, prefix_size = 0;
|
||||
int name_size;
|
||||
|
||||
err = squashfs_read_metadata(sb, &entry, &start, &offset,
|
||||
sizeof(entry));
|
||||
|
@ -67,15 +67,16 @@ ssize_t squashfs_listxattr(struct dentry *d, char *buffer,
|
|||
|
||||
name_size = le16_to_cpu(entry.size);
|
||||
handler = squashfs_xattr_handler(le16_to_cpu(entry.type));
|
||||
if (handler)
|
||||
prefix_size = handler->list(handler, d, buffer, rest,
|
||||
NULL, name_size);
|
||||
if (prefix_size) {
|
||||
if (handler && (!handler->list || handler->list(d))) {
|
||||
const char *prefix = handler->prefix ?: handler->name;
|
||||
size_t prefix_size = strlen(prefix);
|
||||
|
||||
if (buffer) {
|
||||
if (prefix_size + name_size + 1 > rest) {
|
||||
err = -ERANGE;
|
||||
goto failed;
|
||||
}
|
||||
memcpy(buffer, prefix, prefix_size);
|
||||
buffer += prefix_size;
|
||||
}
|
||||
err = squashfs_read_metadata(sb, buffer, &start,
|
||||
|
@ -212,25 +213,10 @@ static int squashfs_xattr_get(struct inode *inode, int name_index,
|
|||
}
|
||||
|
||||
|
||||
static size_t squashfs_xattr_handler_list(const struct xattr_handler *handler,
|
||||
struct dentry *d, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
{
|
||||
int len = strlen(handler->prefix);
|
||||
|
||||
if (list && len <= list_size)
|
||||
memcpy(list, handler->prefix, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
|
||||
struct dentry *d, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (name[0] == '\0')
|
||||
return -EINVAL;
|
||||
|
||||
return squashfs_xattr_get(d_inode(d), handler->flags, name,
|
||||
buffer, size);
|
||||
}
|
||||
|
@ -241,22 +227,15 @@ static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
|
|||
static const struct xattr_handler squashfs_xattr_user_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.flags = SQUASHFS_XATTR_USER,
|
||||
.list = squashfs_xattr_handler_list,
|
||||
.get = squashfs_xattr_handler_get
|
||||
};
|
||||
|
||||
/*
|
||||
* Trusted namespace support
|
||||
*/
|
||||
static size_t squashfs_trusted_xattr_handler_list(const struct xattr_handler *handler,
|
||||
struct dentry *d, char *list,
|
||||
size_t list_size, const char *name,
|
||||
size_t name_len)
|
||||
static bool squashfs_trusted_xattr_handler_list(struct dentry *d)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return 0;
|
||||
return squashfs_xattr_handler_list(handler, d, list, list_size, name,
|
||||
name_len);
|
||||
return capable(CAP_SYS_ADMIN);
|
||||
}
|
||||
|
||||
static const struct xattr_handler squashfs_xattr_trusted_handler = {
|
||||
|
@ -272,7 +251,6 @@ static const struct xattr_handler squashfs_xattr_trusted_handler = {
|
|||
static const struct xattr_handler squashfs_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.flags = SQUASHFS_XATTR_SECURITY,
|
||||
.list = squashfs_xattr_handler_list,
|
||||
.get = squashfs_xattr_handler_get
|
||||
};
|
||||
|
||||
|
|
167
fs/xattr.c
167
fs/xattr.c
|
@ -208,25 +208,6 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
|
|||
return error;
|
||||
}
|
||||
|
||||
/* Compare an extended attribute value with the given value */
|
||||
int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
|
||||
const char *value, size_t size, gfp_t flags)
|
||||
{
|
||||
char *xattr_value = NULL;
|
||||
int rc;
|
||||
|
||||
rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
|
||||
rc = -EINVAL;
|
||||
else
|
||||
rc = 0;
|
||||
kfree(xattr_value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
|
||||
{
|
||||
|
@ -700,13 +681,20 @@ xattr_resolve_name(const struct xattr_handler **handlers, const char **name)
|
|||
return NULL;
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
const char *n = strcmp_prefix(*name, handler->prefix);
|
||||
const char *n;
|
||||
|
||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||
if (n) {
|
||||
if (!handler->prefix ^ !*n) {
|
||||
if (*n)
|
||||
continue;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
*name = n;
|
||||
break;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -718,8 +706,8 @@ generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t s
|
|||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (!handler)
|
||||
return -EOPNOTSUPP;
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->get(handler, dentry, name, buffer, size);
|
||||
}
|
||||
|
||||
|
@ -735,19 +723,25 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
|||
|
||||
if (!buffer) {
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
size += handler->list(handler, dentry, NULL, 0,
|
||||
NULL, 0);
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
size += strlen(handler->name) + 1;
|
||||
}
|
||||
} else {
|
||||
char *buf = buffer;
|
||||
size_t len;
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
size = handler->list(handler, dentry, buf, buffer_size,
|
||||
NULL, 0);
|
||||
if (size > buffer_size)
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
len = strlen(handler->name);
|
||||
if (len + 1 > buffer_size)
|
||||
return -ERANGE;
|
||||
buf += size;
|
||||
buffer_size -= size;
|
||||
memcpy(buf, handler->name, len + 1);
|
||||
buf += len + 1;
|
||||
buffer_size -= len + 1;
|
||||
}
|
||||
size = buf - buffer;
|
||||
}
|
||||
|
@ -765,8 +759,8 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
|
|||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (!handler)
|
||||
return -EOPNOTSUPP;
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, name, value, size, flags);
|
||||
}
|
||||
|
||||
|
@ -780,8 +774,8 @@ generic_removexattr(struct dentry *dentry, const char *name)
|
|||
const struct xattr_handler *handler;
|
||||
|
||||
handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
|
||||
if (!handler)
|
||||
return -EOPNOTSUPP;
|
||||
if (IS_ERR(handler))
|
||||
return PTR_ERR(handler);
|
||||
return handler->set(handler, dentry, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
|
@ -808,7 +802,7 @@ EXPORT_SYMBOL(generic_removexattr);
|
|||
const char *xattr_full_name(const struct xattr_handler *handler,
|
||||
const char *name)
|
||||
{
|
||||
size_t prefix_len = strlen(handler->prefix);
|
||||
size_t prefix_len = strlen(xattr_prefix(handler));
|
||||
|
||||
return name - prefix_len;
|
||||
}
|
||||
|
@ -863,8 +857,22 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
/**
|
||||
* simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
|
||||
* @xattrs: target simple_xattr list
|
||||
* @name: name of the extended attribute
|
||||
* @value: value of the xattr. If %NULL, will remove the attribute.
|
||||
* @size: size of the new xattr
|
||||
* @flags: %XATTR_{CREATE|REPLACE}
|
||||
*
|
||||
* %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
|
||||
* with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
|
||||
* otherwise, fails with -ENODATA.
|
||||
*
|
||||
* Returns 0 on success, -errno on failure.
|
||||
*/
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct simple_xattr *xattr;
|
||||
struct simple_xattr *new_xattr = NULL;
|
||||
|
@ -914,73 +922,64 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
|
||||
* @xattrs: target simple_xattr list
|
||||
* @name: name of the new extended attribute
|
||||
* @value: value of the new xattr. If %NULL, will remove the attribute
|
||||
* @size: size of the new xattr
|
||||
* @flags: %XATTR_{CREATE|REPLACE}
|
||||
*
|
||||
* %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
|
||||
* with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
|
||||
* otherwise, fails with -ENODATA.
|
||||
*
|
||||
* Returns 0 on success, -errno on failure.
|
||||
*/
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
if (size == 0)
|
||||
value = ""; /* empty EA, do not remove */
|
||||
return __simple_xattr_set(xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* xattr REMOVE operation for in-memory/pseudo filesystems
|
||||
*/
|
||||
int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name)
|
||||
{
|
||||
return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE);
|
||||
}
|
||||
|
||||
static bool xattr_is_trusted(const char *name)
|
||||
{
|
||||
return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
|
||||
}
|
||||
|
||||
static int xattr_list_one(char **buffer, ssize_t *remaining_size,
|
||||
const char *name)
|
||||
{
|
||||
size_t len = strlen(name) + 1;
|
||||
if (*buffer) {
|
||||
if (*remaining_size < len)
|
||||
return -ERANGE;
|
||||
memcpy(*buffer, name, len);
|
||||
*buffer += len;
|
||||
}
|
||||
*remaining_size -= len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* xattr LIST operation for in-memory/pseudo filesystems
|
||||
*/
|
||||
ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
|
||||
size_t size)
|
||||
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
char *buffer, size_t size)
|
||||
{
|
||||
bool trusted = capable(CAP_SYS_ADMIN);
|
||||
struct simple_xattr *xattr;
|
||||
size_t used = 0;
|
||||
ssize_t remaining_size = size;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
if (inode->i_acl) {
|
||||
err = xattr_list_one(&buffer, &remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_ACCESS);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (inode->i_default_acl) {
|
||||
err = xattr_list_one(&buffer, &remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_DEFAULT);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_lock(&xattrs->lock);
|
||||
list_for_each_entry(xattr, &xattrs->head, list) {
|
||||
size_t len;
|
||||
|
||||
/* skip "trusted." attributes for unprivileged callers */
|
||||
if (!trusted && xattr_is_trusted(xattr->name))
|
||||
continue;
|
||||
|
||||
len = strlen(xattr->name) + 1;
|
||||
used += len;
|
||||
if (buffer) {
|
||||
if (size < used) {
|
||||
used = -ERANGE;
|
||||
break;
|
||||
}
|
||||
memcpy(buffer, xattr->name, len);
|
||||
buffer += len;
|
||||
}
|
||||
err = xattr_list_one(&buffer, &remaining_size, xattr->name);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
spin_unlock(&xattrs->lock);
|
||||
|
||||
return used;
|
||||
return size - remaining_size;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -39,9 +39,6 @@ xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry,
|
|||
struct xfs_inode *ip = XFS_I(d_inode(dentry));
|
||||
int error, asize = size;
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Convert Linux syscall to XFS internal ATTR flags */
|
||||
if (!size) {
|
||||
xflags |= ATTR_KERNOVAL;
|
||||
|
@ -84,9 +81,6 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry,
|
|||
struct xfs_inode *ip = XFS_I(d_inode(dentry));
|
||||
int error;
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Convert Linux syscall to XFS internal ATTR flags */
|
||||
if (flags & XATTR_CREATE)
|
||||
xflags |= ATTR_CREATE;
|
||||
|
@ -135,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
|
||||
|
@ -164,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
|
||||
|
@ -227,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.
|
||||
|
@ -236,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(POSIX_ACL_XATTR_ACCESS,
|
||||
strlen(POSIX_ACL_XATTR_ACCESS) + 1,
|
||||
data, size, &context.count);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (posix_acl_default_exists(inode)) {
|
||||
error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
|
||||
strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
|
||||
data, size, &context.count);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return context.count;
|
||||
}
|
||||
|
|
|
@ -9,16 +9,12 @@
|
|||
#ifndef _POSIX_ACL_XATTR_H
|
||||
#define _POSIX_ACL_XATTR_H
|
||||
|
||||
#include <uapi/linux/xattr.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
||||
/* Extended attribute names */
|
||||
#define POSIX_ACL_XATTR_ACCESS "system.posix_acl_access"
|
||||
#define POSIX_ACL_XATTR_DEFAULT "system.posix_acl_default"
|
||||
|
||||
/* Supported ACL a_version fields */
|
||||
#define POSIX_ACL_XATTR_VERSION 0x0002
|
||||
|
||||
|
||||
/* An undefined entry e_id value */
|
||||
#define ACL_UNDEFINED_ID (-1)
|
||||
|
||||
|
|
|
@ -19,12 +19,16 @@
|
|||
struct inode;
|
||||
struct dentry;
|
||||
|
||||
/*
|
||||
* struct xattr_handler: When @name is set, match attributes with exactly that
|
||||
* name. When @prefix is set instead, match attributes with that prefix and
|
||||
* with a non-empty suffix.
|
||||
*/
|
||||
struct xattr_handler {
|
||||
const char *name;
|
||||
const char *prefix;
|
||||
int flags; /* fs private flags */
|
||||
size_t (*list)(const struct xattr_handler *, struct dentry *dentry,
|
||||
char *list, size_t list_size, const char *name,
|
||||
size_t name_len);
|
||||
bool (*list)(struct dentry *dentry);
|
||||
int (*get)(const struct xattr_handler *, struct dentry *dentry,
|
||||
const char *name, void *buffer, size_t size);
|
||||
int (*set)(const struct xattr_handler *, struct dentry *dentry,
|
||||
|
@ -53,8 +57,11 @@ int generic_setxattr(struct dentry *dentry, const char *name, const void *value,
|
|||
int generic_removexattr(struct dentry *dentry, const char *name);
|
||||
ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name,
|
||||
char **xattr_value, size_t size, gfp_t flags);
|
||||
int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
|
||||
const char *value, size_t size, gfp_t flags);
|
||||
|
||||
static inline const char *xattr_prefix(const struct xattr_handler *handler)
|
||||
{
|
||||
return handler->prefix ?: handler->name;
|
||||
}
|
||||
|
||||
struct simple_xattrs {
|
||||
struct list_head head;
|
||||
|
@ -95,8 +102,7 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
|||
void *buffer, size_t size);
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags);
|
||||
int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name);
|
||||
ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
|
||||
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, char *buffer,
|
||||
size_t size);
|
||||
void simple_xattr_list_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr);
|
||||
|
|
147
mm/shmem.c
147
mm/shmem.c
|
@ -2564,99 +2564,52 @@ static int shmem_initxattrs(struct inode *inode,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int shmem_xattr_handler_get(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return simple_xattr_get(&info->xattrs, name, buffer, size);
|
||||
}
|
||||
|
||||
static int shmem_xattr_handler_set(const struct xattr_handler *handler,
|
||||
struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
|
||||
name = xattr_full_name(handler, name);
|
||||
return simple_xattr_set(&info->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
static const struct xattr_handler shmem_security_xattr_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = shmem_xattr_handler_get,
|
||||
.set = shmem_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler shmem_trusted_xattr_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = shmem_xattr_handler_get,
|
||||
.set = shmem_xattr_handler_set,
|
||||
};
|
||||
|
||||
static const struct xattr_handler *shmem_xattr_handlers[] = {
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&shmem_security_xattr_handler,
|
||||
&shmem_trusted_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int shmem_xattr_validate(const char *name)
|
||||
{
|
||||
struct { const char *prefix; size_t len; } arr[] = {
|
||||
{ XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
|
||||
{ XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arr); i++) {
|
||||
size_t preflen = arr[i].len;
|
||||
if (strncmp(name, arr[i].prefix, preflen) == 0) {
|
||||
if (!name[preflen])
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
int err;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_getxattr(dentry, name, buffer, size);
|
||||
|
||||
err = shmem_xattr_validate(name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return simple_xattr_get(&info->xattrs, name, buffer, size);
|
||||
}
|
||||
|
||||
static int shmem_setxattr(struct dentry *dentry, const char *name,
|
||||
const void *value, size_t size, int flags)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
int err;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_setxattr(dentry, name, value, size, flags);
|
||||
|
||||
err = shmem_xattr_validate(name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return simple_xattr_set(&info->xattrs, name, value, size, flags);
|
||||
}
|
||||
|
||||
static int shmem_removexattr(struct dentry *dentry, const char *name)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
int err;
|
||||
|
||||
/*
|
||||
* If this is a request for a synthetic attribute in the system.*
|
||||
* namespace use the generic infrastructure to resolve a handler
|
||||
* for it via sb->s_xattr.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return generic_removexattr(dentry, name);
|
||||
|
||||
err = shmem_xattr_validate(name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return simple_xattr_remove(&info->xattrs, name);
|
||||
}
|
||||
|
||||
static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
{
|
||||
struct shmem_inode_info *info = SHMEM_I(d_inode(dentry));
|
||||
return simple_xattr_list(&info->xattrs, buffer, size);
|
||||
return simple_xattr_list(d_inode(dentry), &info->xattrs, buffer, size);
|
||||
}
|
||||
#endif /* CONFIG_TMPFS_XATTR */
|
||||
|
||||
|
@ -2664,10 +2617,10 @@ static const struct inode_operations shmem_short_symlink_operations = {
|
|||
.readlink = generic_readlink,
|
||||
.get_link = simple_get_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -2675,10 +2628,10 @@ static const struct inode_operations shmem_symlink_inode_operations = {
|
|||
.readlink = generic_readlink,
|
||||
.get_link = shmem_get_link,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -3150,10 +3103,10 @@ static const struct inode_operations shmem_inode_operations = {
|
|||
.getattr = shmem_getattr,
|
||||
.setattr = shmem_setattr,
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
.set_acl = simple_set_acl,
|
||||
#endif
|
||||
};
|
||||
|
@ -3172,10 +3125,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
|
|||
.tmpfile = shmem_tmpfile,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.setattr = shmem_setattr,
|
||||
|
@ -3185,10 +3138,10 @@ static const struct inode_operations shmem_dir_inode_operations = {
|
|||
|
||||
static const struct inode_operations shmem_special_inode_operations = {
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
.setxattr = shmem_setxattr,
|
||||
.getxattr = shmem_getxattr,
|
||||
.setxattr = generic_setxattr,
|
||||
.getxattr = generic_getxattr,
|
||||
.listxattr = shmem_listxattr,
|
||||
.removexattr = shmem_removexattr,
|
||||
.removexattr = generic_removexattr,
|
||||
#endif
|
||||
#ifdef CONFIG_TMPFS_POSIX_ACL
|
||||
.setattr = shmem_setattr,
|
||||
|
|
|
@ -1519,8 +1519,6 @@ static int smack_inode_getsecurity(const struct inode *inode,
|
|||
* @inode: the object
|
||||
* @buffer: where they go
|
||||
* @buffer_size: size of buffer
|
||||
*
|
||||
* Returns 0 on success, -EINVAL otherwise
|
||||
*/
|
||||
static int smack_inode_listsecurity(struct inode *inode, char *buffer,
|
||||
size_t buffer_size)
|
||||
|
|
Loading…
Reference in a new issue