These two are backports for 5.15.y. Conflict resolution in done in both patches.
I have tested LTP-nfs fchown02 and chown02 on 5.15.y with below patches applied. The tests passed.
I would like to have a review as I am not familiar with this code.
Thanks to Vegard for helping me with this.
Regards, Harshit
Christian Brauner (2): nfs: use vfs setgid helper nfsd: use vfs setgid helper
fs/attr.c | 1 + fs/internal.h | 2 -- fs/nfs/inode.c | 4 +--- fs/nfsd/vfs.c | 4 +++- include/linux/fs.h | 2 ++ 5 files changed, 7 insertions(+), 6 deletions(-)
From: Christian Brauner brauner@kernel.org
commit 4f704d9a8352f5c0a8fcdb6213b934630342bd44 upstream.
We've aligned setgid behavior over multiple kernel releases. The details can be found in the following two merge messages: cf619f891971 ("Merge tag 'fs.ovl.setgid.v6.2') 426b4ca2d6a5 ("Merge tag 'fs.setgid.v6.0') Consistent setgid stripping behavior is now encapsulated in the setattr_should_drop_sgid() helper which is used by all filesystems that strip setgid bits outside of vfs proper. Switch nfs to rely on this helper as well. Without this patch the setgid stripping tests in xfstests will fail.
Signed-off-by: Christian Brauner (Microsoft) brauner@kernel.org Reviewed-by: Christoph Hellwig hch@lst.de Message-Id: 20230313-fs-nfs-setgid-v2-1-9a59f436cfc0@kernel.org Signed-off-by: Christian Brauner brauner@kernel.org [Harshit: backport to 5.15.y] Conflicts: fs/internal.h -- minor conflcit due to code change differences. include/linux/fs.h -- Used struct user_namespace *mnt_userns instead of struct mnt_idmap *idmap fs/nfs/inode.c -- Used init_user_ns instead of nop_mnt_idmap
Signed-off-by: Harshit Mogalapalli harshit.m.mogalapalli@oracle.com --- fs/attr.c | 1 + fs/internal.h | 2 -- fs/nfs/inode.c | 4 +--- include/linux/fs.h | 2 ++ 4 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/fs/attr.c b/fs/attr.c index 0ca14cbd4b8b..28e953e86960 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -47,6 +47,7 @@ int setattr_should_drop_sgid(struct user_namespace *mnt_userns, return ATTR_KILL_SGID; return 0; } +EXPORT_SYMBOL(setattr_should_drop_sgid);
/** * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to diff --git a/fs/internal.h b/fs/internal.h index 1ff8cfc94467..d241eaa0c58b 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -235,5 +235,3 @@ int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry, /* * fs/attr.c */ -int setattr_should_drop_sgid(struct user_namespace *mnt_userns, - const struct inode *inode); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e4524635a129..d8f01d222c49 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -731,9 +731,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, if ((attr->ia_valid & ATTR_KILL_SUID) != 0 && inode->i_mode & S_ISUID) inode->i_mode &= ~S_ISUID; - if ((attr->ia_valid & ATTR_KILL_SGID) != 0 && - (inode->i_mode & (S_ISGID | S_IXGRP)) == - (S_ISGID | S_IXGRP)) + if (setattr_should_drop_sgid(&init_user_ns, inode)) inode->i_mode &= ~S_ISGID; if ((attr->ia_valid & ATTR_MODE) != 0) { int mode = attr->ia_mode & S_IALLUGO; diff --git a/include/linux/fs.h b/include/linux/fs.h index c0dd2794e1ba..6bba7a58c95c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3135,6 +3135,8 @@ extern struct inode *new_inode(struct super_block *sb); extern void free_inode_nonrcu(struct inode *inode); extern int setattr_should_drop_suidgid(struct user_namespace *, struct inode *); extern int file_remove_privs(struct file *); +int setattr_should_drop_sgid(struct user_namespace *mnt_userns, + const struct inode *inode);
extern void __insert_inode_hash(struct inode *, unsigned long hashval); static inline void insert_inode_hash(struct inode *inode)
From: Christian Brauner brauner@kernel.org
commit 2d8ae8c417db284f598dffb178cc01e7db0f1821 upstream.
We've aligned setgid behavior over multiple kernel releases. The details can be found in commit cf619f891971 ("Merge tag 'fs.ovl.setgid.v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping") and commit 426b4ca2d6a5 ("Merge tag 'fs.setgid.v6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux"). Consistent setgid stripping behavior is now encapsulated in the setattr_should_drop_sgid() helper which is used by all filesystems that strip setgid bits outside of vfs proper. Usually ATTR_KILL_SGID is raised in e.g., chown_common() and is subject to the setattr_should_drop_sgid() check to determine whether the setgid bit can be retained. Since nfsd is raising ATTR_KILL_SGID unconditionally it will cause notify_change() to strip it even if the caller had the necessary privileges to retain it. Ensure that nfsd only raises ATR_KILL_SGID if the caller lacks the necessary privileges to retain the setgid bit.
Without this patch the setgid stripping tests in LTP will fail:
As you can see, the problem is S_ISGID (0002000) was dropped on a non-group-executable file while chown was invoked by super-user, while
[...]
fchown02.c:66: TFAIL: testfile2: wrong mode permissions 0100700, expected 0102700
[...]
chown02.c:57: TFAIL: testfile2: wrong mode permissions 0100700, expected 0102700
With this patch all tests pass.
Reported-by: Sherry Yang sherry.yang@oracle.com Signed-off-by: Christian Brauner brauner@kernel.org Reviewed-by: Jeff Layton jlayton@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Chuck Lever chuck.lever@oracle.com [Harshit: backport to 5.15.y: Use init_user_ns instead of nop_mnt_idmap as we don't have commit abf08576afe3 ("fs: port vfs_*() helpers to struct mnt_idmap")] Signed-off-by: Harshit Mogalapalli harshit.m.mogalapalli@oracle.com --- fs/nfsd/vfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d4adc599737d..15a86876e3d9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -322,7 +322,9 @@ nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) iap->ia_mode &= ~S_ISGID; } else { /* set ATTR_KILL_* bits and let VFS handle it */ - iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID); + iap->ia_valid |= ATTR_KILL_SUID; + iap->ia_valid |= + setattr_should_drop_sgid(&init_user_ns, inode); } } }
linux-stable-mirror@lists.linaro.org