Merge tag 'selinux-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / security / selinux / ss / services.c
index 8ad34fd031d13d5d3811c936ef07cbd3b1038a97..313919bd42f8cde415bc2fdf6ec5f669e1d77a60 100644 (file)
@@ -482,11 +482,11 @@ static void security_dump_masked_av(struct policydb *policydb,
 
        /* init permission_names */
        if (common_dat &&
-           hashtab_map(common_dat->permissions.table,
+           hashtab_map(&common_dat->permissions.table,
                        dump_masked_av_helper, permission_names) < 0)
                goto out;
 
-       if (hashtab_map(tclass_dat->permissions.table,
+       if (hashtab_map(&tclass_dat->permissions.table,
                        dump_masked_av_helper, permission_names) < 0)
                goto out;
 
@@ -1441,7 +1441,7 @@ static int string_to_context_struct(struct policydb *pol,
 
        *p++ = 0;
 
-       usrdatum = hashtab_search(pol->p_users.table, scontextp);
+       usrdatum = hashtab_search(&pol->p_users.table, scontextp);
        if (!usrdatum)
                goto out;
 
@@ -1457,7 +1457,7 @@ static int string_to_context_struct(struct policydb *pol,
 
        *p++ = 0;
 
-       role = hashtab_search(pol->p_roles.table, scontextp);
+       role = hashtab_search(&pol->p_roles.table, scontextp);
        if (!role)
                goto out;
        ctx->role = role->value;
@@ -1469,7 +1469,7 @@ static int string_to_context_struct(struct policydb *pol,
        oldc = *p;
        *p++ = 0;
 
-       typdatum = hashtab_search(pol->p_types.table, scontextp);
+       typdatum = hashtab_search(&pol->p_types.table, scontextp);
        if (!typdatum || typdatum->attribute)
                goto out;
 
@@ -1490,42 +1490,6 @@ out:
        return rc;
 }
 
-int context_add_hash(struct policydb *policydb,
-                    struct context *context)
-{
-       int rc;
-       char *str;
-       int len;
-
-       if (context->str) {
-               context->hash = context_compute_hash(context->str);
-       } else {
-               rc = context_struct_to_string(policydb, context,
-                                             &str, &len);
-               if (rc)
-                       return rc;
-               context->hash = context_compute_hash(str);
-               kfree(str);
-       }
-       return 0;
-}
-
-static int context_struct_to_sid(struct selinux_state *state,
-                                struct context *context, u32 *sid)
-{
-       int rc;
-       struct sidtab *sidtab = state->ss->sidtab;
-       struct policydb *policydb = &state->ss->policydb;
-
-       if (!context->hash) {
-               rc = context_add_hash(policydb, context);
-               if (rc)
-                       return rc;
-       }
-
-       return sidtab_context_to_sid(sidtab, context, sid);
-}
-
 static int security_context_to_sid_core(struct selinux_state *state,
                                        const char *scontext, u32 scontext_len,
                                        u32 *sid, u32 def_sid, gfp_t gfp_flags,
@@ -1580,7 +1544,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
                str = NULL;
        } else if (rc)
                goto out_unlock;
-       rc = context_struct_to_sid(state, &context, sid);
+       rc = sidtab_context_to_sid(sidtab, &context, sid);
        context_destroy(&context);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
@@ -1707,7 +1671,7 @@ static void filename_compute_type(struct policydb *policydb,
        ft.tclass = tclass;
        ft.name = objname;
 
-       datum = hashtab_search(policydb->filename_trans, &ft);
+       datum = hashtab_search(&policydb->filename_trans, &ft);
        while (datum) {
                if (ebitmap_get_bit(&datum->stypes, stype - 1)) {
                        newcontext->type = datum->otype;
@@ -1731,7 +1695,6 @@ static int security_compute_sid(struct selinux_state *state,
        struct class_datum *cladatum = NULL;
        struct context *scontext, *tcontext, newcontext;
        struct sidtab_entry *sentry, *tentry;
-       struct role_trans *roletr = NULL;
        struct avtab_key avkey;
        struct avtab_datum *avdatum;
        struct avtab_node *node;
@@ -1812,7 +1775,7 @@ static int security_compute_sid(struct selinux_state *state,
        } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
                newcontext.role = tcontext->role;
        } else {
-               if ((tclass == policydb->process_class) || (sock == true))
+               if ((tclass == policydb->process_class) || sock)
                        newcontext.role = scontext->role;
                else
                        newcontext.role = OBJECT_R_VAL;
@@ -1824,7 +1787,7 @@ static int security_compute_sid(struct selinux_state *state,
        } else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
                newcontext.type = tcontext->type;
        } else {
-               if ((tclass == policydb->process_class) || (sock == true)) {
+               if ((tclass == policydb->process_class) || sock) {
                        /* Use the type of process. */
                        newcontext.type = scontext->type;
                } else {
@@ -1864,16 +1827,16 @@ static int security_compute_sid(struct selinux_state *state,
        /* Check for class-specific changes. */
        if (specified & AVTAB_TRANSITION) {
                /* Look for a role transition rule. */
-               for (roletr = policydb->role_tr; roletr;
-                    roletr = roletr->next) {
-                       if ((roletr->role == scontext->role) &&
-                           (roletr->type == tcontext->type) &&
-                           (roletr->tclass == tclass)) {
-                               /* Use the role transition rule. */
-                               newcontext.role = roletr->new_role;
-                               break;
-                       }
-               }
+               struct role_trans_datum *rtd;
+               struct role_trans_key rtk = {
+                       .role = scontext->role,
+                       .type = tcontext->type,
+                       .tclass = tclass,
+               };
+
+               rtd = hashtab_search(&policydb->role_tr, &rtk);
+               if (rtd)
+                       newcontext.role = rtd->new_role;
        }
 
        /* Set the MLS attributes.
@@ -1891,7 +1854,7 @@ static int security_compute_sid(struct selinux_state *state,
                        goto out_unlock;
        }
        /* Obtain the sid for the context. */
-       rc = context_struct_to_sid(state, &newcontext, out_sid);
+       rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
        context_destroy(&newcontext);
@@ -2043,7 +2006,6 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
                        context_init(newc);
                        newc->str = s;
                        newc->len = oldc->len;
-                       newc->hash = oldc->hash;
                        return 0;
                }
                kfree(s);
@@ -2062,7 +2024,7 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
 
        /* Convert the user. */
        rc = -EINVAL;
-       usrdatum = hashtab_search(args->newp->p_users.table,
+       usrdatum = hashtab_search(&args->newp->p_users.table,
                                  sym_name(args->oldp,
                                           SYM_USERS, oldc->user - 1));
        if (!usrdatum)
@@ -2071,7 +2033,7 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
 
        /* Convert the role. */
        rc = -EINVAL;
-       role = hashtab_search(args->newp->p_roles.table,
+       role = hashtab_search(&args->newp->p_roles.table,
                              sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
        if (!role)
                goto bad;
@@ -2079,7 +2041,7 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
 
        /* Convert the type. */
        rc = -EINVAL;
-       typdatum = hashtab_search(args->newp->p_types.table,
+       typdatum = hashtab_search(&args->newp->p_types.table,
                                  sym_name(args->oldp,
                                           SYM_TYPES, oldc->type - 1));
        if (!typdatum)
@@ -2120,10 +2082,6 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
                        goto bad;
        }
 
-       rc = context_add_hash(args->newp, newc);
-       if (rc)
-               goto bad;
-
        return 0;
 bad:
        /* Map old representation to string and save it. */
@@ -2133,7 +2091,6 @@ bad:
        context_destroy(newc);
        newc->str = s;
        newc->len = len;
-       newc->hash = context_compute_hash(s);
        pr_info("SELinux:  Context %s became invalid (unmapped).\n",
                newc->str);
        return 0;
@@ -2350,12 +2307,14 @@ int security_port_sid(struct selinux_state *state,
                      u8 protocol, u16 port, u32 *out_sid)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        struct ocontext *c;
        int rc = 0;
 
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        c = policydb->ocontexts[OCON_PORT];
        while (c) {
@@ -2368,7 +2327,7 @@ int security_port_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = context_struct_to_sid(state, &c->context[0],
+                       rc = sidtab_context_to_sid(sidtab, &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
                                goto out;
@@ -2393,12 +2352,14 @@ int security_ib_pkey_sid(struct selinux_state *state,
                         u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        struct ocontext *c;
        int rc = 0;
 
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        c = policydb->ocontexts[OCON_IBPKEY];
        while (c) {
@@ -2412,7 +2373,7 @@ int security_ib_pkey_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = context_struct_to_sid(state,
+                       rc = sidtab_context_to_sid(sidtab,
                                                   &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
@@ -2437,12 +2398,14 @@ int security_ib_endport_sid(struct selinux_state *state,
                            const char *dev_name, u8 port_num, u32 *out_sid)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        struct ocontext *c;
        int rc = 0;
 
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        c = policydb->ocontexts[OCON_IBENDPORT];
        while (c) {
@@ -2457,7 +2420,7 @@ int security_ib_endport_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = context_struct_to_sid(state, &c->context[0],
+                       rc = sidtab_context_to_sid(sidtab, &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
                                goto out;
@@ -2480,12 +2443,14 @@ int security_netif_sid(struct selinux_state *state,
                       char *name, u32 *if_sid)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        int rc = 0;
        struct ocontext *c;
 
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        c = policydb->ocontexts[OCON_NETIF];
        while (c) {
@@ -2496,11 +2461,11 @@ int security_netif_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0] || !c->sid[1]) {
-                       rc = context_struct_to_sid(state, &c->context[0],
+                       rc = sidtab_context_to_sid(sidtab, &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
                                goto out;
-                       rc = context_struct_to_sid(state, &c->context[1],
+                       rc = sidtab_context_to_sid(sidtab, &c->context[1],
                                                   &c->sid[1]);
                        if (rc)
                                goto out;
@@ -2541,12 +2506,14 @@ int security_node_sid(struct selinux_state *state,
                      u32 *out_sid)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        int rc;
        struct ocontext *c;
 
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        switch (domain) {
        case AF_INET: {
@@ -2588,7 +2555,7 @@ int security_node_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = context_struct_to_sid(state,
+                       rc = sidtab_context_to_sid(sidtab,
                                                   &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
@@ -2656,7 +2623,7 @@ int security_get_user_sids(struct selinux_state *state,
                goto out_unlock;
 
        rc = -EINVAL;
-       user = hashtab_search(policydb->p_users.table, username);
+       user = hashtab_search(&policydb->p_users.table, username);
        if (!user)
                goto out_unlock;
 
@@ -2672,17 +2639,12 @@ int security_get_user_sids(struct selinux_state *state,
                usercon.role = i + 1;
                ebitmap_for_each_positive_bit(&role->types, tnode, j) {
                        usercon.type = j + 1;
-                       /*
-                        * The same context struct is reused here so the hash
-                        * must be reset.
-                        */
-                       usercon.hash = 0;
 
                        if (mls_setup_user_range(policydb, fromcon, user,
                                                 &usercon))
                                continue;
 
-                       rc = context_struct_to_sid(state, &usercon, &sid);
+                       rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
                        if (rc)
                                goto out_unlock;
                        if (mynel < maxnel) {
@@ -2753,6 +2715,7 @@ static inline int __security_genfs_sid(struct selinux_state *state,
                                       u32 *sid)
 {
        struct policydb *policydb = &state->ss->policydb;
+       struct sidtab *sidtab = state->ss->sidtab;
        int len;
        u16 sclass;
        struct genfs *genfs;
@@ -2787,7 +2750,7 @@ static inline int __security_genfs_sid(struct selinux_state *state,
                goto out;
 
        if (!c->sid[0]) {
-               rc = context_struct_to_sid(state, &c->context[0], &c->sid[0]);
+               rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
                if (rc)
                        goto out;
        }
@@ -2829,6 +2792,7 @@ int security_genfs_sid(struct selinux_state *state,
 int security_fs_use(struct selinux_state *state, struct super_block *sb)
 {
        struct policydb *policydb;
+       struct sidtab *sidtab;
        int rc = 0;
        struct ocontext *c;
        struct superblock_security_struct *sbsec = sb->s_security;
@@ -2837,6 +2801,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
+       sidtab = state->ss->sidtab;
 
        c = policydb->ocontexts[OCON_FSUSE];
        while (c) {
@@ -2848,7 +2813,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
        if (c) {
                sbsec->behavior = c->v.behavior;
                if (!c->sid[0]) {
-                       rc = context_struct_to_sid(state, &c->context[0],
+                       rc = sidtab_context_to_sid(sidtab, &c->context[0],
                                                   &c->sid[0]);
                        if (rc)
                                goto out;
@@ -3010,7 +2975,7 @@ static int security_preserve_bools(struct selinux_state *state,
        if (rc)
                goto out;
        for (i = 0; i < nbools; i++) {
-               booldatum = hashtab_search(policydb->p_bools.table, bnames[i]);
+               booldatum = hashtab_search(&policydb->p_bools.table, bnames[i]);
                if (booldatum)
                        booldatum->state = bvalues[i];
        }
@@ -3096,7 +3061,7 @@ int security_sid_mls_copy(struct selinux_state *state,
                        goto out_unlock;
                }
        }
-       rc = context_struct_to_sid(state, &newcon, new_sid);
+       rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
        context_destroy(&newcon);
@@ -3224,8 +3189,8 @@ int security_get_classes(struct selinux_state *state,
        if (!*classes)
                goto out;
 
-       rc = hashtab_map(policydb->p_classes.table, get_classes_callback,
-                       *classes);
+       rc = hashtab_map(&policydb->p_classes.table, get_classes_callback,
+                        *classes);
        if (rc) {
                int i;
                for (i = 0; i < *nclasses; i++)
@@ -3261,7 +3226,7 @@ int security_get_permissions(struct selinux_state *state,
        read_lock(&state->ss->policy_rwlock);
 
        rc = -EINVAL;
-       match = hashtab_search(policydb->p_classes.table, class);
+       match = hashtab_search(&policydb->p_classes.table, class);
        if (!match) {
                pr_err("SELinux: %s:  unrecognized class %s\n",
                        __func__, class);
@@ -3275,14 +3240,14 @@ int security_get_permissions(struct selinux_state *state,
                goto out;
 
        if (match->comdatum) {
-               rc = hashtab_map(match->comdatum->permissions.table,
-                               get_permissions_callback, *perms);
+               rc = hashtab_map(&match->comdatum->permissions.table,
+                                get_permissions_callback, *perms);
                if (rc)
                        goto err;
        }
 
-       rc = hashtab_map(match->permissions.table, get_permissions_callback,
-                       *perms);
+       rc = hashtab_map(&match->permissions.table, get_permissions_callback,
+                        *perms);
        if (rc)
                goto err;
 
@@ -3400,7 +3365,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
        case AUDIT_SUBJ_USER:
        case AUDIT_OBJ_USER:
                rc = -EINVAL;
-               userdatum = hashtab_search(policydb->p_users.table, rulestr);
+               userdatum = hashtab_search(&policydb->p_users.table, rulestr);
                if (!userdatum)
                        goto out;
                tmprule->au_ctxt.user = userdatum->value;
@@ -3408,7 +3373,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
        case AUDIT_SUBJ_ROLE:
        case AUDIT_OBJ_ROLE:
                rc = -EINVAL;
-               roledatum = hashtab_search(policydb->p_roles.table, rulestr);
+               roledatum = hashtab_search(&policydb->p_roles.table, rulestr);
                if (!roledatum)
                        goto out;
                tmprule->au_ctxt.role = roledatum->value;
@@ -3416,7 +3381,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
        case AUDIT_SUBJ_TYPE:
        case AUDIT_OBJ_TYPE:
                rc = -EINVAL;
-               typedatum = hashtab_search(policydb->p_types.table, rulestr);
+               typedatum = hashtab_search(&policydb->p_types.table, rulestr);
                if (!typedatum)
                        goto out;
                tmprule->au_ctxt.type = typedatum->value;
@@ -3689,7 +3654,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
                if (!mls_context_isvalid(policydb, &ctx_new))
                        goto out_free;
 
-               rc = context_struct_to_sid(state, &ctx_new, sid);
+               rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
                if (rc)
                        goto out_free;