selinux: Fix regression for Xorg
[deliverable/linux.git] / security / selinux / ss / services.c
index ab6dbce5fd2aad4c1bfdd4d604bdda674e47ea85..f3f5dca810069e757d4e89ca54e37bf9d0960883 100644 (file)
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)
        return tclass;
 }
 
+/*
+ * Get kernel value for class from its policy value
+ */
+static u16 map_class(u16 pol_value)
+{
+       u16 i;
+
+       for (i = 1; i < current_mapping_size; i++) {
+               if (current_mapping[i].value == pol_value)
+                       return i;
+       }
+
+       return SECCLASS_NULL;
+}
+
 static void map_decision(u16 tclass, struct av_decision *avd,
                         int allow_unknown)
 {
@@ -464,7 +479,7 @@ static void security_dump_masked_av(struct context *scontext,
        if (!permissions)
                return;
 
-       tclass_name = policydb.p_class_val_to_name[tclass - 1];
+       tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
        tclass_dat = policydb.class_val_to_struct[tclass - 1];
        common_dat = tclass_dat->comdatum;
 
@@ -530,12 +545,18 @@ static void type_attribute_bounds_av(struct context *scontext,
        struct context lo_scontext;
        struct context lo_tcontext;
        struct av_decision lo_avd;
-       struct type_datum *source
-               = policydb.type_val_to_struct[scontext->type - 1];
-       struct type_datum *target
-               = policydb.type_val_to_struct[tcontext->type - 1];
+       struct type_datum *source;
+       struct type_datum *target;
        u32 masked = 0;
 
+       source = flex_array_get_ptr(policydb.type_val_to_struct_array,
+                                   scontext->type - 1);
+       BUG_ON(!source);
+
+       target = flex_array_get_ptr(policydb.type_val_to_struct_array,
+                                   tcontext->type - 1);
+       BUG_ON(!target);
+
        if (source->bounds) {
                memset(&lo_avd, 0, sizeof(lo_avd));
 
@@ -710,7 +731,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
        audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
                  "security_validate_transition:  denied for"
                  " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
-                 o, n, t, policydb.p_class_val_to_name[tclass-1]);
+                 o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
 out:
        kfree(o);
        kfree(n);
@@ -828,7 +849,8 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 
        index = new_context->type;
        while (true) {
-               type = policydb.type_val_to_struct[index - 1];
+               type = flex_array_get_ptr(policydb.type_val_to_struct_array,
+                                         index - 1);
                BUG_ON(!type);
 
                /* not bounded anymore */
@@ -1005,9 +1027,9 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
        }
 
        /* Compute the size of the context. */
-       *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
-       *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
-       *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+       *scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
+       *scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
+       *scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
        *scontext_len += mls_compute_context_len(context);
 
        if (!scontext)
@@ -1023,12 +1045,12 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
         * Copy the user name, role name and type name into the context.
         */
        sprintf(scontextp, "%s:%s:%s",
-               policydb.p_user_val_to_name[context->user - 1],
-               policydb.p_role_val_to_name[context->role - 1],
-               policydb.p_type_val_to_name[context->type - 1]);
-       scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
-                    1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
-                    1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
+               sym_name(&policydb, SYM_USERS, context->user - 1),
+               sym_name(&policydb, SYM_ROLES, context->role - 1),
+               sym_name(&policydb, SYM_TYPES, context->type - 1));
+       scontextp += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) +
+                    1 + strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) +
+                    1 + strlen(sym_name(&policydb, SYM_TYPES, context->type - 1));
 
        mls_sid_to_context(context, &scontextp);
 
@@ -1326,7 +1348,7 @@ static int compute_sid_handle_invalid_context(
                  " for scontext=%s"
                  " tcontext=%s"
                  " tclass=%s",
-                 n, s, t, policydb.p_class_val_to_name[tclass-1]);
+                 n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
 out:
        kfree(s);
        kfree(t);
@@ -1336,10 +1358,27 @@ out:
        return -EACCES;
 }
 
+static void filename_compute_type(struct policydb *p, struct context *newcontext,
+                                 u32 scon, u32 tcon, u16 tclass,
+                                 const char *objname)
+{
+       struct filename_trans *ft;
+       for (ft = p->filename_trans; ft; ft = ft->next) {
+               if (ft->stype == scon &&
+                   ft->ttype == tcon &&
+                   ft->tclass == tclass &&
+                   !strcmp(ft->name, objname)) {
+                       newcontext->type = ft->otype;
+                       return;
+               }
+       }
+}
+
 static int security_compute_sid(u32 ssid,
                                u32 tsid,
                                u16 orig_tclass,
                                u32 specified,
+                               const char *objname,
                                u32 *out_sid,
                                bool kern)
 {
@@ -1350,6 +1389,7 @@ static int security_compute_sid(u32 ssid,
        struct avtab_node *node;
        u16 tclass;
        int rc = 0;
+       bool sock;
 
        if (!ss_initialized) {
                switch (orig_tclass) {
@@ -1367,10 +1407,13 @@ static int security_compute_sid(u32 ssid,
 
        read_lock(&policy_rwlock);
 
-       if (kern)
+       if (kern) {
                tclass = unmap_class(orig_tclass);
-       else
+               sock = security_is_socket_class(orig_tclass);
+       } else {
                tclass = orig_tclass;
+               sock = security_is_socket_class(map_class(tclass));
+       }
 
        scontext = sidtab_search(&sidtab, ssid);
        if (!scontext) {
@@ -1401,7 +1444,7 @@ static int security_compute_sid(u32 ssid,
        }
 
        /* Set the role and type to default values. */
-       if (tclass == policydb.process_class) {
+       if ((tclass == policydb.process_class) || (sock == true)) {
                /* Use the current role and type of process. */
                newcontext.role = scontext->role;
                newcontext.type = scontext->type;
@@ -1435,25 +1478,29 @@ static int security_compute_sid(u32 ssid,
                newcontext.type = avdatum->data;
        }
 
+       /* if we have a qstr this is a file trans check so check those rules */
+       if (objname)
+               filename_compute_type(&policydb, &newcontext, scontext->type,
+                                     tcontext->type, tclass, objname);
+
        /* Check for class-specific changes. */
-       if  (tclass == policydb.process_class) {
-               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) {
-                                       /* Use the role transition rule. */
-                                       newcontext.role = roletr->new_role;
-                                       break;
-                               }
+       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;
                        }
                }
        }
 
        /* Set the MLS attributes.
           This is done last because it may allocate memory. */
-       rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
+       rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+                            &newcontext, sock);
        if (rc)
                goto out_unlock;
 
@@ -1488,22 +1535,18 @@ out:
  * if insufficient memory is available, or %0 if the new SID was
  * computed successfully.
  */
-int security_transition_sid(u32 ssid,
-                           u32 tsid,
-                           u16 tclass,
-                           u32 *out_sid)
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
+                           const struct qstr *qstr, u32 *out_sid)
 {
        return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-                                   out_sid, true);
+                                   qstr ? qstr->name : NULL, out_sid, true);
 }
 
-int security_transition_sid_user(u32 ssid,
-                                u32 tsid,
-                                u16 tclass,
-                                u32 *out_sid)
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
+                                const char *objname, u32 *out_sid)
 {
        return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-                                   out_sid, false);
+                                   objname, out_sid, false);
 }
 
 /**
@@ -1524,8 +1567,8 @@ int security_member_sid(u32 ssid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid,
-                                   false);
+       return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
+                                   out_sid, false);
 }
 
 /**
@@ -1546,8 +1589,8 @@ int security_change_sid(u32 ssid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid,
-                                   false);
+       return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
+                                   out_sid, false);
 }
 
 /* Clone the SID into the new SID table. */
@@ -1647,7 +1690,7 @@ static int convert_context(u32 key,
        /* Convert the user. */
        rc = -EINVAL;
        usrdatum = hashtab_search(args->newp->p_users.table,
-                                 args->oldp->p_user_val_to_name[c->user - 1]);
+                                 sym_name(args->oldp, SYM_USERS, c->user - 1));
        if (!usrdatum)
                goto bad;
        c->user = usrdatum->value;
@@ -1655,7 +1698,7 @@ static int convert_context(u32 key,
        /* Convert the role. */
        rc = -EINVAL;
        role = hashtab_search(args->newp->p_roles.table,
-                             args->oldp->p_role_val_to_name[c->role - 1]);
+                             sym_name(args->oldp, SYM_ROLES, c->role - 1));
        if (!role)
                goto bad;
        c->role = role->value;
@@ -1663,7 +1706,7 @@ static int convert_context(u32 key,
        /* Convert the type. */
        rc = -EINVAL;
        typdatum = hashtab_search(args->newp->p_types.table,
-                                 args->oldp->p_type_val_to_name[c->type - 1]);
+                                 sym_name(args->oldp, SYM_TYPES, c->type - 1));
        if (!typdatum)
                goto bad;
        c->type = typdatum->value;
@@ -2319,14 +2362,14 @@ int security_get_bools(int *len, char ***names, int **values)
                size_t name_len;
 
                (*values)[i] = policydb.bool_val_to_struct[i]->state;
-               name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
+               name_len = strlen(sym_name(&policydb, SYM_BOOLS, i)) + 1;
 
                rc = -ENOMEM;
                (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
                if (!(*names)[i])
                        goto err;
 
-               strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
+               strncpy((*names)[i], sym_name(&policydb, SYM_BOOLS, i), name_len);
                (*names)[i][name_len - 1] = 0;
        }
        rc = 0;
@@ -2361,7 +2404,7 @@ int security_set_bools(int len, int *values)
                        audit_log(current->audit_context, GFP_ATOMIC,
                                AUDIT_MAC_CONFIG_CHANGE,
                                "bool=%s val=%d old_val=%d auid=%u ses=%u",
-                               policydb.p_bool_val_to_name[i],
+                               sym_name(&policydb, SYM_BOOLS, i),
                                !!values[i],
                                policydb.bool_val_to_struct[i]->state,
                                audit_get_loginuid(current),
@@ -3125,7 +3168,7 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
                goto out;
 
        rc = -ENOMEM;
-       secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
+       secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
                                  GFP_ATOMIC);
        if (secattr->domain == NULL)
                goto out;
This page took 0.03334 seconds and 5 git commands to generate.