aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2011-04-28 15:11:21 -0400
committerEric Paris <eparis@redhat.com>2011-04-28 15:15:53 -0400
commit2463c26d50adc282d19317013ba0ff473823ca47 (patch)
treee92438150bb380c0dc0867b00f1ae89f73646b2a /security/selinux/ss
parent3f058ef7787e1b48720622346de9a5317aeb749a (diff)
SELinux: put name based create rules in a hashtable
To shorten the list we need to run if filename trans rules exist for the type of the given parent directory I put them in a hashtable. Given the policy we are expecting to use in Fedora this takes the worst case list run from about 5,000 entries to 17. Signed-off-by: Eric Paris <eparis@redhat.com> Reviewed-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss')
-rw-r--r--security/selinux/ss/policydb.c167
-rw-r--r--security/selinux/ss/policydb.h9
-rw-r--r--security/selinux/ss/services.c20
3 files changed, 135 insertions, 61 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index ca7a7231b5a2..549120c56edd 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -184,6 +184,43 @@ out:
184 return rc; 184 return rc;
185} 185}
186 186
187static u32 filenametr_hash(struct hashtab *h, const void *k)
188{
189 const struct filename_trans *ft = k;
190 unsigned long hash;
191 unsigned int byte_num;
192 unsigned char focus;
193
194 hash = ft->stype ^ ft->ttype ^ ft->tclass;
195
196 byte_num = 0;
197 while ((focus = ft->name[byte_num++]))
198 hash = partial_name_hash(focus, hash);
199 return hash & (h->size - 1);
200}
201
202static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
203{
204 const struct filename_trans *ft1 = k1;
205 const struct filename_trans *ft2 = k2;
206 int v;
207
208 v = ft1->stype - ft2->stype;
209 if (v)
210 return v;
211
212 v = ft1->ttype - ft2->ttype;
213 if (v)
214 return v;
215
216 v = ft1->tclass - ft2->tclass;
217 if (v)
218 return v;
219
220 return strcmp(ft1->name, ft2->name);
221
222}
223
187static u32 rangetr_hash(struct hashtab *h, const void *k) 224static u32 rangetr_hash(struct hashtab *h, const void *k)
188{ 225{
189 const struct range_trans *key = k; 226 const struct range_trans *key = k;
@@ -236,6 +273,10 @@ static int policydb_init(struct policydb *p)
236 if (rc) 273 if (rc)
237 goto out; 274 goto out;
238 275
276 p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10));
277 if (!p->filename_trans)
278 goto out;
279
239 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); 280 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
240 if (!p->range_tr) 281 if (!p->range_tr)
241 goto out; 282 goto out;
@@ -246,6 +287,8 @@ static int policydb_init(struct policydb *p)
246 287
247 return 0; 288 return 0;
248out: 289out:
290 hashtab_destroy(p->filename_trans);
291 hashtab_destroy(p->range_tr);
249 for (i = 0; i < SYM_NUM; i++) 292 for (i = 0; i < SYM_NUM; i++)
250 hashtab_destroy(p->symtab[i].table); 293 hashtab_destroy(p->symtab[i].table);
251 return rc; 294 return rc;
@@ -675,6 +718,16 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
675 cat_destroy, 718 cat_destroy,
676}; 719};
677 720
721static int filenametr_destroy(void *key, void *datum, void *p)
722{
723 struct filename_trans *ft = key;
724 kfree(ft->name);
725 kfree(key);
726 kfree(datum);
727 cond_resched();
728 return 0;
729}
730
678static int range_tr_destroy(void *key, void *datum, void *p) 731static int range_tr_destroy(void *key, void *datum, void *p)
679{ 732{
680 struct mls_range *rt = datum; 733 struct mls_range *rt = datum;
@@ -709,7 +762,6 @@ void policydb_destroy(struct policydb *p)
709 int i; 762 int i;
710 struct role_allow *ra, *lra = NULL; 763 struct role_allow *ra, *lra = NULL;
711 struct role_trans *tr, *ltr = NULL; 764 struct role_trans *tr, *ltr = NULL;
712 struct filename_trans *ft, *nft;
713 765
714 for (i = 0; i < SYM_NUM; i++) { 766 for (i = 0; i < SYM_NUM; i++) {
715 cond_resched(); 767 cond_resched();
@@ -773,6 +825,9 @@ void policydb_destroy(struct policydb *p)
773 } 825 }
774 kfree(lra); 826 kfree(lra);
775 827
828 hashtab_map(p->filename_trans, filenametr_destroy, NULL);
829 hashtab_destroy(p->filename_trans);
830
776 hashtab_map(p->range_tr, range_tr_destroy, NULL); 831 hashtab_map(p->range_tr, range_tr_destroy, NULL);
777 hashtab_destroy(p->range_tr); 832 hashtab_destroy(p->range_tr);
778 833
@@ -788,14 +843,6 @@ void policydb_destroy(struct policydb *p)
788 flex_array_free(p->type_attr_map_array); 843 flex_array_free(p->type_attr_map_array);
789 } 844 }
790 845
791 ft = p->filename_trans;
792 while (ft) {
793 nft = ft->next;
794 kfree(ft->name);
795 kfree(ft);
796 ft = nft;
797 }
798
799 ebitmap_destroy(&p->filename_trans_ttypes); 846 ebitmap_destroy(&p->filename_trans_ttypes);
800 ebitmap_destroy(&p->policycaps); 847 ebitmap_destroy(&p->policycaps);
801 ebitmap_destroy(&p->permissive_map); 848 ebitmap_destroy(&p->permissive_map);
@@ -1806,9 +1853,10 @@ out:
1806 1853
1807static int filename_trans_read(struct policydb *p, void *fp) 1854static int filename_trans_read(struct policydb *p, void *fp)
1808{ 1855{
1809 struct filename_trans *ft, *last; 1856 struct filename_trans *ft;
1810 u32 nel, len; 1857 struct filename_trans_datum *otype;
1811 char *name; 1858 char *name;
1859 u32 nel, len;
1812 __le32 buf[4]; 1860 __le32 buf[4];
1813 int rc, i; 1861 int rc, i;
1814 1862
@@ -1817,25 +1865,23 @@ static int filename_trans_read(struct policydb *p, void *fp)
1817 1865
1818 rc = next_entry(buf, fp, sizeof(u32)); 1866 rc = next_entry(buf, fp, sizeof(u32));
1819 if (rc) 1867 if (rc)
1820 goto out; 1868 return rc;
1821 nel = le32_to_cpu(buf[0]); 1869 nel = le32_to_cpu(buf[0]);
1822 1870
1823 last = p->filename_trans;
1824 while (last && last->next)
1825 last = last->next;
1826
1827 for (i = 0; i < nel; i++) { 1871 for (i = 0; i < nel; i++) {
1872 ft = NULL;
1873 otype = NULL;
1874 name = NULL;
1875
1828 rc = -ENOMEM; 1876 rc = -ENOMEM;
1829 ft = kzalloc(sizeof(*ft), GFP_KERNEL); 1877 ft = kzalloc(sizeof(*ft), GFP_KERNEL);
1830 if (!ft) 1878 if (!ft)
1831 goto out; 1879 goto out;
1832 1880
1833 /* add it to the tail of the list */ 1881 rc = -ENOMEM;
1834 if (!last) 1882 otype = kmalloc(sizeof(*otype), GFP_KERNEL);
1835 p->filename_trans = ft; 1883 if (!otype)
1836 else 1884 goto out;
1837 last->next = ft;
1838 last = ft;
1839 1885
1840 /* length of the path component string */ 1886 /* length of the path component string */
1841 rc = next_entry(buf, fp, sizeof(u32)); 1887 rc = next_entry(buf, fp, sizeof(u32));
@@ -1863,14 +1909,22 @@ static int filename_trans_read(struct policydb *p, void *fp)
1863 ft->stype = le32_to_cpu(buf[0]); 1909 ft->stype = le32_to_cpu(buf[0]);
1864 ft->ttype = le32_to_cpu(buf[1]); 1910 ft->ttype = le32_to_cpu(buf[1]);
1865 ft->tclass = le32_to_cpu(buf[2]); 1911 ft->tclass = le32_to_cpu(buf[2]);
1866 ft->otype = le32_to_cpu(buf[3]); 1912
1913 otype->otype = le32_to_cpu(buf[3]);
1867 1914
1868 rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1); 1915 rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1);
1869 if (rc) 1916 if (rc)
1870 goto out; 1917 goto out;
1918
1919 hashtab_insert(p->filename_trans, ft, otype);
1871 } 1920 }
1872 rc = 0; 1921 hash_eval(p->filename_trans, "filenametr");
1922 return 0;
1873out: 1923out:
1924 kfree(ft);
1925 kfree(name);
1926 kfree(otype);
1927
1874 return rc; 1928 return rc;
1875} 1929}
1876 1930
@@ -3131,43 +3185,60 @@ static int range_write(struct policydb *p, void *fp)
3131 return 0; 3185 return 0;
3132} 3186}
3133 3187
3134static int filename_trans_write(struct policydb *p, void *fp) 3188static int filename_write_helper(void *key, void *data, void *ptr)
3135{ 3189{
3136 struct filename_trans *ft;
3137 u32 len, nel = 0;
3138 __le32 buf[4]; 3190 __le32 buf[4];
3191 struct filename_trans *ft = key;
3192 struct filename_trans_datum *otype = data;
3193 void *fp = ptr;
3139 int rc; 3194 int rc;
3195 u32 len;
3140 3196
3141 for (ft = p->filename_trans; ft; ft = ft->next) 3197 len = strlen(ft->name);
3142 nel++; 3198 buf[0] = cpu_to_le32(len);
3143
3144 buf[0] = cpu_to_le32(nel);
3145 rc = put_entry(buf, sizeof(u32), 1, fp); 3199 rc = put_entry(buf, sizeof(u32), 1, fp);
3146 if (rc) 3200 if (rc)
3147 return rc; 3201 return rc;
3148 3202
3149 for (ft = p->filename_trans; ft; ft = ft->next) { 3203 rc = put_entry(ft->name, sizeof(char), len, fp);
3150 len = strlen(ft->name); 3204 if (rc)
3151 buf[0] = cpu_to_le32(len); 3205 return rc;
3152 rc = put_entry(buf, sizeof(u32), 1, fp);
3153 if (rc)
3154 return rc;
3155 3206
3156 rc = put_entry(ft->name, sizeof(char), len, fp); 3207 buf[0] = ft->stype;
3157 if (rc) 3208 buf[1] = ft->ttype;
3158 return rc; 3209 buf[2] = ft->tclass;
3210 buf[3] = otype->otype;
3159 3211
3160 buf[0] = ft->stype; 3212 rc = put_entry(buf, sizeof(u32), 4, fp);
3161 buf[1] = ft->ttype; 3213 if (rc)
3162 buf[2] = ft->tclass; 3214 return rc;
3163 buf[3] = ft->otype;
3164 3215
3165 rc = put_entry(buf, sizeof(u32), 4, fp);
3166 if (rc)
3167 return rc;
3168 }
3169 return 0; 3216 return 0;
3170} 3217}
3218
3219static int filename_trans_write(struct policydb *p, void *fp)
3220{
3221 u32 nel;
3222 __le32 buf[1];
3223 int rc;
3224
3225 nel = 0;
3226 rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel);
3227 if (rc)
3228 return rc;
3229
3230 buf[0] = cpu_to_le32(nel);
3231 rc = put_entry(buf, sizeof(u32), 1, fp);
3232 if (rc)
3233 return rc;
3234
3235 rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
3236 if (rc)
3237 return rc;
3238
3239 return 0;
3240}
3241
3171/* 3242/*
3172 * Write the configuration data in a policy database 3243 * Write the configuration data in a policy database
3173 * structure to a policy database binary representation 3244 * structure to a policy database binary representation
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index f054a9d4d114..b846c0387180 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -79,11 +79,13 @@ struct role_trans {
79}; 79};
80 80
81struct filename_trans { 81struct filename_trans {
82 struct filename_trans *next;
83 u32 stype; /* current process */ 82 u32 stype; /* current process */
84 u32 ttype; /* parent dir context */ 83 u32 ttype; /* parent dir context */
85 u16 tclass; /* class of new object */ 84 u16 tclass; /* class of new object */
86 const char *name; /* last path component */ 85 const char *name; /* last path component */
86};
87
88struct filename_trans_datum {
87 u32 otype; /* expected of new object */ 89 u32 otype; /* expected of new object */
88}; 90};
89 91
@@ -227,10 +229,11 @@ struct policydb {
227 /* role transitions */ 229 /* role transitions */
228 struct role_trans *role_tr; 230 struct role_trans *role_tr;
229 231
232 /* file transitions with the last path component */
230 /* quickly exclude lookups when parent ttype has no rules */ 233 /* quickly exclude lookups when parent ttype has no rules */
231 struct ebitmap filename_trans_ttypes; 234 struct ebitmap filename_trans_ttypes;
232 /* file transitions with the last path component */ 235 /* actual set of filename_trans rules */
233 struct filename_trans *filename_trans; 236 struct hashtab *filename_trans;
234 237
235 /* bools indexed by (value - 1) */ 238 /* bools indexed by (value - 1) */
236 struct cond_bool_datum **bool_val_to_struct; 239 struct cond_bool_datum **bool_val_to_struct;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 6a22eaebf3b7..e11b4b038f4a 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1362,7 +1362,8 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext
1362 u32 stype, u32 ttype, u16 tclass, 1362 u32 stype, u32 ttype, u16 tclass,
1363 const char *objname) 1363 const char *objname)
1364{ 1364{
1365 struct filename_trans *ft; 1365 struct filename_trans ft;
1366 struct filename_trans_datum *otype;
1366 1367
1367 /* 1368 /*
1368 * Most filename trans rules are going to live in specific directories 1369 * Most filename trans rules are going to live in specific directories
@@ -1372,15 +1373,14 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext
1372 if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) 1373 if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype))
1373 return; 1374 return;
1374 1375
1375 for (ft = p->filename_trans; ft; ft = ft->next) { 1376 ft.stype = stype;
1376 if (ft->stype == stype && 1377 ft.ttype = ttype;
1377 ft->ttype == ttype && 1378 ft.tclass = tclass;
1378 ft->tclass == tclass && 1379 ft.name = objname;
1379 !strcmp(ft->name, objname)) { 1380
1380 newcontext->type = ft->otype; 1381 otype = hashtab_search(p->filename_trans, &ft);
1381 return; 1382 if (otype)
1382 } 1383 newcontext->type = otype->otype;
1383 }
1384} 1384}
1385 1385
1386static int security_compute_sid(u32 ssid, 1386static int security_compute_sid(u32 ssid,