From 98e9cb5711c68223f0e4d5201b9a6add255ec550 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 2 Dec 2015 14:44:36 +0100 Subject: vfs: Distinguish between full xattr names and proper prefixes Add an additional "name" field to struct xattr_handler. When the name is set, the handler matches attributes with exactly that name. When the prefix is set instead, the handler matches attributes with the given prefix and with a non-empty suffix. This patch should avoid bugs like the one fixed in commit c361016a in the future. Signed-off-by: Andreas Gruenbacher Reviewed-by: James Morris Signed-off-by: Al Viro --- fs/ext2/xattr_security.c | 4 ---- fs/ext2/xattr_trusted.c | 4 ---- fs/ext2/xattr_user.c | 4 ---- 3 files changed, 12 deletions(-) (limited to 'fs/ext2') diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index dfb08750370d..118bf231bc7f 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -28,8 +28,6 @@ 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 +37,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); } diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 3150dd3a7859..3f8f2bc6539e 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c @@ -32,8 +32,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 +41,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); } diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index 339a49bbb8ef..afd45ab1218c 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c @@ -34,8 +34,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 +45,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; -- cgit From 764a5c6b1fa4306dd7573c1d80914254909cd036 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 2 Dec 2015 14:44:43 +0100 Subject: 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 Signed-off-by: Al Viro --- fs/ext2/xattr.c | 15 ++++++++++----- fs/ext2/xattr_security.c | 17 ----------------- fs/ext2/xattr_trusted.c | 19 +++---------------- fs/ext2/xattr_user.c | 19 +++---------------- 4 files changed, 16 insertions(+), 54 deletions(-) (limited to 'fs/ext2') diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index fa70848afa8f..cd95d14f9cc2 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -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; } diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c index 118bf231bc7f..ba97f243b050 100644 --- a/fs/ext2/xattr_security.c +++ b/fs/ext2/xattr_security.c @@ -7,22 +7,6 @@ #include #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, }; diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c index 3f8f2bc6539e..2c94d1930626 100644 --- a/fs/ext2/xattr_trusted.c +++ b/fs/ext2/xattr_trusted.c @@ -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 diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c index afd45ab1218c..72a2a96d677f 100644 --- a/fs/ext2/xattr_user.c +++ b/fs/ext2/xattr_user.c @@ -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 -- cgit