--- /dev/null
+From db978da8fa1d0819b210c137d31a339149b88875 Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Thu, 10 Nov 2016 22:18:28 +0100
+Subject: proc: Pass file mode to proc_pid_make_inode
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit db978da8fa1d0819b210c137d31a339149b88875 upstream.
+
+Pass the file mode of the proc inode to be created to
+proc_pid_make_inode. In proc_pid_make_inode, initialize inode->i_mode
+before calling security_task_to_inode. This allows selinux to set
+isec->sclass right away without introducing "half-initialized" inode
+security structs.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/base.c | 23 +++++++++--------------
+ fs/proc/fd.c | 6 ++----
+ fs/proc/internal.h | 2 +-
+ fs/proc/namespaces.c | 3 +--
+ security/selinux/hooks.c | 1 +
+ 5 files changed, 14 insertions(+), 21 deletions(-)
+
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -1676,7 +1676,8 @@ const struct inode_operations proc_pid_l
+
+ /* building an inode */
+
+-struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
++struct inode *proc_pid_make_inode(struct super_block * sb,
++ struct task_struct *task, umode_t mode)
+ {
+ struct inode * inode;
+ struct proc_inode *ei;
+@@ -1690,6 +1691,7 @@ struct inode *proc_pid_make_inode(struct
+
+ /* Common stuff */
+ ei = PROC_I(inode);
++ inode->i_mode = mode;
+ inode->i_ino = get_next_ino();
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ inode->i_op = &proc_def_inode_operations;
+@@ -2041,7 +2043,9 @@ proc_map_files_instantiate(struct inode
+ struct proc_inode *ei;
+ struct inode *inode;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK |
++ ((mode & FMODE_READ ) ? S_IRUSR : 0) |
++ ((mode & FMODE_WRITE) ? S_IWUSR : 0));
+ if (!inode)
+ return -ENOENT;
+
+@@ -2050,12 +2054,6 @@ proc_map_files_instantiate(struct inode
+
+ inode->i_op = &proc_map_files_link_inode_operations;
+ inode->i_size = 64;
+- inode->i_mode = S_IFLNK;
+-
+- if (mode & FMODE_READ)
+- inode->i_mode |= S_IRUSR;
+- if (mode & FMODE_WRITE)
+- inode->i_mode |= S_IWUSR;
+
+ d_set_d_op(dentry, &tid_map_files_dentry_operations);
+ d_add(dentry, inode);
+@@ -2409,12 +2407,11 @@ static int proc_pident_instantiate(struc
+ struct inode *inode;
+ struct proc_inode *ei;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, p->mode);
+ if (!inode)
+ goto out;
+
+ ei = PROC_I(inode);
+- inode->i_mode = p->mode;
+ if (S_ISDIR(inode->i_mode))
+ set_nlink(inode, 2); /* Use getattr to fix if necessary */
+ if (p->iop)
+@@ -3109,11 +3106,10 @@ static int proc_pid_instantiate(struct i
+ {
+ struct inode *inode;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
+ if (!inode)
+ goto out;
+
+- inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ inode->i_op = &proc_tgid_base_inode_operations;
+ inode->i_fop = &proc_tgid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+@@ -3404,11 +3400,10 @@ static int proc_task_instantiate(struct
+ struct dentry *dentry, struct task_struct *task, const void *ptr)
+ {
+ struct inode *inode;
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
+
+ if (!inode)
+ goto out;
+- inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ inode->i_op = &proc_tid_base_inode_operations;
+ inode->i_fop = &proc_tid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+--- a/fs/proc/fd.c
++++ b/fs/proc/fd.c
+@@ -183,14 +183,13 @@ proc_fd_instantiate(struct inode *dir, s
+ struct proc_inode *ei;
+ struct inode *inode;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK);
+ if (!inode)
+ goto out;
+
+ ei = PROC_I(inode);
+ ei->fd = fd;
+
+- inode->i_mode = S_IFLNK;
+ inode->i_op = &proc_pid_link_inode_operations;
+ inode->i_size = 64;
+
+@@ -322,14 +321,13 @@ proc_fdinfo_instantiate(struct inode *di
+ struct proc_inode *ei;
+ struct inode *inode;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR);
+ if (!inode)
+ goto out;
+
+ ei = PROC_I(inode);
+ ei->fd = fd;
+
+- inode->i_mode = S_IFREG | S_IRUSR;
+ inode->i_fop = &proc_fdinfo_file_operations;
+
+ d_set_d_op(dentry, &tid_fd_dentry_operations);
+--- a/fs/proc/internal.h
++++ b/fs/proc/internal.h
+@@ -163,7 +163,7 @@ extern int proc_pid_statm(struct seq_fil
+ extern const struct dentry_operations pid_dentry_operations;
+ extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+ extern int proc_setattr(struct dentry *, struct iattr *);
+-extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *);
++extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t);
+ extern int pid_revalidate(struct dentry *, unsigned int);
+ extern int pid_delete_dentry(const struct dentry *);
+ extern int proc_pid_readdir(struct file *, struct dir_context *);
+--- a/fs/proc/namespaces.c
++++ b/fs/proc/namespaces.c
+@@ -92,12 +92,11 @@ static int proc_ns_instantiate(struct in
+ struct inode *inode;
+ struct proc_inode *ei;
+
+- inode = proc_pid_make_inode(dir->i_sb, task);
++ inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK | S_IRWXUGO);
+ if (!inode)
+ goto out;
+
+ ei = PROC_I(inode);
+- inode->i_mode = S_IFLNK|S_IRWXUGO;
+ inode->i_op = &proc_ns_link_inode_operations;
+ ei->ns_ops = ns_ops;
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -3958,6 +3958,7 @@ static void selinux_task_to_inode(struct
+ struct inode_security_struct *isec = inode->i_security;
+ u32 sid = task_sid(p);
+
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = sid;
+ isec->initialized = LABEL_INITIALIZED;
+ }
--- /dev/null
+From 13457d073c29da92001f6ee809075eaa8757fb96 Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Thu, 10 Nov 2016 22:18:29 +0100
+Subject: selinux: Clean up initialization of isec->sclass
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit 13457d073c29da92001f6ee809075eaa8757fb96 upstream.
+
+Now that isec->initialized == LABEL_INITIALIZED implies that
+isec->sclass is valid, skip such inodes immediately in
+inode_doinit_with_dentry.
+
+For the remaining inodes, initialize isec->sclass at the beginning of
+inode_doinit_with_dentry to simplify the code.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/hooks.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1395,12 +1395,15 @@ static int inode_doinit_with_dentry(stru
+ int rc = 0;
+
+ if (isec->initialized == LABEL_INITIALIZED)
+- goto out;
++ return 0;
+
+ mutex_lock(&isec->lock);
+ if (isec->initialized == LABEL_INITIALIZED)
+ goto out_unlock;
+
++ if (isec->sclass == SECCLASS_FILE)
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
++
+ sbsec = inode->i_sb->s_security;
+ if (!(sbsec->flags & SE_SBINITIALIZED)) {
+ /* Defer initialization until selinux_complete_init,
+@@ -1518,7 +1521,6 @@ static int inode_doinit_with_dentry(stru
+ isec->sid = sbsec->sid;
+
+ /* Try to obtain a transition SID. */
+- isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ rc = security_transition_sid(isec->task_sid, sbsec->sid,
+ isec->sclass, NULL, &sid);
+ if (rc)
+@@ -1554,7 +1556,6 @@ static int inode_doinit_with_dentry(stru
+ */
+ if (!dentry)
+ goto out_unlock;
+- isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ rc = selinux_genfs_get_sid(dentry, isec->sclass,
+ sbsec->flags, &sid);
+ dput(dentry);
+@@ -1569,9 +1570,6 @@ static int inode_doinit_with_dentry(stru
+
+ out_unlock:
+ mutex_unlock(&isec->lock);
+-out:
+- if (isec->sclass == SECCLASS_FILE)
+- isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ return rc;
+ }
+
--- /dev/null
+From 9287aed2ad1ff1bde5eb190bcd6dccd5f1cf47d3 Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Tue, 15 Nov 2016 11:06:40 +0100
+Subject: selinux: Convert isec->lock into a spinlock
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit 9287aed2ad1ff1bde5eb190bcd6dccd5f1cf47d3 upstream.
+
+Convert isec->lock from a mutex into a spinlock. Instead of holding
+the lock while sleeping in inode_doinit_with_dentry, set
+isec->initialized to LABEL_PENDING and release the lock. Then, when
+the sid has been determined, re-acquire the lock. If isec->initialized
+is still set to LABEL_PENDING, set isec->sid; otherwise, the sid has
+been set by another task (LABEL_INITIALIZED) or invalidated
+(LABEL_INVALID) in the meantime.
+
+This fixes a deadlock on gfs2 where
+
+ * one task is in inode_doinit_with_dentry -> gfs2_getxattr, holds
+ isec->lock, and tries to acquire the inode's glock, and
+
+ * another task is in do_xmote -> inode_go_inval ->
+ selinux_inode_invalidate_secctx, holds the inode's glock, and
+ tries to acquire isec->lock.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+[PM: minor tweaks to keep checkpatch.pl happy]
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/hooks.c | 101 +++++++++++++++++++++++---------------
+ security/selinux/include/objsec.h | 5 +
+ 2 files changed, 66 insertions(+), 40 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -231,7 +231,7 @@ static int inode_alloc_security(struct i
+ if (!isec)
+ return -ENOMEM;
+
+- mutex_init(&isec->lock);
++ spin_lock_init(&isec->lock);
+ INIT_LIST_HEAD(&isec->list);
+ isec->inode = inode;
+ isec->sid = SECINITSID_UNLABELED;
+@@ -1387,7 +1387,8 @@ static int inode_doinit_with_dentry(stru
+ {
+ struct superblock_security_struct *sbsec = NULL;
+ struct inode_security_struct *isec = inode->i_security;
+- u32 sid;
++ u32 task_sid, sid = 0;
++ u16 sclass;
+ struct dentry *dentry;
+ #define INITCONTEXTLEN 255
+ char *context = NULL;
+@@ -1397,7 +1398,7 @@ static int inode_doinit_with_dentry(stru
+ if (isec->initialized == LABEL_INITIALIZED)
+ return 0;
+
+- mutex_lock(&isec->lock);
++ spin_lock(&isec->lock);
+ if (isec->initialized == LABEL_INITIALIZED)
+ goto out_unlock;
+
+@@ -1416,12 +1417,18 @@ static int inode_doinit_with_dentry(stru
+ goto out_unlock;
+ }
+
++ sclass = isec->sclass;
++ task_sid = isec->task_sid;
++ sid = isec->sid;
++ isec->initialized = LABEL_PENDING;
++ spin_unlock(&isec->lock);
++
+ switch (sbsec->behavior) {
+ case SECURITY_FS_USE_NATIVE:
+ break;
+ case SECURITY_FS_USE_XATTR:
+ if (!(inode->i_opflags & IOP_XATTR)) {
+- isec->sid = sbsec->def_sid;
++ sid = sbsec->def_sid;
+ break;
+ }
+ /* Need a dentry, since the xattr API requires one.
+@@ -1443,7 +1450,7 @@ static int inode_doinit_with_dentry(stru
+ * inode_doinit with a dentry, before these inodes could
+ * be used again by userspace.
+ */
+- goto out_unlock;
++ goto out;
+ }
+
+ len = INITCONTEXTLEN;
+@@ -1451,7 +1458,7 @@ static int inode_doinit_with_dentry(stru
+ if (!context) {
+ rc = -ENOMEM;
+ dput(dentry);
+- goto out_unlock;
++ goto out;
+ }
+ context[len] = '\0';
+ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
+@@ -1462,14 +1469,14 @@ static int inode_doinit_with_dentry(stru
+ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
+ if (rc < 0) {
+ dput(dentry);
+- goto out_unlock;
++ goto out;
+ }
+ len = rc;
+ context = kmalloc(len+1, GFP_NOFS);
+ if (!context) {
+ rc = -ENOMEM;
+ dput(dentry);
+- goto out_unlock;
++ goto out;
+ }
+ context[len] = '\0';
+ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
+@@ -1481,7 +1488,7 @@ static int inode_doinit_with_dentry(stru
+ "%d for dev=%s ino=%ld\n", __func__,
+ -rc, inode->i_sb->s_id, inode->i_ino);
+ kfree(context);
+- goto out_unlock;
++ goto out;
+ }
+ /* Map ENODATA to the default file SID */
+ sid = sbsec->def_sid;
+@@ -1511,28 +1518,25 @@ static int inode_doinit_with_dentry(stru
+ }
+ }
+ kfree(context);
+- isec->sid = sid;
+ break;
+ case SECURITY_FS_USE_TASK:
+- isec->sid = isec->task_sid;
++ sid = task_sid;
+ break;
+ case SECURITY_FS_USE_TRANS:
+ /* Default to the fs SID. */
+- isec->sid = sbsec->sid;
++ sid = sbsec->sid;
+
+ /* Try to obtain a transition SID. */
+- rc = security_transition_sid(isec->task_sid, sbsec->sid,
+- isec->sclass, NULL, &sid);
++ rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
+ if (rc)
+- goto out_unlock;
+- isec->sid = sid;
++ goto out;
+ break;
+ case SECURITY_FS_USE_MNTPOINT:
+- isec->sid = sbsec->mntpoint_sid;
++ sid = sbsec->mntpoint_sid;
+ break;
+ default:
+ /* Default to the fs superblock SID. */
+- isec->sid = sbsec->sid;
++ sid = sbsec->sid;
+
+ if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
+ /* We must have a dentry to determine the label on
+@@ -1555,21 +1559,30 @@ static int inode_doinit_with_dentry(stru
+ * could be used again by userspace.
+ */
+ if (!dentry)
+- goto out_unlock;
+- rc = selinux_genfs_get_sid(dentry, isec->sclass,
++ goto out;
++ rc = selinux_genfs_get_sid(dentry, sclass,
+ sbsec->flags, &sid);
+ dput(dentry);
+ if (rc)
+- goto out_unlock;
+- isec->sid = sid;
++ goto out;
+ }
+ break;
+ }
+
+- isec->initialized = LABEL_INITIALIZED;
++out:
++ spin_lock(&isec->lock);
++ if (isec->initialized == LABEL_PENDING) {
++ if (!sid || rc) {
++ isec->initialized = LABEL_INVALID;
++ goto out_unlock;
++ }
++
++ isec->initialized = LABEL_INITIALIZED;
++ isec->sid = sid;
++ }
+
+ out_unlock:
+- mutex_unlock(&isec->lock);
++ spin_unlock(&isec->lock);
+ return rc;
+ }
+
+@@ -3199,9 +3212,11 @@ static void selinux_inode_post_setxattr(
+ }
+
+ isec = backing_inode_security(dentry);
++ spin_lock(&isec->lock);
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = newsid;
+ isec->initialized = LABEL_INITIALIZED;
++ spin_unlock(&isec->lock);
+
+ return;
+ }
+@@ -3298,9 +3313,11 @@ static int selinux_inode_setsecurity(str
+ if (rc)
+ return rc;
+
++ spin_lock(&isec->lock);
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = newsid;
+ isec->initialized = LABEL_INITIALIZED;
++ spin_unlock(&isec->lock);
+ return 0;
+ }
+
+@@ -3956,9 +3973,11 @@ static void selinux_task_to_inode(struct
+ struct inode_security_struct *isec = inode->i_security;
+ u32 sid = task_sid(p);
+
++ spin_lock(&isec->lock);
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ isec->sid = sid;
+ isec->initialized = LABEL_INITIALIZED;
++ spin_unlock(&isec->lock);
+ }
+
+ /* Returns error only if unable to parse addresses */
+@@ -4277,24 +4296,24 @@ static int selinux_socket_post_create(st
+ const struct task_security_struct *tsec = current_security();
+ struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
+ struct sk_security_struct *sksec;
++ u16 sclass = socket_type_to_security_class(family, type, protocol);
++ u32 sid = SECINITSID_KERNEL;
+ int err = 0;
+
+- isec->sclass = socket_type_to_security_class(family, type, protocol);
+-
+- if (kern)
+- isec->sid = SECINITSID_KERNEL;
+- else {
+- err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
++ if (!kern) {
++ err = socket_sockcreate_sid(tsec, sclass, &sid);
+ if (err)
+ return err;
+ }
+
++ isec->sclass = sclass;
++ isec->sid = sid;
+ isec->initialized = LABEL_INITIALIZED;
+
+ if (sock->sk) {
+ sksec = sock->sk->sk_security;
+- sksec->sid = isec->sid;
+- sksec->sclass = isec->sclass;
++ sksec->sclass = sclass;
++ sksec->sid = sid;
+ err = selinux_netlbl_socket_post_create(sock->sk, family);
+ }
+
+@@ -4478,16 +4497,22 @@ static int selinux_socket_accept(struct
+ int err;
+ struct inode_security_struct *isec;
+ struct inode_security_struct *newisec;
++ u16 sclass;
++ u32 sid;
+
+ err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
+ if (err)
+ return err;
+
+- newisec = inode_security_novalidate(SOCK_INODE(newsock));
+-
+ isec = inode_security_novalidate(SOCK_INODE(sock));
+- newisec->sclass = isec->sclass;
+- newisec->sid = isec->sid;
++ spin_lock(&isec->lock);
++ sclass = isec->sclass;
++ sid = isec->sid;
++ spin_unlock(&isec->lock);
++
++ newisec = inode_security_novalidate(SOCK_INODE(newsock));
++ newisec->sclass = sclass;
++ newisec->sid = sid;
+ newisec->initialized = LABEL_INITIALIZED;
+
+ return 0;
+@@ -6010,9 +6035,9 @@ static void selinux_inode_invalidate_sec
+ {
+ struct inode_security_struct *isec = inode->i_security;
+
+- mutex_lock(&isec->lock);
++ spin_lock(&isec->lock);
+ isec->initialized = LABEL_INVALID;
+- mutex_unlock(&isec->lock);
++ spin_unlock(&isec->lock);
+ }
+
+ /*
+--- a/security/selinux/include/objsec.h
++++ b/security/selinux/include/objsec.h
+@@ -39,7 +39,8 @@ struct task_security_struct {
+
+ enum label_initialized {
+ LABEL_INVALID, /* invalid or not initialized */
+- LABEL_INITIALIZED /* initialized */
++ LABEL_INITIALIZED, /* initialized */
++ LABEL_PENDING
+ };
+
+ struct inode_security_struct {
+@@ -52,7 +53,7 @@ struct inode_security_struct {
+ u32 sid; /* SID of this object */
+ u16 sclass; /* security class of this object */
+ unsigned char initialized; /* initialization flag */
+- struct mutex lock;
++ spinlock_t lock;
+ };
+
+ struct file_security_struct {
--- /dev/null
+From 83370b31a915493231e5b9addc72e4bef69f8d31 Mon Sep 17 00:00:00 2001
+From: Tianyue Ren <rentianyue@kylinos.cn>
+Date: Fri, 9 Oct 2020 09:36:30 +0800
+Subject: selinux: fix error initialization in inode_doinit_with_dentry()
+
+From: Tianyue Ren <rentianyue@kylinos.cn>
+
+commit 83370b31a915493231e5b9addc72e4bef69f8d31 upstream.
+
+Mark the inode security label as invalid if we cannot find
+a dentry so that we will retry later rather than marking it
+initialized with the unlabeled SID.
+
+Fixes: 9287aed2ad1f ("selinux: Convert isec->lock into a spinlock")
+Signed-off-by: Tianyue Ren <rentianyue@kylinos.cn>
+[PM: minor comment tweaks]
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/hooks.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1450,7 +1450,13 @@ static int inode_doinit_with_dentry(stru
+ * inode_doinit with a dentry, before these inodes could
+ * be used again by userspace.
+ */
+- goto out;
++ isec->initialized = LABEL_INVALID;
++ /*
++ * There is nothing useful to jump to the "out"
++ * label, except a needless spin lock/unlock
++ * cycle.
++ */
++ return 0;
+ }
+
+ len = INITCONTEXTLEN;
+@@ -1558,8 +1564,15 @@ static int inode_doinit_with_dentry(stru
+ * inode_doinit() with a dentry, before these inodes
+ * could be used again by userspace.
+ */
+- if (!dentry)
+- goto out;
++ if (!dentry) {
++ isec->initialized = LABEL_INVALID;
++ /*
++ * There is nothing useful to jump to the "out"
++ * label, except a needless spin lock/unlock
++ * cycle.
++ */
++ return 0;
++ }
+ rc = selinux_genfs_get_sid(dentry, sclass,
+ sbsec->flags, &sid);
+ dput(dentry);
--- /dev/null
+From 200ea5a2292dc444a818b096ae6a32ba3caa51b9 Mon Sep 17 00:00:00 2001
+From: Paul Moore <paul@paul-moore.com>
+Date: Tue, 3 Nov 2020 11:49:38 -0500
+Subject: selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
+
+From: Paul Moore <paul@paul-moore.com>
+
+commit 200ea5a2292dc444a818b096ae6a32ba3caa51b9 upstream.
+
+A previous fix, commit 83370b31a915 ("selinux: fix error initialization
+in inode_doinit_with_dentry()"), changed how failures were handled
+before a SELinux policy was loaded. Unfortunately that patch was
+potentially problematic for two reasons: it set the isec->initialized
+state without holding a lock, and it didn't set the inode's SELinux
+label to the "default" for the particular filesystem. The later can
+be a problem if/when a later attempt to revalidate the inode fails
+and SELinux reverts to the existing inode label.
+
+This patch should restore the default inode labeling that existed
+before the original fix, without affecting the LABEL_INVALID marking
+such that revalidation will still be attempted in the future.
+
+Fixes: 83370b31a915 ("selinux: fix error initialization in inode_doinit_with_dentry()")
+Reported-by: Sven Schnelle <svens@linux.ibm.com>
+Tested-by: Sven Schnelle <svens@linux.ibm.com>
+Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/hooks.c | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1450,13 +1450,7 @@ static int inode_doinit_with_dentry(stru
+ * inode_doinit with a dentry, before these inodes could
+ * be used again by userspace.
+ */
+- isec->initialized = LABEL_INVALID;
+- /*
+- * There is nothing useful to jump to the "out"
+- * label, except a needless spin lock/unlock
+- * cycle.
+- */
+- return 0;
++ goto out_invalid;
+ }
+
+ len = INITCONTEXTLEN;
+@@ -1564,15 +1558,8 @@ static int inode_doinit_with_dentry(stru
+ * inode_doinit() with a dentry, before these inodes
+ * could be used again by userspace.
+ */
+- if (!dentry) {
+- isec->initialized = LABEL_INVALID;
+- /*
+- * There is nothing useful to jump to the "out"
+- * label, except a needless spin lock/unlock
+- * cycle.
+- */
+- return 0;
+- }
++ if (!dentry)
++ goto out_invalid;
+ rc = selinux_genfs_get_sid(dentry, sclass,
+ sbsec->flags, &sid);
+ dput(dentry);
+@@ -1585,11 +1572,10 @@ static int inode_doinit_with_dentry(stru
+ out:
+ spin_lock(&isec->lock);
+ if (isec->initialized == LABEL_PENDING) {
+- if (!sid || rc) {
++ if (rc) {
+ isec->initialized = LABEL_INVALID;
+ goto out_unlock;
+ }
+-
+ isec->initialized = LABEL_INITIALIZED;
+ isec->sid = sid;
+ }
+@@ -1597,6 +1583,15 @@ out:
+ out_unlock:
+ spin_unlock(&isec->lock);
+ return rc;
++
++out_invalid:
++ spin_lock(&isec->lock);
++ if (isec->initialized == LABEL_PENDING) {
++ isec->initialized = LABEL_INVALID;
++ isec->sid = sid;
++ }
++ spin_unlock(&isec->lock);
++ return 0;
+ }
+
+ /* Convert a Linux signal to an access vector. */
--- /dev/null
+From 420591128cb206201dc444c2d42fb6f299b2ecd0 Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Thu, 10 Nov 2016 22:18:27 +0100
+Subject: selinux: Minor cleanups
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit 420591128cb206201dc444c2d42fb6f299b2ecd0 upstream.
+
+Fix the comment for function __inode_security_revalidate, which returns
+an integer.
+
+Use the LABEL_* constants consistently for isec->initialized.
+
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Alexander Grund <theflamefire89@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/selinux/hooks.c | 3 ++-
+ security/selinux/selinuxfs.c | 4 ++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -237,6 +237,7 @@ static int inode_alloc_security(struct i
+ isec->sid = SECINITSID_UNLABELED;
+ isec->sclass = SECCLASS_FILE;
+ isec->task_sid = sid;
++ isec->initialized = LABEL_INVALID;
+ inode->i_security = isec;
+
+ return 0;
+@@ -247,7 +248,7 @@ static int inode_doinit_with_dentry(stru
+ /*
+ * Try reloading inode security labels that have been marked as invalid. The
+ * @may_sleep parameter indicates when sleeping and thus reloading labels is
+- * allowed; when set to false, returns ERR_PTR(-ECHILD) when the label is
++ * allowed; when set to false, returns -ECHILD when the label is
+ * invalid. The @opt_dentry parameter should be set to a dentry of the inode;
+ * when no dentry is available, set it to NULL instead.
+ */
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -1301,7 +1301,7 @@ static int sel_make_bools(void)
+ goto out;
+
+ isec->sid = sid;
+- isec->initialized = 1;
++ isec->initialized = LABEL_INITIALIZED;
+ inode->i_fop = &sel_bool_ops;
+ inode->i_ino = i|SEL_BOOL_INO_OFFSET;
+ d_add(dentry, inode);
+@@ -1835,7 +1835,7 @@ static int sel_fill_super(struct super_b
+ isec = (struct inode_security_struct *)inode->i_security;
+ isec->sid = SECINITSID_DEVNULL;
+ isec->sclass = SECCLASS_CHR_FILE;
+- isec->initialized = 1;
++ isec->initialized = LABEL_INITIALIZED;
+
+ init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
+ d_add(dentry, inode);
arm-crypto-comment-out-gcc-warning-that-breaks-clang-builds.patch
mt7601u-add-usb-device-id-for-some-versions-of-xiaodu-wifi-dongle.patch
ion-make-user_ion_handle_put_nolock-a-void-function.patch
+selinux-minor-cleanups.patch
+proc-pass-file-mode-to-proc_pid_make_inode.patch
+selinux-clean-up-initialization-of-isec-sclass.patch
+selinux-convert-isec-lock-into-a-spinlock.patch
+selinux-fix-error-initialization-in-inode_doinit_with_dentry.patch
+selinux-fix-inode_doinit_with_dentry-label_invalid-error-handling.patch