selinux: remove the 'checkreqprot' functionality
authorPaul Moore <paul@paul-moore.com>
Thu, 16 Mar 2023 15:43:08 +0000 (11:43 -0400)
committerPaul Moore <paul@paul-moore.com>
Mon, 20 Mar 2023 16:33:50 +0000 (12:33 -0400)
We originally promised that the SELinux 'checkreqprot' functionality
would be removed no sooner than June 2021, and now that it is March
2023 it seems like it is a good time to do the final removal.  The
deprecation notice in the kernel provides plenty of detail on why
'checkreqprot' is not desirable, with the key point repeated below:

  This was a compatibility mechanism for legacy userspace and
  for the READ_IMPLIES_EXEC personality flag.  However, if set to
  1, it weakens security by allowing mappings to be made executable
  without authorization by policy.  The default value of checkreqprot
  at boot was changed starting in Linux v4.4 to 0 (i.e. check the
  actual protection), and Android and Linux distributions have been
  explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
  initialization for some time.

Along with the official deprecation notice, we have been discussing
this on-list and directly with several of the larger SELinux-based
distros and everyone is happy to see this feature finally removed.
In an attempt to catch all of the smaller, and DIY, Linux systems
we have been writing a deprecation notice URL into the kernel log,
along with a growing ssleep() penalty, when admins enabled
checkreqprot at runtime or via the kernel command line.  We have
yet to have anyone come to us and raise an objection to the
deprecation or planned removal.

It is worth noting that while this patch removes the checkreqprot
functionality, it leaves the user visible interfaces (kernel command
line and selinuxfs file) intact, just inert.  This should help
prevent breakages with existing userspace tools that correctly, but
unnecessarily, disable checkreqprot at boot or runtime.  Admins
that attempt to enable checkreqprot will be met with a removal
message in the kernel log.

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Documentation/ABI/obsolete/sysfs-selinux-checkreqprot [deleted file]
Documentation/ABI/removed/sysfs-selinux-checkreqprot [new file with mode: 0644]
security/selinux/Kconfig
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/selinuxfs.c

diff --git a/Documentation/ABI/obsolete/sysfs-selinux-checkreqprot b/Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
deleted file mode 100644 (file)
index ed6b52c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-What:          /sys/fs/selinux/checkreqprot
-Date:          April 2005 (predates git)
-KernelVersion: 2.6.12-rc2 (predates git)
-Contact:       selinux@vger.kernel.org
-Description:
-
-       The selinuxfs "checkreqprot" node allows SELinux to be configured
-       to check the protection requested by userspace for mmap/mprotect
-       calls instead of the actual protection applied by the kernel.
-       This was a compatibility mechanism for legacy userspace and
-       for the READ_IMPLIES_EXEC personality flag.  However, if set to
-       1, it weakens security by allowing mappings to be made executable
-       without authorization by policy.  The default value of checkreqprot
-       at boot was changed starting in Linux v4.4 to 0 (i.e. check the
-       actual protection), and Android and Linux distributions have been
-       explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
-       initialization for some time.  Support for setting checkreqprot to 1
-       will be removed no sooner than June 2021, at which point the kernel
-       will always cease using checkreqprot internally and will always
-       check the actual protections being applied upon mmap/mprotect calls.
-       The checkreqprot selinuxfs node will remain for backward compatibility
-       but will discard writes of the "0" value and will reject writes of the
-       "1" value when this mechanism is removed.
diff --git a/Documentation/ABI/removed/sysfs-selinux-checkreqprot b/Documentation/ABI/removed/sysfs-selinux-checkreqprot
new file mode 100644 (file)
index 0000000..f599a0a
--- /dev/null
@@ -0,0 +1,26 @@
+What:          /sys/fs/selinux/checkreqprot
+Date:          April 2005 (predates git)
+KernelVersion: 2.6.12-rc2 (predates git)
+Contact:       selinux@vger.kernel.org
+Description:
+
+       REMOVAL UPDATE: The SELinux checkreqprot functionality was removed in
+       March 2023, the original deprecation notice is shown below.
+
+       The selinuxfs "checkreqprot" node allows SELinux to be configured
+       to check the protection requested by userspace for mmap/mprotect
+       calls instead of the actual protection applied by the kernel.
+       This was a compatibility mechanism for legacy userspace and
+       for the READ_IMPLIES_EXEC personality flag.  However, if set to
+       1, it weakens security by allowing mappings to be made executable
+       without authorization by policy.  The default value of checkreqprot
+       at boot was changed starting in Linux v4.4 to 0 (i.e. check the
+       actual protection), and Android and Linux distributions have been
+       explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
+       initialization for some time.  Support for setting checkreqprot to 1
+       will be removed no sooner than June 2021, at which point the kernel
+       will always cease using checkreqprot internally and will always
+       check the actual protections being applied upon mmap/mprotect calls.
+       The checkreqprot selinuxfs node will remain for backward compatibility
+       but will discard writes of the "0" value and will reject writes of the
+       "1" value when this mechanism is removed.
index 9e921fc725386ed9c79511012a2679b6ecb52bb1..4ea9461232559fea913a60d26af0d047533c236d 100644 (file)
@@ -70,29 +70,6 @@ config SECURITY_SELINUX_AVC_STATS
          /sys/fs/selinux/avc/cache_stats, which may be monitored via
          tools such as avcstat.
 
-config SECURITY_SELINUX_CHECKREQPROT_VALUE
-       int "NSA SELinux checkreqprot default value"
-       depends on SECURITY_SELINUX
-       range 0 1
-       default 0
-       help
-         This option sets the default value for the 'checkreqprot' flag
-         that determines whether SELinux checks the protection requested
-         by the application or the protection that will be applied by the
-         kernel (including any implied execute for read-implies-exec) for
-         mmap and mprotect calls.  If this option is set to 0 (zero),
-         SELinux will default to checking the protection that will be applied
-         by the kernel.  If this option is set to 1 (one), SELinux will
-         default to checking the protection requested by the application.
-         The checkreqprot flag may be changed from the default via the
-         'checkreqprot=' boot parameter.  It may also be changed at runtime
-         via /sys/fs/selinux/checkreqprot if authorized by policy.
-
-         WARNING: this option is deprecated and will be removed in a future
-         kernel release.
-
-         If you are unsure how to answer this question, answer 0.
-
 config SECURITY_SELINUX_SIDTAB_HASH_BITS
        int "NSA SELinux sidtab hashtable size"
        depends on SECURITY_SELINUX
index db6d8b68b5437dfe7fdb3a3f13c549fccb466ef7..9a58971f9a16c251115fe178aa70b9c44faedb28 100644 (file)
@@ -136,17 +136,13 @@ static int __init selinux_enabled_setup(char *str)
 __setup("selinux=", selinux_enabled_setup);
 #endif
 
-static unsigned int selinux_checkreqprot_boot =
-       CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
-
 static int __init checkreqprot_setup(char *str)
 {
        unsigned long checkreqprot;
 
        if (!kstrtoul(str, 0, &checkreqprot)) {
-               selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
                if (checkreqprot)
-                       pr_err("SELinux: checkreqprot set to 1 via kernel parameter.  This is deprecated and will be rejected in a future kernel release.\n");
+                       pr_err("SELinux: checkreqprot set to 1 via kernel parameter.  This is no longer supported.\n");
        }
        return 1;
 }
@@ -3712,7 +3708,8 @@ static int selinux_mmap_addr(unsigned long addr)
        return rc;
 }
 
-static int selinux_mmap_file(struct file *file, unsigned long reqprot,
+static int selinux_mmap_file(struct file *file,
+                            unsigned long reqprot __always_unused,
                             unsigned long prot, unsigned long flags)
 {
        struct common_audit_data ad;
@@ -3727,23 +3724,17 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
                        return rc;
        }
 
-       if (checkreqprot_get())
-               prot = reqprot;
-
        return file_map_prot_check(file, prot,
                                   (flags & MAP_TYPE) == MAP_SHARED);
 }
 
 static int selinux_file_mprotect(struct vm_area_struct *vma,
-                                unsigned long reqprot,
+                                unsigned long reqprot __always_unused,
                                 unsigned long prot)
 {
        const struct cred *cred = current_cred();
        u32 sid = cred_sid(cred);
 
-       if (checkreqprot_get())
-               prot = reqprot;
-
        if (default_noexec &&
            (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
                int rc = 0;
@@ -7202,9 +7193,6 @@ static __init int selinux_init(void)
 
        memset(&selinux_state, 0, sizeof(selinux_state));
        enforcing_set(selinux_enforcing_boot);
-       if (CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE)
-               pr_err("SELinux: CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE is non-zero.  This is deprecated and will be rejected in a future kernel release.\n");
-       checkreqprot_set(selinux_checkreqprot_boot);
        selinux_avc_init();
        mutex_init(&selinux_state.status_lock);
        mutex_init(&selinux_state.policy_mutex);
index cb38d1894cfc06ad8b94ca228680a4b89de045ea..312112d214bbbebac2a434bee4e1d0a71457948d 100644 (file)
@@ -95,7 +95,6 @@ struct selinux_state {
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
        bool enforcing;
 #endif
-       bool checkreqprot;
        bool initialized;
        bool policycap[__POLICYDB_CAP_MAX];
 
@@ -145,14 +144,8 @@ static inline void enforcing_set(bool value)
 
 static inline bool checkreqprot_get(void)
 {
-       return READ_ONCE(selinux_state.checkreqprot);
-}
-
-static inline void checkreqprot_set(bool value)
-{
-       if (value)
-               pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-checkreqprot\n");
-       WRITE_ONCE(selinux_state.checkreqprot, value);
+       /* non-zero/true checkreqprot values are no longer supported */
+       return 0;
 }
 
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
index 08164d074e56b4d7f11956fa563d69294963de90..68688bc8491254472b3d111a260370a72c7adec3 100644 (file)
@@ -728,23 +728,20 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       length = -EINVAL;
-       if (sscanf(page, "%u", &new_value) != 1)
+       if (sscanf(page, "%u", &new_value) != 1) {
+               length = -EINVAL;
                goto out;
+       }
+       length = count;
 
        if (new_value) {
                char comm[sizeof(current->comm)];
 
                memcpy(comm, current->comm, sizeof(comm));
-               pr_err("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
+               pr_err("SELinux: %s (%d) set checkreqprot to 1. This is no longer supported.\n",
                       comm, current->pid);
        }
 
-       checkreqprot_set((new_value ? 1 : 0));
-       if (new_value)
-               ssleep(15);
-       length = count;
-
        selinux_ima_measure_state();
 
 out: