aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/kernfs/inode.c48
-rw-r--r--include/linux/kernfs.h15
-rw-r--r--include/linux/lsm_hooks.h13
-rw-r--r--include/linux/security.h9
-rw-r--r--security/security.c6
5 files changed, 82 insertions, 9 deletions
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index a365088caa3c..673ef598d97d 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -288,12 +288,11 @@ 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)
+static int kernfs_node_xattr_get(const struct xattr_handler *handler,
+ struct kernfs_node *kn, 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_noalloc(kn);
@@ -303,13 +302,11 @@ static int kernfs_xattr_get(const struct xattr_handler *handler,
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)
+static int kernfs_node_xattr_set(const struct xattr_handler *handler,
+ struct kernfs_node *kn, 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);
@@ -319,6 +316,25 @@ static int kernfs_xattr_set(const struct xattr_handler *handler,
return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
}
+static int kernfs_xattr_get(const struct xattr_handler *handler,
+ struct dentry *unused, struct inode *inode,
+ const char *suffix, void *value, size_t size)
+{
+ struct kernfs_node *kn = inode->i_private;
+
+ return kernfs_node_xattr_get(handler, kn, suffix, 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)
+{
+ struct kernfs_node *kn = inode->i_private;
+
+ return kernfs_node_xattr_set(handler, kn, suffix, value, size, flags);
+}
+
static const struct xattr_handler kernfs_trusted_xattr_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = kernfs_xattr_get,
@@ -336,3 +352,17 @@ const struct xattr_handler *kernfs_xattr_handlers[] = {
&kernfs_security_xattr_handler,
NULL
};
+
+int kernfs_security_xattr_get(struct kernfs_node *kn, const char *suffix,
+ void *value, size_t size)
+{
+ return kernfs_node_xattr_get(&kernfs_security_xattr_handler,
+ kn, suffix, value, size);
+}
+
+int kernfs_security_xattr_set(struct kernfs_node *kn, const char *suffix,
+ void *value, size_t size, int flags)
+{
+ return kernfs_node_xattr_set(&kernfs_security_xattr_handler,
+ kn, suffix, value, size, flags);
+}
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index c8893f663470..39eea07c2900 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -371,6 +371,11 @@ __poll_t kernfs_generic_poll(struct kernfs_open_file *of,
struct poll_table_struct *pt);
void kernfs_notify(struct kernfs_node *kn);
+int kernfs_security_xattr_get(struct kernfs_node *kn, const char *suffix,
+ void *value, size_t size);
+int kernfs_security_xattr_set(struct kernfs_node *kn, const char *suffix,
+ void *value, size_t size, int flags);
+
const void *kernfs_super_ns(struct super_block *sb);
int kernfs_get_tree(struct fs_context *fc);
void kernfs_free_fs_context(struct fs_context *fc);
@@ -473,6 +478,16 @@ static inline int kernfs_setattr(struct kernfs_node *kn,
static inline void kernfs_notify(struct kernfs_node *kn) { }
+static inline int kernfs_security_xattr_get(struct kernfs_node *kn,
+ const char *suffix, void *value,
+ size_t size)
+{ return -ENOSYS; }
+
+static inline int kernfs_security_xattr_set(struct kernfs_node *kn,
+ const char *suffix, void *value,
+ size_t size, int flags)
+{ return -ENOSYS; }
+
static inline const void *kernfs_super_ns(struct super_block *sb)
{ return NULL; }
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index a9b8ff578b6b..0dd5bda719e6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -445,6 +445,15 @@
* to abort the copy up. Note that the caller is responsible for reading
* and writing the xattrs as this hook is merely a filter.
*
+ * Security hooks for kernfs node operations
+ *
+ * @kernfs_init_security
+ * Initialize the security context of a newly created kernfs node based
+ * on its own and its parent's attributes.
+ *
+ * @kn_dir the parent kernfs node
+ * @kn the new child kernfs node
+ *
* Security hooks for file operations
*
* @file_permission:
@@ -1578,6 +1587,9 @@ union security_list_options {
int (*inode_copy_up)(struct dentry *src, struct cred **new);
int (*inode_copy_up_xattr)(const char *name);
+ int (*kernfs_init_security)(struct kernfs_node *kn_dir,
+ struct kernfs_node *kn);
+
int (*file_permission)(struct file *file, int mask);
int (*file_alloc_security)(struct file *file);
void (*file_free_security)(struct file *file);
@@ -1879,6 +1891,7 @@ struct security_hook_heads {
struct hlist_head inode_getsecid;
struct hlist_head inode_copy_up;
struct hlist_head inode_copy_up_xattr;
+ struct hlist_head kernfs_init_security;
struct hlist_head file_permission;
struct hlist_head file_alloc_security;
struct hlist_head file_free_security;
diff --git a/include/linux/security.h b/include/linux/security.h
index 49f2685324b0..d543293216b9 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -51,6 +51,7 @@ struct fown_struct;
struct file_operations;
struct msg_msg;
struct xattr;
+struct kernfs_node;
struct xfrm_sec_ctx;
struct mm_struct;
struct fs_context;
@@ -299,6 +300,8 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
void security_inode_getsecid(struct inode *inode, u32 *secid);
int security_inode_copy_up(struct dentry *src, struct cred **new);
int security_inode_copy_up_xattr(const char *name);
+int security_kernfs_init_security(struct kernfs_node *kn_dir,
+ struct kernfs_node *kn);
int security_file_permission(struct file *file, int mask);
int security_file_alloc(struct file *file);
void security_file_free(struct file *file);
@@ -801,6 +804,12 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new)
return 0;
}
+static inline int security_kernfs_init_security(struct kernfs_node *kn_dir,
+ struct kernfs_node *kn)
+{
+ return 0;
+}
+
static inline int security_inode_copy_up_xattr(const char *name)
{
return -EOPNOTSUPP;
diff --git a/security/security.c b/security/security.c
index 23cbb1a295a3..8d6ef9da94eb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1318,6 +1318,12 @@ int security_inode_copy_up_xattr(const char *name)
}
EXPORT_SYMBOL(security_inode_copy_up_xattr);
+int security_kernfs_init_security(struct kernfs_node *kn_dir,
+ struct kernfs_node *kn)
+{
+ return call_int_hook(kernfs_init_security, 0, kn_dir, kn);
+}
+
int security_file_permission(struct file *file, int mask)
{
int ret;