aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2005-09-03 18:55:16 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:05:50 -0400
commit782ebb992ec20b5afdd5786ee8c2f1b58b631f24 (patch)
treeadf0af44fa591d803ec6b9ab7541ff3e5745dd93 /security/selinux/ss/services.c
parent720d6c29e146e96cca858057469951e91e0e6850 (diff)
[PATCH] selinux: Reduce memory use by avtab
This patch improves memory use by SELinux by both reducing the avtab node size and reducing the number of avtab nodes. The memory savings are substantial, e.g. on a 64-bit system after boot, James Morris reported the following data for the targeted and strict policies: #objs objsize kernmem Targeted: Before: 237888 40 9.1MB After: 19968 24 468KB Strict: Before: 571680 40 21.81MB After: 221052 24 5.06MB The improvement in memory use comes at a cost in the speed of security server computations of access vectors, but these computations are only required on AVC cache misses, and performance measurements by James Morris using a number of benchmarks have shown that the change does not cause any significant degradation. Note that a rebuilt policy via an updated policy toolchain (libsepol/checkpolicy) is required in order to gain the full benefits of this patch, although some memory savings benefits are immediately applied even to older policies (in particular, the reduction in avtab node size). Sources for the updated toolchain are presently available from the sourceforge CVS tree (http://sourceforge.net/cvs/?group_id=21266), and tarballs are available from http://www.flux.utah.edu/~sds. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r--security/selinux/ss/services.c76
1 files changed, 41 insertions, 35 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 014120474e69..92b89dc99bcd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext,
266 struct constraint_node *constraint; 266 struct constraint_node *constraint;
267 struct role_allow *ra; 267 struct role_allow *ra;
268 struct avtab_key avkey; 268 struct avtab_key avkey;
269 struct avtab_datum *avdatum; 269 struct avtab_node *node;
270 struct class_datum *tclass_datum; 270 struct class_datum *tclass_datum;
271 struct ebitmap *sattr, *tattr;
272 struct ebitmap_node *snode, *tnode;
273 unsigned int i, j;
271 274
272 /* 275 /*
273 * Remap extended Netlink classes for old policy versions. 276 * Remap extended Netlink classes for old policy versions.
@@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext,
300 * If a specific type enforcement rule was defined for 303 * If a specific type enforcement rule was defined for
301 * this permission check, then use it. 304 * this permission check, then use it.
302 */ 305 */
303 avkey.source_type = scontext->type;
304 avkey.target_type = tcontext->type;
305 avkey.target_class = tclass; 306 avkey.target_class = tclass;
306 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); 307 avkey.specified = AVTAB_AV;
307 if (avdatum) { 308 sattr = &policydb.type_attr_map[scontext->type - 1];
308 if (avdatum->specified & AVTAB_ALLOWED) 309 tattr = &policydb.type_attr_map[tcontext->type - 1];
309 avd->allowed = avtab_allowed(avdatum); 310 ebitmap_for_each_bit(sattr, snode, i) {
310 if (avdatum->specified & AVTAB_AUDITDENY) 311 if (!ebitmap_node_get_bit(snode, i))
311 avd->auditdeny = avtab_auditdeny(avdatum); 312 continue;
312 if (avdatum->specified & AVTAB_AUDITALLOW) 313 ebitmap_for_each_bit(tattr, tnode, j) {
313 avd->auditallow = avtab_auditallow(avdatum); 314 if (!ebitmap_node_get_bit(tnode, j))
314 } 315 continue;
316 avkey.source_type = i + 1;
317 avkey.target_type = j + 1;
318 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
319 node != NULL;
320 node = avtab_search_node_next(node, avkey.specified)) {
321 if (node->key.specified == AVTAB_ALLOWED)
322 avd->allowed |= node->datum.data;
323 else if (node->key.specified == AVTAB_AUDITALLOW)
324 avd->auditallow |= node->datum.data;
325 else if (node->key.specified == AVTAB_AUDITDENY)
326 avd->auditdeny &= node->datum.data;
327 }
315 328
316 /* Check conditional av table for additional permissions */ 329 /* Check conditional av table for additional permissions */
317 cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); 330 cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
331
332 }
333 }
318 334
319 /* 335 /*
320 * Remove any permissions prohibited by a constraint (this includes 336 * Remove any permissions prohibited by a constraint (this includes
@@ -797,7 +813,6 @@ static int security_compute_sid(u32 ssid,
797 struct avtab_key avkey; 813 struct avtab_key avkey;
798 struct avtab_datum *avdatum; 814 struct avtab_datum *avdatum;
799 struct avtab_node *node; 815 struct avtab_node *node;
800 unsigned int type_change = 0;
801 int rc = 0; 816 int rc = 0;
802 817
803 if (!ss_initialized) { 818 if (!ss_initialized) {
@@ -862,33 +877,23 @@ static int security_compute_sid(u32 ssid,
862 avkey.source_type = scontext->type; 877 avkey.source_type = scontext->type;
863 avkey.target_type = tcontext->type; 878 avkey.target_type = tcontext->type;
864 avkey.target_class = tclass; 879 avkey.target_class = tclass;
865 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); 880 avkey.specified = specified;
881 avdatum = avtab_search(&policydb.te_avtab, &avkey);
866 882
867 /* If no permanent rule, also check for enabled conditional rules */ 883 /* If no permanent rule, also check for enabled conditional rules */
868 if(!avdatum) { 884 if(!avdatum) {
869 node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); 885 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
870 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 886 for (; node != NULL; node = avtab_search_node_next(node, specified)) {
871 if (node->datum.specified & AVTAB_ENABLED) { 887 if (node->key.specified & AVTAB_ENABLED) {
872 avdatum = &node->datum; 888 avdatum = &node->datum;
873 break; 889 break;
874 } 890 }
875 } 891 }
876 } 892 }
877 893
878 type_change = (avdatum && (avdatum->specified & specified)); 894 if (avdatum) {
879 if (type_change) {
880 /* Use the type from the type transition/member/change rule. */ 895 /* Use the type from the type transition/member/change rule. */
881 switch (specified) { 896 newcontext.type = avdatum->data;
882 case AVTAB_TRANSITION:
883 newcontext.type = avtab_transition(avdatum);
884 break;
885 case AVTAB_MEMBER:
886 newcontext.type = avtab_member(avdatum);
887 break;
888 case AVTAB_CHANGE:
889 newcontext.type = avtab_change(avdatum);
890 break;
891 }
892 } 897 }
893 898
894 /* Check for class-specific changes. */ 899 /* Check for class-specific changes. */
@@ -1502,6 +1507,7 @@ int security_get_user_sids(u32 fromsid,
1502 struct user_datum *user; 1507 struct user_datum *user;
1503 struct role_datum *role; 1508 struct role_datum *role;
1504 struct av_decision avd; 1509 struct av_decision avd;
1510 struct ebitmap_node *rnode, *tnode;
1505 int rc = 0, i, j; 1511 int rc = 0, i, j;
1506 1512
1507 if (!ss_initialized) { 1513 if (!ss_initialized) {
@@ -1532,13 +1538,13 @@ int security_get_user_sids(u32 fromsid,
1532 } 1538 }
1533 memset(mysids, 0, maxnel*sizeof(*mysids)); 1539 memset(mysids, 0, maxnel*sizeof(*mysids));
1534 1540
1535 for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { 1541 ebitmap_for_each_bit(&user->roles, rnode, i) {
1536 if (!ebitmap_get_bit(&user->roles, i)) 1542 if (!ebitmap_node_get_bit(rnode, i))
1537 continue; 1543 continue;
1538 role = policydb.role_val_to_struct[i]; 1544 role = policydb.role_val_to_struct[i];
1539 usercon.role = i+1; 1545 usercon.role = i+1;
1540 for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { 1546 ebitmap_for_each_bit(&role->types, tnode, j) {
1541 if (!ebitmap_get_bit(&role->types, j)) 1547 if (!ebitmap_node_get_bit(tnode, j))
1542 continue; 1548 continue;
1543 usercon.type = j+1; 1549 usercon.type = j+1;
1544 1550