summaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-04-28 21:11:21 +0200
committerEric Paris <eparis@redhat.com>2011-04-28 21:15:52 +0200
commit03a4c0182a156547edd5f2717c1702590fe36bbf (patch)
treec4585fab7c37d4eb2cc46e93c925e7c2a5e7b1a2 /security/selinux
parentSELinux: rename filename_compute_type argument to *type instead of *con (diff)
downloadlinux-03a4c0182a156547edd5f2717c1702590fe36bbf.tar.xz
linux-03a4c0182a156547edd5f2717c1702590fe36bbf.zip
SELinux: skip filename trans rules if ttype does not match parent dir
Right now we walk to filename trans rule list for every inode that is created. First passes at policy using this facility creates around 5000 filename trans rules. Running a list of 5000 entries every time is a bad idea. This patch adds a new ebitmap to policy which has a bit set for each ttype that has at least 1 filename trans rule. Thus when an inode is created we can quickly determine if any rules exist for this parent directory type and can skip the list if we know there is definitely no relevant entry. Signed-off-by: Eric Paris <eparis@redhat.com> Reviewed-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux')
-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 &&