mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-09-22 09:34:56 +02:00
selinux: prune /sys/fs/selinux/user
commitad1ac3d740upstream. Remove the previously deprecated /sys/fs/selinux/user interface aside from a residual stub for userspace compatibility. Commitd7b6918e22("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
058a5e7054
commit
05b63fbddf
@@ -301,8 +301,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);
|
||||
|
||||
@@ -1005,69 +1005,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user