aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/include/avc.h3
-rw-r--r--security/selinux/ss/services.c142
3 files changed, 121 insertions, 26 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index b2ab60859832..7823e84dbe8d 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
137 * @tclass: target security class 137 * @tclass: target security class
138 * @av: access vector 138 * @av: access vector
139 */ 139 */
140void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 140static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
141{ 141{
142 const char **common_pts = NULL; 142 const char **common_pts = NULL;
143 u32 common_base = 0; 143 u32 common_base = 0;
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index d12ff1a9c0aa..46a940d9af67 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -127,9 +127,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
127 u32 events, u32 ssid, u32 tsid, 127 u32 events, u32 ssid, u32 tsid,
128 u16 tclass, u32 perms); 128 u16 tclass, u32 perms);
129 129
130/* Shows permission in human readable form */
131void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
132
133/* Exported to selinuxfs */ 130/* Exported to selinuxfs */
134int avc_get_hash_stats(char *page); 131int avc_get_hash_stats(char *page);
135extern unsigned int avc_cache_threshold; 132extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 500e6f78e115..ff17820d35ec 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -22,6 +22,11 @@
22 * 22 *
23 * Added validation of kernel classes and permissions 23 * Added validation of kernel classes and permissions
24 * 24 *
25 * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
26 *
27 * Added support for bounds domain and audit messaged on masked permissions
28 *
29 * Copyright (C) 2008, 2009 NEC Corporation
25 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. 30 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
26 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 31 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
27 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC 32 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
@@ -279,6 +284,95 @@ mls_ops:
279} 284}
280 285
281/* 286/*
287 * security_dump_masked_av - dumps masked permissions during
288 * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
289 */
290static int dump_masked_av_helper(void *k, void *d, void *args)
291{
292 struct perm_datum *pdatum = d;
293 char **permission_names = args;
294
295 BUG_ON(pdatum->value < 1 || pdatum->value > 32);
296
297 permission_names[pdatum->value - 1] = (char *)k;
298
299 return 0;
300}
301
302static void security_dump_masked_av(struct context *scontext,
303 struct context *tcontext,
304 u16 tclass,
305 u32 permissions,
306 const char *reason)
307{
308 struct common_datum *common_dat;
309 struct class_datum *tclass_dat;
310 struct audit_buffer *ab;
311 char *tclass_name;
312 char *scontext_name = NULL;
313 char *tcontext_name = NULL;
314 char *permission_names[32];
315 int index, length;
316 bool need_comma = false;
317
318 if (!permissions)
319 return;
320
321 tclass_name = policydb.p_class_val_to_name[tclass - 1];
322 tclass_dat = policydb.class_val_to_struct[tclass - 1];
323 common_dat = tclass_dat->comdatum;
324
325 /* init permission_names */
326 if (common_dat &&
327 hashtab_map(common_dat->permissions.table,
328 dump_masked_av_helper, permission_names) < 0)
329 goto out;
330
331 if (hashtab_map(tclass_dat->permissions.table,
332 dump_masked_av_helper, permission_names) < 0)
333 goto out;
334
335 /* get scontext/tcontext in text form */
336 if (context_struct_to_string(scontext,
337 &scontext_name, &length) < 0)
338 goto out;
339
340 if (context_struct_to_string(tcontext,
341 &tcontext_name, &length) < 0)
342 goto out;
343
344 /* audit a message */
345 ab = audit_log_start(current->audit_context,
346 GFP_ATOMIC, AUDIT_SELINUX_ERR);
347 if (!ab)
348 goto out;
349
350 audit_log_format(ab, "op=security_compute_av reason=%s "
351 "scontext=%s tcontext=%s tclass=%s perms=",
352 reason, scontext_name, tcontext_name, tclass_name);
353
354 for (index = 0; index < 32; index++) {
355 u32 mask = (1 << index);
356
357 if ((mask & permissions) == 0)
358 continue;
359
360 audit_log_format(ab, "%s%s",
361 need_comma ? "," : "",
362 permission_names[index]
363 ? permission_names[index] : "????");
364 need_comma = true;
365 }
366 audit_log_end(ab);
367out:
368 /* release scontext/tcontext */
369 kfree(tcontext_name);
370 kfree(scontext_name);
371
372 return;
373}
374
375/*
282 * security_boundary_permission - drops violated permissions 376 * security_boundary_permission - drops violated permissions
283 * on boundary constraint. 377 * on boundary constraint.
284 */ 378 */
@@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext,
347 } 441 }
348 442
349 if (masked) { 443 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */ 444 /* mask violated permissions */
359 avd->allowed &= ~masked; 445 avd->allowed &= ~masked;
360 446
361 /* notice to userspace via audit message */ 447 /* audit masked permissions */
362 ab = audit_log_start(current->audit_context, 448 security_dump_masked_av(scontext, tcontext,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR); 449 tclass, masked, "bounds");
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 } 450 }
373} 451}
374 452
@@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext,
480 if ((constraint->permissions & (avd->allowed)) && 558 if ((constraint->permissions & (avd->allowed)) &&
481 !constraint_expr_eval(scontext, tcontext, NULL, 559 !constraint_expr_eval(scontext, tcontext, NULL,
482 constraint->expr)) { 560 constraint->expr)) {
483 avd->allowed = (avd->allowed) & ~(constraint->permissions); 561 avd->allowed &= ~(constraint->permissions);
484 } 562 }
485 constraint = constraint->next; 563 constraint = constraint->next;
486 } 564 }
@@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext,
499 break; 577 break;
500 } 578 }
501 if (!ra) 579 if (!ra)
502 avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | 580 avd->allowed &= ~(PROCESS__TRANSITION |
503 PROCESS__DYNTRANSITION); 581 PROCESS__DYNTRANSITION);
504 } 582 }
505 583
506 /* 584 /*
@@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
687 } 765 }
688 index = type->bounds; 766 index = type->bounds;
689 } 767 }
768
769 if (rc) {
770 char *old_name = NULL;
771 char *new_name = NULL;
772 int length;
773
774 if (!context_struct_to_string(old_context,
775 &old_name, &length) &&
776 !context_struct_to_string(new_context,
777 &new_name, &length)) {
778 audit_log(current->audit_context,
779 GFP_ATOMIC, AUDIT_SELINUX_ERR,
780 "op=security_bounded_transition "
781 "result=denied "
782 "oldcontext=%s newcontext=%s",
783 old_name, new_name);
784 }
785 kfree(new_name);
786 kfree(old_name);
787 }
690out: 788out:
691 read_unlock(&policy_rwlock); 789 read_unlock(&policy_rwlock);
692 790