--- /dev/null
+From 8b129e70cf645e8e7f1a6a14e97db0068c8e6276 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:18 -0800
+Subject: attr: add in_group_or_capable()
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 11c2a8700cdcabf9b639b7204a1e38e2a0b6798e upstream.
+
+[backport to 5.15.y, prior to vfsgid_t]
+
+In setattr_{copy,prepare}() we need to perform the same permission
+checks to determine whether we need to drop the setgid bit or not.
+Instead of open-coding it twice add a simple helper the encapsulates the
+logic. We will reuse this helpers to make dropping the setgid bit during
+write operations more consistent in a follow up patch.
+
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/attr.c | 8 ++++----
+ fs/inode.c | 28 ++++++++++++++++++++++++----
+ fs/internal.h | 2 ++
+ 3 files changed, 30 insertions(+), 8 deletions(-)
+
+diff --git a/fs/attr.c b/fs/attr.c
+index f581c4d008971..686840aa91c8b 100644
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -18,6 +18,8 @@
+ #include <linux/evm.h>
+ #include <linux/ima.h>
+
++#include "internal.h"
++
+ /**
+ * chown_ok - verify permissions to chown inode
+ * @mnt_userns: user namespace of the mount @inode was found from
+@@ -141,8 +143,7 @@ int setattr_prepare(struct user_namespace *mnt_userns, struct dentry *dentry,
+ mapped_gid = i_gid_into_mnt(mnt_userns, inode);
+
+ /* Also check the setgid bit! */
+- if (!in_group_p(mapped_gid) &&
+- !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
++ if (!in_group_or_capable(mnt_userns, inode, mapped_gid))
+ attr->ia_mode &= ~S_ISGID;
+ }
+
+@@ -257,8 +258,7 @@ void setattr_copy(struct user_namespace *mnt_userns, struct inode *inode,
+ if (ia_valid & ATTR_MODE) {
+ umode_t mode = attr->ia_mode;
+ kgid_t kgid = i_gid_into_mnt(mnt_userns, inode);
+- if (!in_group_p(kgid) &&
+- !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
++ if (!in_group_or_capable(mnt_userns, inode, kgid))
+ mode &= ~S_ISGID;
+ inode->i_mode = mode;
+ }
+diff --git a/fs/inode.c b/fs/inode.c
+index 957b2d18ec29f..a71fb82279bb1 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -2321,6 +2321,28 @@ struct timespec64 current_time(struct inode *inode)
+ }
+ EXPORT_SYMBOL(current_time);
+
++/**
++ * in_group_or_capable - check whether caller is CAP_FSETID privileged
++ * @mnt_userns: user namespace of the mount @inode was found from
++ * @inode: inode to check
++ * @gid: the new/current gid of @inode
++ *
++ * Check wether @gid is in the caller's group list or if the caller is
++ * privileged with CAP_FSETID over @inode. This can be used to determine
++ * whether the setgid bit can be kept or must be dropped.
++ *
++ * Return: true if the caller is sufficiently privileged, false if not.
++ */
++bool in_group_or_capable(struct user_namespace *mnt_userns,
++ const struct inode *inode, kgid_t gid)
++{
++ if (in_group_p(gid))
++ return true;
++ if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
++ return true;
++ return false;
++}
++
+ /**
+ * mode_strip_sgid - handle the sgid bit for non-directories
+ * @mnt_userns: User namespace of the mount the inode was created from
+@@ -2342,11 +2364,9 @@ umode_t mode_strip_sgid(struct user_namespace *mnt_userns,
+ return mode;
+ if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID))
+ return mode;
+- if (in_group_p(i_gid_into_mnt(mnt_userns, dir)))
+- return mode;
+- if (capable_wrt_inode_uidgid(mnt_userns, dir, CAP_FSETID))
++ if (in_group_or_capable(mnt_userns, dir,
++ i_gid_into_mnt(mnt_userns, dir)))
+ return mode;
+-
+ return mode & ~S_ISGID;
+ }
+ EXPORT_SYMBOL(mode_strip_sgid);
+diff --git a/fs/internal.h b/fs/internal.h
+index 9075490f21a62..c898147272817 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -150,6 +150,8 @@ extern int vfs_open(const struct path *, struct file *);
+ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
+ extern void inode_add_lru(struct inode *inode);
+ extern int dentry_needs_remove_privs(struct dentry *dentry);
++bool in_group_or_capable(struct user_namespace *mnt_userns,
++ const struct inode *inode, kgid_t gid);
+
+ /*
+ * fs-writeback.c
+--
+2.39.2
+
--- /dev/null
+From fdba6071d3b7bd547ea334d8b9a69ccf07bfbfcd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:20 -0800
+Subject: attr: add setattr_should_drop_sgid()
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 72ae017c5451860443a16fb2a8c243bff3e396b8 upstream.
+
+[backport to 5.15.y, prior to vfsgid_t]
+
+The current setgid stripping logic during write and ownership change
+operations is inconsistent and strewn over multiple places. In order to
+consolidate it and make more consistent we'll add a new helper
+setattr_should_drop_sgid(). The function retains the old behavior where
+we remove the S_ISGID bit unconditionally when S_IXGRP is set but also
+when it isn't set and the caller is neither in the group of the inode
+nor privileged over the inode.
+
+We will use this helper both in write operation permission removal such
+as file_remove_privs() as well as in ownership change operations.
+
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/attr.c | 28 ++++++++++++++++++++++++++++
+ fs/internal.h | 6 ++++++
+ 2 files changed, 34 insertions(+)
+
+diff --git a/fs/attr.c b/fs/attr.c
+index f045431bab1ad..965be68ed8fa0 100644
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -20,6 +20,34 @@
+
+ #include "internal.h"
+
++/**
++ * setattr_should_drop_sgid - determine whether the setgid bit needs to be
++ * removed
++ * @mnt_userns: user namespace of the mount @inode was found from
++ * @inode: inode to check
++ *
++ * This function determines whether the setgid bit needs to be removed.
++ * We retain backwards compatibility and require setgid bit to be removed
++ * unconditionally if S_IXGRP is set. Otherwise we have the exact same
++ * requirements as setattr_prepare() and setattr_copy().
++ *
++ * Return: ATTR_KILL_SGID if setgid bit needs to be removed, 0 otherwise.
++ */
++int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
++ const struct inode *inode)
++{
++ umode_t mode = inode->i_mode;
++
++ if (!(mode & S_ISGID))
++ return 0;
++ if (mode & S_IXGRP)
++ return ATTR_KILL_SGID;
++ if (!in_group_or_capable(mnt_userns, inode,
++ i_gid_into_mnt(mnt_userns, inode)))
++ return ATTR_KILL_SGID;
++ return 0;
++}
++
+ /*
+ * The logic we want is
+ *
+diff --git a/fs/internal.h b/fs/internal.h
+index c898147272817..45cf31d7380b8 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -231,3 +231,9 @@ struct xattr_ctx {
+ int setxattr_copy(const char __user *name, struct xattr_ctx *ctx);
+ int do_setxattr(struct user_namespace *mnt_userns, struct dentry *dentry,
+ struct xattr_ctx *ctx);
++
++/*
++ * fs/attr.c
++ */
++int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
++ const struct inode *inode);
+--
+2.39.2
+
--- /dev/null
+From fb111ba84f9782fa9d00fe857c578321fdf60658 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:21 -0800
+Subject: attr: use consistent sgid stripping checks
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit ed5a7047d2011cb6b2bf84ceb6680124cc6a7d95 upstream.
+
+[backport to 5.15.y, prior to vfsgid_t]
+
+Currently setgid stripping in file_remove_privs()'s should_remove_suid()
+helper is inconsistent with other parts of the vfs. Specifically, it only
+raises ATTR_KILL_SGID if the inode is S_ISGID and S_IXGRP but not if the
+inode isn't in the caller's groups and the caller isn't privileged over the
+inode although we require this already in setattr_prepare() and
+setattr_copy() and so all filesystem implement this requirement implicitly
+because they have to use setattr_{prepare,copy}() anyway.
+
+But the inconsistency shows up in setgid stripping bugs for overlayfs in
+xfstests (e.g., generic/673, generic/683, generic/685, generic/686,
+generic/687). For example, we test whether suid and setgid stripping works
+correctly when performing various write-like operations as an unprivileged
+user (fallocate, reflink, write, etc.):
+
+echo "Test 1 - qa_user, non-exec file $verb"
+setup_testfile
+chmod a+rws $junk_file
+commit_and_check "$qa_user" "$verb" 64k 64k
+
+The test basically creates a file with 6666 permissions. While the file has
+the S_ISUID and S_ISGID bits set it does not have the S_IXGRP set. On a
+regular filesystem like xfs what will happen is:
+
+sys_fallocate()
+-> vfs_fallocate()
+ -> xfs_file_fallocate()
+ -> file_modified()
+ -> __file_remove_privs()
+ -> dentry_needs_remove_privs()
+ -> should_remove_suid()
+ -> __remove_privs()
+ newattrs.ia_valid = ATTR_FORCE | kill;
+ -> notify_change()
+ -> setattr_copy()
+
+In should_remove_suid() we can see that ATTR_KILL_SUID is raised
+unconditionally because the file in the test has S_ISUID set.
+
+But we also see that ATTR_KILL_SGID won't be set because while the file
+is S_ISGID it is not S_IXGRP (see above) which is a condition for
+ATTR_KILL_SGID being raised.
+
+So by the time we call notify_change() we have attr->ia_valid set to
+ATTR_KILL_SUID | ATTR_FORCE. Now notify_change() sees that
+ATTR_KILL_SUID is set and does:
+
+ia_valid = attr->ia_valid |= ATTR_MODE
+attr->ia_mode = (inode->i_mode & ~S_ISUID);
+
+which means that when we call setattr_copy() later we will definitely
+update inode->i_mode. Note that attr->ia_mode still contains S_ISGID.
+
+Now we call into the filesystem's ->setattr() inode operation which will
+end up calling setattr_copy(). Since ATTR_MODE is set we will hit:
+
+if (ia_valid & ATTR_MODE) {
+ umode_t mode = attr->ia_mode;
+ vfsgid_t vfsgid = i_gid_into_vfsgid(mnt_userns, inode);
+ if (!vfsgid_in_group_p(vfsgid) &&
+ !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
+ mode &= ~S_ISGID;
+ inode->i_mode = mode;
+}
+
+and since the caller in the test is neither capable nor in the group of the
+inode the S_ISGID bit is stripped.
+
+But assume the file isn't suid then ATTR_KILL_SUID won't be raised which
+has the consequence that neither the setgid nor the suid bits are stripped
+even though it should be stripped because the inode isn't in the caller's
+groups and the caller isn't privileged over the inode.
+
+If overlayfs is in the mix things become a bit more complicated and the bug
+shows up more clearly. When e.g., ovl_setattr() is hit from
+ovl_fallocate()'s call to file_remove_privs() then ATTR_KILL_SUID and
+ATTR_KILL_SGID might be raised but because the check in notify_change() is
+questioning the ATTR_KILL_SGID flag again by requiring S_IXGRP for it to be
+stripped the S_ISGID bit isn't removed even though it should be stripped:
+
+sys_fallocate()
+-> vfs_fallocate()
+ -> ovl_fallocate()
+ -> file_remove_privs()
+ -> dentry_needs_remove_privs()
+ -> should_remove_suid()
+ -> __remove_privs()
+ newattrs.ia_valid = ATTR_FORCE | kill;
+ -> notify_change()
+ -> ovl_setattr()
+ // TAKE ON MOUNTER'S CREDS
+ -> ovl_do_notify_change()
+ -> notify_change()
+ // GIVE UP MOUNTER'S CREDS
+ // TAKE ON MOUNTER'S CREDS
+ -> vfs_fallocate()
+ -> xfs_file_fallocate()
+ -> file_modified()
+ -> __file_remove_privs()
+ -> dentry_needs_remove_privs()
+ -> should_remove_suid()
+ -> __remove_privs()
+ newattrs.ia_valid = attr_force | kill;
+ -> notify_change()
+
+The fix for all of this is to make file_remove_privs()'s
+should_remove_suid() helper to perform the same checks as we already
+require in setattr_prepare() and setattr_copy() and have notify_change()
+not pointlessly requiring S_IXGRP again. It doesn't make any sense in the
+first place because the caller must calculate the flags via
+should_remove_suid() anyway which would raise ATTR_KILL_SGID.
+
+While we're at it we move should_remove_suid() from inode.c to attr.c
+where it belongs with the rest of the iattr helpers. Especially since it
+returns ATTR_KILL_S{G,U}ID flags. We also rename it to
+setattr_should_drop_suidgid() to better reflect that it indicates both
+setuid and setgid bit removal and also that it returns attr flags.
+
+Running xfstests with this doesn't report any regressions. We should really
+try and use consistent checks.
+
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/trace/ftrace.rst | 2 +-
+ fs/attr.c | 33 +++++++++++++++++++--------------
+ fs/fuse/file.c | 2 +-
+ fs/inode.c | 7 ++++---
+ fs/internal.h | 2 +-
+ fs/ocfs2/file.c | 4 ++--
+ fs/open.c | 8 ++++----
+ include/linux/fs.h | 2 +-
+ 8 files changed, 33 insertions(+), 27 deletions(-)
+
+diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
+index 4e5b26f03d5b1..d036946bce7ab 100644
+--- a/Documentation/trace/ftrace.rst
++++ b/Documentation/trace/ftrace.rst
+@@ -2929,7 +2929,7 @@ Produces::
+ bash-1994 [000] .... 4342.324898: ima_get_action <-process_measurement
+ bash-1994 [000] .... 4342.324898: ima_match_policy <-ima_get_action
+ bash-1994 [000] .... 4342.324899: do_truncate <-do_last
+- bash-1994 [000] .... 4342.324899: should_remove_suid <-do_truncate
++ bash-1994 [000] .... 4342.324899: setattr_should_drop_suidgid <-do_truncate
+ bash-1994 [000] .... 4342.324899: notify_change <-do_truncate
+ bash-1994 [000] .... 4342.324900: current_fs_time <-notify_change
+ bash-1994 [000] .... 4342.324900: current_kernel_time <-current_fs_time
+diff --git a/fs/attr.c b/fs/attr.c
+index 965be68ed8fa0..0ca14cbd4b8bb 100644
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -48,34 +48,39 @@ int setattr_should_drop_sgid(struct user_namespace *mnt_userns,
+ return 0;
+ }
+
+-/*
+- * The logic we want is
++/**
++ * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
++ * be dropped
++ * @mnt_userns: user namespace of the mount @inode was found from
++ * @inode: inode to check
+ *
+- * if suid or (sgid and xgrp)
+- * remove privs
++ * This function determines whether the set{g,u}id bits need to be removed.
++ * If the setuid bit needs to be removed ATTR_KILL_SUID is returned. If the
++ * setgid bit needs to be removed ATTR_KILL_SGID is returned. If both
++ * set{g,u}id bits need to be removed the corresponding mask of both flags is
++ * returned.
++ *
++ * Return: A mask of ATTR_KILL_S{G,U}ID indicating which - if any - setid bits
++ * to remove, 0 otherwise.
+ */
+-int should_remove_suid(struct dentry *dentry)
++int setattr_should_drop_suidgid(struct user_namespace *mnt_userns,
++ struct inode *inode)
+ {
+- umode_t mode = d_inode(dentry)->i_mode;
++ umode_t mode = inode->i_mode;
+ int kill = 0;
+
+ /* suid always must be killed */
+ if (unlikely(mode & S_ISUID))
+ kill = ATTR_KILL_SUID;
+
+- /*
+- * sgid without any exec bits is just a mandatory locking mark; leave
+- * it alone. If some exec bits are set, it's a real sgid; kill it.
+- */
+- if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
+- kill |= ATTR_KILL_SGID;
++ kill |= setattr_should_drop_sgid(mnt_userns, inode);
+
+ if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
+ return kill;
+
+ return 0;
+ }
+-EXPORT_SYMBOL(should_remove_suid);
++EXPORT_SYMBOL(setattr_should_drop_suidgid);
+
+ /**
+ * chown_ok - verify permissions to chown inode
+@@ -440,7 +445,7 @@ int notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
+ }
+ }
+ if (ia_valid & ATTR_KILL_SGID) {
+- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
++ if (mode & S_ISGID) {
+ if (!(ia_valid & ATTR_MODE)) {
+ ia_valid = attr->ia_valid |= ATTR_MODE;
+ attr->ia_mode = inode->i_mode;
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index cc95a1c376449..2b19d281351e5 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1295,7 +1295,7 @@ static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ return err;
+
+ if (fc->handle_killpriv_v2 &&
+- should_remove_suid(file_dentry(file))) {
++ setattr_should_drop_suidgid(&init_user_ns, file_inode(file))) {
+ goto writethrough;
+ }
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 3811269259e11..079b64f9b7561 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1869,7 +1869,8 @@ EXPORT_SYMBOL(touch_atime);
+ * response to write or truncate. Return 0 if nothing has to be changed.
+ * Negative value on error (change should be denied).
+ */
+-int dentry_needs_remove_privs(struct dentry *dentry)
++int dentry_needs_remove_privs(struct user_namespace *mnt_userns,
++ struct dentry *dentry)
+ {
+ struct inode *inode = d_inode(dentry);
+ int mask = 0;
+@@ -1878,7 +1879,7 @@ int dentry_needs_remove_privs(struct dentry *dentry)
+ if (IS_NOSEC(inode))
+ return 0;
+
+- mask = should_remove_suid(dentry);
++ mask = setattr_should_drop_suidgid(mnt_userns, inode);
+ ret = security_inode_need_killpriv(dentry);
+ if (ret < 0)
+ return ret;
+@@ -1920,7 +1921,7 @@ int file_remove_privs(struct file *file)
+ if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
+ return 0;
+
+- kill = dentry_needs_remove_privs(dentry);
++ kill = dentry_needs_remove_privs(file_mnt_user_ns(file), dentry);
+ if (kill < 0)
+ return kill;
+ if (kill)
+diff --git a/fs/internal.h b/fs/internal.h
+index 45cf31d7380b8..46df4ce58e87e 100644
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -149,7 +149,7 @@ extern int vfs_open(const struct path *, struct file *);
+ */
+ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
+ extern void inode_add_lru(struct inode *inode);
+-extern int dentry_needs_remove_privs(struct dentry *dentry);
++int dentry_needs_remove_privs(struct user_namespace *, struct dentry *dentry);
+ bool in_group_or_capable(struct user_namespace *mnt_userns,
+ const struct inode *inode, kgid_t gid);
+
+diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
+index fc5f780fa2355..92182d4be247e 100644
+--- a/fs/ocfs2/file.c
++++ b/fs/ocfs2/file.c
+@@ -1994,7 +1994,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
+ }
+ }
+
+- if (file && should_remove_suid(file->f_path.dentry)) {
++ if (file && setattr_should_drop_suidgid(&init_user_ns, file_inode(file))) {
+ ret = __ocfs2_write_remove_suid(inode, di_bh);
+ if (ret) {
+ mlog_errno(ret);
+@@ -2282,7 +2282,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
+ * inode. There's also the dinode i_size state which
+ * can be lost via setattr during extending writes (we
+ * set inode->i_size at the end of a write. */
+- if (should_remove_suid(dentry)) {
++ if (setattr_should_drop_suidgid(&init_user_ns, inode)) {
+ if (meta_level == 0) {
+ ocfs2_inode_unlock_for_extent_tree(inode,
+ &di_bh,
+diff --git a/fs/open.c b/fs/open.c
+index 5e322f188e839..e93c33069055b 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -54,7 +54,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
+ }
+
+ /* Remove suid, sgid, and file capabilities on truncate too */
+- ret = dentry_needs_remove_privs(dentry);
++ ret = dentry_needs_remove_privs(mnt_userns, dentry);
+ if (ret < 0)
+ return ret;
+ if (ret)
+@@ -671,10 +671,10 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
+ newattrs.ia_valid |= ATTR_GID;
+ newattrs.ia_gid = gid;
+ }
+- if (!S_ISDIR(inode->i_mode))
+- newattrs.ia_valid |=
+- ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
+ inode_lock(inode);
++ if (!S_ISDIR(inode->i_mode))
++ newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
++ setattr_should_drop_sgid(mnt_userns, inode);
+ error = security_path_chown(path, uid, gid);
+ if (!error)
+ error = notify_change(mnt_userns, path->dentry, &newattrs,
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index be9be4a7216c7..9601c2d774c88 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -3133,7 +3133,7 @@ extern void __destroy_inode(struct inode *);
+ extern struct inode *new_inode_pseudo(struct super_block *sb);
+ extern struct inode *new_inode(struct super_block *sb);
+ extern void free_inode_nonrcu(struct inode *inode);
+-extern int should_remove_suid(struct dentry *);
++extern int setattr_should_drop_suidgid(struct user_namespace *, struct inode *);
+ extern int file_remove_privs(struct file *);
+
+ extern void __insert_inode_hash(struct inode *, unsigned long hashval);
+--
+2.39.2
+
--- /dev/null
+From 80a4bd6121353782815eb919865483ed4a7a414f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:16 -0800
+Subject: fs: add mode_strip_sgid() helper
+
+From: Yang Xu <xuyang2018.jy@fujitsu.com>
+
+commit 2b3416ceff5e6bd4922f6d1c61fb68113dd82302 upsream.
+
+Add a dedicated helper to handle the setgid bit when creating a new file
+in a setgid directory. This is a preparatory patch for moving setgid
+stripping into the vfs. The patch contains no functional changes.
+
+Currently the setgid stripping logic is open-coded directly in
+inode_init_owner() and the individual filesystems are responsible for
+handling setgid inheritance. Since this has proven to be brittle as
+evidenced by old issues we uncovered over the last months (see [1] to
+[3] below) we will try to move this logic into the vfs.
+
+Link: e014f37db1a2 ("xfs: use setattr_copy to set vfs inode attributes") [1]
+Link: 01ea173e103e ("xfs: fix up non-directory creation in SGID directories") [2]
+Link: fd84bfdddd16 ("ceph: fix up non-directory creation in SGID directories") [3]
+Link: https://lore.kernel.org/r/1657779088-2242-1-git-send-email-xuyang2018.jy@fujitsu.com
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Reviewed-and-Tested-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/inode.c | 36 ++++++++++++++++++++++++++++++++----
+ include/linux/fs.h | 2 ++
+ 2 files changed, 34 insertions(+), 4 deletions(-)
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 8279c700a2b7f..3740102c9bd5e 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -2165,10 +2165,8 @@ void inode_init_owner(struct user_namespace *mnt_userns, struct inode *inode,
+ /* Directories are special, and always inherit S_ISGID */
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+- else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) &&
+- !in_group_p(i_gid_into_mnt(mnt_userns, dir)) &&
+- !capable_wrt_inode_uidgid(mnt_userns, dir, CAP_FSETID))
+- mode &= ~S_ISGID;
++ else
++ mode = mode_strip_sgid(mnt_userns, dir, mode);
+ } else
+ inode_fsgid_set(inode, mnt_userns);
+ inode->i_mode = mode;
+@@ -2324,3 +2322,33 @@ struct timespec64 current_time(struct inode *inode)
+ return timestamp_truncate(now, inode);
+ }
+ EXPORT_SYMBOL(current_time);
++
++/**
++ * mode_strip_sgid - handle the sgid bit for non-directories
++ * @mnt_userns: User namespace of the mount the inode was created from
++ * @dir: parent directory inode
++ * @mode: mode of the file to be created in @dir
++ *
++ * If the @mode of the new file has both the S_ISGID and S_IXGRP bit
++ * raised and @dir has the S_ISGID bit raised ensure that the caller is
++ * either in the group of the parent directory or they have CAP_FSETID
++ * in their user namespace and are privileged over the parent directory.
++ * In all other cases, strip the S_ISGID bit from @mode.
++ *
++ * Return: the new mode to use for the file
++ */
++umode_t mode_strip_sgid(struct user_namespace *mnt_userns,
++ const struct inode *dir, umode_t mode)
++{
++ if ((mode & (S_ISGID | S_IXGRP)) != (S_ISGID | S_IXGRP))
++ return mode;
++ if (S_ISDIR(mode) || !dir || !(dir->i_mode & S_ISGID))
++ return mode;
++ if (in_group_p(i_gid_into_mnt(mnt_userns, dir)))
++ return mode;
++ if (capable_wrt_inode_uidgid(mnt_userns, dir, CAP_FSETID))
++ return mode;
++
++ return mode & ~S_ISGID;
++}
++EXPORT_SYMBOL(mode_strip_sgid);
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 1e1ac116dd136..be9be4a7216c7 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1941,6 +1941,8 @@ extern long compat_ptr_ioctl(struct file *file, unsigned int cmd,
+ void inode_init_owner(struct user_namespace *mnt_userns, struct inode *inode,
+ const struct inode *dir, umode_t mode);
+ extern bool may_open_dev(const struct path *path);
++umode_t mode_strip_sgid(struct user_namespace *mnt_userns,
++ const struct inode *dir, umode_t mode);
+
+ /*
+ * This is the "filldir" function type, used by readdir() to let
+--
+2.39.2
+
--- /dev/null
+From 1f0af87a30c99969ad586ca55ba5c4c2b00f0dfb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:17 -0800
+Subject: fs: move S_ISGID stripping into the vfs_*() helpers
+
+From: Yang Xu <xuyang2018.jy@fujitsu.com>
+
+commit 1639a49ccdce58ea248841ed9b23babcce6dbb0b upsream.
+
+Move setgid handling out of individual filesystems and into the VFS
+itself to stop the proliferation of setgid inheritance bugs.
+
+Creating files that have both the S_IXGRP and S_ISGID bit raised in
+directories that themselves have the S_ISGID bit set requires additional
+privileges to avoid security issues.
+
+When a filesystem creates a new inode it needs to take care that the
+caller is either in the group of the newly created inode or they have
+CAP_FSETID in their current user namespace and are privileged over the
+parent directory of the new inode. If any of these two conditions is
+true then the S_ISGID bit can be raised for an S_IXGRP file and if not
+it needs to be stripped.
+
+However, there are several key issues with the current implementation:
+
+* S_ISGID stripping logic is entangled with umask stripping.
+
+ If a filesystem doesn't support or enable POSIX ACLs then umask
+ stripping is done directly in the vfs before calling into the
+ filesystem.
+ If the filesystem does support POSIX ACLs then unmask stripping may be
+ done in the filesystem itself when calling posix_acl_create().
+
+ Since umask stripping has an effect on S_ISGID inheritance, e.g., by
+ stripping the S_IXGRP bit from the file to be created and all relevant
+ filesystems have to call posix_acl_create() before inode_init_owner()
+ where we currently take care of S_ISGID handling S_ISGID handling is
+ order dependent. IOW, whether or not you get a setgid bit depends on
+ POSIX ACLs and umask and in what order they are called.
+
+ Note that technically filesystems are free to impose their own
+ ordering between posix_acl_create() and inode_init_owner() meaning
+ that there's additional ordering issues that influence S_SIGID
+ inheritance.
+
+* Filesystems that don't rely on inode_init_owner() don't get S_ISGID
+ stripping logic.
+
+ While that may be intentional (e.g. network filesystems might just
+ defer setgid stripping to a server) it is often just a security issue.
+
+This is not just ugly it's unsustainably messy especially since we do
+still have bugs in this area years after the initial round of setgid
+bugfixes.
+
+So the current state is quite messy and while we won't be able to make
+it completely clean as posix_acl_create() is still a filesystem specific
+call we can improve the S_SIGD stripping situation quite a bit by
+hoisting it out of inode_init_owner() and into the vfs creation
+operations. This means we alleviate the burden for filesystems to handle
+S_ISGID stripping correctly and can standardize the ordering between
+S_ISGID and umask stripping in the vfs.
+
+We add a new helper vfs_prepare_mode() so S_ISGID handling is now done
+in the VFS before umask handling. This has S_ISGID handling is
+unaffected unaffected by whether umask stripping is done by the VFS
+itself (if no POSIX ACLs are supported or enabled) or in the filesystem
+in posix_acl_create() (if POSIX ACLs are supported).
+
+The vfs_prepare_mode() helper is called directly in vfs_*() helpers that
+create new filesystem objects. We need to move them into there to make
+sure that filesystems like overlayfs hat have callchains like:
+
+sys_mknod()
+-> do_mknodat(mode)
+ -> .mknod = ovl_mknod(mode)
+ -> ovl_create(mode)
+ -> vfs_mknod(mode)
+
+get S_ISGID stripping done when calling into lower filesystems via
+vfs_*() creation helpers. Moving vfs_prepare_mode() into e.g.
+vfs_mknod() takes care of that. This is in any case semantically cleaner
+because S_ISGID stripping is VFS security requirement.
+
+Security hooks so far have seen the mode with the umask applied but
+without S_ISGID handling done. The relevant hooks are called outside of
+vfs_*() creation helpers so by calling vfs_prepare_mode() from vfs_*()
+helpers the security hooks would now see the mode without umask
+stripping applied. For now we fix this by passing the mode with umask
+settings applied to not risk any regressions for LSM hooks. IOW, nothing
+changes for LSM hooks. It is worth pointing out that security hooks
+never saw the mode that is seen by the filesystem when actually creating
+the file. They have always been completely misplaced for that to work.
+
+The following filesystems use inode_init_owner() and thus relied on
+S_ISGID stripping: spufs, 9p, bfs, btrfs, ext2, ext4, f2fs, hfsplus,
+hugetlbfs, jfs, minix, nilfs2, ntfs3, ocfs2, omfs, overlayfs, ramfs,
+reiserfs, sysv, ubifs, udf, ufs, xfs, zonefs, bpf, tmpfs.
+
+All of the above filesystems end up calling inode_init_owner() when new
+filesystem objects are created through the ->mkdir(), ->mknod(),
+->create(), ->tmpfile(), ->rename() inode operations.
+
+Since directories always inherit the S_ISGID bit with the exception of
+xfs when irix_sgid_inherit mode is turned on S_ISGID stripping doesn't
+apply. The ->symlink() and ->link() inode operations trivially inherit
+the mode from the target and the ->rename() inode operation inherits the
+mode from the source inode. All other creation inode operations will get
+S_ISGID handling via vfs_prepare_mode() when called from their relevant
+vfs_*() helpers.
+
+In addition to this there are filesystems which allow the creation of
+filesystem objects through ioctl()s or - in the case of spufs -
+circumventing the vfs in other ways. If filesystem objects are created
+through ioctl()s the vfs doesn't know about it and can't apply regular
+permission checking including S_ISGID logic. Therfore, a filesystem
+relying on S_ISGID stripping in inode_init_owner() in their ioctl()
+callpath will be affected by moving this logic into the vfs. We audited
+those filesystems:
+
+* btrfs allows the creation of filesystem objects through various
+ ioctls(). Snapshot creation literally takes a snapshot and so the mode
+ is fully preserved and S_ISGID stripping doesn't apply.
+
+ Creating a new subvolum relies on inode_init_owner() in
+ btrfs_new_subvol_inode() but only creates directories and doesn't
+ raise S_ISGID.
+
+* ocfs2 has a peculiar implementation of reflinks. In contrast to e.g.
+ xfs and btrfs FICLONE/FICLONERANGE ioctl() that is only concerned with
+ the actual extents ocfs2 uses a separate ioctl() that also creates the
+ target file.
+
+ Iow, ocfs2 circumvents the vfs entirely here and did indeed rely on
+ inode_init_owner() to strip the S_ISGID bit. This is the only place
+ where a filesystem needs to call mode_strip_sgid() directly but this
+ is self-inflicted pain.
+
+* spufs doesn't go through the vfs at all and doesn't use ioctl()s
+ either. Instead it has a dedicated system call spufs_create() which
+ allows the creation of filesystem objects. But spufs only creates
+ directories and doesn't allo S_SIGID bits, i.e. it specifically only
+ allows 0777 bits.
+
+* bpf uses vfs_mkobj() but also doesn't allow S_ISGID bits to be created.
+
+The patch will have an effect on ext2 when the EXT2_MOUNT_GRPID mount
+option is used, on ext4 when the EXT4_MOUNT_GRPID mount option is used,
+and on xfs when the XFS_FEAT_GRPID mount option is used. When any of
+these filesystems are mounted with their respective GRPID option then
+newly created files inherit the parent directories group
+unconditionally. In these cases non of the filesystems call
+inode_init_owner() and thus did never strip the S_ISGID bit for newly
+created files. Moving this logic into the VFS means that they now get
+the S_ISGID bit stripped. This is a user visible change. If this leads
+to regressions we will either need to figure out a better way or we need
+to revert. However, given the various setgid bugs that we found just in
+the last two years this is a regression risk we should take.
+
+Associated with this change is a new set of fstests to enforce the
+semantics for all new filesystems.
+
+Link: https://lore.kernel.org/ceph-devel/20220427092201.wvsdjbnc7b4dttaw@wittgenstein [1]
+Link: e014f37db1a2 ("xfs: use setattr_copy to set vfs inode attributes") [2]
+Link: 01ea173e103e ("xfs: fix up non-directory creation in SGID directories") [3]
+Link: fd84bfdddd16 ("ceph: fix up non-directory creation in SGID directories") [4]
+Link: https://lore.kernel.org/r/1657779088-2242-3-git-send-email-xuyang2018.jy@fujitsu.com
+Suggested-by: Dave Chinner <david@fromorbit.com>
+Suggested-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-and-Tested-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
+[<brauner@kernel.org>: rewrote commit message]
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/inode.c | 2 --
+ fs/namei.c | 82 ++++++++++++++++++++++++++++++++++++++++--------
+ fs/ocfs2/namei.c | 1 +
+ 3 files changed, 70 insertions(+), 15 deletions(-)
+
+diff --git a/fs/inode.c b/fs/inode.c
+index 3740102c9bd5e..957b2d18ec29f 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -2165,8 +2165,6 @@ void inode_init_owner(struct user_namespace *mnt_userns, struct inode *inode,
+ /* Directories are special, and always inherit S_ISGID */
+ if (S_ISDIR(mode))
+ mode |= S_ISGID;
+- else
+- mode = mode_strip_sgid(mnt_userns, dir, mode);
+ } else
+ inode_fsgid_set(inode, mnt_userns);
+ inode->i_mode = mode;
+diff --git a/fs/namei.c b/fs/namei.c
+index 81b31d9a063f2..02e99606c65be 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -3000,6 +3000,65 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
+ }
+ EXPORT_SYMBOL(unlock_rename);
+
++/**
++ * mode_strip_umask - handle vfs umask stripping
++ * @dir: parent directory of the new inode
++ * @mode: mode of the new inode to be created in @dir
++ *
++ * Umask stripping depends on whether or not the filesystem supports POSIX
++ * ACLs. If the filesystem doesn't support it umask stripping is done directly
++ * in here. If the filesystem does support POSIX ACLs umask stripping is
++ * deferred until the filesystem calls posix_acl_create().
++ *
++ * Returns: mode
++ */
++static inline umode_t mode_strip_umask(const struct inode *dir, umode_t mode)
++{
++ if (!IS_POSIXACL(dir))
++ mode &= ~current_umask();
++ return mode;
++}
++
++/**
++ * vfs_prepare_mode - prepare the mode to be used for a new inode
++ * @mnt_userns: user namespace of the mount the inode was found from
++ * @dir: parent directory of the new inode
++ * @mode: mode of the new inode
++ * @mask_perms: allowed permission by the vfs
++ * @type: type of file to be created
++ *
++ * This helper consolidates and enforces vfs restrictions on the @mode of a new
++ * object to be created.
++ *
++ * Umask stripping depends on whether the filesystem supports POSIX ACLs (see
++ * the kernel documentation for mode_strip_umask()). Moving umask stripping
++ * after setgid stripping allows the same ordering for both non-POSIX ACL and
++ * POSIX ACL supporting filesystems.
++ *
++ * Note that it's currently valid for @type to be 0 if a directory is created.
++ * Filesystems raise that flag individually and we need to check whether each
++ * filesystem can deal with receiving S_IFDIR from the vfs before we enforce a
++ * non-zero type.
++ *
++ * Returns: mode to be passed to the filesystem
++ */
++static inline umode_t vfs_prepare_mode(struct user_namespace *mnt_userns,
++ const struct inode *dir, umode_t mode,
++ umode_t mask_perms, umode_t type)
++{
++ mode = mode_strip_sgid(mnt_userns, dir, mode);
++ mode = mode_strip_umask(dir, mode);
++
++ /*
++ * Apply the vfs mandated allowed permission mask and set the type of
++ * file to be created before we call into the filesystem.
++ */
++ mode &= (mask_perms & ~S_IFMT);
++ mode |= (type & S_IFMT);
++
++ return mode;
++}
++
+ /**
+ * vfs_create - create new file
+ * @mnt_userns: user namespace of the mount the inode was found from
+@@ -3025,8 +3084,8 @@ int vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
+
+ if (!dir->i_op->create)
+ return -EACCES; /* shouldn't it be ENOSYS? */
+- mode &= S_IALLUGO;
+- mode |= S_IFREG;
++
++ mode = vfs_prepare_mode(mnt_userns, dir, mode, S_IALLUGO, S_IFREG);
+ error = security_inode_create(dir, dentry, mode);
+ if (error)
+ return error;
+@@ -3291,8 +3350,7 @@ static struct dentry *lookup_open(struct nameidata *nd, struct file *file,
+ if (open_flag & O_CREAT) {
+ if (open_flag & O_EXCL)
+ open_flag &= ~O_TRUNC;
+- if (!IS_POSIXACL(dir->d_inode))
+- mode &= ~current_umask();
++ mode = vfs_prepare_mode(mnt_userns, dir->d_inode, mode, mode, mode);
+ if (likely(got_write))
+ create_error = may_o_create(mnt_userns, &nd->path,
+ dentry, mode);
+@@ -3525,8 +3583,7 @@ struct dentry *vfs_tmpfile(struct user_namespace *mnt_userns,
+ child = d_alloc(dentry, &slash_name);
+ if (unlikely(!child))
+ goto out_err;
+- if (!IS_POSIXACL(dir))
+- mode &= ~current_umask();
++ mode = vfs_prepare_mode(mnt_userns, dir, mode, mode, mode);
+ error = dir->i_op->tmpfile(mnt_userns, dir, child, mode);
+ if (error)
+ goto out_err;
+@@ -3804,6 +3861,7 @@ int vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
+ if (!dir->i_op->mknod)
+ return -EPERM;
+
++ mode = vfs_prepare_mode(mnt_userns, dir, mode, mode, mode);
+ error = devcgroup_inode_mknod(mode, dev);
+ if (error)
+ return error;
+@@ -3854,9 +3912,8 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
+ if (IS_ERR(dentry))
+ goto out1;
+
+- if (!IS_POSIXACL(path.dentry->d_inode))
+- mode &= ~current_umask();
+- error = security_path_mknod(&path, dentry, mode, dev);
++ error = security_path_mknod(&path, dentry,
++ mode_strip_umask(path.dentry->d_inode, mode), dev);
+ if (error)
+ goto out2;
+
+@@ -3926,7 +3983,7 @@ int vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
+ if (!dir->i_op->mkdir)
+ return -EPERM;
+
+- mode &= (S_IRWXUGO|S_ISVTX);
++ mode = vfs_prepare_mode(mnt_userns, dir, mode, S_IRWXUGO | S_ISVTX, 0);
+ error = security_inode_mkdir(dir, dentry, mode);
+ if (error)
+ return error;
+@@ -3954,9 +4011,8 @@ int do_mkdirat(int dfd, struct filename *name, umode_t mode)
+ if (IS_ERR(dentry))
+ goto out_putname;
+
+- if (!IS_POSIXACL(path.dentry->d_inode))
+- mode &= ~current_umask();
+- error = security_path_mkdir(&path, dentry, mode);
++ error = security_path_mkdir(&path, dentry,
++ mode_strip_umask(path.dentry->d_inode, mode));
+ if (!error) {
+ struct user_namespace *mnt_userns;
+ mnt_userns = mnt_user_ns(path.mnt);
+diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
+index 11807034dd483..5b8237ceb8cce 100644
+--- a/fs/ocfs2/namei.c
++++ b/fs/ocfs2/namei.c
+@@ -197,6 +197,7 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode)
+ * callers. */
+ if (S_ISDIR(mode))
+ set_nlink(inode, 2);
++ mode = mode_strip_sgid(&init_user_ns, dir, mode);
+ inode_init_owner(&init_user_ns, inode, dir, mode);
+ status = dquot_initialize(inode);
+ if (status)
+--
+2.39.2
+
--- /dev/null
+From 848d854458122c791de5912b9de0f621badb04bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:19 -0800
+Subject: fs: move should_remove_suid()
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit e243e3f94c804ecca9a8241b5babe28f35258ef4 upstream.
+
+Move the helper from inode.c to attr.c. This keeps the the core of the
+set{g,u}id stripping logic in one place when we add follow-up changes.
+It is the better place anyway, since should_remove_suid() returns
+ATTR_KILL_S{G,U}ID flags.
+
+Reviewed-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/attr.c | 29 +++++++++++++++++++++++++++++
+ fs/inode.c | 29 -----------------------------
+ 2 files changed, 29 insertions(+), 29 deletions(-)
+
+diff --git a/fs/attr.c b/fs/attr.c
+index 686840aa91c8b..f045431bab1ad 100644
+--- a/fs/attr.c
++++ b/fs/attr.c
+@@ -20,6 +20,35 @@
+
+ #include "internal.h"
+
++/*
++ * The logic we want is
++ *
++ * if suid or (sgid and xgrp)
++ * remove privs
++ */
++int should_remove_suid(struct dentry *dentry)
++{
++ umode_t mode = d_inode(dentry)->i_mode;
++ int kill = 0;
++
++ /* suid always must be killed */
++ if (unlikely(mode & S_ISUID))
++ kill = ATTR_KILL_SUID;
++
++ /*
++ * sgid without any exec bits is just a mandatory locking mark; leave
++ * it alone. If some exec bits are set, it's a real sgid; kill it.
++ */
++ if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
++ kill |= ATTR_KILL_SGID;
++
++ if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
++ return kill;
++
++ return 0;
++}
++EXPORT_SYMBOL(should_remove_suid);
++
+ /**
+ * chown_ok - verify permissions to chown inode
+ * @mnt_userns: user namespace of the mount @inode was found from
+diff --git a/fs/inode.c b/fs/inode.c
+index a71fb82279bb1..3811269259e11 100644
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1864,35 +1864,6 @@ void touch_atime(const struct path *path)
+ }
+ EXPORT_SYMBOL(touch_atime);
+
+-/*
+- * The logic we want is
+- *
+- * if suid or (sgid and xgrp)
+- * remove privs
+- */
+-int should_remove_suid(struct dentry *dentry)
+-{
+- umode_t mode = d_inode(dentry)->i_mode;
+- int kill = 0;
+-
+- /* suid always must be killed */
+- if (unlikely(mode & S_ISUID))
+- kill = ATTR_KILL_SUID;
+-
+- /*
+- * sgid without any exec bits is just a mandatory locking mark; leave
+- * it alone. If some exec bits are set, it's a real sgid; kill it.
+- */
+- if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
+- kill |= ATTR_KILL_SGID;
+-
+- if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
+- return kill;
+-
+- return 0;
+-}
+-EXPORT_SYMBOL(should_remove_suid);
+-
+ /*
+ * Return mask of changes for notify_change() that need to be done as a
+ * response to write or truncate. Return 0 if nothing has to be changed.
+--
+2.39.2
+
--- /dev/null
+From 3a27dd1a0eb7c05d001d126d952f5075d5cb3cfc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:22 -0800
+Subject: fs: use consistent setgid checks in is_sxid()
+
+From: Christian Brauner <brauner@kernel.org>
+
+commit 8d84e39d76bd83474b26cb44f4b338635676e7e8 upstream.
+
+Now that we made the VFS setgid checking consistent an inode can't be
+marked security irrelevant even if the setgid bit is still set. Make
+this function consistent with all other helpers.
+
+Note that enforcing consistent setgid stripping checks for file
+modification and mode- and ownership changes will cause the setgid bit
+to be lost in more cases than useed to be the case. If an unprivileged
+user wrote to a non-executable setgid file that they don't have
+privilege over the setgid bit will be dropped. This will lead to
+temporary failures in some xfstests until they have been updated.
+
+Reported-by: Miklos Szeredi <miklos@szeredi.hu>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/fs.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 9601c2d774c88..23ecfecdc4504 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -3571,7 +3571,7 @@ int __init list_bdev_fs_names(char *buf, size_t size);
+
+ static inline bool is_sxid(umode_t mode)
+ {
+- return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP));
++ return mode & (S_ISUID | S_ISGID);
+ }
+
+ static inline int check_sticky(struct user_namespace *mnt_userns,
+--
+2.39.2
+
--- /dev/null
+From f95bbac94d96e3d7999c616778397948e788d500 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 2 Feb 2023 08:26:56 +0000
+Subject: iommu/amd: Add a length limitation for the ivrs_acpihid command-line
+ parameter
+
+From: Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
+
+[ Upstream commit b6b26d86c61c441144c72f842f7469bb686e1211 ]
+
+The 'acpiid' buffer in the parse_ivrs_acpihid function may overflow,
+because the string specifier in the format string sscanf()
+has no width limitation.
+
+Found by InfoTeCS on behalf of Linux Verification Center
+(linuxtesting.org) with SVACE.
+
+Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ilia.Gavrilov <Ilia.Gavrilov@infotecs.ru>
+Reviewed-by: Kim Phillips <kim.phillips@amd.com>
+Link: https://lore.kernel.org/r/20230202082719.1513849-1-Ilia.Gavrilov@infotecs.ru
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/amd/init.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index 6c11db3356f78..50ea582be5910 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -3224,15 +3224,26 @@ static int __init parse_ivrs_hpet(char *str)
+ return 1;
+ }
+
++#define ACPIID_LEN (ACPIHID_UID_LEN + ACPIHID_HID_LEN)
++
+ static int __init parse_ivrs_acpihid(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+ char *hid, *uid, *p, *addr;
+- char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
++ char acpiid[ACPIID_LEN] = {0};
+ int i;
+
+ addr = strchr(str, '@');
+ if (!addr) {
++ addr = strchr(str, '=');
++ if (!addr)
++ goto not_found;
++
++ ++addr;
++
++ if (strlen(addr) > ACPIID_LEN)
++ goto not_found;
++
+ if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 ||
+ sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) {
+ pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
+@@ -3245,6 +3256,9 @@ static int __init parse_ivrs_acpihid(char *str)
+ /* We have the '@', make it the terminator to get just the acpiid */
+ *addr++ = 0;
+
++ if (strlen(str) > ACPIID_LEN + 1)
++ goto not_found;
++
+ if (sscanf(str, "=%s", acpiid) != 1)
+ goto not_found;
+
+--
+2.39.2
+
--- /dev/null
+From 3c18ee515ee86665867f0292e4e06c1541c257cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Jul 2022 17:08:22 +0530
+Subject: iommu/amd: Add PCI segment support for ivrs_[ioapic/hpet/acpihid]
+ commands
+
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+
+[ Upstream commit bbe3a106580c21bc883fb0c9fa3da01534392fe8 ]
+
+By default, PCI segment is zero and can be omitted. To support system
+with non-zero PCI segment ID, modify the parsing functions to allow
+PCI segment ID.
+
+Co-developed-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Link: https://lore.kernel.org/r/20220706113825.25582-33-vasant.hegde@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: b6b26d86c61c ("iommu/amd: Add a length limitation for the ivrs_acpihid command-line parameter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt | 34 ++++++++++----
+ drivers/iommu/amd/init.c | 44 ++++++++++++-------
+ 2 files changed, 52 insertions(+), 26 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index bcb102c91b190..d49437b9a6980 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2200,23 +2200,39 @@
+
+ ivrs_ioapic [HW,X86-64]
+ Provide an override to the IOAPIC-ID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map IOAPIC-ID decimal 10 to
+- PCI device 00:14.0 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
++ For example:
++ * To map IOAPIC-ID decimal 10 to PCI device 00:14.0
++ write the parameter as:
+ ivrs_ioapic[10]=00:14.0
++ * To map IOAPIC-ID decimal 10 to PCI segment 0x1 and
++ PCI device 00:14.0 write the parameter as:
++ ivrs_ioapic[10]=0001:00:14.0
+
+ ivrs_hpet [HW,X86-64]
+ Provide an override to the HPET-ID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map HPET-ID decimal 0 to
+- PCI device 00:14.0 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
++ For example:
++ * To map HPET-ID decimal 0 to PCI device 00:14.0
++ write the parameter as:
+ ivrs_hpet[0]=00:14.0
++ * To map HPET-ID decimal 10 to PCI segment 0x1 and
++ PCI device 00:14.0 write the parameter as:
++ ivrs_ioapic[10]=0001:00:14.0
+
+ ivrs_acpihid [HW,X86-64]
+ Provide an override to the ACPI-HID:UID<->DEVICE-ID
+- mapping provided in the IVRS ACPI table. For
+- example, to map UART-HID:UID AMD0020:0 to
+- PCI device 00:14.5 write the parameter as:
++ mapping provided in the IVRS ACPI table.
++
++ For example, to map UART-HID:UID AMD0020:0 to
++ PCI segment 0x1 and PCI device ID 00:14.5,
++ write the parameter as:
++ ivrs_acpihid[0001:00:14.5]=AMD0020:0
++
++ By default, PCI segment is 0, and can be omitted.
++ For example, PCI device 00:14.5 write the parameter as:
+ ivrs_acpihid[00:14.5]=AMD0020:0
+
+ js= [HW,JOY] Analog joystick
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index ce91a6d8532f3..6961fe80e8eea 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -85,6 +85,10 @@
+ #define ACPI_DEVFLAG_ATSDIS 0x10000000
+
+ #define LOOP_TIMEOUT 2000000
++
++#define IVRS_GET_SBDF_ID(seg, bus, dev, fd) (((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \
++ | ((dev & 0x1f) << 3) | (fn & 0x7))
++
+ /*
+ * ACPI table definitions
+ *
+@@ -3146,15 +3150,17 @@ static int __init parse_amd_iommu_options(char *str)
+
+ static int __init parse_ivrs_ioapic(char *str)
+ {
+- unsigned int bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ int ret, id, i;
+- u16 devid;
++ u32 devid;
+
+ ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+-
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_ioapic%s\n", str);
+- return 1;
++ ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_ioapic%s\n", str);
++ return 1;
++ }
+ }
+
+ if (early_ioapic_map_size == EARLY_MAP_SIZE) {
+@@ -3163,7 +3169,7 @@ static int __init parse_ivrs_ioapic(char *str)
+ return 1;
+ }
+
+- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+
+ cmdline_maps = true;
+ i = early_ioapic_map_size++;
+@@ -3176,15 +3182,17 @@ static int __init parse_ivrs_ioapic(char *str)
+
+ static int __init parse_ivrs_hpet(char *str)
+ {
+- unsigned int bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ int ret, id, i;
+- u16 devid;
++ u32 devid;
+
+ ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+-
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_hpet%s\n", str);
+- return 1;
++ ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_hpet%s\n", str);
++ return 1;
++ }
+ }
+
+ if (early_hpet_map_size == EARLY_MAP_SIZE) {
+@@ -3193,7 +3201,7 @@ static int __init parse_ivrs_hpet(char *str)
+ return 1;
+ }
+
+- devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+
+ cmdline_maps = true;
+ i = early_hpet_map_size++;
+@@ -3206,15 +3214,18 @@ static int __init parse_ivrs_hpet(char *str)
+
+ static int __init parse_ivrs_acpihid(char *str)
+ {
+- u32 bus, dev, fn;
++ u32 seg = 0, bus, dev, fn;
+ char *hid, *uid, *p;
+ char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
+ int ret, i;
+
+ ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
+ if (ret != 4) {
+- pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
+- return 1;
++ ret = sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid);
++ if (ret != 5) {
++ pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
++ return 1;
++ }
+ }
+
+ p = acpiid;
+@@ -3236,8 +3247,7 @@ static int __init parse_ivrs_acpihid(char *str)
+ i = early_acpihid_map_size++;
+ memcpy(early_acpihid_map[i].hid, hid, strlen(hid));
+ memcpy(early_acpihid_map[i].uid, uid, strlen(uid));
+- early_acpihid_map[i].devid =
+- ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
++ early_acpihid_map[i].devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
+ early_acpihid_map[i].cmd_line = true;
+
+ return 1;
+--
+2.39.2
+
--- /dev/null
+From dc5e3d9d7c18b7f9dcb8bf4c1cf02cfefad299ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Sep 2022 10:56:38 -0500
+Subject: iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid
+ options
+
+From: Kim Phillips <kim.phillips@amd.com>
+
+[ Upstream commit 1198d2316dc4265a97d0e8445a22c7a6d17580a4 ]
+
+Currently, these options cause the following libkmod error:
+
+libkmod: ERROR ../libkmod/libkmod-config.c:489 kcmdline_parse_result: \
+ Ignoring bad option on kernel command line while parsing module \
+ name: 'ivrs_xxxx[XX:XX'
+
+Fix by introducing a new parameter format for these options and
+throw a warning for the deprecated format.
+
+Users are still allowed to omit the PCI Segment if zero.
+
+Adding a Link: to the reason why we're modding the syntax parsing
+in the driver and not in libkmod.
+
+Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/linux-modules/20200310082308.14318-2-lucas.demarchi@intel.com/
+Reported-by: Kim Phillips <kim.phillips@amd.com>
+Co-developed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Signed-off-by: Kim Phillips <kim.phillips@amd.com>
+Link: https://lore.kernel.org/r/20220919155638.391481-2-kim.phillips@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Stable-dep-of: b6b26d86c61c ("iommu/amd: Add a length limitation for the ivrs_acpihid command-line parameter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../admin-guide/kernel-parameters.txt | 27 +++++--
+ drivers/iommu/amd/init.c | 79 +++++++++++++------
+ 2 files changed, 76 insertions(+), 30 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index d49437b9a6980..4dbbc95316691 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2202,7 +2202,13 @@
+ Provide an override to the IOAPIC-ID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
+ By default, PCI segment is 0, and can be omitted.
+- For example:
++
++ For example, to map IOAPIC-ID decimal 10 to
++ PCI segment 0x1 and PCI device 00:14.0,
++ write the parameter as:
++ ivrs_ioapic=10@0001:00:14.0
++
++ Deprecated formats:
+ * To map IOAPIC-ID decimal 10 to PCI device 00:14.0
+ write the parameter as:
+ ivrs_ioapic[10]=00:14.0
+@@ -2214,7 +2220,13 @@
+ Provide an override to the HPET-ID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
+ By default, PCI segment is 0, and can be omitted.
+- For example:
++
++ For example, to map HPET-ID decimal 10 to
++ PCI segment 0x1 and PCI device 00:14.0,
++ write the parameter as:
++ ivrs_hpet=10@0001:00:14.0
++
++ Deprecated formats:
+ * To map HPET-ID decimal 0 to PCI device 00:14.0
+ write the parameter as:
+ ivrs_hpet[0]=00:14.0
+@@ -2225,15 +2237,20 @@
+ ivrs_acpihid [HW,X86-64]
+ Provide an override to the ACPI-HID:UID<->DEVICE-ID
+ mapping provided in the IVRS ACPI table.
++ By default, PCI segment is 0, and can be omitted.
+
+ For example, to map UART-HID:UID AMD0020:0 to
+ PCI segment 0x1 and PCI device ID 00:14.5,
+ write the parameter as:
+- ivrs_acpihid[0001:00:14.5]=AMD0020:0
++ ivrs_acpihid=AMD0020:0@0001:00:14.5
+
+- By default, PCI segment is 0, and can be omitted.
+- For example, PCI device 00:14.5 write the parameter as:
++ Deprecated formats:
++ * To map UART-HID:UID AMD0020:0 to PCI segment is 0,
++ PCI device ID 00:14.5, write the parameter as:
+ ivrs_acpihid[00:14.5]=AMD0020:0
++ * To map UART-HID:UID AMD0020:0 to PCI segment 0x1 and
++ PCI device ID 00:14.5, write the parameter as:
++ ivrs_acpihid[0001:00:14.5]=AMD0020:0
+
+ js= [HW,JOY] Analog joystick
+ See Documentation/input/joydev/joystick.rst.
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index 6961fe80e8eea..6c11db3356f78 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -3151,18 +3151,24 @@ static int __init parse_amd_iommu_options(char *str)
+ static int __init parse_ivrs_ioapic(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- int ret, id, i;
++ int id, i;
+ u32 devid;
+
+- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+- if (ret != 4) {
+- ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_ioapic%s\n", str);
+- return 1;
+- }
++ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
++ goto found;
++
++ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
++ pr_warn("ivrs_ioapic%s option format deprecated; use ivrs_ioapic=%d@%04x:%02x:%02x.%d instead\n",
++ str, id, seg, bus, dev, fn);
++ goto found;
+ }
+
++ pr_err("Invalid command line: ivrs_ioapic%s\n", str);
++ return 1;
++
++found:
+ if (early_ioapic_map_size == EARLY_MAP_SIZE) {
+ pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",
+ str);
+@@ -3183,18 +3189,24 @@ static int __init parse_ivrs_ioapic(char *str)
+ static int __init parse_ivrs_hpet(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- int ret, id, i;
++ int id, i;
+ u32 devid;
+
+- ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+- if (ret != 4) {
+- ret = sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_hpet%s\n", str);
+- return 1;
+- }
++ if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
++ goto found;
++
++ if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
++ sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
++ pr_warn("ivrs_hpet%s option format deprecated; use ivrs_hpet=%d@%04x:%02x:%02x.%d instead\n",
++ str, id, seg, bus, dev, fn);
++ goto found;
+ }
+
++ pr_err("Invalid command line: ivrs_hpet%s\n", str);
++ return 1;
++
++found:
+ if (early_hpet_map_size == EARLY_MAP_SIZE) {
+ pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n",
+ str);
+@@ -3215,19 +3227,36 @@ static int __init parse_ivrs_hpet(char *str)
+ static int __init parse_ivrs_acpihid(char *str)
+ {
+ u32 seg = 0, bus, dev, fn;
+- char *hid, *uid, *p;
++ char *hid, *uid, *p, *addr;
+ char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
+- int ret, i;
+-
+- ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
+- if (ret != 4) {
+- ret = sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid);
+- if (ret != 5) {
+- pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
+- return 1;
++ int i;
++
++ addr = strchr(str, '@');
++ if (!addr) {
++ if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 ||
++ sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) {
++ pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
++ str, acpiid, seg, bus, dev, fn);
++ goto found;
+ }
++ goto not_found;
+ }
+
++ /* We have the '@', make it the terminator to get just the acpiid */
++ *addr++ = 0;
++
++ if (sscanf(str, "=%s", acpiid) != 1)
++ goto not_found;
++
++ if (sscanf(addr, "%x:%x.%x", &bus, &dev, &fn) == 3 ||
++ sscanf(addr, "%x:%x:%x.%x", &seg, &bus, &dev, &fn) == 4)
++ goto found;
++
++not_found:
++ pr_err("Invalid command line: ivrs_acpihid%s\n", str);
++ return 1;
++
++found:
+ p = acpiid;
+ hid = strsep(&p, ":");
+ uid = p;
+--
+2.39.2
+
--- /dev/null
+From 2c4dbc49aca94706c550e5bea18e1647dc03a001 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Feb 2023 11:42:48 +0100
+Subject: irqdomain: Fix mapping-creation race
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 601363cc08da25747feb87c55573dd54de91d66a ]
+
+Parallel probing of devices that share interrupts (e.g. when a driver
+uses asynchronous probing) can currently result in two mappings for the
+same hardware interrupt to be created due to missing serialisation.
+
+Make sure to hold the irq_domain_mutex when creating mappings so that
+looking for an existing mapping before creating a new one is done
+atomically.
+
+Fixes: 765230b5f084 ("driver-core: add asynchronous probing support for drivers")
+Fixes: b62b2cf5759b ("irqdomain: Fix handling of type settings for existing mappings")
+Link: https://lore.kernel.org/r/YuJXMHoT4ijUxnRb@hovoldconsulting.com
+Cc: stable@vger.kernel.org # 4.8
+Cc: Dmitry Torokhov <dtor@chromium.org>
+Cc: Jon Hunter <jonathanh@nvidia.com>
+Tested-by: Hsin-Yi Wang <hsinyi@chromium.org>
+Tested-by: Mark-PK Tsai <mark-pk.tsai@mediatek.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230213104302.17307-7-johan+linaro@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/irq/irqdomain.c | 64 ++++++++++++++++++++++++++++++------------
+ 1 file changed, 46 insertions(+), 18 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index f95196063884a..e0b67784ac1e0 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -25,6 +25,9 @@ static DEFINE_MUTEX(irq_domain_mutex);
+
+ static struct irq_domain *irq_default_domain;
+
++static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
++ unsigned int nr_irqs, int node, void *arg,
++ bool realloc, const struct irq_affinity_desc *affinity);
+ static void irq_domain_check_hierarchy(struct irq_domain *domain);
+
+ struct irqchip_fwid {
+@@ -703,9 +706,9 @@ unsigned int irq_create_direct_mapping(struct irq_domain *domain)
+ EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
+ #endif
+
+-static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
+- irq_hw_number_t hwirq,
+- const struct irq_affinity_desc *affinity)
++static unsigned int irq_create_mapping_affinity_locked(struct irq_domain *domain,
++ irq_hw_number_t hwirq,
++ const struct irq_affinity_desc *affinity)
+ {
+ struct device_node *of_node = irq_domain_get_of_node(domain);
+ int virq;
+@@ -720,7 +723,7 @@ static unsigned int __irq_create_mapping_affinity(struct irq_domain *domain,
+ return 0;
+ }
+
+- if (irq_domain_associate(domain, virq, hwirq)) {
++ if (irq_domain_associate_locked(domain, virq, hwirq)) {
+ irq_free_desc(virq);
+ return 0;
+ }
+@@ -756,14 +759,20 @@ unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
+ return 0;
+ }
+
++ mutex_lock(&irq_domain_mutex);
++
+ /* Check if mapping already exists */
+ virq = irq_find_mapping(domain, hwirq);
+ if (virq) {
+ pr_debug("existing mapping on virq %d\n", virq);
+- return virq;
++ goto out;
+ }
+
+- return __irq_create_mapping_affinity(domain, hwirq, affinity);
++ virq = irq_create_mapping_affinity_locked(domain, hwirq, affinity);
++out:
++ mutex_unlock(&irq_domain_mutex);
++
++ return virq;
+ }
+ EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
+
+@@ -830,6 +839,8 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+ if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
+ type &= IRQ_TYPE_SENSE_MASK;
+
++ mutex_lock(&irq_domain_mutex);
++
+ /*
+ * If we've already configured this interrupt,
+ * don't do it again, or hell will break loose.
+@@ -842,7 +853,7 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+ * interrupt number.
+ */
+ if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
+- return virq;
++ goto out;
+
+ /*
+ * If the trigger type has not been set yet, then set
+@@ -850,35 +861,45 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
+ */
+ if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
+ irq_data = irq_get_irq_data(virq);
+- if (!irq_data)
+- return 0;
++ if (!irq_data) {
++ virq = 0;
++ goto out;
++ }
+
+ irqd_set_trigger_type(irq_data, type);
+- return virq;
++ goto out;
+ }
+
+ pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
+ hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
+- return 0;
++ virq = 0;
++ goto out;
+ }
+
+ if (irq_domain_is_hierarchy(domain)) {
+- virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
+- if (virq <= 0)
+- return 0;
++ virq = irq_domain_alloc_irqs_locked(domain, -1, 1, NUMA_NO_NODE,
++ fwspec, false, NULL);
++ if (virq <= 0) {
++ virq = 0;
++ goto out;
++ }
+ } else {
+ /* Create mapping */
+- virq = __irq_create_mapping_affinity(domain, hwirq, NULL);
++ virq = irq_create_mapping_affinity_locked(domain, hwirq, NULL);
+ if (!virq)
+- return virq;
++ goto out;
+ }
+
+ irq_data = irq_get_irq_data(virq);
+- if (WARN_ON(!irq_data))
+- return 0;
++ if (WARN_ON(!irq_data)) {
++ virq = 0;
++ goto out;
++ }
+
+ /* Store trigger type */
+ irqd_set_trigger_type(irq_data, type);
++out:
++ mutex_unlock(&irq_domain_mutex);
+
+ return virq;
+ }
+@@ -1910,6 +1931,13 @@ void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
+ irq_set_handler_data(virq, handler_data);
+ }
+
++static int irq_domain_alloc_irqs_locked(struct irq_domain *domain, int irq_base,
++ unsigned int nr_irqs, int node, void *arg,
++ bool realloc, const struct irq_affinity_desc *affinity)
++{
++ return -EINVAL;
++}
++
+ static void irq_domain_check_hierarchy(struct irq_domain *domain)
+ {
+ }
+--
+2.39.2
+
--- /dev/null
+From f022ff9b48467b05cf4b294a6bd75d036ae13486 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Mar 2022 07:29:03 +0200
+Subject: nbd: use the correct block_device in nbd_bdev_reset
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 2a852a693f8839bb877fc731ffbc9ece3a9c16d7 ]
+
+The bdev parameter to ->ioctl contains the block device that the ioctl
+is called on, which can be the partition. But the openers check in
+nbd_bdev_reset really needs to check use the whole device, so switch to
+using that.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220330052917.2566582-2-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: e5cfefa97bcc ("block: fix scan partition for exclusively open device again")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/nbd.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
+index c1ef1df42eb66..ade8b839e4458 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -1167,11 +1167,11 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
+ return -ENOSPC;
+ }
+
+-static void nbd_bdev_reset(struct block_device *bdev)
++static void nbd_bdev_reset(struct nbd_device *nbd)
+ {
+- if (bdev->bd_openers > 1)
++ if (nbd->disk->part0->bd_openers > 1)
+ return;
+- set_capacity(bdev->bd_disk, 0);
++ set_capacity(nbd->disk, 0);
+ }
+
+ static void nbd_parse_flags(struct nbd_device *nbd)
+@@ -1337,7 +1337,7 @@ static int nbd_start_device(struct nbd_device *nbd)
+ return nbd_set_size(nbd, config->bytesize, nbd_blksize(config));
+ }
+
+-static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *bdev)
++static int nbd_start_device_ioctl(struct nbd_device *nbd)
+ {
+ struct nbd_config *config = nbd->config;
+ int ret;
+@@ -1358,7 +1358,7 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *b
+
+ flush_workqueue(nbd->recv_workq);
+ mutex_lock(&nbd->config_lock);
+- nbd_bdev_reset(bdev);
++ nbd_bdev_reset(nbd);
+ /* user requested, ignore socket errors */
+ if (test_bit(NBD_RT_DISCONNECT_REQUESTED, &config->runtime_flags))
+ ret = 0;
+@@ -1372,7 +1372,7 @@ static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
+ {
+ nbd_clear_sock(nbd);
+ __invalidate_device(bdev, true);
+- nbd_bdev_reset(bdev);
++ nbd_bdev_reset(nbd);
+ if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
+ &nbd->config->runtime_flags))
+ nbd_config_put(nbd);
+@@ -1418,7 +1418,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
+ config->flags = arg;
+ return 0;
+ case NBD_DO_IT:
+- return nbd_start_device_ioctl(nbd, bdev);
++ return nbd_start_device_ioctl(nbd);
+ case NBD_CLEAR_QUE:
+ /*
+ * This is for compatibility only. The queue is always cleared
+--
+2.39.2
+
s390-ftrace-remove-dead-code.patch
risc-v-don-t-check-text_mutex-during-stop_machine.patch
ext4-fix-deadlock-during-directory-rename.patch
+irqdomain-fix-mapping-creation-race.patch
+nbd-use-the-correct-block_device-in-nbd_bdev_reset.patch
+iommu-amd-add-pci-segment-support-for-ivrs_-ioapic-h.patch
+iommu-amd-fix-ill-formed-ivrs_ioapic-ivrs_hpet-and-i.patch
+iommu-amd-add-a-length-limitation-for-the-ivrs_acpih.patch
+staging-rtl8723bs-clean-up-comparsions-to-null.patch
+staging-rtl8723bs-placing-opening-braces-in-previous.patch
+staging-rtl8723bs-fix-placement-of-braces.patch
+staging-rtl8723bs-fix-key-store-index-handling.patch
+watch_queue-fix-ioc_watch_queue_set_size-alloc-error.patch
+tpm-eventlog-don-t-abort-tpm_read_log-on-faulty-acpi.patch
+xfs-use-setattr_copy-to-set-vfs-inode-attributes.patch
+xfs-remove-xfs_prealloc_sync.patch
+xfs-fallocate-should-call-file_modified.patch
+xfs-set-prealloc-flag-in-xfs_alloc_file_space.patch
+fs-add-mode_strip_sgid-helper.patch
+fs-move-s_isgid-stripping-into-the-vfs_-helpers.patch
+attr-add-in_group_or_capable.patch
+fs-move-should_remove_suid.patch
+attr-add-setattr_should_drop_sgid.patch
+attr-use-consistent-sgid-stripping-checks.patch
+fs-use-consistent-setgid-checks-in-is_sxid.patch
--- /dev/null
+From 8c5a283820d4ad87f765f895fe00bea5497b10cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 29 Aug 2021 17:45:33 +0200
+Subject: staging: rtl8723bs: clean up comparsions to NULL
+
+From: Michael Straube <straube.linux@gmail.com>
+
+[ Upstream commit cd1f1450092216b3e39516f8db58869b6fc20575 ]
+
+Clean up comparsions to NULL reported by checkpatch.
+
+x == NULL -> !x
+x != NULL -> x
+
+Signed-off-by: Michael Straube <straube.linux@gmail.com>
+Link: https://lore.kernel.org/r/20210829154533.11054-1-straube.linux@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 05cbcc415c9b ("staging: rtl8723bs: Fix key-store index handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/staging/rtl8723bs/core/rtw_ap.c | 20 ++--
+ drivers/staging/rtl8723bs/core/rtw_cmd.c | 96 +++++++++----------
+ .../staging/rtl8723bs/core/rtw_ioctl_set.c | 4 +-
+ drivers/staging/rtl8723bs/core/rtw_mlme.c | 6 +-
+ drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 56 +++++------
+ drivers/staging/rtl8723bs/core/rtw_security.c | 6 +-
+ .../staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 24 ++---
+ .../staging/rtl8723bs/os_dep/ioctl_linux.c | 18 ++--
+ drivers/staging/rtl8723bs/os_dep/os_intfs.c | 4 +-
+ 9 files changed, 117 insertions(+), 117 deletions(-)
+
+diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c
+index 6064dd6a76b42..674592e914e26 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_ap.c
++++ b/drivers/staging/rtl8723bs/core/rtw_ap.c
+@@ -891,7 +891,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+ &ie_len,
+ (pbss_network->ie_length - _BEACON_IE_OFFSET_)
+ );
+- if (p != NULL) {
++ if (p) {
+ memcpy(supportRate, p + 2, ie_len);
+ supportRateNum = ie_len;
+ }
+@@ -903,7 +903,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+ &ie_len,
+ pbss_network->ie_length - _BEACON_IE_OFFSET_
+ );
+- if (p != NULL) {
++ if (p) {
+ memcpy(supportRate + supportRateNum, p + 2, ie_len);
+ supportRateNum += ie_len;
+ }
+@@ -991,7 +991,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+ break;
+ }
+
+- if ((p == NULL) || (ie_len == 0))
++ if (!p || ie_len == 0)
+ break;
+ }
+
+@@ -1021,7 +1021,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+ break;
+ }
+
+- if ((p == NULL) || (ie_len == 0))
++ if (!p || ie_len == 0)
+ break;
+ }
+ }
+@@ -1145,7 +1145,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
+ psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->mac_address);
+ if (!psta) {
+ psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->mac_address);
+- if (psta == NULL)
++ if (!psta)
+ return _FAIL;
+ }
+
+@@ -1275,7 +1275,7 @@ u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta)
+ }
+
+ psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
+- if (psetstakey_para == NULL) {
++ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1311,12 +1311,12 @@ static int rtw_ap_set_key(
+ int res = _SUCCESS;
+
+ pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd == NULL) {
++ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+ psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm));
+- if (psetkeyparm == NULL) {
++ if (!psetkeyparm) {
+ kfree(pcmd);
+ res = _FAIL;
+ goto exit;
+@@ -1474,11 +1474,11 @@ static void update_bcn_wps_ie(struct adapter *padapter)
+ &wps_ielen
+ );
+
+- if (pwps_ie == NULL || wps_ielen == 0)
++ if (!pwps_ie || wps_ielen == 0)
+ return;
+
+ pwps_ie_src = pmlmepriv->wps_beacon_ie;
+- if (pwps_ie_src == NULL)
++ if (!pwps_ie_src)
+ return;
+
+ wps_offset = (uint)(pwps_ie - ie);
+diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
+index 93e3a4c9e1159..5f4f603b3b366 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
++++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
+@@ -251,7 +251,7 @@ int _rtw_enqueue_cmd(struct __queue *queue, struct cmd_obj *obj)
+ {
+ unsigned long irqL;
+
+- if (obj == NULL)
++ if (!obj)
+ goto exit;
+
+ /* spin_lock_bh(&queue->lock); */
+@@ -319,7 +319,7 @@ int rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+ int res = _FAIL;
+ struct adapter *padapter = pcmdpriv->padapter;
+
+- if (cmd_obj == NULL)
++ if (!cmd_obj)
+ goto exit;
+
+ cmd_obj->padapter = padapter;
+@@ -484,7 +484,7 @@ int rtw_cmd_thread(void *context)
+ /* call callback function for post-processed */
+ if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) {
+ pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+- if (pcmd_callback == NULL) {
++ if (!pcmd_callback) {
+ rtw_free_cmd_obj(pcmd);
+ } else {
+ /* todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!= NULL) */
+@@ -503,7 +503,7 @@ int rtw_cmd_thread(void *context)
+ /* free all cmd_obj resources */
+ do {
+ pcmd = rtw_dequeue_cmd(pcmdpriv);
+- if (pcmd == NULL) {
++ if (!pcmd) {
+ rtw_unregister_cmd_alive(padapter);
+ break;
+ }
+@@ -542,11 +542,11 @@ u8 rtw_sitesurvey_cmd(struct adapter *padapter, struct ndis_802_11_ssid *ssid,
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL)
++ if (!ph2c)
+ return _FAIL;
+
+ psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
+- if (psurveyPara == NULL) {
++ if (!psurveyPara) {
+ kfree(ph2c);
+ return _FAIL;
+ }
+@@ -604,13 +604,13 @@ u8 rtw_setdatarate_cmd(struct adapter *padapter, u8 *rateset)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pbsetdataratepara = rtw_zmalloc(sizeof(struct setdatarate_parm));
+- if (pbsetdataratepara == NULL) {
++ if (!pbsetdataratepara) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -640,7 +640,7 @@ u8 rtw_createbss_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd == NULL) {
++ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -673,7 +673,7 @@ int rtw_startbss_cmd(struct adapter *padapter, int flags)
+ } else {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd == NULL) {
++ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -725,7 +725,7 @@ u8 rtw_joinbss_cmd(struct adapter *padapter, struct wlan_network *pnetwork)
+ u8 *ptmp = NULL;
+
+ pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd == NULL) {
++ if (!pcmd) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -837,7 +837,7 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu
+
+ /* prepare cmd parameter */
+ param = rtw_zmalloc(sizeof(*param));
+- if (param == NULL) {
++ if (!param) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -846,7 +846,7 @@ u8 rtw_disassoc_cmd(struct adapter *padapter, u32 deauth_timeout_ms, bool enqueu
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ cmdobj = rtw_zmalloc(sizeof(*cmdobj));
+- if (cmdobj == NULL) {
++ if (!cmdobj) {
+ res = _FAIL;
+ kfree(param);
+ goto exit;
+@@ -874,7 +874,7 @@ u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infrast
+
+ psetop = rtw_zmalloc(sizeof(struct setopmode_parm));
+
+- if (psetop == NULL) {
++ if (!psetop) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -882,7 +882,7 @@ u8 rtw_setopmode_cmd(struct adapter *padapter, enum ndis_802_11_network_infrast
+
+ if (enqueue) {
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ kfree(psetop);
+ res = _FAIL;
+ goto exit;
+@@ -910,7 +910,7 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_
+ u8 res = _SUCCESS;
+
+ psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
+- if (psetstakey_para == NULL) {
++ if (!psetstakey_para) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -932,14 +932,14 @@ u8 rtw_setstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 unicast_
+
+ if (enqueue) {
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ kfree(psetstakey_para);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp));
+- if (psetstakey_rsp == NULL) {
++ if (!psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ res = _FAIL;
+@@ -977,20 +977,20 @@ u8 rtw_clearstakey_cmd(struct adapter *padapter, struct sta_info *sta, u8 enqueu
+ }
+ } else {
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm));
+- if (psetstakey_para == NULL) {
++ if (!psetstakey_para) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+ }
+
+ psetstakey_rsp = rtw_zmalloc(sizeof(struct set_stakey_rsp));
+- if (psetstakey_rsp == NULL) {
++ if (!psetstakey_rsp) {
+ kfree(ph2c);
+ kfree(psetstakey_para);
+ res = _FAIL;
+@@ -1022,13 +1022,13 @@ u8 rtw_addbareq_cmd(struct adapter *padapter, u8 tid, u8 *addr)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ paddbareq_parm = rtw_zmalloc(sizeof(struct addBaReq_parm));
+- if (paddbareq_parm == NULL) {
++ if (!paddbareq_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1054,13 +1054,13 @@ u8 rtw_reset_securitypriv_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1089,13 +1089,13 @@ u8 rtw_free_assoc_resources_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1125,13 +1125,13 @@ u8 rtw_dynamic_chk_wk_cmd(struct adapter *padapter)
+
+ /* only primary padapter does this cmd */
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1173,7 +1173,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconf
+
+ /* prepare cmd parameter */
+ setChannelPlan_param = rtw_zmalloc(sizeof(struct SetChannelPlan_param));
+- if (setChannelPlan_param == NULL) {
++ if (!setChannelPlan_param) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -1182,7 +1182,7 @@ u8 rtw_set_chplan_cmd(struct adapter *padapter, u8 chplan, u8 enqueue, u8 swconf
+ if (enqueue) {
+ /* need enqueue, prepare cmd_obj and enqueue */
+ pcmdobj = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmdobj == NULL) {
++ if (!pcmdobj) {
+ kfree(setChannelPlan_param);
+ res = _FAIL;
+ goto exit;
+@@ -1432,13 +1432,13 @@ u8 rtw_lps_ctrl_wk_cmd(struct adapter *padapter, u8 lps_ctrl_type, u8 enqueue)
+
+ if (enqueue) {
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1474,13 +1474,13 @@ u8 rtw_dm_in_lps_wk_cmd(struct adapter *padapter)
+
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1540,13 +1540,13 @@ u8 rtw_dm_ra_mask_wk_cmd(struct adapter *padapter, u8 *psta)
+
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1575,13 +1575,13 @@ u8 rtw_ps_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ ppscmd = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ppscmd == NULL) {
++ if (!ppscmd) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ppscmd);
+ res = _FAIL;
+ goto exit;
+@@ -1647,13 +1647,13 @@ u8 rtw_chk_hi_queue_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1741,13 +1741,13 @@ u8 rtw_c2h_packet_wk_cmd(struct adapter *padapter, u8 *pbuf, u16 length)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1776,13 +1776,13 @@ u8 rtw_c2h_wk_cmd(struct adapter *padapter, u8 *c2h_evt)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ pdrvextra_cmd_parm = rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+- if (pdrvextra_cmd_parm == NULL) {
++ if (!pdrvextra_cmd_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -1957,7 +1957,7 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
+ struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
+
+- if (pcmd->parmbuf == NULL)
++ if (!pcmd->parmbuf)
+ goto exit;
+
+ if (pcmd->res != H2C_SUCCESS)
+@@ -1980,9 +1980,9 @@ void rtw_createbss_cmd_callback(struct adapter *padapter, struct cmd_obj *pcmd)
+ } else {
+ pwlan = rtw_alloc_network(pmlmepriv);
+ spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
+- if (pwlan == NULL) {
++ if (!pwlan) {
+ pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
+- if (pwlan == NULL) {
++ if (!pwlan) {
+ spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
+ goto createbss_cmd_fail;
+ }
+diff --git a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
+index 5cfde71766173..8c11daff2d590 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
++++ b/drivers/staging/rtl8723bs/core/rtw_ioctl_set.c
+@@ -370,7 +370,7 @@ u8 rtw_set_802_11_bssid_list_scan(struct adapter *padapter, struct ndis_802_11_s
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+ u8 res = true;
+
+- if (padapter == NULL) {
++ if (!padapter) {
+ res = false;
+ goto exit;
+ }
+@@ -481,7 +481,7 @@ u16 rtw_get_cur_max_rate(struct adapter *adapter)
+ return 0;
+
+ psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
+- if (psta == NULL)
++ if (!psta)
+ return 0;
+
+ short_GI = query_ra_short_GI(psta);
+diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+index 952c3e14d1b33..26c40042d2bed 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
++++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
+@@ -439,7 +439,7 @@ struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
+ pwlan = list_entry(plist, struct wlan_network, list);
+
+ if (!pwlan->fixed) {
+- if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
++ if (!oldest || time_after(oldest->last_scanned, pwlan->last_scanned))
+ oldest = pwlan;
+ }
+ }
+@@ -542,7 +542,7 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t
+ /* TODO: don't select network in the same ess as oldest if it's new enough*/
+ }
+
+- if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned))
++ if (!oldest || time_after(oldest->last_scanned, pnetwork->last_scanned))
+ oldest = pnetwork;
+
+ }
+@@ -1816,7 +1816,7 @@ static int rtw_check_join_candidate(struct mlme_priv *mlme
+ goto exit;
+ }
+
+- if (*candidate == NULL || (*candidate)->network.rssi < competitor->network.rssi) {
++ if (!*candidate || (*candidate)->network.rssi < competitor->network.rssi) {
+ *candidate = competitor;
+ updated = true;
+ }
+diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+index 1a4b4c75c4bf5..e923f306cf0c3 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
++++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+@@ -742,11 +742,11 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
+ }
+
+ pstat = rtw_get_stainfo(pstapriv, sa);
+- if (pstat == NULL) {
++ if (!pstat) {
+
+ /* allocate a new one */
+ pstat = rtw_alloc_stainfo(pstapriv, sa);
+- if (pstat == NULL) {
++ if (!pstat) {
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto auth_fail;
+ }
+@@ -814,7 +814,7 @@ unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len,
+ len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
+
+- if ((p == NULL) || (ie_len <= 0)) {
++ if (!p || ie_len <= 0) {
+ status = WLAN_STATUS_CHALLENGE_FAIL;
+ goto auth_fail;
+ }
+@@ -1034,7 +1034,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
+
+ /* check if the supported rate is ok */
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+- if (p == NULL) {
++ if (!p) {
+ /* use our own rate set as statoin used */
+ /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
+ /* supportRateNum = AP_BSSRATE_LEN; */
+@@ -1047,7 +1047,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
+
+ p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len,
+ pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+- if (p != NULL) {
++ if (p) {
+
+ if (supportRateNum <= sizeof(supportRate)) {
+ memcpy(supportRate+supportRateNum, p+2, ie_len);
+@@ -1294,7 +1294,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
+ /* get a unique AID */
+ if (pstat->aid == 0) {
+ for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
+- if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
++ if (!pstapriv->sta_aid[pstat->aid - 1])
+ break;
+
+ /* if (pstat->aid > NUM_STA) { */
+@@ -1940,7 +1940,7 @@ static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool
+ goto exit;
+
+ pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
+- if (pxmitbuf == NULL) {
++ if (!pxmitbuf) {
+ rtw_free_xmitframe(pxmitpriv, pmgntframe);
+ pmgntframe = NULL;
+ goto exit;
+@@ -2293,7 +2293,7 @@ void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p
+ struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
+ unsigned int rate_len;
+
+- if (da == NULL)
++ if (!da)
+ return;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+@@ -2617,7 +2617,7 @@ void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short
+ __le16 le_tmp;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL)
++ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+@@ -2748,7 +2748,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
+ __le16 lestatus, le_tmp;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL)
++ if (!pmgntframe)
+ return;
+
+ /* update attribute */
+@@ -2836,7 +2836,7 @@ void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_i
+ break;
+ }
+
+- if ((pbuf == NULL) || (ie_len == 0)) {
++ if (!pbuf || ie_len == 0) {
+ break;
+ }
+ }
+@@ -2880,7 +2880,7 @@ void issue_assocreq(struct adapter *padapter)
+ u8 vs_ie_length = 0;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL)
++ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+@@ -3057,7 +3057,7 @@ static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
+ pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL)
++ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+@@ -3196,7 +3196,7 @@ static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
+ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL)
++ if (!pmgntframe)
+ goto exit;
+
+ /* update attribute */
+@@ -3309,7 +3309,7 @@ static int _issue_deauth(struct adapter *padapter, unsigned char *da,
+ __le16 le_tmp;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL) {
++ if (!pmgntframe) {
+ goto exit;
+ }
+
+@@ -3635,7 +3635,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter)
+ action = ACT_PUBLIC_BSSCOEXIST;
+
+ pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+- if (pmgntframe == NULL) {
++ if (!pmgntframe) {
+ return;
+ }
+
+@@ -3702,7 +3702,7 @@ static void issue_action_BSSCoexistPacket(struct adapter *padapter)
+ pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
+
+ p = rtw_get_ie(pbss_network->ies + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->ie_length - _FIXED_IE_LENGTH_);
+- if ((p == NULL) || (len == 0)) {/* non-HT */
++ if (!p || len == 0) {/* non-HT */
+
+ if (pbss_network->configuration.ds_config <= 0)
+ continue;
+@@ -3765,7 +3765,7 @@ unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
+ return _SUCCESS;
+
+ psta = rtw_get_stainfo(pstapriv, addr);
+- if (psta == NULL)
++ if (!psta)
+ return _SUCCESS;
+
+ if (initiator == 0) {/* recipient */
+@@ -4637,13 +4637,13 @@ void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsi
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd_obj == NULL) {
++ if (!pcmd_obj) {
+ return;
+ }
+
+ cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = rtw_zmalloc(cmdsz);
+- if (pevtcmd == NULL) {
++ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+@@ -4689,12 +4689,12 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int
+ struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+ pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (pcmd_obj == NULL)
++ if (!pcmd_obj)
+ return;
+
+ cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+ pevtcmd = rtw_zmalloc(cmdsz);
+- if (pevtcmd == NULL) {
++ if (!pevtcmd) {
+ kfree(pcmd_obj);
+ return;
+ }
+@@ -5143,12 +5143,12 @@ void survey_timer_hdl(struct timer_list *t)
+ }
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ goto exit_survey_timer_hdl;
+ }
+
+ psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
+- if (psurveyPara == NULL) {
++ if (!psurveyPara) {
+ kfree(ph2c);
+ goto exit_survey_timer_hdl;
+ }
+@@ -5777,7 +5777,7 @@ u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
+ u8 res = _SUCCESS;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+@@ -5801,13 +5801,13 @@ u8 set_tx_beacon_cmd(struct adapter *padapter)
+ int len_diff = 0;
+
+ ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
+- if (ph2c == NULL) {
++ if (!ph2c) {
+ res = _FAIL;
+ goto exit;
+ }
+
+ ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param));
+- if (ptxBeacon_parm == NULL) {
++ if (!ptxBeacon_parm) {
+ kfree(ph2c);
+ res = _FAIL;
+ goto exit;
+@@ -5867,7 +5867,7 @@ u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
+ void (*event_callback)(struct adapter *dev, u8 *pbuf);
+ struct evt_priv *pevt_priv = &(padapter->evtpriv);
+
+- if (pbuf == NULL)
++ if (!pbuf)
+ goto _abort_event_;
+
+ peventbuf = (uint *)pbuf;
+diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c
+index b050bf62e3b94..ac731415f7332 100644
+--- a/drivers/staging/rtl8723bs/core/rtw_security.c
++++ b/drivers/staging/rtl8723bs/core/rtw_security.c
+@@ -51,7 +51,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
+ struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+ struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx;
+
+- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
++ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return;
+
+ hw_hdr_offset = TXDESC_OFFSET;
+@@ -476,7 +476,7 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
+ struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx;
+ u32 res = _SUCCESS;
+
+- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
++ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_OFFSET;
+@@ -1043,7 +1043,7 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
+
+ u32 res = _SUCCESS;
+
+- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
++ if (!((struct xmit_frame *)pxmitframe)->buf_addr)
+ return _FAIL;
+
+ hw_hdr_offset = TXDESC_OFFSET;
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+index 448c4248ca4cf..20d05b4ee63e2 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+@@ -391,7 +391,7 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
+ }
+ else
+ {
+- if (scanned == NULL) {
++ if (!scanned) {
+ rtw_warn_on(1);
+ return;
+ }
+@@ -432,7 +432,7 @@ void rtw_cfg80211_indicate_connect(struct adapter *padapter)
+ struct wlan_bssid_ex *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+ struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
+
+- if (scanned == NULL) {
++ if (!scanned) {
+ rtw_warn_on(1);
+ goto check_bss;
+ }
+@@ -551,10 +551,10 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ goto exit;
+ }
+
+- if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL))
++ if (strcmp(param->u.crypt.alg, "none") == 0 && !psta)
+ goto exit;
+
+- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL))
++ if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta)
+ {
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+@@ -907,7 +907,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ }
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+- if (pbcmc_sta == NULL)
++ if (!pbcmc_sta)
+ {
+ /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
+ }
+@@ -947,7 +947,7 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
+
+ param_len = sizeof(struct ieee_param) + params->key_len;
+ param = rtw_malloc(param_len);
+- if (param == NULL)
++ if (!param)
+ return -1;
+
+ memset(param, 0, param_len);
+@@ -1098,7 +1098,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
+ }
+
+ psta = rtw_get_stainfo(pstapriv, (u8 *)mac);
+- if (psta == NULL) {
++ if (!psta) {
+ ret = -ENOENT;
+ goto exit;
+ }
+@@ -1327,7 +1327,7 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
+ struct rtw_wdev_priv *pwdev_priv;
+ struct mlme_priv *pmlmepriv;
+
+- if (ndev == NULL) {
++ if (!ndev) {
+ ret = -EINVAL;
+ goto exit;
+ }
+@@ -1571,7 +1571,7 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
+ u8 *pwpa, *pwpa2;
+ u8 null_addr[] = {0, 0, 0, 0, 0, 0};
+
+- if (pie == NULL || !ielen) {
++ if (!pie || !ielen) {
+ /* Treat this as normal case, but need to clear WIFI_UNDER_WPS */
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+ goto exit;
+@@ -1583,7 +1583,7 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
+ }
+
+ buf = rtw_zmalloc(ielen);
+- if (buf == NULL) {
++ if (!buf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+@@ -1873,7 +1873,7 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
+ pwep = rtw_malloc(wep_total_len);
+- if (pwep == NULL) {
++ if (!pwep) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+@@ -2708,7 +2708,7 @@ static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,
+ struct adapter *padapter;
+ struct rtw_wdev_priv *pwdev_priv;
+
+- if (ndev == NULL) {
++ if (!ndev) {
+ ret = -EINVAL;
+ goto exit;
+ }
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+index 295121c268bd4..f23ab3e103455 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+@@ -153,7 +153,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
+
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+- if (psta == NULL) {
++ if (!psta) {
+ /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
+ } else {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+@@ -206,7 +206,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
+ }
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+- if (pbcmc_sta == NULL) {
++ if (!pbcmc_sta) {
+ /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
+ } else {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+@@ -236,9 +236,9 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie
+ int ret = 0;
+ u8 null_addr[] = {0, 0, 0, 0, 0, 0};
+
+- if ((ielen > MAX_WPA_IE_LEN) || (pie == NULL)) {
++ if (ielen > MAX_WPA_IE_LEN || !pie) {
+ _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
+- if (pie == NULL)
++ if (!pie)
+ return ret;
+ else
+ return -EINVAL;
+@@ -246,7 +246,7 @@ static int rtw_set_wpa_ie(struct adapter *padapter, char *pie, unsigned short ie
+
+ if (ielen) {
+ buf = rtw_zmalloc(ielen);
+- if (buf == NULL) {
++ if (!buf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+@@ -491,7 +491,7 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
+ return -EINVAL;
+
+ param = rtw_malloc(p->length);
+- if (param == NULL)
++ if (!param)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+@@ -571,7 +571,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
+ goto exit;
+ }
+
+- if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
++ if (strcmp(param->u.crypt.alg, "none") == 0 && !psta) {
+ /* todo:clear default encryption keys */
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
+@@ -583,7 +583,7 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
+ }
+
+
+- if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
++ if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) {
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+@@ -1227,7 +1227,7 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
+ return -EINVAL;
+
+ param = rtw_malloc(p->length);
+- if (param == NULL)
++ if (!param)
+ return -ENOMEM;
+
+ if (copy_from_user(param, p->pointer, p->length)) {
+diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+index 23f4f706f935c..279347be77c40 100644
+--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
++++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+@@ -488,7 +488,7 @@ void rtw_unregister_netdevs(struct dvobj_priv *dvobj)
+
+ padapter = dvobj->padapters;
+
+- if (padapter == NULL)
++ if (!padapter)
+ return;
+
+ pnetdev = padapter->pnetdev;
+@@ -594,7 +594,7 @@ struct dvobj_priv *devobj_init(void)
+ struct dvobj_priv *pdvobj = NULL;
+
+ pdvobj = rtw_zmalloc(sizeof(*pdvobj));
+- if (pdvobj == NULL)
++ if (!pdvobj)
+ return NULL;
+
+ mutex_init(&pdvobj->hw_init_mutex);
+--
+2.39.2
+
--- /dev/null
+From d3b57f3361d05a5b0b03b863fd47307f0cec6ee7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 16:35:11 +0100
+Subject: staging: rtl8723bs: Fix key-store index handling
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 05cbcc415c9b8c8bc4f9a09f8e03610a89042f03 ]
+
+There are 2 issues with the key-store index handling
+
+1. The non WEP key stores can store keys with indexes 0 - BIP_MAX_KEYID,
+ this means that they should be an array with BIP_MAX_KEYID + 1
+ entries. But some of the arrays where just BIP_MAX_KEYID entries
+ big. While one other array was hardcoded to a size of 6 entries,
+ instead of using the BIP_MAX_KEYID define.
+
+2. The rtw_cfg80211_set_encryption() and wpa_set_encryption() functions
+ index check where checking that the passed in key-index would fit
+ inside both the WEP key store (which only has 4 entries) as well as
+ in the non WEP key stores. This breaks any attempts to set non WEP
+ keys with index 4 or 5.
+
+Issue 2. specifically breaks wifi connection with some access points
+which advertise PMF support. Without this fix connecting to these
+access points fails with the following wpa_supplicant messages:
+
+ nl80211: kernel reports: key addition failed
+ wlan0: WPA: Failed to configure IGTK to the driver
+ wlan0: RSN: Failed to configure IGTK
+ wlan0: CTRL-EVENT-DISCONNECTED bssid=... reason=1 locally_generated=1
+
+Fix 1. by using the right size for the key-stores. After this 2. can
+safely be fixed by checking the right max-index value depending on the
+used algorithm, fixing wifi not working with some PMF capable APs.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20230306153512.162104-1-hdegoede@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../staging/rtl8723bs/include/rtw_security.h | 8 ++---
+ .../staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 26 ++++++++-------
+ .../staging/rtl8723bs/os_dep/ioctl_linux.c | 33 ++++++++++---------
+ 3 files changed, 36 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/staging/rtl8723bs/include/rtw_security.h b/drivers/staging/rtl8723bs/include/rtw_security.h
+index a68b738584623..7587fa8885274 100644
+--- a/drivers/staging/rtl8723bs/include/rtw_security.h
++++ b/drivers/staging/rtl8723bs/include/rtw_security.h
+@@ -107,13 +107,13 @@ struct security_priv {
+
+ u32 dot118021XGrpPrivacy; /* This specify the privacy algthm. used for Grp key */
+ u32 dot118021XGrpKeyid; /* key id used for Grp Key (tx key index) */
+- union Keytype dot118021XGrpKey[BIP_MAX_KEYID]; /* 802.1x Group Key, for inx0 and inx1 */
+- union Keytype dot118021XGrptxmickey[BIP_MAX_KEYID];
+- union Keytype dot118021XGrprxmickey[BIP_MAX_KEYID];
++ union Keytype dot118021XGrpKey[BIP_MAX_KEYID + 1]; /* 802.1x Group Key, for inx0 and inx1 */
++ union Keytype dot118021XGrptxmickey[BIP_MAX_KEYID + 1];
++ union Keytype dot118021XGrprxmickey[BIP_MAX_KEYID + 1];
+ union pn48 dot11Grptxpn; /* PN48 used for Grp Key xmit. */
+ union pn48 dot11Grprxpn; /* PN48 used for Grp Key recv. */
+ u32 dot11wBIPKeyid; /* key id used for BIP Key (tx key index) */
+- union Keytype dot11wBIPKey[6]; /* BIP Key, for index4 and index5 */
++ union Keytype dot11wBIPKey[BIP_MAX_KEYID + 1]; /* BIP Key, for index4 and index5 */
+ union pn48 dot11wBIPtxpn; /* PN48 used for Grp Key xmit. */
+ union pn48 dot11wBIPrxpn; /* PN48 used for Grp Key recv. */
+
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+index b7a3f3df72723..b33424a9e83b7 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+@@ -711,6 +711,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+ {
+ int ret = 0;
++ u8 max_idx;
+ u32 wep_key_idx, wep_key_len;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+ struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+@@ -724,26 +725,29 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ goto exit;
+ }
+
+- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+- if (param->u.crypt.idx >= WEP_KEYS
+- || param->u.crypt.idx >= BIP_MAX_KEYID) {
+- ret = -EINVAL;
+- goto exit;
+- }
+- } else {
+- {
++ if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
++ param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
++ param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
+ ret = -EINVAL;
+ goto exit;
+ }
++
++ if (strcmp(param->u.crypt.alg, "WEP") == 0)
++ max_idx = WEP_KEYS - 1;
++ else
++ max_idx = BIP_MAX_KEYID;
++
++ if (param->u.crypt.idx > max_idx) {
++ netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
++ ret = -EINVAL;
++ goto exit;
+ }
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+- if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
++ if (wep_key_len <= 0) {
+ ret = -EINVAL;
+ goto exit;
+ }
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+index f23ab3e103455..0d2cb3e7ea4df 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+@@ -60,6 +60,7 @@ static int wpa_set_auth_algs(struct net_device *dev, u32 value)
+ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
+ {
+ int ret = 0;
++ u8 max_idx;
+ u32 wep_key_idx, wep_key_len, wep_total_len;
+ struct ndis_802_11_wep *pwep = NULL;
+ struct adapter *padapter = rtw_netdev_priv(dev);
+@@ -74,19 +75,22 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
+ goto exit;
+ }
+
+- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+- if (param->u.crypt.idx >= WEP_KEYS ||
+- param->u.crypt.idx >= BIP_MAX_KEYID) {
+- ret = -EINVAL;
+- goto exit;
+- }
+- } else {
+- {
+- ret = -EINVAL;
+- goto exit;
+- }
++ if (param->sta_addr[0] != 0xff || param->sta_addr[1] != 0xff ||
++ param->sta_addr[2] != 0xff || param->sta_addr[3] != 0xff ||
++ param->sta_addr[4] != 0xff || param->sta_addr[5] != 0xff) {
++ ret = -EINVAL;
++ goto exit;
++ }
++
++ if (strcmp(param->u.crypt.alg, "WEP") == 0)
++ max_idx = WEP_KEYS - 1;
++ else
++ max_idx = BIP_MAX_KEYID;
++
++ if (param->u.crypt.idx > max_idx) {
++ netdev_err(dev, "Error crypt.idx %d > %d\n", param->u.crypt.idx, max_idx);
++ ret = -EINVAL;
++ goto exit;
+ }
+
+ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+@@ -98,9 +102,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+- if (wep_key_idx > WEP_KEYS)
+- return -EINVAL;
+-
+ if (wep_key_len > 0) {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material);
+--
+2.39.2
+
--- /dev/null
+From d463310beae64ddc2445b2e280131864634e6c21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 28 May 2022 14:31:15 +0200
+Subject: staging: rtl8723bs: fix placement of braces
+
+From: Hannes Braun <hannesbraun@mail.de>
+
+[ Upstream commit a8b088d6d98dafddda9874f98ac2a7cefc51639b ]
+
+This patch should eliminate the following errors/warnings emitted by
+checkpatch.pl:
+- that open brace { should be on the previous line
+- else should follow close brace '}'
+- braces {} are not necessary for single statement blocks
+
+Signed-off-by: Hannes Braun <hannesbraun@mail.de>
+Link: https://lore.kernel.org/r/20220528123115.13024-1-hannesbraun@mail.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 05cbcc415c9b ("staging: rtl8723bs: Fix key-store index handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 223 +++++-------------
+ 1 file changed, 65 insertions(+), 158 deletions(-)
+
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+index 2404f7f84d82a..b7a3f3df72723 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+@@ -366,9 +366,8 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
+ int freq = (int)cur_network->network.configuration.ds_config;
+ struct ieee80211_channel *chan;
+
+- if (pwdev->iftype != NL80211_IFTYPE_ADHOC) {
++ if (pwdev->iftype != NL80211_IFTYPE_ADHOC)
+ return;
+- }
+
+ if (!rtw_cfg80211_check_bss(padapter)) {
+ struct wlan_bssid_ex *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+@@ -544,9 +543,8 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ goto exit;
+ }
+
+- if (wep_key_len > 0) {
++ if (wep_key_len > 0)
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+- }
+
+ if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+ /* wep default key has not been set, so use this key index as default key. */
+@@ -582,9 +580,8 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+- if (param->u.crypt.key_len == 13) {
++ if (param->u.crypt.key_len == 13)
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+- }
+
+ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+@@ -626,24 +623,16 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ }
+
+- if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) /* psk/802_1x */
+- {
+- if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+- {
+- if (param->u.crypt.set_tx == 1) /* pairwise key */
+- {
++ if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
++ if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
++ if (param->u.crypt.set_tx == 1) { /* pairwise key */
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+- if (strcmp(param->u.crypt.alg, "WEP") == 0)
+- {
++ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ psta->dot118021XPrivacy = _WEP40_;
+ if (param->u.crypt.key_len == 13)
+- {
+ psta->dot118021XPrivacy = _WEP104_;
+- }
+- }
+- else if (strcmp(param->u.crypt.alg, "TKIP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ psta->dot118021XPrivacy = _TKIP_;
+
+ /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
+@@ -653,14 +642,10 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ psecuritypriv->busetkipkey = true;
+
+- }
+- else if (strcmp(param->u.crypt.alg, "CCMP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+
+ psta->dot118021XPrivacy = _AES_;
+- }
+- else
+- {
++ } else {
+ psta->dot118021XPrivacy = _NO_PRIVACY_;
+ }
+
+@@ -670,21 +655,14 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ psta->bpairwise_key_installed = true;
+
+- }
+- else/* group key??? */
+- {
+- if (strcmp(param->u.crypt.alg, "WEP") == 0)
+- {
++ } else { /* group key??? */
++ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+ if (param->u.crypt.key_len == 13)
+- {
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+- }
+- }
+- else if (strcmp(param->u.crypt.alg, "TKIP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+@@ -696,15 +674,11 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ psecuritypriv->busetkipkey = true;
+
+- }
+- else if (strcmp(param->u.crypt.alg, "CCMP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+- }
+- else
+- {
++ } else {
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ }
+
+@@ -717,8 +691,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+- if (pbcmc_sta)
+- {
++ if (pbcmc_sta) {
+ pbcmc_sta->ieee8021x_blocked = false;
+ pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
+ }
+@@ -746,20 +719,16 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+- if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len)
+- {
++ if (param_len < (u32) ((u8 *) param->u.crypt.key - (u8 *) param) + param->u.crypt.key_len) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+- {
++ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
+ if (param->u.crypt.idx >= WEP_KEYS
+- || param->u.crypt.idx >= BIP_MAX_KEYID
+- )
+- {
++ || param->u.crypt.idx >= BIP_MAX_KEYID) {
+ ret = -EINVAL;
+ goto exit;
+ }
+@@ -770,19 +739,16 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ }
+ }
+
+- if (strcmp(param->u.crypt.alg, "WEP") == 0)
+- {
++ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+- if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0))
+- {
++ if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+- if (psecuritypriv->bWepDefaultKeyIdxSet == 0)
+- {
++ if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+ /* wep default key has not been set, so use this key index as default key. */
+
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+@@ -791,8 +757,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+- if (wep_key_len == 13)
+- {
++ if (wep_key_len == 13) {
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ }
+@@ -809,13 +774,11 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ goto exit;
+ }
+
+- if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) /* 802_1x */
+- {
++ if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
+ struct sta_info *psta, *pbcmc_sta;
+ struct sta_priv *pstapriv = &padapter->stapriv;
+
+- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) /* sta mode */
+- {
++ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
+ psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+ if (psta) {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+@@ -824,18 +787,15 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+- {
++ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) {
+ psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+ }
+
+- if (param->u.crypt.set_tx == 1)/* pairwise key */
+- {
++ if (param->u.crypt.set_tx == 1) { /* pairwise key */
+
+ memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+- if (strcmp(param->u.crypt.alg, "TKIP") == 0)/* set mic key */
+- {
++ if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
+ /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
+ memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
+ memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
+@@ -845,11 +805,8 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ }
+
+ rtw_setstakey_cmd(padapter, psta, true, true);
+- }
+- else/* group key */
+- {
+- if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0)
+- {
++ } else { /* group key */
++ if (strcmp(param->u.crypt.alg, "TKIP") == 0 || strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
+ memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
+@@ -857,9 +814,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+
+ padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
+ rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
+- }
+- else if (strcmp(param->u.crypt.alg, "BIP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
+ /* save the IGTK key, length 16 bytes */
+ memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+ /*
+@@ -873,25 +828,19 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
+ }
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+- if (!pbcmc_sta)
+- {
++ if (!pbcmc_sta) {
+ /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
+- }
+- else
+- {
++ } else {
+ /* Jeff: don't disable ieee8021x_blocked while clearing key */
+ if (strcmp(param->u.crypt.alg, "none") != 0)
+ pbcmc_sta->ieee8021x_blocked = false;
+
+ if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
+- (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled))
+- {
++ (padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption3Enabled)) {
+ pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
+ }
+ }
+- }
+- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) /* adhoc mode */
+- {
++ } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
+ }
+ }
+
+@@ -949,39 +898,29 @@ static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
+
+
+ if (!mac_addr || is_broadcast_ether_addr(mac_addr))
+- {
+ param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
+- } else {
++ else
+ param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */
+- }
+
+ param->u.crypt.idx = key_index;
+
+ if (params->seq_len && params->seq)
+- {
+ memcpy(param->u.crypt.seq, (u8 *)params->seq, params->seq_len);
+- }
+
+- if (params->key_len && params->key)
+- {
++ if (params->key_len && params->key) {
+ param->u.crypt.key_len = params->key_len;
+ memcpy(param->u.crypt.key, (u8 *)params->key, params->key_len);
+ }
+
+- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
+- {
++ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
+ ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
+- }
+- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+- {
++ } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
+ if (mac_addr)
+ memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
+
+ ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
+- }
+- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true
+- || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
+- {
++ } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true
++ || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
+ ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
+ }
+
+@@ -1007,8 +946,7 @@ static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
+ struct adapter *padapter = rtw_netdev_priv(ndev);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+- if (key_index == psecuritypriv->dot11PrivacyKeyIndex)
+- {
++ if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
+ /* clear the flag of wep default key set. */
+ psecuritypriv->bWepDefaultKeyIdxSet = 0;
+ }
+@@ -1024,16 +962,14 @@ static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
+ struct adapter *padapter = rtw_netdev_priv(ndev);
+ struct security_priv *psecuritypriv = &padapter->securitypriv;
+
+- if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) /* set wep default key */
+- {
++ if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) { /* set wep default key */
+ psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
+
+ psecuritypriv->dot11PrivacyKeyIndex = key_index;
+
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+- if (psecuritypriv->dot11DefKeylen[key_index] == 13)
+- {
++ if (psecuritypriv->dot11DefKeylen[key_index] == 13) {
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ }
+@@ -1071,9 +1007,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
+
+ /* for infra./P2PClient mode */
+ if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+- && check_fwstate(pmlmepriv, _FW_LINKED)
+- )
+- {
++ && check_fwstate(pmlmepriv, _FW_LINKED)) {
+ struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+
+ if (memcmp((u8 *)mac, cur_network->network.mac_address, ETH_ALEN)) {
+@@ -1099,9 +1033,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
+ if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)
+ || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)
+ || check_fwstate(pmlmepriv, WIFI_AP_STATE))
+- && check_fwstate(pmlmepriv, _FW_LINKED)
+- )
+- {
++ && check_fwstate(pmlmepriv, _FW_LINKED)) {
+ /* TODO: should acquire station info... */
+ }
+
+@@ -1121,8 +1053,7 @@ static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
+ struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+ int ret = 0;
+
+- if (adapter_to_dvobj(padapter)->processing_dev_remove == true)
+- {
++ if (adapter_to_dvobj(padapter)->processing_dev_remove == true) {
+ ret = -EPERM;
+ goto exit;
+ }
+@@ -1141,8 +1072,7 @@ static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
+
+ old_type = rtw_wdev->iftype;
+
+- if (old_type != type)
+- {
++ if (old_type != type) {
+ pmlmeext->action_public_rxseq = 0xffff;
+ pmlmeext->action_public_dialog_token = 0xff;
+ }
+@@ -1164,8 +1094,7 @@ static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
+
+ rtw_wdev->iftype = type;
+
+- if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false)
+- {
++ if (rtw_set_802_11_infrastructure_mode(padapter, networkType) == false) {
+ rtw_wdev->iftype = old_type;
+ ret = -EPERM;
+ goto exit;
+@@ -1230,9 +1159,7 @@ void rtw_cfg80211_surveydone_event_callback(struct adapter *padapter)
+
+ /* report network only if the current channel set contains the channel to which this network belongs */
+ if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.configuration.ds_config) >= 0
+- && true == rtw_validate_ssid(&(pnetwork->network.ssid))
+- )
+- {
++ && true == rtw_validate_ssid(&(pnetwork->network.ssid))) {
+ /* ev =translate_scan(padapter, a, pnetwork, ev, stop); */
+ rtw_cfg80211_inform_bss(padapter, pnetwork);
+ }
+@@ -1249,13 +1176,10 @@ static int rtw_cfg80211_set_probe_req_wpsp2pie(struct adapter *padapter, char *b
+ u8 *wps_ie;
+ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+- if (len > 0)
+- {
++ if (len > 0) {
+ wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
+- if (wps_ie)
+- {
+- if (pmlmepriv->wps_probe_req_ie)
+- {
++ if (wps_ie) {
++ if (pmlmepriv->wps_probe_req_ie) {
+ pmlmepriv->wps_probe_req_ie_len = 0;
+ kfree(pmlmepriv->wps_probe_req_ie);
+ pmlmepriv->wps_probe_req_ie = NULL;
+@@ -1307,10 +1231,8 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
+ pwdev_priv->scan_request = request;
+ spin_unlock_bh(&pwdev_priv->scan_req_lock);
+
+- if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
+- {
+- if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS|_FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
+- {
++ if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
++ if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS|_FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
+ need_indicate_scan_done = true;
+ goto check_need_indicate_scan_done;
+ }
+@@ -1333,15 +1255,13 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
+ goto check_need_indicate_scan_done;
+ }
+
+- if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true)
+- {
++ if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
+ static unsigned long lastscantime = 0;
+ unsigned long passtime;
+
+ passtime = jiffies_to_msecs(jiffies - lastscantime);
+ lastscantime = jiffies;
+- if (passtime > 12000)
+- {
++ if (passtime > 12000) {
+ need_indicate_scan_done = true;
+ goto check_need_indicate_scan_done;
+ }
+@@ -1380,9 +1300,7 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
+ } else if (request->n_channels <= 4) {
+ for (j = request->n_channels - 1; j >= 0; j--)
+ for (i = 0; i < survey_times; i++)
+- {
+ memcpy(&ch[j*survey_times+i], &ch[j], sizeof(struct rtw_ieee80211_channel));
+- }
+ _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, ch, survey_times * request->n_channels);
+ } else {
+ _status = rtw_sitesurvey_cmd(padapter, ssid, RTW_SSID_SCAN_AMOUNT, NULL, 0);
+@@ -1391,14 +1309,11 @@ static int cfg80211_rtw_scan(struct wiphy *wiphy
+
+
+ if (_status == false)
+- {
+ ret = -1;
+- }
+
+ check_need_indicate_scan_done:
+ kfree(ssid);
+- if (need_indicate_scan_done)
+- {
++ if (need_indicate_scan_done) {
+ rtw_cfg80211_surveydone_event_callback(padapter);
+ rtw_cfg80211_indicate_scan_done(padapter, false);
+ }
+@@ -1424,9 +1339,7 @@ static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32
+
+
+ if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
+- {
+ psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
+- }
+
+ return 0;
+
+@@ -1585,8 +1498,7 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
+ if (pairwise_cipher == 0)
+ pairwise_cipher = WPA_CIPHER_NONE;
+
+- switch (group_cipher)
+- {
++ switch (group_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+@@ -1609,8 +1521,7 @@ static int rtw_cfg80211_set_wpa_ie(struct adapter *padapter, u8 *pie, size_t iel
+ break;
+ }
+
+- switch (pairwise_cipher)
+- {
++ switch (pairwise_cipher) {
+ case WPA_CIPHER_NONE:
+ padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
+ padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
+@@ -1731,8 +1642,7 @@ static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
+
+ rtw_wdev->iftype = NL80211_IFTYPE_STATION;
+
+- if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure) == false)
+- {
++ if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure) == false) {
+ rtw_wdev->iftype = old_type;
+ ret = -EPERM;
+ goto leave_ibss;
+@@ -1792,9 +1702,8 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
+ ret = -EBUSY;
+ goto exit;
+ }
+- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true) {
++ if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == true)
+ rtw_scan_abort(padapter);
+- }
+
+ psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
+ psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
+@@ -2287,9 +2196,8 @@ static int rtw_cfg80211_add_monitor_if(struct adapter *padapter, char *name, str
+ mon_ndev->ieee80211_ptr = mon_wdev;
+
+ ret = cfg80211_register_netdevice(mon_ndev);
+- if (ret) {
++ if (ret)
+ goto out;
+- }
+
+ *ndev = pwdev_priv->pmon_ndev = mon_ndev;
+ memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ+1);
+@@ -2402,11 +2310,10 @@ static int rtw_add_beacon(struct adapter *adapter, const u8 *head, size_t head_l
+ rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, WLAN_EID_VENDOR_SPECIFIC, P2P_OUI, 4);
+ rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, WLAN_EID_VENDOR_SPECIFIC, WFD_OUI, 4);
+
+- if (rtw_check_beacon_data(adapter, pbuf, len) == _SUCCESS) {
++ if (rtw_check_beacon_data(adapter, pbuf, len) == _SUCCESS)
+ ret = 0;
+- } else {
++ else
+ ret = -EINVAL;
+- }
+
+
+ kfree(pbuf);
+--
+2.39.2
+
--- /dev/null
+From ae2b09751e9377de8a482d56e363f92cccb01d96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jan 2022 09:14:54 +0530
+Subject: Staging: rtl8723bs: Placing opening { braces in previous line
+
+From: Jagath Jog J <jagathjog1996@gmail.com>
+
+[ Upstream commit 1d7280898f683ca824fc5eab5c486a583a81473b ]
+
+Fix following checkpatch.pl error by placing opening {
+braces in previous line
+ERROR: that open brace { should be on the previous line
+
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
+Link: https://lore.kernel.org/r/20220124034456.8665-2-jagathjog1996@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 05cbcc415c9b ("staging: rtl8723bs: Fix key-store index handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 98 ++++++-------------
+ 1 file changed, 32 insertions(+), 66 deletions(-)
+
+diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+index 20d05b4ee63e2..2404f7f84d82a 100644
+--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
++++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+@@ -113,13 +113,10 @@ static struct ieee80211_supported_band *rtw_spt_band_alloc(
+ struct ieee80211_supported_band *spt_band = NULL;
+ int n_channels, n_bitrates;
+
+- if (band == NL80211_BAND_2GHZ)
+- {
++ if (band == NL80211_BAND_2GHZ) {
+ n_channels = RTW_2G_CHANNELS_NUM;
+ n_bitrates = RTW_G_RATES_NUM;
+- }
+- else
+- {
++ } else {
+ goto exit;
+ }
+
+@@ -135,8 +132,7 @@ static struct ieee80211_supported_band *rtw_spt_band_alloc(
+ spt_band->n_channels = n_channels;
+ spt_band->n_bitrates = n_bitrates;
+
+- if (band == NL80211_BAND_2GHZ)
+- {
++ if (band == NL80211_BAND_2GHZ) {
+ rtw_2g_channels_init(spt_band->channels);
+ rtw_2g_rates_init(spt_band->bitrates);
+ }
+@@ -235,8 +231,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
+ {
+ u16 wapi_len = 0;
+
+- if (rtw_get_wapi_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &wapi_len) > 0)
+- {
++ if (rtw_get_wapi_ie(pnetwork->network.ies, pnetwork->network.ie_length, NULL, &wapi_len) > 0) {
+ if (wapi_len > 0)
+ goto exit;
+ }
+@@ -244,8 +239,7 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
+
+ /* To reduce PBC Overlap rate */
+ /* spin_lock_bh(&pwdev_priv->scan_req_lock); */
+- if (adapter_wdev_data(padapter)->scan_request)
+- {
++ if (adapter_wdev_data(padapter)->scan_request) {
+ u8 *psr = NULL, sr = 0;
+ struct ndis_802_11_ssid *pssid = &pnetwork->network.ssid;
+ struct cfg80211_scan_request *request = adapter_wdev_data(padapter)->scan_request;
+@@ -258,14 +252,12 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct adapter *padapter, struct wl
+ if (wpsie && wpsielen > 0)
+ psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
+
+- if (sr != 0)
+- {
+- if (request->n_ssids == 1 && request->n_channels == 1) /* it means under processing WPS */
+- {
++ if (sr != 0) {
++ /* it means under processing WPS */
++ if (request->n_ssids == 1 && request->n_channels == 1) {
+ if (ssids[0].ssid_len != 0 &&
+ (pssid->ssid_length != ssids[0].ssid_len ||
+- memcmp(pssid->ssid, ssids[0].ssid, ssids[0].ssid_len)))
+- {
++ memcmp(pssid->ssid, ssids[0].ssid, ssids[0].ssid_len))) {
+ if (psr)
+ *psr = 0; /* clear sr */
+ }
+@@ -374,8 +366,7 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
+ int freq = (int)cur_network->network.configuration.ds_config;
+ struct ieee80211_channel *chan;
+
+- if (pwdev->iftype != NL80211_IFTYPE_ADHOC)
+- {
++ if (pwdev->iftype != NL80211_IFTYPE_ADHOC) {
+ return;
+ }
+
+@@ -383,14 +374,11 @@ void rtw_cfg80211_ibss_indicate_connect(struct adapter *padapter)
+ struct wlan_bssid_ex *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
+ struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
+
+- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)
+- {
++ if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
+
+ memcpy(&cur_network->network, pnetwork, sizeof(struct wlan_bssid_ex));
+ rtw_cfg80211_inform_bss(padapter, cur_network);
+- }
+- else
+- {
++ } else {
+ if (!scanned) {
+ rtw_warn_on(1);
+ return;
+@@ -473,9 +461,7 @@ void rtw_cfg80211_indicate_connect(struct adapter *padapter)
+ roam_info.resp_ie_len =
+ pmlmepriv->assoc_rsp_len-sizeof(struct ieee80211_hdr_3addr)-6;
+ cfg80211_roamed(padapter->pnetdev, &roam_info, GFP_ATOMIC);
+- }
+- else
+- {
++ } else {
+ cfg80211_connect_result(padapter->pnetdev, cur_network->network.mac_address
+ , pmlmepriv->assoc_req+sizeof(struct ieee80211_hdr_3addr)+2
+ , pmlmepriv->assoc_req_len-sizeof(struct ieee80211_hdr_3addr)-2
+@@ -527,24 +513,19 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+- if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len)
+- {
++ if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
+ param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
+- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
+- {
+- if (param->u.crypt.idx >= WEP_KEYS)
+- {
++ param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
++ if (param->u.crypt.idx >= WEP_KEYS) {
+ ret = -EINVAL;
+ goto exit;
+ }
+- }
+- else
+- {
++ } else {
+ psta = rtw_get_stainfo(pstapriv, param->sta_addr);
+ if (!psta)
+ /* ret = -EINVAL; */
+@@ -554,24 +535,20 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ if (strcmp(param->u.crypt.alg, "none") == 0 && !psta)
+ goto exit;
+
+- if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta)
+- {
++ if (strcmp(param->u.crypt.alg, "WEP") == 0 && !psta) {
+ wep_key_idx = param->u.crypt.idx;
+ wep_key_len = param->u.crypt.key_len;
+
+- if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0))
+- {
++ if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+- if (wep_key_len > 0)
+- {
++ if (wep_key_len > 0) {
+ wep_key_len = wep_key_len <= 5 ? 5 : 13;
+ }
+
+- if (psecuritypriv->bWepDefaultKeyIdxSet == 0)
+- {
++ if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
+ /* wep default key has not been set, so use this key index as default key. */
+
+ psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
+@@ -579,8 +556,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+
+- if (wep_key_len == 13)
+- {
++ if (wep_key_len == 13) {
+ psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ }
+@@ -598,24 +574,19 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ }
+
+-
+- if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) /* group key */
+- {
+- if (param->u.crypt.set_tx == 0) /* group key */
+- {
+- if (strcmp(param->u.crypt.alg, "WEP") == 0)
+- {
++ /* group key */
++ if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
++ /* group key */
++ if (param->u.crypt.set_tx == 0) {
++ if (strcmp(param->u.crypt.alg, "WEP") == 0) {
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+
+ psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
+- if (param->u.crypt.key_len == 13)
+- {
++ if (param->u.crypt.key_len == 13) {
+ psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
+ }
+
+- }
+- else if (strcmp(param->u.crypt.alg, "TKIP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
+
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+@@ -627,15 +598,11 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+
+ psecuritypriv->busetkipkey = true;
+
+- }
+- else if (strcmp(param->u.crypt.alg, "CCMP") == 0)
+- {
++ } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
+ psecuritypriv->dot118021XGrpPrivacy = _AES_;
+
+ memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
+- }
+- else
+- {
++ } else {
+ psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
+ }
+
+@@ -648,8 +615,7 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
+ rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
+
+ pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+- if (pbcmc_sta)
+- {
++ if (pbcmc_sta) {
+ pbcmc_sta->ieee8021x_blocked = false;
+ pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;/* rx will use bmc_sta's dot118021XPrivacy */
+ }
+--
+2.39.2
+
--- /dev/null
+From b8e38b713d9cf62b761c2af3dcef58380152214c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Feb 2023 10:25:52 +0100
+Subject: tpm/eventlog: Don't abort tpm_read_log on faulty ACPI address
+
+From: Morten Linderud <morten@linderud.pw>
+
+[ Upstream commit 80a6c216b16d7f5c584d2148c2e4345ea4eb06ce ]
+
+tpm_read_log_acpi() should return -ENODEV when no eventlog from the ACPI
+table is found. If the firmware vendor includes an invalid log address
+we are unable to map from the ACPI memory and tpm_read_log() returns -EIO
+which would abort discovery of the eventlog.
+
+Change the return value from -EIO to -ENODEV when acpi_os_map_iomem()
+fails to map the event log.
+
+The following hardware was used to test this issue:
+ Framework Laptop (Pre-production)
+ BIOS: INSYDE Corp, Revision: 3.2
+ TPM Device: NTC, Firmware Revision: 7.2
+
+Dump of the faulty ACPI TPM2 table:
+ [000h 0000 4] Signature : "TPM2" [Trusted Platform Module hardware interface Table]
+ [004h 0004 4] Table Length : 0000004C
+ [008h 0008 1] Revision : 04
+ [009h 0009 1] Checksum : 2B
+ [00Ah 0010 6] Oem ID : "INSYDE"
+ [010h 0016 8] Oem Table ID : "TGL-ULT"
+ [018h 0024 4] Oem Revision : 00000002
+ [01Ch 0028 4] Asl Compiler ID : "ACPI"
+ [020h 0032 4] Asl Compiler Revision : 00040000
+
+ [024h 0036 2] Platform Class : 0000
+ [026h 0038 2] Reserved : 0000
+ [028h 0040 8] Control Address : 0000000000000000
+ [030h 0048 4] Start Method : 06 [Memory Mapped I/O]
+
+ [034h 0052 12] Method Parameters : 00 00 00 00 00 00 00 00 00 00 00 00
+ [040h 0064 4] Minimum Log Length : 00010000
+ [044h 0068 8] Log Address : 000000004053D000
+
+Fixes: 0cf577a03f21 ("tpm: Fix handling of missing event log")
+Tested-by: Erkki Eilonen <erkki@bearmetal.eu>
+Signed-off-by: Morten Linderud <morten@linderud.pw>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/eventlog/acpi.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
+index 0913d3eb8d518..cd266021d0103 100644
+--- a/drivers/char/tpm/eventlog/acpi.c
++++ b/drivers/char/tpm/eventlog/acpi.c
+@@ -143,8 +143,12 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
+
+ ret = -EIO;
+ virt = acpi_os_map_iomem(start, len);
+- if (!virt)
++ if (!virt) {
++ dev_warn(&chip->dev, "%s: Failed to map ACPI memory\n", __func__);
++ /* try EFI log next */
++ ret = -ENODEV;
+ goto err;
++ }
+
+ memcpy_fromio(log->bios_event_log, virt, len);
+
+--
+2.39.2
+
--- /dev/null
+From f64f2da35cfb3521462ecec2efd2c67ad4b09381 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 16:21:06 +0100
+Subject: watch_queue: fix IOC_WATCH_QUEUE_SET_SIZE alloc error paths
+
+From: David Disseldorp <ddiss@suse.de>
+
+[ Upstream commit 03e1d60e177eedbd302b77af4ea5e21b5a7ade31 ]
+
+The watch_queue_set_size() allocation error paths return the ret value
+set via the prior pipe_resize_ring() call, which will always be zero.
+
+As a result, IOC_WATCH_QUEUE_SET_SIZE callers such as "keyctl watch"
+fail to detect kernel wqueue->notes allocation failures and proceed to
+KEYCTL_WATCH_KEY, with any notifications subsequently lost.
+
+Fixes: c73be61cede58 ("pipe: Add general notification queue support")
+Signed-off-by: David Disseldorp <ddiss@suse.de>
+Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/watch_queue.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/kernel/watch_queue.c b/kernel/watch_queue.c
+index 1059ef6c3711a..54cbaa9711398 100644
+--- a/kernel/watch_queue.c
++++ b/kernel/watch_queue.c
+@@ -274,6 +274,7 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes)
+ if (ret < 0)
+ goto error;
+
++ ret = -ENOMEM;
+ pages = kcalloc(sizeof(struct page *), nr_pages, GFP_KERNEL);
+ if (!pages)
+ goto error;
+--
+2.39.2
+
--- /dev/null
+From e5772e2e8f1bfd5feeb4caa9e37d2a6600aa82de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:14 -0800
+Subject: xfs: fallocate() should call file_modified()
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit fbe7e520036583a783b13ff9744e35c2a329d9a4 upsream.
+
+In XFS, we always update the inode change and modification time when
+any fallocate() operation succeeds. Furthermore, as various
+fallocate modes can change the file contents (extending EOF,
+punching holes, zeroing things, shifting extents), we should drop
+file privileges like suid just like we do for a regular write().
+There's already a VFS helper that figures all this out for us, so
+use that.
+
+The net effect of this is that we no longer drop suid/sgid if the
+caller is root, but we also now drop file capabilities.
+
+We also move the xfs_update_prealloc_flags() function so that it now
+is only called by the scope that needs to set the the prealloc flag.
+
+Based on a patch from Darrick Wong.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_file.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
+index 752b676c92e3f..020e0a412287a 100644
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -954,6 +954,10 @@ xfs_file_fallocate(
+ goto out_unlock;
+ }
+
++ error = file_modified(file);
++ if (error)
++ goto out_unlock;
++
+ if (mode & FALLOC_FL_PUNCH_HOLE) {
+ error = xfs_free_file_space(ip, offset, len);
+ if (error)
+@@ -1055,11 +1059,12 @@ xfs_file_fallocate(
+ if (error)
+ goto out_unlock;
+ }
+- }
+
+- error = xfs_update_prealloc_flags(ip, flags);
+- if (error)
+- goto out_unlock;
++ error = xfs_update_prealloc_flags(ip, XFS_PREALLOC_SET);
++ if (error)
++ goto out_unlock;
++
++ }
+
+ /* Change file size if needed */
+ if (new_size) {
+--
+2.39.2
+
--- /dev/null
+From 562ab7efef31bd4458c90e038a0d630232e89b16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:13 -0800
+Subject: xfs: remove XFS_PREALLOC_SYNC
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit 472c6e46f589c26057596dcba160712a5b3e02c5 upstream.
+
+[partial backport for dependency -
+ xfs_ioc_space() still uses XFS_PREALLOC_SYNC]
+
+Callers can acheive the same thing by calling xfs_log_force_inode()
+after making their modifications. There is no need for
+xfs_update_prealloc_flags() to do this.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_file.c | 13 +++++++------
+ fs/xfs/xfs_pnfs.c | 6 ++++--
+ 2 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
+index 240eb932c014b..752b676c92e3f 100644
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -95,8 +95,6 @@ xfs_update_prealloc_flags(
+ ip->i_diflags &= ~XFS_DIFLAG_PREALLOC;
+
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+- if (flags & XFS_PREALLOC_SYNC)
+- xfs_trans_set_sync(tp);
+ return xfs_trans_commit(tp);
+ }
+
+@@ -1059,9 +1057,6 @@ xfs_file_fallocate(
+ }
+ }
+
+- if (file->f_flags & O_DSYNC)
+- flags |= XFS_PREALLOC_SYNC;
+-
+ error = xfs_update_prealloc_flags(ip, flags);
+ if (error)
+ goto out_unlock;
+@@ -1084,8 +1079,14 @@ xfs_file_fallocate(
+ * leave shifted extents past EOF and hence losing access to
+ * the data that is contained within them.
+ */
+- if (do_file_insert)
++ if (do_file_insert) {
+ error = xfs_insert_file_space(ip, offset, len);
++ if (error)
++ goto out_unlock;
++ }
++
++ if (file->f_flags & O_DSYNC)
++ error = xfs_log_force_inode(ip);
+
+ out_unlock:
+ xfs_iunlock(ip, iolock);
+diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
+index 8865f7d4404ae..3a82a13d880c2 100644
+--- a/fs/xfs/xfs_pnfs.c
++++ b/fs/xfs/xfs_pnfs.c
+@@ -164,10 +164,12 @@ xfs_fs_map_blocks(
+ * that the blocks allocated and handed out to the client are
+ * guaranteed to be present even after a server crash.
+ */
+- error = xfs_update_prealloc_flags(ip,
+- XFS_PREALLOC_SET | XFS_PREALLOC_SYNC);
++ error = xfs_update_prealloc_flags(ip, XFS_PREALLOC_SET);
++ if (!error)
++ error = xfs_log_force_inode(ip);
+ if (error)
+ goto out_unlock;
++
+ } else {
+ xfs_iunlock(ip, lock_flags);
+ }
+--
+2.39.2
+
--- /dev/null
+From 4eafcd9d73d2055b99e9547db132f08df7458c9e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:15 -0800
+Subject: xfs: set prealloc flag in xfs_alloc_file_space()
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit 0b02c8c0d75a738c98c35f02efb36217c170d78c upsream.
+
+Now that we only call xfs_update_prealloc_flags() from
+xfs_file_fallocate() in the case where we need to set the
+preallocation flag, do this in xfs_alloc_file_space() where we
+already have the inode joined into a transaction and get
+rid of the call to xfs_update_prealloc_flags() from the fallocate
+code.
+
+This also means that we now correctly avoid setting the
+XFS_DIFLAG_PREALLOC flag when xfs_is_always_cow_inode() is true, as
+these inodes will never have preallocated extents.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_bmap_util.c | 9 +++------
+ fs/xfs/xfs_file.c | 8 --------
+ 2 files changed, 3 insertions(+), 14 deletions(-)
+
+diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
+index 73a36b7be3bd1..fd2ad6a3019ca 100644
+--- a/fs/xfs/xfs_bmap_util.c
++++ b/fs/xfs/xfs_bmap_util.c
+@@ -851,9 +851,6 @@ xfs_alloc_file_space(
+ rblocks = 0;
+ }
+
+- /*
+- * Allocate and setup the transaction.
+- */
+ error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write,
+ dblocks, rblocks, false, &tp);
+ if (error)
+@@ -870,9 +867,9 @@ xfs_alloc_file_space(
+ if (error)
+ goto error;
+
+- /*
+- * Complete the transaction
+- */
++ ip->i_diflags |= XFS_DIFLAG_PREALLOC;
++ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
++
+ error = xfs_trans_commit(tp);
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ if (error)
+diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
+index 020e0a412287a..8cd0c3df253f9 100644
+--- a/fs/xfs/xfs_file.c
++++ b/fs/xfs/xfs_file.c
+@@ -909,7 +909,6 @@ xfs_file_fallocate(
+ struct inode *inode = file_inode(file);
+ struct xfs_inode *ip = XFS_I(inode);
+ long error;
+- enum xfs_prealloc_flags flags = 0;
+ uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
+ loff_t new_size = 0;
+ bool do_file_insert = false;
+@@ -1007,8 +1006,6 @@ xfs_file_fallocate(
+ }
+ do_file_insert = true;
+ } else {
+- flags |= XFS_PREALLOC_SET;
+-
+ if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+ offset + len > i_size_read(inode)) {
+ new_size = offset + len;
+@@ -1059,11 +1056,6 @@ xfs_file_fallocate(
+ if (error)
+ goto out_unlock;
+ }
+-
+- error = xfs_update_prealloc_flags(ip, XFS_PREALLOC_SET);
+- if (error)
+- goto out_unlock;
+-
+ }
+
+ /* Change file size if needed */
+--
+2.39.2
+
--- /dev/null
+From 56b19146aae8a2c743cf53881605414b4c70c718 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Mar 2023 10:59:12 -0800
+Subject: xfs: use setattr_copy to set vfs inode attributes
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+commit e014f37db1a2d109afa750042ac4d69cf3e3d88e upsream.
+
+Filipe Manana pointed out that XFS' behavior w.r.t. setuid/setgid
+revocation isn't consistent with btrfs[1] or ext4. Those two
+filesystems use the VFS function setattr_copy to convey certain
+attributes from struct iattr into the VFS inode structure.
+
+Andrey Zhadchenko reported[2] that XFS uses the wrong user namespace to
+decide if it should clear setgid and setuid on a file attribute update.
+This is a second symptom of the problem that Filipe noticed.
+
+XFS, on the other hand, open-codes setattr_copy in xfs_setattr_mode,
+xfs_setattr_nonsize, and xfs_setattr_time. Regrettably, setattr_copy is
+/not/ a simple copy function; it contains additional logic to clear the
+setgid bit when setting the mode, and XFS' version no longer matches.
+
+The VFS implements its own setuid/setgid stripping logic, which
+establishes consistent behavior. It's a tad unfortunate that it's
+scattered across notify_change, should_remove_suid, and setattr_copy but
+XFS should really follow the Linux VFS. Adapt XFS to use the VFS
+functions and get rid of the old functions.
+
+[1] https://lore.kernel.org/fstests/CAL3q7H47iNQ=Wmk83WcGB-KBJVOEtR9+qGczzCeXJ9Y2KCV25Q@mail.gmail.com/
+[2] https://lore.kernel.org/linux-xfs/20220221182218.748084-1-andrey.zhadchenko@virtuozzo.com/
+
+Fixes: 7fa294c8991c ("userns: Allow chown and setgid preservation")
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Tested-by: Leah Rumancik <leah.rumancik@gmail.com>
+Acked-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/xfs/xfs_iops.c | 56 +++--------------------------------------------
+ fs/xfs/xfs_pnfs.c | 3 ++-
+ 2 files changed, 5 insertions(+), 54 deletions(-)
+
+diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
+index a607d6aca5c4d..1eb71275e5b09 100644
+--- a/fs/xfs/xfs_iops.c
++++ b/fs/xfs/xfs_iops.c
+@@ -634,37 +634,6 @@ xfs_vn_getattr(
+ return 0;
+ }
+
+-static void
+-xfs_setattr_mode(
+- struct xfs_inode *ip,
+- struct iattr *iattr)
+-{
+- struct inode *inode = VFS_I(ip);
+- umode_t mode = iattr->ia_mode;
+-
+- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+-
+- inode->i_mode &= S_IFMT;
+- inode->i_mode |= mode & ~S_IFMT;
+-}
+-
+-void
+-xfs_setattr_time(
+- struct xfs_inode *ip,
+- struct iattr *iattr)
+-{
+- struct inode *inode = VFS_I(ip);
+-
+- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+-
+- if (iattr->ia_valid & ATTR_ATIME)
+- inode->i_atime = iattr->ia_atime;
+- if (iattr->ia_valid & ATTR_CTIME)
+- inode->i_ctime = iattr->ia_ctime;
+- if (iattr->ia_valid & ATTR_MTIME)
+- inode->i_mtime = iattr->ia_mtime;
+-}
+-
+ static int
+ xfs_vn_change_ok(
+ struct user_namespace *mnt_userns,
+@@ -763,16 +732,6 @@ xfs_setattr_nonsize(
+ gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
+ uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
+
+- /*
+- * CAP_FSETID overrides the following restrictions:
+- *
+- * The set-user-ID and set-group-ID bits of a file will be
+- * cleared upon successful return from chown()
+- */
+- if ((inode->i_mode & (S_ISUID|S_ISGID)) &&
+- !capable(CAP_FSETID))
+- inode->i_mode &= ~(S_ISUID|S_ISGID);
+-
+ /*
+ * Change the ownerships and register quota modifications
+ * in the transaction.
+@@ -784,7 +743,6 @@ xfs_setattr_nonsize(
+ olddquot1 = xfs_qm_vop_chown(tp, ip,
+ &ip->i_udquot, udqp);
+ }
+- inode->i_uid = uid;
+ }
+ if (!gid_eq(igid, gid)) {
+ if (XFS_IS_GQUOTA_ON(mp)) {
+@@ -795,15 +753,10 @@ xfs_setattr_nonsize(
+ olddquot2 = xfs_qm_vop_chown(tp, ip,
+ &ip->i_gdquot, gdqp);
+ }
+- inode->i_gid = gid;
+ }
+ }
+
+- if (mask & ATTR_MODE)
+- xfs_setattr_mode(ip, iattr);
+- if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+- xfs_setattr_time(ip, iattr);
+-
++ setattr_copy(mnt_userns, inode, iattr);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+ XFS_STATS_INC(mp, xs_ig_attrchg);
+@@ -1028,11 +981,8 @@ xfs_setattr_size(
+ xfs_inode_clear_eofblocks_tag(ip);
+ }
+
+- if (iattr->ia_valid & ATTR_MODE)
+- xfs_setattr_mode(ip, iattr);
+- if (iattr->ia_valid & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
+- xfs_setattr_time(ip, iattr);
+-
++ ASSERT(!(iattr->ia_valid & (ATTR_UID | ATTR_GID)));
++ setattr_copy(mnt_userns, inode, iattr);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+ XFS_STATS_INC(mp, xs_ig_attrchg);
+diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c
+index 5e1d29d8b2e73..8865f7d4404ae 100644
+--- a/fs/xfs/xfs_pnfs.c
++++ b/fs/xfs/xfs_pnfs.c
+@@ -283,7 +283,8 @@ xfs_fs_commit_blocks(
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+
+- xfs_setattr_time(ip, iattr);
++ ASSERT(!(iattr->ia_valid & (ATTR_UID | ATTR_GID)));
++ setattr_copy(&init_user_ns, inode, iattr);
+ if (update_isize) {
+ i_size_write(inode, iattr->ia_size);
+ ip->i_disk_size = iattr->ia_size;
+--
+2.39.2
+