History

Merge tag 'selinux-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux updates from Paul Moore: "Beyond the usual smattering of bug fixes, we've got three small improvements worth highlighting: - improved SELinux policy symbol table performance due to a reworking of the insert and search functions - allow reading of SELinux labels before the policy is loaded, allowing for some more "exotic" initramfs approaches - improved checking an error reporting about process class/permissions during SELinux policy load" * tag 'selinux-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: complete the inlining of hashtab functions selinux: prepare for inlining of hashtab functions selinux: specialize symtab insert and search functions selinux: Fix spelling mistakes in the comments selinux: fixed a checkpatch warning with the sizeof macro selinux: log error messages on required process class / permissions scripts/selinux/mdp: fix initial SID handling selinux: allow reading labels before policy is loaded

Linus Torvalds committed 6 years ago

Commit 49e917d2 parents 9ecc6ea 54b27f915 files · +258 −166Browse files

Unified · Split

15 files
  1. scripts/selinux/mdp/mdp.c +18 −5
  2. security/selinux/hooks.c +6 −1
  3. security/selinux/netif.c +1 −1
  4. security/selinux/netnode.c +1 −1
  5. security/selinux/netport.c +1 −1
  6. security/selinux/ss/conditional.c +4 −4
  7. security/selinux/ss/conditional.h +1 −1
  8. security/selinux/ss/hashtab.c +6 −53
  9. security/selinux/ss/hashtab.h +65 −12
  10. security/selinux/ss/mls.c +12 −11
  11. security/selinux/ss/policydb.c +95 −53
  12. security/selinux/ss/policydb.h +9 −0
  13. security/selinux/ss/services.c +19 −19
  14. security/selinux/ss/symtab.c +17 −4
  15. security/selinux/ss/symtab.h +3 −0
scripts/selinux/mdp/mdp.c+18−5
@@ -67,8 +67,14 @@ int main(int argc, char *argv[]) · 66 unmodified lines
6767
6868 initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
6969 /* print out the sids */
70− for (i = 1; i < initial_sid_to_string_len; i++)
71− fprintf(fout, "sid %s\n", initial_sid_to_string[i]);
70+ for (i = 1; i < initial_sid_to_string_len; i++) {
71+ const char *name = initial_sid_to_string[i];
72+
73+ if (name)
74+ fprintf(fout, "sid %s\n", name);
75+ else
76+ fprintf(fout, "sid unused%d\n", i);
77+ }
7278 fprintf(fout, "\n");
7379
7480 /* print out the class permissions */
@@ -126,9 +132,16 @@ int main(int argc, char *argv[]) · 51 unmodified lines
126132 #define OBJUSERROLETYPE "user_u:object_r:base_t"
127133
128134 /* default sids */
129− for (i = 1; i < initial_sid_to_string_len; i++)
130− fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n",
131− initial_sid_to_string[i], mls ? ":" SYSTEMLOW : "");
135+ for (i = 1; i < initial_sid_to_string_len; i++) {
136+ const char *name = initial_sid_to_string[i];
137+
138+ if (name)
139+ fprintf(fout, "sid %s ", name);
140+ else
141+ fprintf(fout, "sid unused%d\n", i);
142+ fprintf(fout, SUBJUSERROLETYPE "%s\n",
143+ mls ? ":" SYSTEMLOW : "");
144+ }
132145 fprintf(fout, "\n");
133146
134147 #define FS_USE(behavior, fstype) \
security/selinux/hooks.c+6−1
@@ -3332,7 +3332,12 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void · 3331 unmodified lines
33323332 char *context = NULL;
33333333 struct inode_security_struct *isec;
33343334
3335− if (strcmp(name, XATTR_SELINUX_SUFFIX))
3335+ /*
3336+ * If we're not initialized yet, then we can't validate contexts, so
3337+ * just let vfs_getxattr fall back to using the on-disk xattr.
3338+ */
3339+ if (!selinux_initialized(&selinux_state) ||
3340+ strcmp(name, XATTR_SELINUX_SUFFIX))
33363341 return -EOPNOTSUPP;
33373342
33383343 /*
security/selinux/netif.c+1−1
@@ -124,7 +124,7 @@ static void sel_netif_destroy(struct sel_netif *netif) · 123 unmodified lines
124124 * @sid: interface SID
125125 *
126126 * Description:
127− * This function determines the SID of a network interface by quering the
127+ * This function determines the SID of a network interface by querying the
128128 * security policy. The result is added to the network interface table to
129129 * speedup future queries. Returns zero on success, negative values on
130130 * failure.
security/selinux/netnode.c+1−1
@@ -181,7 +181,7 @@ static void sel_netnode_insert(struct sel_netnode *node) · 180 unmodified lines
181181 * @sid: node SID
182182 *
183183 * Description:
184− * This function determines the SID of a network address by quering the
184+ * This function determines the SID of a network address by querying the
185185 * security policy. The result is added to the network address table to
186186 * speedup future queries. Returns zero on success, negative values on
187187 * failure.
security/selinux/netport.c+1−1
@@ -130,7 +130,7 @@ static void sel_netport_insert(struct sel_netport *port) · 129 unmodified lines
130130 * @sid: port SID
131131 *
132132 * Description:
133− * This function determines the SID of a network port by quering the security
133+ * This function determines the SID of a network port by querying the security
134134 * policy. The result is added to the network port table to speedup future
135135 * queries. Returns zero on success, negative values on failure.
136136 *
security/selinux/ss/conditional.c+4−4
@@ -203,7 +203,7 @@ static int bool_isvalid(struct cond_bool_datum *b) · 202 unmodified lines
203203 return 1;
204204 }
205205
206−int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
206+int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
207207 {
208208 char *key = NULL;
209209 struct cond_bool_datum *booldatum;
@@ -215,7 +215,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) · 5 unmodified lines
215215 if (!booldatum)
216216 return -ENOMEM;
217217
218− rc = next_entry(buf, fp, sizeof buf);
218+ rc = next_entry(buf, fp, sizeof(buf));
219219 if (rc)
220220 goto err;
221221
@@ -238,7 +238,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) · 16 unmodified lines
238238 if (rc)
239239 goto err;
240240 key[len] = '\0';
241− rc = hashtab_insert(h, key, booldatum);
241+ rc = symtab_insert(s, key, booldatum);
242242 if (rc)
243243 goto err;
244244
@@ -416,7 +416,7 @@ int cond_read_list(struct policydb *p, void *fp) · 171 unmodified lines
416416 u32 i, len;
417417 int rc;
418418
419− rc = next_entry(buf, fp, sizeof buf);
419+ rc = next_entry(buf, fp, sizeof(buf));
420420 if (rc)
421421 return rc;
422422
security/selinux/ss/conditional.h+1−1
@@ -69,7 +69,7 @@ int cond_destroy_bool(void *key, void *datum, void *p); · 68 unmodified lines
6969
7070 int cond_index_bool(void *key, void *datum, void *datap);
7171
72−int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
72+int cond_read_bool(struct policydb *p, struct symtab *s, void *fp);
7373 int cond_read_list(struct policydb *p, void *fp);
7474 int cond_write_bool(void *key, void *datum, void *ptr);
7575 int cond_write_list(struct policydb *p, void *fp);
security/selinux/ss/hashtab.c+6−53
@@ -7,7 +7,6 @@ · 6 unmodified lines
77 #include <linux/kernel.h>
88 #include <linux/slab.h>
99 #include <linux/errno.h>
10−#include <linux/sched.h>
1110 #include "hashtab.h"
1211
1312 static struct kmem_cache *hashtab_node_cachep;
@@ -29,16 +28,10 @@ static u32 hashtab_compute_size(u32 nel) · 15 unmodified lines
2928 return nel == 0 ? 0 : roundup_pow_of_two(nel);
3029 }
3130
32−int hashtab_init(struct hashtab *h,
33− u32 (*hash_value)(struct hashtab *h, const void *key),
34− int (*keycmp)(struct hashtab *h, const void *key1,
35− const void *key2),
36− u32 nel_hint)
31+int hashtab_init(struct hashtab *h, u32 nel_hint)
3732 {
3833 h->size = hashtab_compute_size(nel_hint);
3934 h->nel = 0;
40− h->hash_value = hash_value;
41− h->keycmp = keycmp;
4235 if (!h->size)
4336 return 0;
4437
@@ -46,63 +39,23 @@ int hashtab_init(struct hashtab *h, · 1 unmodified line
4639 return h->htable ? 0 : -ENOMEM;
4740 }
4841
49−int hashtab_insert(struct hashtab *h, void *key, void *datum)
42+int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
43+ void *key, void *datum)
5044 {
51− u32 hvalue;
52− struct hashtab_node *prev, *cur, *newnode;
53−
54− cond_resched();
55−
56− if (!h->size || h->nel == HASHTAB_MAX_NODES)
57− return -EINVAL;
58−
59− hvalue = h->hash_value(h, key);
60− prev = NULL;
61− cur = h->htable[hvalue];
62− while (cur && h->keycmp(h, key, cur->key) > 0) {
63− prev = cur;
64− cur = cur->next;
65− }
66−
67− if (cur && (h->keycmp(h, key, cur->key) == 0))
68− return -EEXIST;
45+ struct hashtab_node *newnode;
6946
7047 newnode = kmem_cache_zalloc(hashtab_node_cachep, GFP_KERNEL);
7148 if (!newnode)
7249 return -ENOMEM;
7350 newnode->key = key;
7451 newnode->datum = datum;
75− if (prev) {
76− newnode->next = prev->next;
77− prev->next = newnode;
78− } else {
79− newnode->next = h->htable[hvalue];
80− h->htable[hvalue] = newnode;
81− }
52+ newnode->next = *dst;
53+ *dst = newnode;
8254
8355 h->nel++;
8456 return 0;
8557 }
8658
87−void *hashtab_search(struct hashtab *h, const void *key)
88−{
89− u32 hvalue;
90− struct hashtab_node *cur;
91−
92− if (!h->size)
93− return NULL;
94−
95− hvalue = h->hash_value(h, key);
96− cur = h->htable[hvalue];
97− while (cur && h->keycmp(h, key, cur->key) > 0)
98− cur = cur->next;
99−
100− if (!cur || (h->keycmp(h, key, cur->key) != 0))
101− return NULL;
102−
103− return cur->datum;
104−}
105−
10659 void hashtab_destroy(struct hashtab *h)
10760 {
10861 u32 i;
security/selinux/ss/hashtab.h+65−12
@@ -11,7 +11,17 @@ · 10 unmodified lines
1111 #ifndef _SS_HASHTAB_H_
1212 #define _SS_HASHTAB_H_
1313
14−#define HASHTAB_MAX_NODES 0xffffffff
14+#include <linux/types.h>
15+#include <linux/errno.h>
16+#include <linux/sched.h>
17+
18+#define HASHTAB_MAX_NODES U32_MAX
19+
20+struct hashtab_key_params {
21+ u32 (*hash)(const void *key); /* hash function */
22+ int (*cmp)(const void *key1, const void *key2);
23+ /* key comparison function */
24+};
1525
1626 struct hashtab_node {
1727 void *key;
@@ -23,10 +33,6 @@ struct hashtab { · 5 unmodified lines
2333 struct hashtab_node **htable; /* hash table */
2434 u32 size; /* number of slots in hash table */
2535 u32 nel; /* number of elements in hash table */
26− u32 (*hash_value)(struct hashtab *h, const void *key);
27− /* hash function */
28− int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
29− /* key comparison function */
3036 };
3137
3238 struct hashtab_info {
@@ -39,11 +45,10 @@ struct hashtab_info { · 6 unmodified lines
3945 *
4046 * Returns -ENOMEM if insufficient space is available or 0 otherwise.
4147 */
42−int hashtab_init(struct hashtab *h,
43− u32 (*hash_value)(struct hashtab *h, const void *key),
44− int (*keycmp)(struct hashtab *h, const void *key1,
45− const void *key2),
46− u32 nel_hint);
48+int hashtab_init(struct hashtab *h, u32 nel_hint);
49+
50+int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
51+ void *key, void *datum);
4752
4853 /*
4954 * Inserts the specified (key, datum) pair into the specified hash table.
@@ -53,7 +58,34 @@ int hashtab_init(struct hashtab *h, · 3 unmodified lines
5358 * -EINVAL for general errors or
5459 0 otherwise.
5560 */
56−int hashtab_insert(struct hashtab *h, void *k, void *d);
61+static inline int hashtab_insert(struct hashtab *h, void *key, void *datum,
62+ struct hashtab_key_params key_params)
63+{
64+ u32 hvalue;
65+ struct hashtab_node *prev, *cur;
66+
67+ cond_resched();
68+
69+ if (!h->size || h->nel == HASHTAB_MAX_NODES)
70+ return -EINVAL;
71+
72+ hvalue = key_params.hash(key) & (h->size - 1);
73+ prev = NULL;
74+ cur = h->htable[hvalue];
75+ while (cur) {
76+ int cmp = key_params.cmp(key, cur->key);
77+
78+ if (cmp == 0)
79+ return -EEXIST;
80+ if (cmp < 0)
81+ break;
82+ prev = cur;
83+ cur = cur->next;
84+ }
85+
86+ return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue],
87+ key, datum);
88+}
5789
5890 /*
5991 * Searches for the entry with the specified key in the hash table.
@@ -61,7 +93,28 @@ int hashtab_insert(struct hashtab *h, void *k, void *d); · 1 unmodified line
6193 * Returns NULL if no entry has the specified key or
6294 * the datum of the entry otherwise.
6395 */
64−void *hashtab_search(struct hashtab *h, const void *k);
96+static inline void *hashtab_search(struct hashtab *h, const void *key,
97+ struct hashtab_key_params key_params)
98+{
99+ u32 hvalue;
100+ struct hashtab_node *cur;
101+
102+ if (!h->size)
103+ return NULL;
104+
105+ hvalue = key_params.hash(key) & (h->size - 1);
106+ cur = h->htable[hvalue];
107+ while (cur) {
108+ int cmp = key_params.cmp(key, cur->key);
109+
110+ if (cmp == 0)
111+ return cur->datum;
112+ if (cmp < 0)
113+ break;
114+ cur = cur->next;
115+ }
116+ return NULL;
117+}
65118
66119 /*
67120 * Destroys the specified hash table.
security/selinux/ss/mls.c+12−11
@@ -165,8 +165,8 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l) · 164 unmodified lines
165165
166166 if (!l->sens || l->sens > p->p_levels.nprim)
167167 return 0;
168− levdatum = hashtab_search(&p->p_levels.table,
169− sym_name(p, SYM_LEVELS, l->sens - 1));
168+ levdatum = symtab_search(&p->p_levels,
169+ sym_name(p, SYM_LEVELS, l->sens - 1));
170170 if (!levdatum)
171171 return 0;
172172
@@ -293,7 +293,7 @@ int mls_context_to_sid(struct policydb *pol, · 120 unmodified lines
293293 *(next_cat++) = '\0';
294294
295295 /* Parse sensitivity. */
296− levdatum = hashtab_search(&pol->p_levels.table, sensitivity);
296+ levdatum = symtab_search(&pol->p_levels, sensitivity);
297297 if (!levdatum)
298298 return -EINVAL;
299299 context->range.level[l].sens = levdatum->level->sens;
@@ -312,7 +312,7 @@ int mls_context_to_sid(struct policydb *pol, · 12 unmodified lines
312312 *rngptr++ = '\0';
313313 }
314314
315− catdatum = hashtab_search(&pol->p_cats.table, cur_cat);
315+ catdatum = symtab_search(&pol->p_cats, cur_cat);
316316 if (!catdatum)
317317 return -EINVAL;
318318
@@ -325,7 +325,7 @@ int mls_context_to_sid(struct policydb *pol, · 6 unmodified lines
325325 if (rngptr == NULL)
326326 continue;
327327
328− rngdatum = hashtab_search(&pol->p_cats.table, rngptr);
328+ rngdatum = symtab_search(&pol->p_cats, rngptr);
329329 if (!rngdatum)
330330 return -EINVAL;
331331
@@ -458,9 +458,10 @@ int mls_convert_context(struct policydb *oldp, · 126 unmodified lines
458458 return 0;
459459
460460 for (l = 0; l < 2; l++) {
461− levdatum = hashtab_search(&newp->p_levels.table,
462− sym_name(oldp, SYM_LEVELS,
463− oldc->range.level[l].sens - 1));
461+ char *name = sym_name(oldp, SYM_LEVELS,
462+ oldc->range.level[l].sens - 1);
463+
464+ levdatum = symtab_search(&newp->p_levels, name);
464465
465466 if (!levdatum)
466467 return -EINVAL;
@@ -470,8 +471,8 @@ int mls_convert_context(struct policydb *oldp, · 3 unmodified lines
470471 node, i) {
471472 int rc;
472473
473− catdatum = hashtab_search(&newp->p_cats.table,
474− sym_name(oldp, SYM_CATS, i));
474+ catdatum = symtab_search(&newp->p_cats,
475+ sym_name(oldp, SYM_CATS, i));
475476 if (!catdatum)
476477 return -EINVAL;
477478 rc = ebitmap_set_bit(&newc->range.level[l].cat,
@@ -506,7 +507,7 @@ int mls_compute_sid(struct policydb *p, · 28 unmodified lines
506507 rtr.source_type = scontext->type;
507508 rtr.target_type = tcontext->type;
508509 rtr.target_class = tclass;
509− r = hashtab_search(&p->range_tr, &rtr);
510+ r = policydb_rangetr_search(p, &rtr);
510511 if (r)
511512 return mls_range_set(newcontext, r);
512513
security/selinux/ss/policydb.c+95−53
@@ -400,7 +400,7 @@ static int roles_init(struct policydb *p) · 399 unmodified lines
400400 if (!key)
401401 goto out;
402402
403− rc = hashtab_insert(&p->p_roles.table, key, role);
403+ rc = symtab_insert(&p->p_roles, key, role);
404404 if (rc)
405405 goto out;
406406
@@ -411,7 +411,7 @@ out: · 4 unmodified lines
411411 return rc;
412412 }
413413
414−static u32 filenametr_hash(struct hashtab *h, const void *k)
414+static u32 filenametr_hash(const void *k)
415415 {
416416 const struct filename_trans_key *ft = k;
417417 unsigned long hash;
@@ -423,10 +423,10 @@ static u32 filenametr_hash(struct hashtab *h, const void *k) · 5 unmodified lines
423423 byte_num = 0;
424424 while ((focus = ft->name[byte_num++]))
425425 hash = partial_name_hash(focus, hash);
426− return hash & (h->size - 1);
426+ return hash;
427427 }
428428
429−static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
429+static int filenametr_cmp(const void *k1, const void *k2)
430430 {
431431 const struct filename_trans_key *ft1 = k1;
432432 const struct filename_trans_key *ft2 = k2;
@@ -444,15 +444,26 @@ static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2) · 11 unmodified lines
444444
445445 }
446446
447−static u32 rangetr_hash(struct hashtab *h, const void *k)
447+static const struct hashtab_key_params filenametr_key_params = {
448+ .hash = filenametr_hash,
449+ .cmp = filenametr_cmp,
450+};
451+
452+struct filename_trans_datum *policydb_filenametr_search(
453+ struct policydb *p, struct filename_trans_key *key)
454+{
455+ return hashtab_search(&p->filename_trans, key, filenametr_key_params);
456+}
457+
458+static u32 rangetr_hash(const void *k)
448459 {
449460 const struct range_trans *key = k;
450461
451− return (key->source_type + (key->target_type << 3) +
452− (key->target_class << 5)) & (h->size - 1);
462+ return key->source_type + (key->target_type << 3) +
463+ (key->target_class << 5);
453464 }
454465
455−static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
466+static int rangetr_cmp(const void *k1, const void *k2)
456467 {
457468 const struct range_trans *key1 = k1, *key2 = k2;
458469 int v;
@@ -470,15 +481,25 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) · 11 unmodified lines
470481 return v;
471482 }
472483
473−static u32 role_trans_hash(struct hashtab *h, const void *k)
484+static const struct hashtab_key_params rangetr_key_params = {
485+ .hash = rangetr_hash,
486+ .cmp = rangetr_cmp,
487+};
488+
489+struct mls_range *policydb_rangetr_search(struct policydb *p,
490+ struct range_trans *key)
491+{
492+ return hashtab_search(&p->range_tr, key, rangetr_key_params);
493+}
494+
495+static u32 role_trans_hash(const void *k)
474496 {
475497 const struct role_trans_key *key = k;
476498
477− return (key->role + (key->type << 3) + (key->tclass << 5)) &
478− (h->size - 1);
499+ return key->role + (key->type << 3) + (key->tclass << 5);
479500 }
480501
481−static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
502+static int role_trans_cmp(const void *k1, const void *k2)
482503 {
483504 const struct role_trans_key *key1 = k1, *key2 = k2;
484505 int v;
@@ -494,6 +515,17 @@ static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2) · 9 unmodified lines
494515 return key1->tclass - key2->tclass;
495516 }
496517
518+static const struct hashtab_key_params roletr_key_params = {
519+ .hash = role_trans_hash,
520+ .cmp = role_trans_cmp,
521+};
522+
523+struct role_trans_datum *policydb_roletr_search(struct policydb *p,
524+ struct role_trans_key *key)
525+{
526+ return hashtab_search(&p->role_tr, key, roletr_key_params);
527+}
528+
497529 /*
498530 * Initialize a policy database structure.
499531 */
@@ -1065,7 +1097,7 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len) · 565 unmodified lines
10651097 return 0;
10661098 }
10671099
1068−static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
1100+static int perm_read(struct policydb *p, struct symtab *s, void *fp)
10691101 {
10701102 char *key = NULL;
10711103 struct perm_datum *perdatum;
@@ -1088,7 +1120,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) · 16 unmodified lines
10881120 if (rc)
10891121 goto bad;
10901122
1091− rc = hashtab_insert(h, key, perdatum);
1123+ rc = symtab_insert(s, key, perdatum);
10921124 if (rc)
10931125 goto bad;
10941126
@@ -1098,7 +1130,7 @@ bad: · 3 unmodified lines
10981130 return rc;
10991131 }
11001132
1101−static int common_read(struct policydb *p, struct hashtab *h, void *fp)
1133+static int common_read(struct policydb *p, struct symtab *s, void *fp)
11021134 {
11031135 char *key = NULL;
11041136 struct common_datum *comdatum;
@@ -1128,12 +1160,12 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) · 23 unmodified lines
11281160 goto bad;
11291161
11301162 for (i = 0; i < nel; i++) {
1131− rc = perm_read(p, &comdatum->permissions.table, fp);
1163+ rc = perm_read(p, &comdatum->permissions, fp);
11321164 if (rc)
11331165 goto bad;
11341166 }
11351167
1136− rc = hashtab_insert(h, key, comdatum);
1168+ rc = symtab_insert(s, key, comdatum);
11371169 if (rc)
11381170 goto bad;
11391171 return 0;
@@ -1262,7 +1294,7 @@ static int read_cons_helper(struct policydb *p, · 122 unmodified lines
12621294 return 0;
12631295 }
12641296
1265−static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1297+static int class_read(struct policydb *p, struct symtab *s, void *fp)
12661298 {
12671299 char *key = NULL;
12681300 struct class_datum *cladatum;
@@ -1300,8 +1332,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) · 31 unmodified lines
13001332 goto bad;
13011333
13021334 rc = -EINVAL;
1303− cladatum->comdatum = hashtab_search(&p->p_commons.table,
1304− cladatum->comkey);
1335+ cladatum->comdatum = symtab_search(&p->p_commons,
1336+ cladatum->comkey);
13051337 if (!cladatum->comdatum) {
13061338 pr_err("SELinux: unknown common %s\n",
13071339 cladatum->comkey);
@@ -1309,7 +1341,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) · 1 unmodified line
13091341 }
13101342 }
13111343 for (i = 0; i < nel; i++) {
1312− rc = perm_read(p, &cladatum->permissions.table, fp);
1344+ rc = perm_read(p, &cladatum->permissions, fp);
13131345 if (rc)
13141346 goto bad;
13151347 }
@@ -1347,7 +1379,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) · 31 unmodified lines
13471379 cladatum->default_type = le32_to_cpu(buf[0]);
13481380 }
13491381
1350− rc = hashtab_insert(h, key, cladatum);
1382+ rc = symtab_insert(s, key, cladatum);
13511383 if (rc)
13521384 goto bad;
13531385
@@ -1357,7 +1389,7 @@ bad: · 3 unmodified lines
13571389 return rc;
13581390 }
13591391
1360−static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1392+static int role_read(struct policydb *p, struct symtab *s, void *fp)
13611393 {
13621394 char *key = NULL;
13631395 struct role_datum *role;
@@ -1404,7 +1436,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) · 40 unmodified lines
14041436 goto bad;
14051437 }
14061438
1407− rc = hashtab_insert(h, key, role);
1439+ rc = symtab_insert(s, key, role);
14081440 if (rc)
14091441 goto bad;
14101442 return 0;
@@ -1413,7 +1445,7 @@ bad: · 2 unmodified lines
14131445 return rc;
14141446 }
14151447
1416−static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1448+static int type_read(struct policydb *p, struct symtab *s, void *fp)
14171449 {
14181450 char *key = NULL;
14191451 struct type_datum *typdatum;
@@ -1451,7 +1483,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) · 31 unmodified lines
14511483 if (rc)
14521484 goto bad;
14531485
1454− rc = hashtab_insert(h, key, typdatum);
1486+ rc = symtab_insert(s, key, typdatum);
14551487 if (rc)
14561488 goto bad;
14571489 return 0;
@@ -1487,7 +1519,7 @@ static int mls_read_level(struct mls_level *lp, void *fp) · 29 unmodified lines
14871519 return 0;
14881520 }
14891521
1490−static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1522+static int user_read(struct policydb *p, struct symtab *s, void *fp)
14911523 {
14921524 char *key = NULL;
14931525 struct user_datum *usrdatum;
@@ -1528,7 +1560,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) · 34 unmodified lines
15281560 goto bad;
15291561 }
15301562
1531− rc = hashtab_insert(h, key, usrdatum);
1563+ rc = symtab_insert(s, key, usrdatum);
15321564 if (rc)
15331565 goto bad;
15341566 return 0;
@@ -1537,7 +1569,7 @@ bad: · 2 unmodified lines
15371569 return rc;
15381570 }
15391571
1540−static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1572+static int sens_read(struct policydb *p, struct symtab *s, void *fp)
15411573 {
15421574 char *key = NULL;
15431575 struct level_datum *levdatum;
@@ -1569,7 +1601,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) · 25 unmodified lines
15691601 if (rc)
15701602 goto bad;
15711603
1572− rc = hashtab_insert(h, key, levdatum);
1604+ rc = symtab_insert(s, key, levdatum);
15731605 if (rc)
15741606 goto bad;
15751607 return 0;
@@ -1578,7 +1610,7 @@ bad: · 2 unmodified lines
15781610 return rc;
15791611 }
15801612
1581−static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1613+static int cat_read(struct policydb *p, struct symtab *s, void *fp)
15821614 {
15831615 char *key = NULL;
15841616 struct cat_datum *catdatum;
@@ -1602,7 +1634,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) · 17 unmodified lines
16021634 if (rc)
16031635 goto bad;
16041636
1605− rc = hashtab_insert(h, key, catdatum);
1637+ rc = symtab_insert(s, key, catdatum);
16061638 if (rc)
16071639 goto bad;
16081640 return 0;
@@ -1611,7 +1643,7 @@ bad: · 2 unmodified lines
16111643 return rc;
16121644 }
16131645
1614−static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
1646+static int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) =
16151647 {
16161648 common_read,
16171649 class_read,
@@ -1751,7 +1783,7 @@ u16 string_to_security_class(struct policydb *p, const char *name) · 133 unmodified lines
17511783 {
17521784 struct class_datum *cladatum;
17531785
1754− cladatum = hashtab_search(&p->p_classes.table, name);
1786+ cladatum = symtab_search(&p->p_classes, name);
17551787 if (!cladatum)
17561788 return 0;
17571789
@@ -1770,9 +1802,9 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) · 12 unmodified lines
17701802 cladatum = p->class_val_to_struct[tclass-1];
17711803 comdatum = cladatum->comdatum;
17721804 if (comdatum)
1773− perdatum = hashtab_search(&comdatum->permissions.table, name);
1805+ perdatum = symtab_search(&comdatum->permissions, name);
17741806 if (!perdatum)
1775− perdatum = hashtab_search(&cladatum->permissions.table, name);
1807+ perdatum = symtab_search(&cladatum->permissions, name);
17761808 if (!perdatum)
17771809 return 0;
17781810
@@ -1796,7 +1828,7 @@ static int range_read(struct policydb *p, void *fp) · 17 unmodified lines
17961828
17971829 nel = le32_to_cpu(buf[0]);
17981830
1799− rc = hashtab_init(&p->range_tr, rangetr_hash, rangetr_cmp, nel);
1831+ rc = hashtab_init(&p->range_tr, nel);
18001832 if (rc)
18011833 return rc;
18021834
@@ -1841,7 +1873,7 @@ static int range_read(struct policydb *p, void *fp) · 38 unmodified lines
18411873 goto out;
18421874 }
18431875
1844− rc = hashtab_insert(&p->range_tr, rt, r);
1876+ rc = hashtab_insert(&p->range_tr, rt, r, rangetr_key_params);
18451877 if (rc)
18461878 goto out;
18471879
@@ -1888,7 +1920,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp) · 40 unmodified lines
18881920 otype = le32_to_cpu(buf[3]);
18891921
18901922 last = NULL;
1891− datum = hashtab_search(&p->filename_trans, &key);
1923+ datum = policydb_filenametr_search(p, &key);
18921924 while (datum) {
18931925 if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
18941926 /* conflicting/duplicate rules are ignored */
@@ -1918,7 +1950,8 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp) · 23 unmodified lines
19181950 if (!ft)
19191951 goto out;
19201952
1921− rc = hashtab_insert(&p->filename_trans, ft, datum);
1953+ rc = hashtab_insert(&p->filename_trans, ft, datum,
1954+ filenametr_key_params);
19221955 if (rc)
19231956 goto out;
19241957 name = NULL;
@@ -2006,7 +2039,8 @@ static int filename_trans_read_helper(struct policydb *p, void *fp) · 81 unmodified lines
20062039 ft->tclass = tclass;
20072040 ft->name = name;
20082041
2009− rc = hashtab_insert(&p->filename_trans, ft, first);
2042+ rc = hashtab_insert(&p->filename_trans, ft, first,
2043+ filenametr_key_params);
20102044 if (rc == -EEXIST)
20112045 pr_err("SELinux: Duplicate filename transition key\n");
20122046 if (rc)
@@ -2044,8 +2078,7 @@ static int filename_trans_read(struct policydb *p, void *fp) · 31 unmodified lines
20442078 if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
20452079 p->compat_filename_trans_count = nel;
20462080
2047− rc = hashtab_init(&p->filename_trans, filenametr_hash,
2048− filenametr_cmp, (1 << 11));
2081+ rc = hashtab_init(&p->filename_trans, (1 << 11));
20492082 if (rc)
20502083 return rc;
20512084
@@ -2055,8 +2088,7 @@ static int filename_trans_read(struct policydb *p, void *fp) · 3 unmodified lines
20552088 return rc;
20562089 }
20572090 } else {
2058− rc = hashtab_init(&p->filename_trans, filenametr_hash,
2059− filenametr_cmp, nel);
2091+ rc = hashtab_init(&p->filename_trans, nel);
20602092 if (rc)
20612093 return rc;
20622094
@@ -2376,7 +2408,7 @@ int policydb_read(struct policydb *p, void *fp) · 313 unmodified lines
23762408 struct role_trans_datum *rtd = NULL;
23772409 int i, j, rc;
23782410 __le32 buf[4];
2379− u32 len, nprim, nel;
2411+ u32 len, nprim, nel, perm;
23802412
23812413 char *policydb_str;
23822414 struct policydb_compat_info *info;
@@ -2509,7 +2541,7 @@ int policydb_read(struct policydb *p, void *fp) · 126 unmodified lines
25092541 }
25102542
25112543 for (j = 0; j < nel; j++) {
2512− rc = read_f[i](p, &p->symtab[i].table, fp);
2544+ rc = read_f[i](p, &p->symtab[i], fp);
25132545 if (rc)
25142546 goto bad;
25152547 }
@@ -2519,8 +2551,10 @@ int policydb_read(struct policydb *p, void *fp) · 3 unmodified lines
25192551
25202552 rc = -EINVAL;
25212553 p->process_class = string_to_security_class(p, "process");
2522− if (!p->process_class)
2554+ if (!p->process_class) {
2555+ pr_err("SELinux: process class is required, not defined in policy\n");
25232556 goto bad;
2557+ }
25242558
25252559 rc = avtab_read(&p->te_avtab, fp, p);
25262560 if (rc)
@@ -2537,7 +2571,7 @@ int policydb_read(struct policydb *p, void *fp) · 10 unmodified lines
25372571 goto bad;
25382572 nel = le32_to_cpu(buf[0]);
25392573
2540− rc = hashtab_init(&p->role_tr, role_trans_hash, role_trans_cmp, nel);
2574+ rc = hashtab_init(&p->role_tr, nel);
25412575 if (rc)
25422576 goto bad;
25432577 for (i = 0; i < nel; i++) {
@@ -2574,7 +2608,7 @@ int policydb_read(struct policydb *p, void *fp) · 30 unmodified lines
25742608 !policydb_role_isvalid(p, rtd->new_role))
25752609 goto bad;
25762610
2577− rc = hashtab_insert(&p->role_tr, rtk, rtd);
2611+ rc = hashtab_insert(&p->role_tr, rtk, rtd, roletr_key_params);
25782612 if (rc)
25792613 goto bad;
25802614
@@ -2618,10 +2652,18 @@ int policydb_read(struct policydb *p, void *fp) · 37 unmodified lines
26182652 goto bad;
26192653
26202654 rc = -EINVAL;
2621− p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition");
2622− p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition");
2623− if (!p->process_trans_perms)
2655+ perm = string_to_av_perm(p, p->process_class, "transition");
2656+ if (!perm) {
2657+ pr_err("SELinux: process transition permission is required, not defined in policy\n");
2658+ goto bad;
2659+ }
2660+ p->process_trans_perms = perm;
2661+ perm = string_to_av_perm(p, p->process_class, "dyntransition");
2662+ if (!perm) {
2663+ pr_err("SELinux: process dyntransition permission is required, not defined in policy\n");
26242664 goto bad;
2665+ }
2666+ p->process_trans_perms |= perm;
26252667
26262668 rc = ocontext_read(p, info, fp);
26272669 if (rc)
security/selinux/ss/policydb.h+9−0
@@ -324,6 +324,15 @@ extern int policydb_role_isvalid(struct policydb *p, unsigned int role); · 323 unmodified lines
324324 extern int policydb_read(struct policydb *p, void *fp);
325325 extern int policydb_write(struct policydb *p, void *fp);
326326
327+extern struct filename_trans_datum *policydb_filenametr_search(
328+ struct policydb *p, struct filename_trans_key *key);
329+
330+extern struct mls_range *policydb_rangetr_search(
331+ struct policydb *p, struct range_trans *key);
332+
333+extern struct role_trans_datum *policydb_roletr_search(
334+ struct policydb *p, struct role_trans_key *key);
335+
327336 #define POLICYDB_CONFIG_MLS 1
328337
329338 /* the config flags related to unknown classes/perms are bits 2 and 3 */
security/selinux/ss/services.c+19−19
@@ -1441,7 +1441,7 @@ static int string_to_context_struct(struct policydb *pol, · 1440 unmodified lines
14411441
14421442 *p++ = 0;
14431443
1444− usrdatum = hashtab_search(&pol->p_users.table, scontextp);
1444+ usrdatum = symtab_search(&pol->p_users, scontextp);
14451445 if (!usrdatum)
14461446 goto out;
14471447
@@ -1457,7 +1457,7 @@ static int string_to_context_struct(struct policydb *pol, · 9 unmodified lines
14571457
14581458 *p++ = 0;
14591459
1460− role = hashtab_search(&pol->p_roles.table, scontextp);
1460+ role = symtab_search(&pol->p_roles, scontextp);
14611461 if (!role)
14621462 goto out;
14631463 ctx->role = role->value;
@@ -1469,7 +1469,7 @@ static int string_to_context_struct(struct policydb *pol, · 5 unmodified lines
14691469 oldc = *p;
14701470 *p++ = 0;
14711471
1472− typdatum = hashtab_search(&pol->p_types.table, scontextp);
1472+ typdatum = symtab_search(&pol->p_types, scontextp);
14731473 if (!typdatum || typdatum->attribute)
14741474 goto out;
14751475
@@ -1671,7 +1671,7 @@ static void filename_compute_type(struct policydb *policydb, · 195 unmodified lines
16711671 ft.tclass = tclass;
16721672 ft.name = objname;
16731673
1674− datum = hashtab_search(&policydb->filename_trans, &ft);
1674+ datum = policydb_filenametr_search(policydb, &ft);
16751675 while (datum) {
16761676 if (ebitmap_get_bit(&datum->stypes, stype - 1)) {
16771677 newcontext->type = datum->otype;
@@ -1834,7 +1834,7 @@ static int security_compute_sid(struct selinux_state *state, · 156 unmodified lines
18341834 .tclass = tclass,
18351835 };
18361836
1837− rtd = hashtab_search(&policydb->role_tr, &rtk);
1837+ rtd = policydb_roletr_search(policydb, &rtk);
18381838 if (rtd)
18391839 newcontext.role = rtd->new_role;
18401840 }
@@ -2024,26 +2024,26 @@ static int convert_context(struct context *oldc, struct context *newc, void *p) · 183 unmodified lines
20242024
20252025 /* Convert the user. */
20262026 rc = -EINVAL;
2027− usrdatum = hashtab_search(&args->newp->p_users.table,
2028− sym_name(args->oldp,
2029− SYM_USERS, oldc->user - 1));
2027+ usrdatum = symtab_search(&args->newp->p_users,
2028+ sym_name(args->oldp,
2029+ SYM_USERS, oldc->user - 1));
20302030 if (!usrdatum)
20312031 goto bad;
20322032 newc->user = usrdatum->value;
20332033
20342034 /* Convert the role. */
20352035 rc = -EINVAL;
2036− role = hashtab_search(&args->newp->p_roles.table,
2037− sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
2036+ role = symtab_search(&args->newp->p_roles,
2037+ sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
20382038 if (!role)
20392039 goto bad;
20402040 newc->role = role->value;
20412041
20422042 /* Convert the type. */
20432043 rc = -EINVAL;
2044− typdatum = hashtab_search(&args->newp->p_types.table,
2045− sym_name(args->oldp,
2046− SYM_TYPES, oldc->type - 1));
2044+ typdatum = symtab_search(&args->newp->p_types,
2045+ sym_name(args->oldp,
2046+ SYM_TYPES, oldc->type - 1));
20472047 if (!typdatum)
20482048 goto bad;
20492049 newc->type = typdatum->value;
@@ -2623,7 +2623,7 @@ int security_get_user_sids(struct selinux_state *state, · 573 unmodified lines
26232623 goto out_unlock;
26242624
26252625 rc = -EINVAL;
2626− user = hashtab_search(&policydb->p_users.table, username);
2626+ user = symtab_search(&policydb->p_users, username);
26272627 if (!user)
26282628 goto out_unlock;
26292629
@@ -2979,7 +2979,7 @@ static int security_preserve_bools(struct selinux_state *state, · 349 unmodified lines
29792979 if (rc)
29802980 goto out;
29812981 for (i = 0; i < nbools; i++) {
2982− booldatum = hashtab_search(&policydb->p_bools.table, bnames[i]);
2982+ booldatum = symtab_search(&policydb->p_bools, bnames[i]);
29832983 if (booldatum)
29842984 booldatum->state = bvalues[i];
29852985 }
@@ -3230,7 +3230,7 @@ int security_get_permissions(struct selinux_state *state, · 244 unmodified lines
32303230 read_lock(&state->ss->policy_rwlock);
32313231
32323232 rc = -EINVAL;
3233− match = hashtab_search(&policydb->p_classes.table, class);
3233+ match = symtab_search(&policydb->p_classes, class);
32343234 if (!match) {
32353235 pr_err("SELinux: %s: unrecognized class %s\n",
32363236 __func__, class);
@@ -3369,7 +3369,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) · 132 unmodified lines
33693369 case AUDIT_SUBJ_USER:
33703370 case AUDIT_OBJ_USER:
33713371 rc = -EINVAL;
3372− userdatum = hashtab_search(&policydb->p_users.table, rulestr);
3372+ userdatum = symtab_search(&policydb->p_users, rulestr);
33733373 if (!userdatum)
33743374 goto out;
33753375 tmprule->au_ctxt.user = userdatum->value;
@@ -3377,7 +3377,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) · 1 unmodified line
33773377 case AUDIT_SUBJ_ROLE:
33783378 case AUDIT_OBJ_ROLE:
33793379 rc = -EINVAL;
3380− roledatum = hashtab_search(&policydb->p_roles.table, rulestr);
3380+ roledatum = symtab_search(&policydb->p_roles, rulestr);
33813381 if (!roledatum)
33823382 goto out;
33833383 tmprule->au_ctxt.role = roledatum->value;
@@ -3385,7 +3385,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) · 1 unmodified line
33853385 case AUDIT_SUBJ_TYPE:
33863386 case AUDIT_OBJ_TYPE:
33873387 rc = -EINVAL;
3388− typedatum = hashtab_search(&policydb->p_types.table, rulestr);
3388+ typedatum = symtab_search(&policydb->p_types, rulestr);
33893389 if (!typedatum)
33903390 goto out;
33913391 tmprule->au_ctxt.type = typedatum->value;
security/selinux/ss/symtab.c+17−4
@@ -9,7 +9,7 @@ · 8 unmodified lines
99 #include <linux/errno.h>
1010 #include "symtab.h"
1111
12−static unsigned int symhash(struct hashtab *h, const void *key)
12+static unsigned int symhash(const void *key)
1313 {
1414 const char *p, *keyp;
1515 unsigned int size;
@@ -20,10 +20,10 @@ static unsigned int symhash(struct hashtab *h, const void *key) · 4 unmodified lines
2020 size = strlen(keyp);
2121 for (p = keyp; (p - keyp) < size; p++)
2222 val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p);
23− return val & (h->size - 1);
23+ return val;
2424 }
2525
26−static int symcmp(struct hashtab *h, const void *key1, const void *key2)
26+static int symcmp(const void *key1, const void *key2)
2727 {
2828 const char *keyp1, *keyp2;
2929
@@ -32,10 +32,23 @@ static int symcmp(struct hashtab *h, const void *key1, const void *key2) · 2 unmodified lines
3232 return strcmp(keyp1, keyp2);
3333 }
3434
35+static const struct hashtab_key_params symtab_key_params = {
36+ .hash = symhash,
37+ .cmp = symcmp,
38+};
3539
3640 int symtab_init(struct symtab *s, unsigned int size)
3741 {
3842 s->nprim = 0;
39− return hashtab_init(&s->table, symhash, symcmp, size);
43+ return hashtab_init(&s->table, size);
4044 }
4145
46+int symtab_insert(struct symtab *s, char *name, void *datum)
47+{
48+ return hashtab_insert(&s->table, name, datum, symtab_key_params);
49+}
50+
51+void *symtab_search(struct symtab *s, const char *name)
52+{
53+ return hashtab_search(&s->table, name, symtab_key_params);
54+}
security/selinux/ss/symtab.h+3−0
@@ -19,6 +19,9 @@ struct symtab { · 18 unmodified lines
1919
2020 int symtab_init(struct symtab *s, unsigned int size);
2121
22+int symtab_insert(struct symtab *s, char *name, void *datum);
23+void *symtab_search(struct symtab *s, const char *name);
24+
2225 #endif /* _SS_SYMTAB_H_ */
2326
2427