aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/policydb.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-11-29 15:47:09 -0500
committerEric Paris <eparis@redhat.com>2010-11-30 17:28:58 -0500
commitac76c05becb6beedbb458d0827d3deaa6f479a72 (patch)
tree255276b52f7b031671ae5948b39d7c92e50ba420 /security/selinux/ss/policydb.c
parent23bdecb000c806cf4ec52764499a600f7200d7a9 (diff)
selinux: convert part of the sym_val_to_name array to use flex_array
The sym_val_to_name type array can be quite large as it grows linearly with the number of types. With known policies having over 5k types these allocations are growing large enough that they are likely to fail. Convert those to flex_array so no allocation is larger than PAGE_SIZE Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r--security/selinux/ss/policydb.c109
1 files changed, 82 insertions, 27 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index af41fdfe1a71..5adca670e5af 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -254,12 +254,17 @@ static int common_index(void *key, void *datum, void *datap)
254{ 254{
255 struct policydb *p; 255 struct policydb *p;
256 struct common_datum *comdatum; 256 struct common_datum *comdatum;
257 struct flex_array *fa;
257 258
258 comdatum = datum; 259 comdatum = datum;
259 p = datap; 260 p = datap;
260 if (!comdatum->value || comdatum->value > p->p_commons.nprim) 261 if (!comdatum->value || comdatum->value > p->p_commons.nprim)
261 return -EINVAL; 262 return -EINVAL;
262 p->p_common_val_to_name[comdatum->value - 1] = key; 263
264 fa = p->sym_val_to_name[SYM_COMMONS];
265 if (flex_array_put_ptr(fa, comdatum->value - 1, key,
266 GFP_KERNEL | __GFP_ZERO))
267 BUG();
263 return 0; 268 return 0;
264} 269}
265 270
@@ -267,12 +272,16 @@ static int class_index(void *key, void *datum, void *datap)
267{ 272{
268 struct policydb *p; 273 struct policydb *p;
269 struct class_datum *cladatum; 274 struct class_datum *cladatum;
275 struct flex_array *fa;
270 276
271 cladatum = datum; 277 cladatum = datum;
272 p = datap; 278 p = datap;
273 if (!cladatum->value || cladatum->value > p->p_classes.nprim) 279 if (!cladatum->value || cladatum->value > p->p_classes.nprim)
274 return -EINVAL; 280 return -EINVAL;
275 p->p_class_val_to_name[cladatum->value - 1] = key; 281 fa = p->sym_val_to_name[SYM_CLASSES];
282 if (flex_array_put_ptr(fa, cladatum->value - 1, key,
283 GFP_KERNEL | __GFP_ZERO))
284 BUG();
276 p->class_val_to_struct[cladatum->value - 1] = cladatum; 285 p->class_val_to_struct[cladatum->value - 1] = cladatum;
277 return 0; 286 return 0;
278} 287}
@@ -281,6 +290,7 @@ static int role_index(void *key, void *datum, void *datap)
281{ 290{
282 struct policydb *p; 291 struct policydb *p;
283 struct role_datum *role; 292 struct role_datum *role;
293 struct flex_array *fa;
284 294
285 role = datum; 295 role = datum;
286 p = datap; 296 p = datap;
@@ -288,7 +298,11 @@ static int role_index(void *key, void *datum, void *datap)
288 || role->value > p->p_roles.nprim 298 || role->value > p->p_roles.nprim
289 || role->bounds > p->p_roles.nprim) 299 || role->bounds > p->p_roles.nprim)
290 return -EINVAL; 300 return -EINVAL;
291 p->p_role_val_to_name[role->value - 1] = key; 301
302 fa = p->sym_val_to_name[SYM_ROLES];
303 if (flex_array_put_ptr(fa, role->value - 1, key,
304 GFP_KERNEL | __GFP_ZERO))
305 BUG();
292 p->role_val_to_struct[role->value - 1] = role; 306 p->role_val_to_struct[role->value - 1] = role;
293 return 0; 307 return 0;
294} 308}
@@ -297,6 +311,7 @@ static int type_index(void *key, void *datum, void *datap)
297{ 311{
298 struct policydb *p; 312 struct policydb *p;
299 struct type_datum *typdatum; 313 struct type_datum *typdatum;
314 struct flex_array *fa;
300 315
301 typdatum = datum; 316 typdatum = datum;
302 p = datap; 317 p = datap;
@@ -306,10 +321,13 @@ static int type_index(void *key, void *datum, void *datap)
306 || typdatum->value > p->p_types.nprim 321 || typdatum->value > p->p_types.nprim
307 || typdatum->bounds > p->p_types.nprim) 322 || typdatum->bounds > p->p_types.nprim)
308 return -EINVAL; 323 return -EINVAL;
309 p->p_type_val_to_name[typdatum->value - 1] = key; 324 fa = p->sym_val_to_name[SYM_TYPES];
310 /* this flex array was all preallocated, this cannot fail */ 325 if (flex_array_put_ptr(fa, typdatum->value - 1, key,
311 if (flex_array_put_ptr(p->type_val_to_struct_array, 326 GFP_KERNEL | __GFP_ZERO))
312 typdatum->value - 1, typdatum, 327 BUG();
328
329 fa = p->type_val_to_struct_array;
330 if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum,
313 GFP_KERNEL | __GFP_ZERO)) 331 GFP_KERNEL | __GFP_ZERO))
314 BUG(); 332 BUG();
315 } 333 }
@@ -321,6 +339,7 @@ static int user_index(void *key, void *datum, void *datap)
321{ 339{
322 struct policydb *p; 340 struct policydb *p;
323 struct user_datum *usrdatum; 341 struct user_datum *usrdatum;
342 struct flex_array *fa;
324 343
325 usrdatum = datum; 344 usrdatum = datum;
326 p = datap; 345 p = datap;
@@ -328,7 +347,11 @@ static int user_index(void *key, void *datum, void *datap)
328 || usrdatum->value > p->p_users.nprim 347 || usrdatum->value > p->p_users.nprim
329 || usrdatum->bounds > p->p_users.nprim) 348 || usrdatum->bounds > p->p_users.nprim)
330 return -EINVAL; 349 return -EINVAL;
331 p->p_user_val_to_name[usrdatum->value - 1] = key; 350
351 fa = p->sym_val_to_name[SYM_USERS];
352 if (flex_array_put_ptr(fa, usrdatum->value - 1, key,
353 GFP_KERNEL | __GFP_ZERO))
354 BUG();
332 p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 355 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
333 return 0; 356 return 0;
334} 357}
@@ -337,6 +360,7 @@ static int sens_index(void *key, void *datum, void *datap)
337{ 360{
338 struct policydb *p; 361 struct policydb *p;
339 struct level_datum *levdatum; 362 struct level_datum *levdatum;
363 struct flex_array *fa;
340 364
341 levdatum = datum; 365 levdatum = datum;
342 p = datap; 366 p = datap;
@@ -345,7 +369,10 @@ static int sens_index(void *key, void *datum, void *datap)
345 if (!levdatum->level->sens || 369 if (!levdatum->level->sens ||
346 levdatum->level->sens > p->p_levels.nprim) 370 levdatum->level->sens > p->p_levels.nprim)
347 return -EINVAL; 371 return -EINVAL;
348 p->p_sens_val_to_name[levdatum->level->sens - 1] = key; 372 fa = p->sym_val_to_name[SYM_LEVELS];
373 if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key,
374 GFP_KERNEL | __GFP_ZERO))
375 BUG();
349 } 376 }
350 377
351 return 0; 378 return 0;
@@ -355,6 +382,7 @@ static int cat_index(void *key, void *datum, void *datap)
355{ 382{
356 struct policydb *p; 383 struct policydb *p;
357 struct cat_datum *catdatum; 384 struct cat_datum *catdatum;
385 struct flex_array *fa;
358 386
359 catdatum = datum; 387 catdatum = datum;
360 p = datap; 388 p = datap;
@@ -362,7 +390,10 @@ static int cat_index(void *key, void *datum, void *datap)
362 if (!catdatum->isalias) { 390 if (!catdatum->isalias) {
363 if (!catdatum->value || catdatum->value > p->p_cats.nprim) 391 if (!catdatum->value || catdatum->value > p->p_cats.nprim)
364 return -EINVAL; 392 return -EINVAL;
365 p->p_cat_val_to_name[catdatum->value - 1] = key; 393 fa = p->sym_val_to_name[SYM_CATS];
394 if (flex_array_put_ptr(fa, catdatum->value - 1, key,
395 GFP_KERNEL | __GFP_ZERO))
396 BUG();
366 } 397 }
367 398
368 return 0; 399 return 0;
@@ -392,9 +423,16 @@ static int policydb_index_classes(struct policydb *p)
392 int rc; 423 int rc;
393 424
394 rc = -ENOMEM; 425 rc = -ENOMEM;
395 p->p_common_val_to_name = 426 p->sym_val_to_name[SYM_COMMONS] = flex_array_alloc(sizeof(char *),
396 kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL); 427 p->p_commons.nprim,
397 if (!p->p_common_val_to_name) 428 GFP_KERNEL | __GFP_ZERO);
429 if (!p->sym_val_to_name[SYM_COMMONS])
430 goto out;
431
432 rc = flex_array_prealloc(p->sym_val_to_name[SYM_COMMONS],
433 0, p->p_commons.nprim - 1,
434 GFP_KERNEL | __GFP_ZERO);
435 if (rc)
398 goto out; 436 goto out;
399 437
400 rc = hashtab_map(p->p_commons.table, common_index, p); 438 rc = hashtab_map(p->p_commons.table, common_index, p);
@@ -408,9 +446,16 @@ static int policydb_index_classes(struct policydb *p)
408 goto out; 446 goto out;
409 447
410 rc = -ENOMEM; 448 rc = -ENOMEM;
411 p->p_class_val_to_name = 449 p->sym_val_to_name[SYM_CLASSES] = flex_array_alloc(sizeof(char *),
412 kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL); 450 p->p_classes.nprim,
413 if (!p->p_class_val_to_name) 451 GFP_KERNEL | __GFP_ZERO);
452 if (!p->sym_val_to_name[SYM_CLASSES])
453 goto out;
454
455 rc = flex_array_prealloc(p->sym_val_to_name[SYM_CLASSES],
456 0, p->p_classes.nprim - 1,
457 GFP_KERNEL | __GFP_ZERO);
458 if (rc)
414 goto out; 459 goto out;
415 460
416 rc = hashtab_map(p->p_classes.table, class_index, p); 461 rc = hashtab_map(p->p_classes.table, class_index, p);
@@ -507,10 +552,18 @@ static int policydb_index_others(struct policydb *p)
507 552
508 for (i = SYM_ROLES; i < SYM_NUM; i++) { 553 for (i = SYM_ROLES; i < SYM_NUM; i++) {
509 rc = -ENOMEM; 554 rc = -ENOMEM;
510 p->sym_val_to_name[i] = 555 p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *),
511 kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL); 556 p->symtab[i].nprim,
557 GFP_KERNEL | __GFP_ZERO);
512 if (!p->sym_val_to_name[i]) 558 if (!p->sym_val_to_name[i])
513 goto out; 559 goto out;
560
561 rc = flex_array_prealloc(p->sym_val_to_name[i],
562 0, p->symtab[i].nprim - 1,
563 GFP_KERNEL | __GFP_ZERO);
564 if (rc)
565 goto out;
566
514 rc = hashtab_map(p->symtab[i].table, index_f[i], p); 567 rc = hashtab_map(p->symtab[i].table, index_f[i], p);
515 if (rc) 568 if (rc)
516 goto out; 569 goto out;
@@ -703,8 +756,10 @@ void policydb_destroy(struct policydb *p)
703 hashtab_destroy(p->symtab[i].table); 756 hashtab_destroy(p->symtab[i].table);
704 } 757 }
705 758
706 for (i = 0; i < SYM_NUM; i++) 759 for (i = 0; i < SYM_NUM; i++) {
707 kfree(p->sym_val_to_name[i]); 760 if (p->sym_val_to_name[i])
761 flex_array_free(p->sym_val_to_name[i]);
762 }
708 763
709 kfree(p->class_val_to_struct); 764 kfree(p->class_val_to_struct);
710 kfree(p->role_val_to_struct); 765 kfree(p->role_val_to_struct);
@@ -1566,9 +1621,9 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1566 printk(KERN_ERR 1621 printk(KERN_ERR
1567 "SELinux: boundary violated policy: " 1622 "SELinux: boundary violated policy: "
1568 "user=%s role=%s bounds=%s\n", 1623 "user=%s role=%s bounds=%s\n",
1569 p->p_user_val_to_name[user->value - 1], 1624 sym_name(p, SYM_USERS, user->value - 1),
1570 p->p_role_val_to_name[bit], 1625 sym_name(p, SYM_ROLES, bit),
1571 p->p_user_val_to_name[upper->value - 1]); 1626 sym_name(p, SYM_USERS, upper->value - 1));
1572 1627
1573 return -EINVAL; 1628 return -EINVAL;
1574 } 1629 }
@@ -1603,9 +1658,9 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1603 printk(KERN_ERR 1658 printk(KERN_ERR
1604 "SELinux: boundary violated policy: " 1659 "SELinux: boundary violated policy: "
1605 "role=%s type=%s bounds=%s\n", 1660 "role=%s type=%s bounds=%s\n",
1606 p->p_role_val_to_name[role->value - 1], 1661 sym_name(p, SYM_ROLES, role->value - 1),
1607 p->p_type_val_to_name[bit], 1662 sym_name(p, SYM_TYPES, bit),
1608 p->p_role_val_to_name[upper->value - 1]); 1663 sym_name(p, SYM_ROLES, upper->value - 1));
1609 1664
1610 return -EINVAL; 1665 return -EINVAL;
1611 } 1666 }
@@ -1637,7 +1692,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1637 printk(KERN_ERR "SELinux: type %s: " 1692 printk(KERN_ERR "SELinux: type %s: "
1638 "bounded by attribute %s", 1693 "bounded by attribute %s",
1639 (char *) key, 1694 (char *) key,
1640 p->p_type_val_to_name[upper->value - 1]); 1695 sym_name(p, SYM_TYPES, upper->value - 1));
1641 return -EINVAL; 1696 return -EINVAL;
1642 } 1697 }
1643 } 1698 }