diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 5591e422256a..4c1811972b8b 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -240,6 +240,7 @@ static int policydb_init(struct policydb *p) if (!p->range_tr) goto out; + ebitmap_init(&p->filename_trans_ttypes); ebitmap_init(&p->policycaps); ebitmap_init(&p->permissive_map); @@ -801,6 +802,7 @@ void policydb_destroy(struct policydb *p) ft = nft; } + ebitmap_destroy(&p->filename_trans_ttypes); ebitmap_destroy(&p->policycaps); ebitmap_destroy(&p->permissive_map); @@ -1868,6 +1870,10 @@ static int filename_trans_read(struct policydb *p, void *fp) ft->ttype = le32_to_cpu(buf[1]); ft->tclass = le32_to_cpu(buf[2]); ft->otype = le32_to_cpu(buf[3]); + + rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1); + if (rc) + goto out; } rc = 0; out: diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 801175f79cf9..f054a9d4d114 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -227,6 +227,8 @@ struct policydb { /* role transitions */ struct role_trans *role_tr; + /* quickly exclude lookups when parent ttype has no rules */ + struct ebitmap filename_trans_ttypes; /* file transitions with the last path component */ struct filename_trans *filename_trans; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 78bb8100b02e..6a22eaebf3b7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1363,6 +1363,15 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext const char *objname) { struct filename_trans *ft; + + /* + * 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; + for (ft = p->filename_trans; ft; ft = ft->next) { if (ft->stype == stype && ft->ttype == ttype &&