]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: allow multiple opens of /sys/fs/selinux/policy
authorStephen Smalley <stephen.smalley.work@gmail.com>
Tue, 5 May 2026 14:06:38 +0000 (10:06 -0400)
committerPaul Moore <paul@paul-moore.com>
Tue, 5 May 2026 19:47:25 +0000 (15:47 -0400)
Currently there can only be a single open of /sys/fs/selinux/policy at
any time. This allows any process to block any other process from
reading the kernel policy. The original motivation seems to have been
a mix of preventing an inconsistent view of the policy size and
preventing userspace from allocating kernel memory without bound, but
this is arguably equally bad. Eliminate the policy_opened flag and
shrink the critical section that the policy mutex is held. While we
are making changes here, drop a couple of extraneous BUG_ONs.

Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/selinux/20100726193414.19538.64028.stgit@paris.rdu.redhat.com/
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/selinuxfs.c

index 6ed6693091323528e6255067bbf59bef74a2f7e1..a43a38a3ae25beef82aacddace2e0eb17db3c3fa 100644 (file)
@@ -76,7 +76,6 @@ struct selinux_fs_info {
        int *bool_pending_values;
        struct dentry *class_dir;
        unsigned long last_class_ino;
-       bool policy_opened;
        unsigned long last_ino;
        struct super_block *sb;
 };
@@ -340,44 +339,31 @@ struct policy_load_memory {
 
 static int sel_open_policy(struct inode *inode, struct file *filp)
 {
-       struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
        struct policy_load_memory *plm = NULL;
        int rc;
 
-       BUG_ON(filp->private_data);
-
-       mutex_lock(&selinux_state.policy_mutex);
-
        rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                          SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
        if (rc)
-               goto err;
-
-       rc = -EBUSY;
-       if (fsi->policy_opened)
-               goto err;
+               return rc;
 
-       rc = -ENOMEM;
        plm = kzalloc_obj(*plm);
        if (!plm)
-               goto err;
+               return -ENOMEM;
 
+       mutex_lock(&selinux_state.policy_mutex);
        rc = security_read_policy(&plm->data, &plm->len);
        if (rc)
                goto err;
-
        if ((size_t)i_size_read(inode) != plm->len) {
                inode_lock(inode);
                i_size_write(inode, plm->len);
                inode_unlock(inode);
        }
-
-       fsi->policy_opened = 1;
+       mutex_unlock(&selinux_state.policy_mutex);
 
        filp->private_data = plm;
 
-       mutex_unlock(&selinux_state.policy_mutex);
-
        return 0;
 err:
        mutex_unlock(&selinux_state.policy_mutex);
@@ -390,13 +376,8 @@ err:
 
 static int sel_release_policy(struct inode *inode, struct file *filp)
 {
-       struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
        struct policy_load_memory *plm = filp->private_data;
 
-       BUG_ON(!plm);
-
-       fsi->policy_opened = 0;
-
        vfree(plm->data);
        kfree(plm);