Fix use of incorrect flags when using splice() with pipe ends and memfd secret. Ensure that pipe and memfd file descriptors are properly recognized and handled to prevent unintended EACCES errors in scenarios where EBADF or EINVAL are expected. This resolves failures in LTP's splice07 test case: ./ltp-bin/testcases/bin/splice07 [skip] splice07.c:54: TFAIL: splice() on pipe read end -> memfd secret expected EBADF, EINVAL: EACCES (13) [skip] splice07.c:54: TFAIL: splice() on memfd secret -> pipe write end expected EBADF, EINVAL: EACCES (13) [skip] Fixes: cbe4134ea4bc ("fs: export anon_inode_make_secure_inode() and fix secretmem LSM bypass") Signed-off-by: Jan Polensky <japo@xxxxxxxxxxxxx> --- fs/anon_inodes.c | 11 +++++++---- include/linux/fs.h | 2 +- mm/secretmem.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 1d847a939f29..f4eade76273b 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -104,6 +104,7 @@ static struct file_system_type anon_inode_fs_type = { * @name: [in] Name of the class of the newfile (e.g., "secretmem") * @context_inode: * [in] Optional parent inode for security inheritance + * @secmem [in] Indicates wheather the inode should be threaded as secretmem * * The function ensures proper security initialization through the LSM hook * security_inode_init_security_anon(). @@ -111,7 +112,7 @@ static struct file_system_type anon_inode_fs_type = { * Return: Pointer to new inode on success, ERR_PTR on failure. */ struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *name, - const struct inode *context_inode) + const struct inode *context_inode, bool secmem) { struct inode *inode; int error; @@ -119,8 +120,10 @@ struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *n inode = alloc_anon_inode(sb); if (IS_ERR(inode)) return inode; - inode->i_flags &= ~S_PRIVATE; - inode->i_op = &anon_inode_operations; + if (!secmem) { + inode->i_flags &= ~S_PRIVATE; + inode->i_op = &anon_inode_operations; + } error = security_inode_init_security_anon(inode, &QSTR(name), context_inode); if (error) { @@ -145,7 +148,7 @@ static struct file *__anon_inode_getfile(const char *name, if (make_inode) { inode = anon_inode_make_secure_inode(anon_inode_mnt->mnt_sb, - name, context_inode); + 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 040c0036320f..50a32bee366e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3609,7 +3609,7 @@ 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 *); struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *name, - const struct inode *context_inode); + const struct inode *context_inode, bool secmem); extern int simple_nosetlease(struct file *, int, struct file_lease **, void **); extern const struct dentry_operations simple_dentry_operations; diff --git a/mm/secretmem.c b/mm/secretmem.c index 9a11a38a6770..d28e1caa8847 100644 --- a/mm/secretmem.c +++ b/mm/secretmem.c @@ -196,7 +196,7 @@ static struct file *secretmem_file_create(unsigned long flags) struct inode *inode; const char *anon_name = "[secretmem]"; - inode = anon_inode_make_secure_inode(secretmem_mnt->mnt_sb, anon_name, NULL); + inode = anon_inode_make_secure_inode(secretmem_mnt->mnt_sb, anon_name, NULL, true); if (IS_ERR(inode)) return ERR_CAST(inode); -- 2.48.1