|
@@ -28,9 +28,9 @@ static const struct inode_operations kernfs_iops = {
|
|
|
.permission = kernfs_iop_permission,
|
|
|
.setattr = kernfs_iop_setattr,
|
|
|
.getattr = kernfs_iop_getattr,
|
|
|
- .setxattr = kernfs_iop_setxattr,
|
|
|
- .removexattr = kernfs_iop_removexattr,
|
|
|
- .getxattr = kernfs_iop_getxattr,
|
|
|
+ .setxattr = generic_setxattr,
|
|
|
+ .removexattr = generic_removexattr,
|
|
|
+ .getxattr = generic_getxattr,
|
|
|
.listxattr = kernfs_iop_listxattr,
|
|
|
};
|
|
|
|
|
@@ -138,17 +138,12 @@ out:
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
|
|
+static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
|
|
|
u32 *secdata_len)
|
|
|
{
|
|
|
- struct kernfs_iattrs *attrs;
|
|
|
void *old_secdata;
|
|
|
size_t old_secdata_len;
|
|
|
|
|
|
- attrs = kernfs_iattrs(kn);
|
|
|
- if (!attrs)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
old_secdata = attrs->ia_secdata;
|
|
|
old_secdata_len = attrs->ia_secdata_len;
|
|
|
|
|
@@ -160,71 +155,6 @@ static int kernfs_node_setsecdata(struct kernfs_node *kn, void **secdata,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int kernfs_iop_setxattr(struct dentry *unused, struct inode *inode,
|
|
|
- const char *name, const void *value,
|
|
|
- size_t size, int flags)
|
|
|
-{
|
|
|
- struct kernfs_node *kn = inode->i_private;
|
|
|
- struct kernfs_iattrs *attrs;
|
|
|
- void *secdata;
|
|
|
- int error;
|
|
|
- u32 secdata_len = 0;
|
|
|
-
|
|
|
- attrs = kernfs_iattrs(kn);
|
|
|
- if (!attrs)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN)) {
|
|
|
- const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
|
|
- error = security_inode_setsecurity(inode, suffix,
|
|
|
- value, size, flags);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
- error = security_inode_getsecctx(inode,
|
|
|
- &secdata, &secdata_len);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
-
|
|
|
- mutex_lock(&kernfs_mutex);
|
|
|
- error = kernfs_node_setsecdata(kn, &secdata, &secdata_len);
|
|
|
- mutex_unlock(&kernfs_mutex);
|
|
|
-
|
|
|
- if (secdata)
|
|
|
- security_release_secctx(secdata, secdata_len);
|
|
|
- return error;
|
|
|
- } else if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) {
|
|
|
- return simple_xattr_set(&attrs->xattrs, name, value, size,
|
|
|
- flags);
|
|
|
- }
|
|
|
-
|
|
|
- return -EINVAL;
|
|
|
-}
|
|
|
-
|
|
|
-int kernfs_iop_removexattr(struct dentry *dentry, const char *name)
|
|
|
-{
|
|
|
- struct kernfs_node *kn = dentry->d_fsdata;
|
|
|
- struct kernfs_iattrs *attrs;
|
|
|
-
|
|
|
- attrs = kernfs_iattrs(kn);
|
|
|
- if (!attrs)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- return simple_xattr_set(&attrs->xattrs, name, NULL, 0, XATTR_REPLACE);
|
|
|
-}
|
|
|
-
|
|
|
-ssize_t kernfs_iop_getxattr(struct dentry *unused, struct inode *inode,
|
|
|
- const char *name, void *buf, size_t size)
|
|
|
-{
|
|
|
- struct kernfs_node *kn = inode->i_private;
|
|
|
- struct kernfs_iattrs *attrs;
|
|
|
-
|
|
|
- attrs = kernfs_iattrs(kn);
|
|
|
- if (!attrs)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- return simple_xattr_get(&attrs->xattrs, name, buf, size);
|
|
|
-}
|
|
|
-
|
|
|
ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
|
|
|
{
|
|
|
struct kernfs_node *kn = dentry->d_fsdata;
|
|
@@ -376,3 +306,83 @@ int kernfs_iop_permission(struct inode *inode, int mask)
|
|
|
|
|
|
return generic_permission(inode, mask);
|
|
|
}
|
|
|
+
|
|
|
+static int kernfs_xattr_get(const struct xattr_handler *handler,
|
|
|
+ struct dentry *unused, struct inode *inode,
|
|
|
+ const char *suffix, void *value, size_t size)
|
|
|
+{
|
|
|
+ const char *name = xattr_full_name(handler, suffix);
|
|
|
+ struct kernfs_node *kn = inode->i_private;
|
|
|
+ struct kernfs_iattrs *attrs;
|
|
|
+
|
|
|
+ attrs = kernfs_iattrs(kn);
|
|
|
+ if (!attrs)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ return simple_xattr_get(&attrs->xattrs, name, value, size);
|
|
|
+}
|
|
|
+
|
|
|
+static int kernfs_xattr_set(const struct xattr_handler *handler,
|
|
|
+ struct dentry *unused, struct inode *inode,
|
|
|
+ const char *suffix, const void *value,
|
|
|
+ size_t size, int flags)
|
|
|
+{
|
|
|
+ const char *name = xattr_full_name(handler, suffix);
|
|
|
+ struct kernfs_node *kn = inode->i_private;
|
|
|
+ struct kernfs_iattrs *attrs;
|
|
|
+
|
|
|
+ attrs = kernfs_iattrs(kn);
|
|
|
+ if (!attrs)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
|
|
|
+}
|
|
|
+
|
|
|
+const struct xattr_handler kernfs_trusted_xattr_handler = {
|
|
|
+ .prefix = XATTR_TRUSTED_PREFIX,
|
|
|
+ .get = kernfs_xattr_get,
|
|
|
+ .set = kernfs_xattr_set,
|
|
|
+};
|
|
|
+
|
|
|
+static int kernfs_security_xattr_set(const struct xattr_handler *handler,
|
|
|
+ struct dentry *unused, struct inode *inode,
|
|
|
+ const char *suffix, const void *value,
|
|
|
+ size_t size, int flags)
|
|
|
+{
|
|
|
+ struct kernfs_node *kn = inode->i_private;
|
|
|
+ struct kernfs_iattrs *attrs;
|
|
|
+ void *secdata;
|
|
|
+ u32 secdata_len = 0;
|
|
|
+ int error;
|
|
|
+
|
|
|
+ attrs = kernfs_iattrs(kn);
|
|
|
+ if (!attrs)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ error = security_inode_setsecurity(inode, suffix, value, size, flags);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+ error = security_inode_getsecctx(inode, &secdata, &secdata_len);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ mutex_lock(&kernfs_mutex);
|
|
|
+ error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
|
|
|
+ mutex_unlock(&kernfs_mutex);
|
|
|
+
|
|
|
+ if (secdata)
|
|
|
+ security_release_secctx(secdata, secdata_len);
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+const struct xattr_handler kernfs_security_xattr_handler = {
|
|
|
+ .prefix = XATTR_SECURITY_PREFIX,
|
|
|
+ .get = kernfs_xattr_get,
|
|
|
+ .set = kernfs_security_xattr_set,
|
|
|
+};
|
|
|
+
|
|
|
+const struct xattr_handler *kernfs_xattr_handlers[] = {
|
|
|
+ &kernfs_trusted_xattr_handler,
|
|
|
+ &kernfs_security_xattr_handler,
|
|
|
+ NULL
|
|
|
+};
|