summaryrefslogtreecommitdiff
path: root/fs/ubifs/xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ubifs/xattr.c')
-rw-r--r--fs/ubifs/xattr.c144
1 files changed, 67 insertions, 77 deletions
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index b043e0441..b5fc27969 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,19 +326,10 @@ out_free:
return err;
}
-int ubifs_setxattr(struct dentry *dentry, const char *name,
- const void *value, size_t size, int flags)
+static ssize_t __ubifs_getxattr(struct inode *host, const char *name,
+ void *buf, size_t size)
{
- 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, const char *name, void *buf,
- size_t size)
-{
- 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_inode *ui;
@@ -383,12 +337,8 @@ ssize_t ubifs_getxattr(struct dentry *dentry, const char *name, void *buf,
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,52 @@ 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, struct inode *inode,
+ const char *name, const void *value,
+ size_t size, int flags)
+{
+ 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
+};