xattr handlers: Simplify list operation
Change the list operation to only return whether or not an attribute should be listed. Copying the attribute names into the buffer is moved to the callers. Since the result only depends on the dentry and not on the attribute name, we do not pass the attribute name to list operations. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
1046cb1195
commit
764a5c6b1f
@ -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,22 +7,6 @@
|
||||
#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,
|
||||
@ -67,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
|
||||
|
@ -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
|
||||
|
@ -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,23 +11,6 @@
|
||||
#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,
|
||||
@ -75,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
|
||||
|
@ -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
|
||||
|
@ -25,40 +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);
|
||||
const char *prefix;
|
||||
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 = xattr_prefix(handler);
|
||||
prefix_len = strlen(prefix);
|
||||
total_len = prefix_len + len + 1;
|
||||
if (list && total_len <= list_size) {
|
||||
memcpy(list, 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)
|
||||
@ -107,17 +73,16 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
|
||||
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_NAME;
|
||||
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,
|
||||
@ -175,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,
|
||||
};
|
||||
@ -183,7 +148,7 @@ 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,
|
||||
};
|
||||
@ -191,7 +156,6 @@ const struct xattr_handler f2fs_xattr_trusted_handler = {
|
||||
const struct xattr_handler f2fs_xattr_advise_handler = {
|
||||
.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,
|
||||
};
|
||||
@ -199,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,
|
||||
};
|
||||
@ -447,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;
|
||||
|
@ -64,24 +64,8 @@ static int jffs2_security_setxattr(const struct xattr_handler *handler,
|
||||
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;
|
||||
|
@ -32,22 +32,9 @@ static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
|
||||
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 = {
|
||||
|
@ -32,24 +32,8 @@ static int jffs2_user_setxattr(const struct xattr_handler *handler,
|
||||
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
|
||||
};
|
||||
|
@ -6263,19 +6263,9 @@ static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
|
||||
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
|
||||
|
@ -823,21 +823,10 @@ out:
|
||||
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->name;
|
||||
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 = {
|
||||
|
@ -840,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;
|
||||
|
@ -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,18 +213,6 @@ failed:
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
@ -238,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 = {
|
||||
@ -269,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
|
||||
};
|
||||
|
||||
|
20
fs/xattr.c
20
fs/xattr.c
@ -723,23 +723,25 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
|
||||
if (!buffer) {
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!handler->list)
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
size += handler->list(handler, dentry, NULL, 0,
|
||||
NULL, 0);
|
||||
size += strlen(handler->name) + 1;
|
||||
}
|
||||
} else {
|
||||
char *buf = buffer;
|
||||
size_t len;
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!handler->list)
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
size = handler->list(handler, dentry, buf, buffer_size,
|
||||
NULL, 0);
|
||||
if (size > buffer_size)
|
||||
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;
|
||||
}
|
||||
|
@ -28,9 +28,7 @@ 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,
|
||||
|
Loading…
Reference in New Issue
Block a user