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; }
/* * Compute access vectors based on a context structure pair for * the permissions in a particular class. */ static int context_struct_compute_av(struct context *scontext, struct context *tcontext, u16 tclass, u32 requested, struct av_decision *avd) { struct constraint_node *constraint; struct role_allow *ra; struct avtab_key avkey; struct avtab_datum *avdatum; struct class_datum *tclass_datum; if (!tclass || tclass > policydb.p_classes.nprim) { printk(KERN_ERR "security_compute_av: unrecognized class %d\n", tclass); return -EINVAL; } tclass_datum = policydb.class_val_to_struct[tclass - 1]; /* * Initialize the access vectors to the default values. */ avd->allowed = 0; avd->decided = 0xffffffff; avd->auditallow = 0; avd->auditdeny = 0xffffffff; avd->seqno = latest_granting; /* * If a specific type enforcement rule was defined for * this permission check, then use it. */ avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); if (avdatum) { if (avdatum->specified & AVTAB_ALLOWED) avd->allowed = avtab_allowed(avdatum); if (avdatum->specified & AVTAB_AUDITDENY) avd->auditdeny = avtab_auditdeny(avdatum); if (avdatum->specified & AVTAB_AUDITALLOW) avd->auditallow = avtab_auditallow(avdatum); } /* * Remove any permissions prohibited by the MLS policy. */ mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed); /* * Remove any permissions prohibited by a constraint. */ constraint = tclass_datum->constraints; while (constraint) { if ((constraint->permissions & (avd->allowed)) && !constraint_expr_eval(scontext, tcontext, constraint->expr)) { avd->allowed = (avd->allowed) & ~(constraint->permissions); } constraint = constraint->next; } /* * If checking process transition permission and the * role is changing, then check the (current_role, new_role) * pair. */ if (tclass == SECCLASS_PROCESS && avd->allowed && PROCESS__TRANSITION && scontext->role != tcontext->role) { for (ra = policydb.role_allow; ra; ra = ra->next) { if (scontext->role == ra->role && tcontext->role == ra->new_role) break; } if (!ra) avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION); } return 0; }