mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 08:08:03 +02:00
selinux: prune /sys/fs/selinux/user
Remove the previously deprecated /sys/fs/selinux/user interface aside
from a residual stub for userspace compatibility.
Commit d7b6918e22 ("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>
This commit is contained in:
parent
19cfa00990
commit
ad1ac3d740
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1018,69 +1018,11 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
|
|||
|
||||
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 @@ int security_node_sid(u16 domain,
|
|||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user