diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 75 |
1 files changed, 42 insertions, 33 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 6ef4af47dac4..973e00e34fa9 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1359,26 +1359,35 @@ out: } static void filename_compute_type(struct policydb *p, struct context *newcontext, - u32 scon, u32 tcon, u16 tclass, - const struct qstr *qstr) -{ - 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, qstr->name)) { - newcontext->type = ft->otype; - return; - } - } + u32 stype, u32 ttype, u16 tclass, + const char *objname) +{ + struct filename_trans ft; + struct filename_trans_datum *otype; + + /* + * Most filename trans rules are going to live in specific directories + * like /dev or /var/run. This bitmap will quickly skip rule searches + * if the ttype does not contain any rules. + */ + if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) + return; + + ft.stype = stype; + ft.ttype = ttype; + ft.tclass = tclass; + ft.name = objname; + + otype = hashtab_search(p->filename_trans, &ft); + if (otype) + newcontext->type = otype->otype; } static int security_compute_sid(u32 ssid, u32 tsid, u16 orig_tclass, u32 specified, - const struct qstr *qstr, + const char *objname, u32 *out_sid, bool kern) { @@ -1478,23 +1487,21 @@ 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 (qstr) + /* if we have a objname this is a file trans check so check those rules */ + if (objname) filename_compute_type(&policydb, &newcontext, scontext->type, - tcontext->type, tclass, qstr); + 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; } } } @@ -1541,13 +1548,14 @@ 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, - qstr, 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, - NULL, out_sid, false); + objname, out_sid, false); } /** @@ -2209,10 +2217,11 @@ out_unlock: goto out; } for (i = 0, j = 0; i < mynel; i++) { + struct av_decision dummy_avd; rc = avc_has_perm_noaudit(fromsid, mysids[i], SECCLASS_PROCESS, /* kernel value */ PROCESS__TRANSITION, AVC_STRICT, - NULL); + &dummy_avd); if (!rc) mysids2[j++] = mysids[i]; cond_resched(); @@ -3190,7 +3199,7 @@ out: * @len: length of data in bytes * */ -int security_read_policy(void **data, ssize_t *len) +int security_read_policy(void **data, size_t *len) { int rc; struct policy_file fp; |