--- /dev/null
+From 4f704d9a8352f5c0a8fcdb6213b934630342bd44 Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Tue, 14 Mar 2023 12:51:10 +0100
+Subject: nfs: use vfs setgid helper
+
+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]
+ 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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(-)
+
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -47,6 +47,7 @@ int setattr_should_drop_sgid(struct user
+ 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
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -235,5 +235,3 @@ int do_setxattr(struct user_namespace *m
+ /*
+ * fs/attr.c
+ */
+-int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
+- const struct inode *inode);
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -731,9 +731,7 @@ void nfs_setattr_update_inode(struct ino
+ 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;
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -3135,6 +3135,8 @@ extern struct inode *new_inode(struct su
+ 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)
--- /dev/null
+From 2d8ae8c417db284f598dffb178cc01e7db0f1821 Mon Sep 17 00:00:00 2001
+From: Christian Brauner <brauner@kernel.org>
+Date: Tue, 2 May 2023 15:36:02 +0200
+Subject: nfsd: use vfs setgid helper
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/vfs.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -322,7 +322,9 @@ nfsd_sanitize_attrs(struct inode *inode,
+ 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);
+ }
+ }
+ }