diff options
Diffstat (limited to 'fs/ubifs/xattr.c')
-rw-r--r-- | fs/ubifs/xattr.c | 143 |
1 files changed, 67 insertions, 76 deletions
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index 413d650..6c277eb 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -249,42 +249,6 @@ out_free: return err; } -/** - * check_namespace - check extended attribute name-space. - * @nm: extended attribute name - * - * This function makes sure the extended attribute name belongs to one of the - * supported extended attribute name-spaces. Returns name-space index in case - * of success and a negative error code in case of failure. - */ -static int check_namespace(const struct qstr *nm) -{ - int type; - - if (nm->len > UBIFS_MAX_NLEN) - return -ENAMETOOLONG; - - if (!strncmp(nm->name, XATTR_TRUSTED_PREFIX, - XATTR_TRUSTED_PREFIX_LEN)) { - if (nm->name[XATTR_TRUSTED_PREFIX_LEN] == '\0') - return -EINVAL; - type = TRUSTED_XATTR; - } else if (!strncmp(nm->name, XATTR_USER_PREFIX, - XATTR_USER_PREFIX_LEN)) { - if (nm->name[XATTR_USER_PREFIX_LEN] == '\0') - return -EINVAL; - type = USER_XATTR; - } else if (!strncmp(nm->name, XATTR_SECURITY_PREFIX, - XATTR_SECURITY_PREFIX_LEN)) { - if (nm->name[XATTR_SECURITY_PREFIX_LEN] == '\0') - return -EINVAL; - type = SECURITY_XATTR; - } else - return -EOPNOTSUPP; - - return type; -} - static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) { struct inode *inode; @@ -302,24 +266,23 @@ static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) return ERR_PTR(-EINVAL); } -static int setxattr(struct inode *host, const char *name, const void *value, - size_t size, int flags) +static int __ubifs_setxattr(struct inode *host, const char *name, + const void *value, size_t size, int flags) { struct inode *inode; struct ubifs_info *c = host->i_sb->s_fs_info; struct qstr nm = QSTR_INIT(name, strlen(name)); struct ubifs_dent_node *xent; union ubifs_key key; - int err, type; + int err; ubifs_assert(inode_is_locked(host)); if (size > UBIFS_MAX_INO_DATA) return -ERANGE; - type = check_namespace(&nm); - if (type < 0) - return type; + if (nm.len > UBIFS_MAX_NLEN) + return -ENAMETOOLONG; xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); if (!xent) @@ -363,17 +326,8 @@ out_free: return err; } -int ubifs_setxattr(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd", - name, d_inode(dentry)->i_ino, dentry, size); - - return setxattr(d_inode(dentry), name, value, size, flags); -} - -ssize_t ubifs_getxattr(struct dentry *dentry, struct inode *host, - const char *name, void *buf, size_t size) +static ssize_t __ubifs_getxattr(struct inode *host, const char *name, + void *buf, size_t size) { struct inode *inode; struct ubifs_info *c = host->i_sb->s_fs_info; @@ -383,12 +337,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, struct inode *host, union ubifs_key key; int err; - dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name, - host->i_ino, dentry, size); - - err = check_namespace(&nm); - if (err < 0) - return err; + if (nm.len > UBIFS_MAX_NLEN) + return -ENAMETOOLONG; xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); if (!xent) @@ -460,8 +410,6 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) lowest_xent_key(c, &key, host->i_ino); while (1) { - int type; - xent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(xent)) { err = PTR_ERR(xent); @@ -471,14 +419,10 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) nm.name = xent->name; nm.len = le16_to_cpu(xent->nlen); - type = check_namespace(&nm); - if (unlikely(type < 0)) { - err = type; - break; - } - /* Show trusted namespace only for "power" users */ - if (type != TRUSTED_XATTR || capable(CAP_SYS_ADMIN)) { + if (strncmp(xent->name, XATTR_TRUSTED_PREFIX, + XATTR_TRUSTED_PREFIX_LEN) || + capable(CAP_SYS_ADMIN)) { memcpy(buffer + written, nm.name, nm.len + 1); written += nm.len + 1; } @@ -538,22 +482,19 @@ out_cancel: return err; } -int ubifs_removexattr(struct dentry *dentry, const char *name) +static int __ubifs_removexattr(struct inode *host, const char *name) { - struct inode *inode, *host = d_inode(dentry); + struct inode *inode; struct ubifs_info *c = host->i_sb->s_fs_info; struct qstr nm = QSTR_INIT(name, strlen(name)); struct ubifs_dent_node *xent; union ubifs_key key; int err; - dbg_gen("xattr '%s', ino %lu ('%pd')", name, - host->i_ino, dentry); ubifs_assert(inode_is_locked(host)); - err = check_namespace(&nm); - if (err < 0) - return err; + if (nm.len > UBIFS_MAX_NLEN) + return -ENAMETOOLONG; xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); if (!xent) @@ -603,7 +544,7 @@ static int init_xattrs(struct inode *inode, const struct xattr *xattr_array, } strcpy(name, XATTR_SECURITY_PREFIX); strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); - err = setxattr(inode, name, xattr->value, xattr->value_len, 0); + err = __ubifs_setxattr(inode, name, xattr->value, xattr->value_len, 0); kfree(name); if (err < 0) break; @@ -626,3 +567,53 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode, } return err; } + +static int ubifs_xattr_get(const struct xattr_handler *handler, + struct dentry *dentry, struct inode *inode, + const char *name, void *buffer, size_t size) +{ + dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name, + inode->i_ino, dentry, size); + + return __ubifs_getxattr(inode, name, buffer, size); +} + +static int ubifs_xattr_set(const struct xattr_handler *handler, + struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + struct inode *inode = d_inode(dentry); + + dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd", + name, inode->i_ino, dentry, size); + + if (value) + return __ubifs_setxattr(inode, name, value, size, flags); + else + return __ubifs_removexattr(inode, name); +} + +const struct xattr_handler ubifs_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .get = ubifs_xattr_get, + .set = ubifs_xattr_set, +}; + +const struct xattr_handler ubifs_trusted_xattr_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .get = ubifs_xattr_get, + .set = ubifs_xattr_set, +}; + +const struct xattr_handler ubifs_security_xattr_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .get = ubifs_xattr_get, + .set = ubifs_xattr_set, +}; + +const struct xattr_handler *ubifs_xattr_handlers[] = { + &ubifs_user_xattr_handler, + &ubifs_trusted_xattr_handler, + &ubifs_security_xattr_handler, + NULL +}; |