From 78f48437a88b3b70aa7d80a32db4f269a0804d18 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 6 May 2025 09:13:05 +0000 Subject: [PATCH V8 3/9] fs: add alloc_anon_secure_inode() for allocating secure anonymous inodes This introduces alloc_anon_secure_inode() combining alloc_anon_inode() with security_inode_init_security_anon(), similar to secretmem's usage. As discussed [1], we need this for cases like secretmem and kvm_gmem when there might be interest to have global access control via LSMs and need proper security labeling while maintaining S_PRIVATE. The new helper avoids duplicating the security initialization for secretmem and kvm_gmem. [1]: https://lore.kernel.org/linux-mm/b9e5fa41-62fd-4b3d-bb2d-24ae9d3c33da@redhat.com Signed-off-by: David Hildenbrand [Shivank: add documentation] Signed-off-by: Shivank Garg --- fs/anon_inodes.c | 46 ++++++++++++++++++++++++++++++++++++++++------ include/linux/fs.h | 1 + 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 583ac81669c2..479efcec20bc 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -55,17 +55,33 @@ static struct file_system_type anon_inode_fs_type = { .kill_sb = kill_anon_super, }; -static struct inode *anon_inode_make_secure_inode( - const char *name, - const struct inode *context_inode) +/** + * anon_inode_make_secure_inode - allocate an anonymous inode with security context + * @sb: [in] Superblock to allocate from + * @name: [in] Name of the class of the newfile (e.g., "secretmem") + * @context_inode: + * [in] Optional parent inode for security inheritance + * @fs_internal: + * [in] If true, keep S_PRIVATE set (flag indicating internal fs inodes) + * + * The function ensures proper security initialization through the LSM hook + * security_inode_init_security_anon(). + * + * Return: Pointer to new inode on success, ERR_PTR on failure. + */ +static struct inode *anon_inode_make_secure_inode(struct super_block *sb, + const char *name, const struct inode *context_inode, + bool fs_internal) { struct inode *inode; int error; - inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); + inode = alloc_anon_inode(sb); if (IS_ERR(inode)) return inode; - inode->i_flags &= ~S_PRIVATE; + if (!fs_internal) + inode->i_flags &= ~S_PRIVATE; + error = security_inode_init_security_anon(inode, &QSTR(name), context_inode); if (error) { @@ -75,6 +91,23 @@ static struct inode *anon_inode_make_secure_inode( return inode; } +/** + * alloc_anon_secure_inode - allocate a secure anonymous inode + * @sb: [in] Superblock to allocate the inode from + * @name: [in] Name of the class of the newfile (e.g., "secretmem") + * + * Specialized version of anon_inode_make_secure_inode() for filesystem use. + * This creates an internal-use inode, marked with S_PRIVATE (hidden from + * userspace). + * + * Return: A pointer to the new inode on success, ERR_PTR on failure. + */ +struct inode *alloc_anon_secure_inode(struct super_block *sb, const char *name) +{ + return anon_inode_make_secure_inode(sb, name, NULL, true); +} +EXPORT_SYMBOL_GPL(alloc_anon_secure_inode); + static struct file *__anon_inode_getfile(const char *name, const struct file_operations *fops, void *priv, int flags, @@ -88,7 +121,8 @@ static struct file *__anon_inode_getfile(const char *name, return ERR_PTR(-ENOENT); if (make_inode) { - inode = anon_inode_make_secure_inode(name, context_inode); + inode = anon_inode_make_secure_inode(anon_inode_mnt->mnt_sb, + name, context_inode, false); if (IS_ERR(inode)) { file = ERR_CAST(inode); goto err; diff --git a/include/linux/fs.h b/include/linux/fs.h index 016b0fe1536e..0fded2e3c661 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3550,6 +3550,7 @@ extern int simple_write_begin(struct file *file, struct address_space *mapping, extern const struct address_space_operations ram_aops; extern int always_delete_dentry(const struct dentry *); extern struct inode *alloc_anon_inode(struct super_block *); +extern struct inode *alloc_anon_secure_inode(struct super_block *, const char *); extern int simple_nosetlease(struct file *, int, struct file_lease **, void **); extern const struct dentry_operations simple_dentry_operations; -- 2.34.1