This patch separates the lookup of the initial SIDs into a separate
lookup table (implemented simply by a fixed-size array), in order to
pave the way for improving the process of converting the sidtab to a new
policy during a policy reload.

The initial SIDs are loaded directly and are skipped during sidtab
conversion, so handling them separately makes things somewhat simpler.
Since there is only a small fixed number of them, they can be stored in
a simple lookup table.

This patch also moves the fallback-to-unlabeled logic from sidtab.c to
the new helper functions in services.c that now handle the unified
lookup in both sidtab and isidtab, simplifying the sidtab interface.

Signed-off-by: Ondrej Mosnacek <[email protected]>
---
 security/selinux/include/security.h |   3 +
 security/selinux/ss/mls.c           |   6 +-
 security/selinux/ss/mls.h           |   2 +-
 security/selinux/ss/policydb.c      |  24 ++-
 security/selinux/ss/policydb.h      |  26 ++-
 security/selinux/ss/services.c      | 238 +++++++++++++++-------------
 security/selinux/ss/services.h      |   1 +
 security/selinux/ss/sidtab.c        |  29 +---
 security/selinux/ss/sidtab.h        |   3 +-
 9 files changed, 187 insertions(+), 145 deletions(-)

diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 23e762d529fa..a1b4b13c2300 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -221,6 +221,9 @@ struct extended_perms {
 /* definitions of av_decision.flags */
 #define AVD_FLAGS_PERMISSIVE   0x0001
 
+struct context *security_sid_to_context_struct(struct selinux_state *state,
+                                              u32 sid, int force);
+
 void security_compute_av(struct selinux_state *state,
                         u32 ssid, u32 tsid,
                         u16 tclass, struct av_decision *avd,
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 2fe459df3c85..cd637ee3fb11 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -235,7 +235,7 @@ int mls_context_to_sid(struct policydb *pol,
                       char oldc,
                       char *scontext,
                       struct context *context,
-                      struct sidtab *s,
+                      struct selinux_state *state,
                       u32 def_sid)
 {
        char *sensitivity, *cur_cat, *next_cat, *rngptr;
@@ -257,10 +257,10 @@ int mls_context_to_sid(struct policydb *pol,
        if (!oldc) {
                struct context *defcon;
 
-               if (def_sid == SECSID_NULL)
+               if (def_sid == SECSID_NULL || state == NULL)
                        return -EINVAL;
 
-               defcon = sidtab_search(s, def_sid);
+               defcon = security_sid_to_context_struct(state, def_sid, 0);
                if (!defcon)
                        return -EINVAL;
 
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 67093647576d..1eca02c8bc5f 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -36,7 +36,7 @@ int mls_context_to_sid(struct policydb *p,
                       char oldc,
                       char *scontext,
                       struct context *context,
-                      struct sidtab *s,
+                      struct selinux_state *state,
                       u32 def_sid);
 
 int mls_from_string(struct policydb *p, char *str, struct context *context,
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f4eadd3f7350..8f7cd5f6e033 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -892,16 +892,12 @@ void policydb_destroy(struct policydb *p)
  * Load the initial SIDs specified in a policy database
  * structure into a SID table.
  */
-int policydb_load_isids(struct policydb *p, struct sidtab *s)
+int policydb_load_isids(struct policydb *p, struct isidtab *s)
 {
        struct ocontext *head, *c;
        int rc;
 
-       rc = sidtab_init(s);
-       if (rc) {
-               pr_err("SELinux:  out of memory on SID table init\n");
-               goto out;
-       }
+       isidtab_init(s);
 
        head = p->ocontexts[OCON_ISID];
        for (c = head; c; c = c->next) {
@@ -911,16 +907,30 @@ int policydb_load_isids(struct policydb *p, struct sidtab 
*s)
                                c->u.name);
                        goto out;
                }
+               if (c->sid[0] > SECINITSID_NUM) {
+                       pr_err("SELinux:  Initial SID %u out of range.\n",
+                               (unsigned)c->sid[0]);
+                       goto out;
+               }
+               if (s->entries[c->sid[0]].set) {
+                       pr_err("SELinux:  Duplicit initial SID %u.\n",
+                               (unsigned)c->sid[0]);
+                       goto out;
+               }
 
-               rc = sidtab_insert(s, c->sid[0], &c->context[0]);
+               rc = context_cpy(&s->entries[c->sid[0]].context, 
&c->context[0]);
                if (rc) {
                        pr_err("SELinux:  unable to load initial SID %s.\n",
                                c->u.name);
                        goto out;
                }
+
+               s->entries[c->sid[0]].set = 1;
        }
        rc = 0;
 out:
+       if (rc != 0)
+               isidtab_destroy(s);
        return rc;
 }
 
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 215f8f30ac5a..0e246bc45c72 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -312,8 +312,32 @@ struct policydb {
        u32 process_trans_perms;
 };
 
+struct isidtab_entry {
+       int set;
+       struct context context;
+};
+
+struct isidtab {
+       struct isidtab_entry entries[SECINITSID_NUM + 1];
+};
+
+static inline void isidtab_init(struct isidtab *t)
+{
+       u32 i;
+       for (i = 0; i <= SECINITSID_NUM; i++)
+               t->entries[i].set = 0;
+}
+
+static inline void isidtab_destroy(struct isidtab *t)
+{
+       u32 i;
+       for (i = 0; i <= SECINITSID_NUM; i++)
+               if (t->entries[i].set)
+                       context_destroy(&t->entries[i].context);
+}
+
 extern void policydb_destroy(struct policydb *p);
-extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
+extern int policydb_load_isids(struct policydb *p, struct isidtab *s);
 extern int policydb_context_isvalid(struct policydb *p, struct context *c);
 extern int policydb_class_isvalid(struct policydb *p, unsigned int class);
 extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 12e414394530..550a00004139 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -89,6 +89,42 @@ void selinux_ss_init(struct selinux_ss **ss)
        *ss = &selinux_ss;
 }
 
+struct context *security_sid_to_context_struct(struct selinux_state *state,
+                                              u32 sid, int force)
+{
+       struct isidtab *isidtab = state->ss->isidtab;
+       struct sidtab *sidtab = &state->ss->sidtab;
+
+       if (sid <= SECINITSID_NUM) {
+               if (isidtab->entries[sid].set)
+                       return &isidtab->entries[sid].context;
+       } else {
+               struct context *context = sidtab_lookup(sidtab, sid);
+               if (context && (!context->len || force))
+                       return context;
+       }
+       if (isidtab->entries[SECINITSID_UNLABELED].set)
+               return &isidtab->entries[SECINITSID_UNLABELED].context;
+       return NULL;
+}
+
+static int security_context_struct_to_sid(struct selinux_state *state,
+                                         struct context *context, u32 *sid)
+{
+       struct isidtab *isidtab = state->ss->isidtab;
+       struct sidtab *sidtab = &state->ss->sidtab;
+       u32 i;
+
+       for (i = 0; i <= SECINITSID_NUM; i++)
+               if (isidtab->entries[i].set &&
+                   context_cmp(context, &isidtab->entries[i].context)) {
+                       *sid = i;
+                       return 0;
+               }
+
+       return sidtab_context_to_sid(sidtab, context, sid);
+}
+
 /* Forward declaration. */
 static int context_struct_to_string(struct policydb *policydb,
                                    struct context *context,
@@ -760,7 +796,6 @@ static int security_compute_validatetrans(struct 
selinux_state *state,
                                          u16 orig_tclass, bool user)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct context *ocontext;
        struct context *ncontext;
        struct context *tcontext;
@@ -776,7 +811,6 @@ static int security_compute_validatetrans(struct 
selinux_state *state,
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
        if (!user)
                tclass = unmap_class(&state->ss->map, orig_tclass);
@@ -789,7 +823,7 @@ static int security_compute_validatetrans(struct 
selinux_state *state,
        }
        tclass_datum = policydb->class_val_to_struct[tclass - 1];
 
-       ocontext = sidtab_search(sidtab, oldsid);
+       ocontext = security_sid_to_context_struct(state, oldsid, 0);
        if (!ocontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, oldsid);
@@ -797,7 +831,7 @@ static int security_compute_validatetrans(struct 
selinux_state *state,
                goto out;
        }
 
-       ncontext = sidtab_search(sidtab, newsid);
+       ncontext = security_sid_to_context_struct(state, newsid, 0);
        if (!ncontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, newsid);
@@ -805,7 +839,7 @@ static int security_compute_validatetrans(struct 
selinux_state *state,
                goto out;
        }
 
-       tcontext = sidtab_search(sidtab, tasksid);
+       tcontext = security_sid_to_context_struct(state, tasksid, 0);
        if (!tcontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, tasksid);
@@ -864,7 +898,6 @@ int security_bounded_transition(struct selinux_state *state,
                                u32 old_sid, u32 new_sid)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct context *old_context, *new_context;
        struct type_datum *type;
        int index;
@@ -876,10 +909,9 @@ int security_bounded_transition(struct selinux_state 
*state,
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
        rc = -EINVAL;
-       old_context = sidtab_search(sidtab, old_sid);
+       old_context = security_sid_to_context_struct(state, old_sid, 0);
        if (!old_context) {
                pr_err("SELinux: %s: unrecognized SID %u\n",
                       __func__, old_sid);
@@ -887,7 +919,7 @@ int security_bounded_transition(struct selinux_state *state,
        }
 
        rc = -EINVAL;
-       new_context = sidtab_search(sidtab, new_sid);
+       new_context = security_sid_to_context_struct(state, new_sid, 0);
        if (!new_context) {
                pr_err("SELinux: %s: unrecognized SID %u\n",
                       __func__, new_sid);
@@ -1014,7 +1046,6 @@ void security_compute_xperms_decision(struct 
selinux_state *state,
                                      struct extended_perms_decision *xpermd)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        u16 tclass;
        struct context *scontext, *tcontext;
        struct avtab_key avkey;
@@ -1034,16 +1065,15 @@ void security_compute_xperms_decision(struct 
selinux_state *state,
                goto allow;
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
-       scontext = sidtab_search(sidtab, ssid);
+       scontext = security_sid_to_context_struct(state, ssid, 0);
        if (!scontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, ssid);
                goto out;
        }
 
-       tcontext = sidtab_search(sidtab, tsid);
+       tcontext = security_sid_to_context_struct(state, tsid, 0);
        if (!tcontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, tsid);
@@ -1112,7 +1142,6 @@ void security_compute_av(struct selinux_state *state,
                         struct extended_perms *xperms)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        u16 tclass;
        struct context *scontext = NULL, *tcontext = NULL;
 
@@ -1123,9 +1152,8 @@ void security_compute_av(struct selinux_state *state,
                goto allow;
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
-       scontext = sidtab_search(sidtab, ssid);
+       scontext = security_sid_to_context_struct(state, ssid, 0);
        if (!scontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, ssid);
@@ -1136,7 +1164,7 @@ void security_compute_av(struct selinux_state *state,
        if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
                avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-       tcontext = sidtab_search(sidtab, tsid);
+       tcontext = security_sid_to_context_struct(state, tsid, 0);
        if (!tcontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, tsid);
@@ -1168,7 +1196,6 @@ void security_compute_av_user(struct selinux_state *state,
                              struct av_decision *avd)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct context *scontext = NULL, *tcontext = NULL;
 
        read_lock(&state->ss->policy_rwlock);
@@ -1177,9 +1204,8 @@ void security_compute_av_user(struct selinux_state *state,
                goto allow;
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
-       scontext = sidtab_search(sidtab, ssid);
+       scontext = security_sid_to_context_struct(state, ssid, 0);
        if (!scontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, ssid);
@@ -1190,7 +1216,7 @@ void security_compute_av_user(struct selinux_state *state,
        if (ebitmap_get_bit(&policydb->permissive_map, scontext->type))
                avd->flags |= AVD_FLAGS_PERMISSIVE;
 
-       tcontext = sidtab_search(sidtab, tsid);
+       tcontext = security_sid_to_context_struct(state, tsid, 0);
        if (!tcontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, tsid);
@@ -1284,7 +1310,6 @@ static int security_sid_to_context_core(struct 
selinux_state *state,
                                        u32 *scontext_len, int force)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct context *context;
        int rc = 0;
 
@@ -1315,11 +1340,7 @@ static int security_sid_to_context_core(struct 
selinux_state *state,
        }
        read_lock(&state->ss->policy_rwlock);
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
-       if (force)
-               context = sidtab_search_force(sidtab, sid);
-       else
-               context = sidtab_search(sidtab, sid);
+       context = security_sid_to_context_struct(state, sid, force);
        if (!context) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, sid);
@@ -1363,7 +1384,7 @@ int security_sid_to_context_force(struct selinux_state 
*state, u32 sid,
  * Caveat:  Mutates scontext.
  */
 static int string_to_context_struct(struct policydb *pol,
-                                   struct sidtab *sidtabp,
+                                   struct selinux_state *state,
                                    char *scontext,
                                    struct context *ctx,
                                    u32 def_sid)
@@ -1425,7 +1446,7 @@ static int string_to_context_struct(struct policydb *pol,
 
        ctx->type = typdatum->value;
 
-       rc = mls_context_to_sid(pol, oldc, p, ctx, sidtabp, def_sid);
+       rc = mls_context_to_sid(pol, oldc, p, ctx, state, def_sid);
        if (rc)
                goto out;
 
@@ -1446,7 +1467,6 @@ static int security_context_to_sid_core(struct 
selinux_state *state,
                                        int force)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        char *scontext2, *str = NULL;
        struct context context;
        int rc = 0;
@@ -1483,16 +1503,17 @@ static int security_context_to_sid_core(struct 
selinux_state *state,
        }
        read_lock(&state->ss->policy_rwlock);
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
-       rc = string_to_context_struct(policydb, sidtab, scontext2,
+
+       rc = string_to_context_struct(policydb, state, scontext2,
                                      &context, def_sid);
+
        if (rc == -EINVAL && force) {
                context.str = str;
                context.len = strlen(str) + 1;
                str = NULL;
        } else if (rc)
                goto out_unlock;
-       rc = sidtab_context_to_sid(sidtab, &context, sid);
+       rc = security_context_struct_to_sid(state, &context, sid);
        context_destroy(&context);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
@@ -1631,7 +1652,6 @@ static int security_compute_sid(struct selinux_state 
*state,
                                bool kern)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct class_datum *cladatum = NULL;
        struct context *scontext = NULL, *tcontext = NULL, newcontext;
        struct role_trans *roletr = NULL;
@@ -1668,16 +1688,15 @@ static int security_compute_sid(struct selinux_state 
*state,
        }
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
-       scontext = sidtab_search(sidtab, ssid);
+       scontext = security_sid_to_context_struct(state, ssid, 0);
        if (!scontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, ssid);
                rc = -EINVAL;
                goto out_unlock;
        }
-       tcontext = sidtab_search(sidtab, tsid);
+       tcontext = security_sid_to_context_struct(state, tsid, 0);
        if (!tcontext) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, tsid);
@@ -1793,7 +1812,7 @@ static int security_compute_sid(struct selinux_state 
*state,
                        goto out_unlock;
        }
        /* Obtain the sid for the context. */
-       rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
+       rc = security_context_struct_to_sid(state, &newcontext, out_sid);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
        context_destroy(&newcontext);
@@ -1881,16 +1900,9 @@ int security_change_sid(struct selinux_state *state,
 }
 
 /* Clone the SID into the new SID table. */
-static int clone_sid(u32 sid,
-                    struct context *context,
-                    void *arg)
+static int clone_sid(u32 sid, struct context *context, void *arg)
 {
-       struct sidtab *s = arg;
-
-       if (sid > SECINITSID_NUM)
-               return sidtab_insert(s, sid, context);
-       else
-               return 0;
+       return sidtab_insert((struct sidtab *)arg, sid, context);
 }
 
 static inline int convert_context_handle_invalid_context(
@@ -1925,9 +1937,7 @@ struct convert_context_args {
  * in the policy `p->newp'.  Verify that the
  * context is valid under the new policy.
  */
-static int convert_context(u32 key,
-                          struct context *c,
-                          void *p)
+static int convert_context(u32 key, struct context *c, void *p)
 {
        struct convert_context_args *args;
        struct context oldc;
@@ -1938,10 +1948,7 @@ static int convert_context(u32 key,
        struct user_datum *usrdatum;
        char *s;
        u32 len;
-       int rc = 0;
-
-       if (key <= SECINITSID_NUM)
-               goto out;
+       int rc;
 
        args = p;
 
@@ -2104,6 +2111,7 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
 {
        struct policydb *policydb;
        struct sidtab *sidtab;
+       struct isidtab *newisidtab = NULL;
        struct policydb *oldpolicydb, *newpolicydb;
        struct sidtab oldsidtab, newsidtab;
        struct selinux_mapping *oldmapping;
@@ -2120,6 +2128,12 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
        }
        newpolicydb = oldpolicydb + 1;
 
+       newisidtab = kmalloc(sizeof(*newisidtab), GFP_KERNEL);
+       if (!newisidtab) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
        policydb = &state->ss->policydb;
        sidtab = &state->ss->sidtab;
 
@@ -2128,20 +2142,31 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
                if (rc)
                        goto out;
 
+               rc = sidtab_init(sidtab);
+               if (rc) {
+                       policydb_destroy(policydb);
+                       goto out;
+               }
+
                policydb->len = len;
                rc = selinux_set_mapping(policydb, secclass_map,
                                         &state->ss->map);
                if (rc) {
+                       sidtab_destroy(sidtab);
                        policydb_destroy(policydb);
                        goto out;
                }
 
-               rc = policydb_load_isids(policydb, sidtab);
+               rc = policydb_load_isids(policydb, newisidtab);
                if (rc) {
+                       sidtab_destroy(sidtab);
                        policydb_destroy(policydb);
                        goto out;
                }
 
+               state->ss->isidtab = newisidtab;
+               newisidtab = NULL; /* do not free new isidtab */
+
                security_load_policycaps(state);
                state->initialized = 1;
                seqno = ++state->ss->latest_granting;
@@ -2162,6 +2187,12 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
        if (rc)
                goto out;
 
+       rc = sidtab_init(&newsidtab);
+       if (rc) {
+               policydb_destroy(newpolicydb);
+               goto out;
+       }
+
        newpolicydb->len = len;
        /* If switching between different policy types, log MLS status */
        if (policydb->mls_enabled && !newpolicydb->mls_enabled)
@@ -2169,9 +2200,10 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
        else if (!policydb->mls_enabled && newpolicydb->mls_enabled)
                pr_info("SELinux: Enabling MLS support...\n");
 
-       rc = policydb_load_isids(newpolicydb, &newsidtab);
+       rc = policydb_load_isids(newpolicydb, newisidtab);
        if (rc) {
                pr_err("SELinux:  unable to load the initial SIDs\n");
+               sidtab_destroy(&newsidtab);
                policydb_destroy(newpolicydb);
                goto out;
        }
@@ -2214,13 +2246,21 @@ int security_load_policy(struct selinux_state *state, 
void *data, size_t len)
 
        /* Install the new policydb and SID table. */
        write_lock_irq(&state->ss->policy_rwlock);
+
        memcpy(policydb, newpolicydb, sizeof(*policydb));
        sidtab_set(sidtab, &newsidtab);
+
+       isidtab_destroy(state->ss->isidtab);
+       kfree(state->ss->isidtab);
+       state->ss->isidtab = newisidtab;
+       newisidtab = NULL;
+
        security_load_policycaps(state);
        oldmapping = state->ss->map.mapping;
        state->ss->map.mapping = newmap.mapping;
        state->ss->map.size = newmap.size;
        seqno = ++state->ss->latest_granting;
+
        write_unlock_irq(&state->ss->policy_rwlock);
 
        /* Free the old policydb and SID table. */
@@ -2241,8 +2281,10 @@ err:
        kfree(newmap.mapping);
        sidtab_destroy(&newsidtab);
        policydb_destroy(newpolicydb);
+       isidtab_destroy(newisidtab);
 
 out:
+       kfree(newisidtab);
        kfree(oldpolicydb);
        return rc;
 }
@@ -2269,14 +2311,12 @@ 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) {
@@ -2289,9 +2329,9 @@ int security_port_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = sidtab_context_to_sid(sidtab,
-                                                  &c->context[0],
-                                                  &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
                }
@@ -2315,14 +2355,12 @@ 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) {
@@ -2336,9 +2374,9 @@ int security_ib_pkey_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = sidtab_context_to_sid(sidtab,
-                                                  &c->context[0],
-                                                  &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
                }
@@ -2361,14 +2399,12 @@ 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) {
@@ -2383,9 +2419,9 @@ int security_ib_endport_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = sidtab_context_to_sid(sidtab,
-                                                  &c->context[0],
-                                                  &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
                }
@@ -2407,14 +2443,12 @@ 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) {
@@ -2425,14 +2459,14 @@ int security_netif_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0] || !c->sid[1]) {
-                       rc = sidtab_context_to_sid(sidtab,
-                                                 &c->context[0],
-                                                 &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
-                       rc = sidtab_context_to_sid(sidtab,
-                                                  &c->context[1],
-                                                  &c->sid[1]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[1],
+                                                           &c->sid[1]);
                        if (rc)
                                goto out;
                }
@@ -2472,14 +2506,12 @@ 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: {
@@ -2521,9 +2553,9 @@ int security_node_sid(struct selinux_state *state,
 
        if (c) {
                if (!c->sid[0]) {
-                       rc = sidtab_context_to_sid(sidtab,
-                                                  &c->context[0],
-                                                  &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
                }
@@ -2561,7 +2593,6 @@ int security_get_user_sids(struct selinux_state *state,
                           u32 *nel)
 {
        struct policydb *policydb;
-       struct sidtab *sidtab;
        struct context *fromcon, usercon;
        u32 *mysids = NULL, *mysids2, sid;
        u32 mynel = 0, maxnel = SIDS_NEL;
@@ -2579,12 +2610,11 @@ int security_get_user_sids(struct selinux_state *state,
        read_lock(&state->ss->policy_rwlock);
 
        policydb = &state->ss->policydb;
-       sidtab = &state->ss->sidtab;
 
        context_init(&usercon);
 
        rc = -EINVAL;
-       fromcon = sidtab_search(sidtab, fromsid);
+       fromcon = security_sid_to_context_struct(state, fromsid, 0);
        if (!fromcon)
                goto out_unlock;
 
@@ -2610,7 +2640,7 @@ int security_get_user_sids(struct selinux_state *state,
                                                 &usercon))
                                continue;
 
-                       rc = sidtab_context_to_sid(sidtab, &usercon, &sid);
+                       rc = security_context_struct_to_sid(state, &usercon, 
&sid);
                        if (rc)
                                goto out_unlock;
                        if (mynel < maxnel) {
@@ -2681,7 +2711,6 @@ 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;
@@ -2716,7 +2745,8 @@ static inline int __security_genfs_sid(struct 
selinux_state *state,
                goto out;
 
        if (!c->sid[0]) {
-               rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]);
+               rc = security_context_struct_to_sid(state, &c->context[0],
+                                                   &c->sid[0]);
                if (rc)
                        goto out;
        }
@@ -2758,7 +2788,6 @@ 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;
@@ -2767,7 +2796,6 @@ 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) {
@@ -2779,8 +2807,9 @@ int security_fs_use(struct selinux_state *state, struct 
super_block *sb)
        if (c) {
                sbsec->behavior = c->v.behavior;
                if (!c->sid[0]) {
-                       rc = sidtab_context_to_sid(sidtab, &c->context[0],
-                                                  &c->sid[0]);
+                       rc = security_context_struct_to_sid(state,
+                                                           &c->context[0],
+                                                           &c->sid[0]);
                        if (rc)
                                goto out;
                }
@@ -2973,7 +3002,6 @@ int security_sid_mls_copy(struct selinux_state *state,
                          u32 sid, u32 mls_sid, u32 *new_sid)
 {
        struct policydb *policydb = &state->ss->policydb;
-       struct sidtab *sidtab = &state->ss->sidtab;
        struct context *context1;
        struct context *context2;
        struct context newcon;
@@ -2992,7 +3020,7 @@ int security_sid_mls_copy(struct selinux_state *state,
        read_lock(&state->ss->policy_rwlock);
 
        rc = -EINVAL;
-       context1 = sidtab_search(sidtab, sid);
+       context1 = security_sid_to_context_struct(state, sid, 0);
        if (!context1) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, sid);
@@ -3000,7 +3028,7 @@ int security_sid_mls_copy(struct selinux_state *state,
        }
 
        rc = -EINVAL;
-       context2 = sidtab_search(sidtab, mls_sid);
+       context2 = security_sid_to_context_struct(state, mls_sid, 0);
        if (!context2) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                        __func__, mls_sid);
@@ -3030,7 +3058,7 @@ int security_sid_mls_copy(struct selinux_state *state,
                }
        }
 
-       rc = sidtab_context_to_sid(sidtab, &newcon, new_sid);
+       rc = security_context_struct_to_sid(state, &newcon, new_sid);
 out_unlock:
        read_unlock(&state->ss->policy_rwlock);
        context_destroy(&newcon);
@@ -3064,7 +3092,6 @@ int security_net_peersid_resolve(struct selinux_state 
*state,
                                 u32 *peer_sid)
 {
        struct policydb *policydb = &state->ss->policydb;
-       struct sidtab *sidtab = &state->ss->sidtab;
        int rc;
        struct context *nlbl_ctx;
        struct context *xfrm_ctx;
@@ -3097,14 +3124,14 @@ int security_net_peersid_resolve(struct selinux_state 
*state,
        read_lock(&state->ss->policy_rwlock);
 
        rc = -EINVAL;
-       nlbl_ctx = sidtab_search(sidtab, nlbl_sid);
+       nlbl_ctx = security_sid_to_context_struct(state, nlbl_sid, 0);
        if (!nlbl_ctx) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, nlbl_sid);
                goto out;
        }
        rc = -EINVAL;
-       xfrm_ctx = sidtab_search(sidtab, xfrm_sid);
+       xfrm_ctx = security_sid_to_context_struct(state, xfrm_sid, 0);
        if (!xfrm_ctx) {
                pr_err("SELinux: %s:  unrecognized SID %d\n",
                       __func__, xfrm_sid);
@@ -3425,7 +3452,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, 
void *vrule,
                goto out;
        }
 
-       ctxt = sidtab_search(&state->ss->sidtab, sid);
+       ctxt = security_sid_to_context_struct(state, sid, 0);
        if (unlikely(!ctxt)) {
                WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n",
                          sid);
@@ -3588,7 +3615,6 @@ int security_netlbl_secattr_to_sid(struct selinux_state 
*state,
                                   u32 *sid)
 {
        struct policydb *policydb = &state->ss->policydb;
-       struct sidtab *sidtab = &state->ss->sidtab;
        int rc;
        struct context *ctx;
        struct context ctx_new;
@@ -3606,7 +3632,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state 
*state,
                *sid = secattr->attr.secid;
        else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
                rc = -EIDRM;
-               ctx = sidtab_search(sidtab, SECINITSID_NETMSG);
+               ctx = security_sid_to_context_struct(state, SECINITSID_NETMSG, 
0);
                if (ctx == NULL)
                        goto out;
 
@@ -3624,7 +3650,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state 
*state,
                if (!mls_context_isvalid(policydb, &ctx_new))
                        goto out_free;
 
-               rc = sidtab_context_to_sid(sidtab, &ctx_new, sid);
+               rc = security_context_struct_to_sid(state, &ctx_new, sid);
                if (rc)
                        goto out_free;
 
@@ -3666,7 +3692,7 @@ int security_netlbl_sid_to_secattr(struct selinux_state 
*state,
        read_lock(&state->ss->policy_rwlock);
 
        rc = -ENOENT;
-       ctx = sidtab_search(&state->ss->sidtab, sid);
+       ctx = security_sid_to_context_struct(state, sid, 0);
        if (ctx == NULL)
                goto out;
 
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h
index 24c7bdcc8075..18a2fb386120 100644
--- a/security/selinux/ss/services.h
+++ b/security/selinux/ss/services.h
@@ -25,6 +25,7 @@ struct selinux_map {
 
 struct selinux_ss {
        struct sidtab sidtab;
+       struct isidtab *isidtab;
        struct policydb policydb;
        rwlock_t policy_rwlock;
        u32 latest_granting;
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index fd75a12fa8fc..98710657a596 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -25,7 +25,7 @@ int sidtab_init(struct sidtab *s)
        for (i = 0; i < SIDTAB_SIZE; i++)
                s->htable[i] = NULL;
        s->nel = 0;
-       s->next_sid = 1;
+       s->next_sid = SECINITSID_NUM + 1;
        s->shutdown = 0;
        spin_lock_init(&s->lock);
        return 0;
@@ -76,7 +76,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context 
*context)
        return 0;
 }
 
-static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
+struct context *sidtab_lookup(struct sidtab *s, u32 sid)
 {
        int hvalue;
        struct sidtab_node *cur;
@@ -89,33 +89,12 @@ static struct context *sidtab_search_core(struct sidtab *s, 
u32 sid, int force)
        while (cur && sid > cur->sid)
                cur = cur->next;
 
-       if (force && cur && sid == cur->sid && cur->context.len)
-               return &cur->context;
-
-       if (!cur || sid != cur->sid || cur->context.len) {
-               /* Remap invalid SIDs to the unlabeled SID. */
-               sid = SECINITSID_UNLABELED;
-               hvalue = SIDTAB_HASH(sid);
-               cur = s->htable[hvalue];
-               while (cur && sid > cur->sid)
-                       cur = cur->next;
-               if (!cur || sid != cur->sid)
-                       return NULL;
-       }
+       if (!cur || sid != cur->sid)
+               return NULL;
 
        return &cur->context;
 }
 
-struct context *sidtab_search(struct sidtab *s, u32 sid)
-{
-       return sidtab_search_core(s, sid, 0);
-}
-
-struct context *sidtab_search_force(struct sidtab *s, u32 sid)
-{
-       return sidtab_search_core(s, sid, 1);
-}
-
 int sidtab_map(struct sidtab *s,
               int (*apply) (u32 sid,
                             struct context *context,
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h
index a1a1d2617b6f..2eadd09a1100 100644
--- a/security/selinux/ss/sidtab.h
+++ b/security/selinux/ss/sidtab.h
@@ -34,8 +34,7 @@ struct sidtab {
 
 int sidtab_init(struct sidtab *s);
 int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
-struct context *sidtab_search(struct sidtab *s, u32 sid);
-struct context *sidtab_search_force(struct sidtab *s, u32 sid);
+struct context *sidtab_lookup(struct sidtab *s, u32 sid);
 
 int sidtab_map(struct sidtab *s,
               int (*apply) (u32 sid,
-- 
2.17.2

_______________________________________________
Selinux mailing list
[email protected]
To unsubscribe, send email to [email protected].
To get help, send an email containing "help" to [email protected].

Reply via email to