]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selinux: prune /sys/fs/selinux/user
authorStephen Smalley <stephen.smalley.work@gmail.com>
Tue, 5 May 2026 12:49:50 +0000 (08:49 -0400)
committerPaul Moore <paul@paul-moore.com>
Tue, 5 May 2026 19:27:44 +0000 (15:27 -0400)
Remove the previously deprecated /sys/fs/selinux/user interface aside
from a residual stub for userspace compatibility.

Commit d7b6918e22c7 ("selinux: Deprecate /sys/fs/selinux/user") started
the deprecation process for /sys/fs/selinux/user:

    The selinuxfs "user" node allows userspace to request a list
    of security contexts that can be reached for a given SELinux
    user from a given starting context. This was used by libselinux
    when various login-style programs requested contexts for
    users, but libselinux stopped using it in 2020.
    Kernel support will be removed no sooner than Dec 2025.

A pr_warn() message has been in place since Linux v6.13, and a 5
second sleep was introduced since Linux v6.17 to help make it more
noticeable.

We are now past the stated deadline of Dec 2025, so remove the
underlying functionality and replace it with a stub that returns a
'0\0' buffer to avoid breaking userspace. This also avoids a local DoS
from logspam and an uninterruptible sleep delay.

Cc: stable@vger.kernel.org
Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Documentation/ABI/removed/sysfs-selinux-user [moved from Documentation/ABI/obsolete/sysfs-selinux-user with 100% similarity]
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/services.c

index d1f16d7f684de31a64ae339c3fea0ad53264b6e2..0babb89921816af2622940e2465bd4b6c4d4aeaa 100644 (file)
@@ -312,8 +312,6 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
 int security_context_to_sid_force(const char *scontext, u32 scontext_len,
                                  u32 *sid);
 
-int security_get_user_sids(u32 fromsid, const char *username, u32 **sids, u32 *nel);
-
 int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
 
 int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
index 343303b73d6f72971a2e5de0dd8eee80b52d56c9..6ed6693091323528e6255067bbf59bef74a2f7e1 100644 (file)
@@ -1018,69 +1018,11 @@ out:
 
 static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
 {
-       char *con = NULL, *user = NULL, *ptr;
-       u32 sid, *sids = NULL;
-       ssize_t length;
-       char *newcon;
-       int rc;
-       u32 i, len, nsids;
-
-       pr_warn_ratelimited("SELinux: %s (%d) wrote to /sys/fs/selinux/user!"
-               " This will not be supported in the future; please update your"
-               " userspace.\n", current->comm, current->pid);
-       ssleep(5);
-
-       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
-                             SECCLASS_SECURITY, SECURITY__COMPUTE_USER,
-                             NULL);
-       if (length)
-               goto out;
-
-       length = -ENOMEM;
-       con = kzalloc(size + 1, GFP_KERNEL);
-       if (!con)
-               goto out;
-
-       length = -ENOMEM;
-       user = kzalloc(size + 1, GFP_KERNEL);
-       if (!user)
-               goto out;
-
-       length = -EINVAL;
-       if (sscanf(buf, "%s %s", con, user) != 2)
-               goto out;
-
-       length = security_context_str_to_sid(con, &sid, GFP_KERNEL);
-       if (length)
-               goto out;
-
-       length = security_get_user_sids(sid, user, &sids, &nsids);
-       if (length)
-               goto out;
-
-       length = sprintf(buf, "%u", nsids) + 1;
-       ptr = buf + length;
-       for (i = 0; i < nsids; i++) {
-               rc = security_sid_to_context(sids[i], &newcon, &len);
-               if (rc) {
-                       length = rc;
-                       goto out;
-               }
-               if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
-                       kfree(newcon);
-                       length = -ERANGE;
-                       goto out;
-               }
-               memcpy(ptr, newcon, len);
-               kfree(newcon);
-               ptr += len;
-               length += len;
-       }
-out:
-       kfree(sids);
-       kfree(user);
-       kfree(con);
-       return length;
+       pr_err_once("SELinux: %s (%d) wrote to user. This is no longer supported.\n",
+                   current->comm, current->pid);
+       buf[0] = '0';
+       buf[1] = 0;
+       return 2;
 }
 
 static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
index e8e7ccbd1e44851ec6c489a7c3af87f5c067620e..143021c5e326d83e31f9f8578fb1fffe1ebbf350 100644 (file)
@@ -2746,131 +2746,6 @@ out:
        return rc;
 }
 
-#define SIDS_NEL 25
-
-/**
- * security_get_user_sids - Obtain reachable SIDs for a user.
- * @fromsid: starting SID
- * @username: username
- * @sids: array of reachable SIDs for user
- * @nel: number of elements in @sids
- *
- * Generate the set of SIDs for legal security contexts
- * for a given user that can be reached by @fromsid.
- * Set *@sids to point to a dynamically allocated
- * array containing the set of SIDs.  Set *@nel to the
- * number of elements in the array.
- */
-
-int security_get_user_sids(u32 fromsid,
-                          const char *username,
-                          u32 **sids,
-                          u32 *nel)
-{
-       struct selinux_policy *policy;
-       struct policydb *policydb;
-       struct sidtab *sidtab;
-       struct context *fromcon, usercon;
-       u32 *mysids = NULL, *mysids2, sid;
-       u32 i, j, mynel, maxnel = SIDS_NEL;
-       struct user_datum *user;
-       struct role_datum *role;
-       struct ebitmap_node *rnode, *tnode;
-       int rc;
-
-       *sids = NULL;
-       *nel = 0;
-
-       if (!selinux_initialized())
-               return 0;
-
-       mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL);
-       if (!mysids)
-               return -ENOMEM;
-
-retry:
-       mynel = 0;
-       rcu_read_lock();
-       policy = rcu_dereference(selinux_state.policy);
-       policydb = &policy->policydb;
-       sidtab = policy->sidtab;
-
-       context_init(&usercon);
-
-       rc = -EINVAL;
-       fromcon = sidtab_search(sidtab, fromsid);
-       if (!fromcon)
-               goto out_unlock;
-
-       rc = -EINVAL;
-       user = symtab_search(&policydb->p_users, username);
-       if (!user)
-               goto out_unlock;
-
-       usercon.user = user->value;
-
-       ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
-               role = policydb->role_val_to_struct[i];
-               usercon.role = i + 1;
-               ebitmap_for_each_positive_bit(&role->types, tnode, j) {
-                       usercon.type = j + 1;
-
-                       if (mls_setup_user_range(policydb, fromcon, user,
-                                                &usercon))
-                               continue;
-
-                       rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
-                       if (rc == -ESTALE) {
-                               rcu_read_unlock();
-                               goto retry;
-                       }
-                       if (rc)
-                               goto out_unlock;
-                       if (mynel < maxnel) {
-                               mysids[mynel++] = sid;
-                       } else {
-                               rc = -ENOMEM;
-                               maxnel += SIDS_NEL;
-                               mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
-                               if (!mysids2)
-                                       goto out_unlock;
-                               memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
-                               kfree(mysids);
-                               mysids = mysids2;
-                               mysids[mynel++] = sid;
-                       }
-               }
-       }
-       rc = 0;
-out_unlock:
-       rcu_read_unlock();
-       if (rc || !mynel) {
-               kfree(mysids);
-               return rc;
-       }
-
-       rc = -ENOMEM;
-       mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
-       if (!mysids2) {
-               kfree(mysids);
-               return rc;
-       }
-       for (i = 0, j = 0; i < mynel; i++) {
-               struct av_decision dummy_avd;
-               rc = avc_has_perm_noaudit(fromsid, mysids[i],
-                                         SECCLASS_PROCESS, /* kernel value */
-                                         PROCESS__TRANSITION, AVC_STRICT,
-                                         &dummy_avd);
-               if (!rc)
-                       mysids2[j++] = mysids[i];
-               cond_resched();
-       }
-       kfree(mysids);
-       *sids = mysids2;
-       *nel = j;
-       return 0;
-}
-
 /**
  * __security_genfs_sid - Helper to obtain a SID for a file in a filesystem
  * @policy: policy