summary refs log tree commit diff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/policydb.h2
-rw-r--r--security/selinux/ss/services.c9
3 files changed, 17 insertions, 0 deletions
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 &&