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)
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