int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) { __u32 *buf; __u32 items, items2; memset(avkey, 0, sizeof(struct avtab_key)); memset(avdatum, 0, sizeof(struct avtab_datum)); buf = next_entry(fp, sizeof(__u32)); if (!buf) { printk(KERN_ERR "security: avtab: truncated entry\n"); goto bad; } items2 = le32_to_cpu(buf[0]); buf = next_entry(fp, sizeof(__u32)*items2); if (!buf) { printk(KERN_ERR "security: avtab: truncated entry\n"); goto bad; } items = 0; avkey->source_type = le32_to_cpu(buf[items++]); avkey->target_type = le32_to_cpu(buf[items++]); avkey->target_class = le32_to_cpu(buf[items++]); avdatum->specified = le32_to_cpu(buf[items++]); if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { printk(KERN_ERR "security: avtab: null entry\n"); goto bad; } if ((avdatum->specified & AVTAB_AV) && (avdatum->specified & AVTAB_TYPE)) { printk(KERN_ERR "security: avtab: entry has both access vectors and types\n"); goto bad; } if (avdatum->specified & AVTAB_AV) { if (avdatum->specified & AVTAB_ALLOWED) avtab_allowed(avdatum) = le32_to_cpu(buf[items++]); if (avdatum->specified & AVTAB_AUDITDENY) avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]); if (avdatum->specified & AVTAB_AUDITALLOW) avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]); } else { if (avdatum->specified & AVTAB_TRANSITION) avtab_transition(avdatum) = le32_to_cpu(buf[items++]); if (avdatum->specified & AVTAB_CHANGE) avtab_change(avdatum) = le32_to_cpu(buf[items++]); if (avdatum->specified & AVTAB_MEMBER) avtab_member(avdatum) = le32_to_cpu(buf[items++]); } if (items != items2) { printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n", items2, items); goto bad; } return 0; bad: return -1; }
static int security_compute_sid(u32 ssid, u32 tsid, u16 tclass, u32 specified, u32 *out_sid) { struct context *scontext = 0, *tcontext = 0, newcontext; struct role_trans *roletr = 0; struct avtab_key avkey; struct avtab_datum *avdatum; unsigned int type_change = 0; int rc = 0; if (!ss_initialized) { switch (tclass) { case SECCLASS_PROCESS: *out_sid = ssid; break; default: *out_sid = tsid; break; } goto out; } POLICY_RDLOCK; scontext = sidtab_search(&sidtab, ssid); if (!scontext) { printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n", ssid); rc = -EINVAL; goto out_unlock; } tcontext = sidtab_search(&sidtab, tsid); if (!tcontext) { printk(KERN_ERR "security_compute_sid: unrecognized SID %d\n", tsid); rc = -EINVAL; goto out_unlock; } context_init(&newcontext); /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: case AVTAB_CHANGE: /* Use the process user identity. */ newcontext.user = scontext->user; break; case AVTAB_MEMBER: /* Use the related object owner. */ newcontext.user = tcontext->user; break; } /* Set the role and type to default values. */ switch (tclass) { case SECCLASS_PROCESS: /* Use the current role and type of process. */ newcontext.role = scontext->role; newcontext.type = scontext->type; break; default: /* Use the well-defined object role. */ newcontext.role = OBJECT_R_VAL; /* Use the type of the related object. */ newcontext.type = tcontext->type; } /* Look for a type transition/member/change rule. */ avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); type_change = (avdatum && (avdatum->specified & specified)); if (type_change) { /* Use the type from the type transition/member/change rule. */ switch (specified) { case AVTAB_TRANSITION: newcontext.type = avtab_transition(avdatum); break; case AVTAB_MEMBER: newcontext.type = avtab_member(avdatum); break; case AVTAB_CHANGE: newcontext.type = avtab_change(avdatum); break; } } /* Check for class-specific changes. */ switch (tclass) { case SECCLASS_PROCESS: 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 (!type_change && !roletr) { /* No change in process role or type. */ *out_sid = ssid; goto out_unlock; } break; default: if (!type_change && (newcontext.user == tcontext->user) && mls_context_cmp(scontext, tcontext)) { /* No change in object type, owner, or MLS attributes. */ *out_sid = tsid; goto out_unlock; } break; } /* Set the MLS attributes. This is done last because it may allocate memory. */ rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext); if (rc) goto out_unlock; /* Check the validity of the context. */ if (!policydb_context_isvalid(&policydb, &newcontext)) { rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass, &newcontext); if (rc) goto out_unlock; } /* Obtain the sid for the context. */ rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid); out_unlock: POLICY_RDUNLOCK; context_destroy(&newcontext); out: return rc; }