Re: type bounds audit messages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Summary of opinions:
- SELINUX_INFO is good, because it is a new audit message type (Eric).
  But it is not unclear whether the most descriptive type name, or not (Steve).
- The { ... } style is not preferable, comma separated permissions list
  is better (Eric).
- The <name>=<value> style is more excellent (Dan).
- The quoted strung should be limited to describe untrusted strings (Steve).
- AVC denials also should use SELINUX_INFO with new style (Dan).
  - It describes an internal inconsistency within the policy, not AVC (Stephen).

Please tell me, if I missed your opinions.

I fixed the message format as follows:
("UNKNOWN[1418]" is AUDIT_SELINUX_INFO newly defined.)

  type=UNKNOWN[1418] msg=audit(1245207615.589:70):      \
      op=security_compute_av masked=bounds              \
      scontext=system_u:system_r:user_webapp_t:s0       \
      tcontext=system_u:object_r:shadow_t:s0:c0         \
      tclass=file perms=getattr,open

However, I think Stephen pointed out a significant thing.

Some of permissions are masked at runtime during security_compute_av()
due to RBAC, Constraint, MLS and Type bounds, although TE allows them.
It's not clear for me whether it should be considered as an error
(SELINUX_ERR) because of an internal inconsistency within the policy,
or should be considered as just an information (SELINUX_INFO) from
the kernel.

--------
[PATCH] Add audit messages for masked SELinux permissions

The following patch adds a few audit messages,
 1. when a multithread process switch its performing domain to unbounded
    one, and the hardwired rule prevent it.

  type=SELINUX_ERR msg=audit(1245207506.618:62):        \
      security_bounded_transition: denied for           \
      oldcontext=system_u:system_r:httpd_t:s0           \
      newcontext=system_u:system_r:guest_webapp_t:s0

 2. when RBAC, MLS/Constraints and Type bounds masks permissions allowed
    with TE rules on security_compute_av().

  * BRAC prevent domain transition
  type=UNKNOWN[1418] msg=audit(1245207539.227:67):      \
      op=security_compute_av masked=rbac                \
      scontext=unconfined_u:unconfined_r:unconfined_t:s0    \
      tcontext=staff_u:staff_r:staff_t:s0               \
      tclass=process perms=transition

  * MCS prevent accesses to *:s0:c0 by *:s0
  type=UNKNOWN[1418] msg=audit(1245212024.689:39):      \
      op=security_compute_av masked=constraint          \
      scontext=system_u:system_r:user_webapp_t:s0       \
      tcontext=system_u:object_r:shadow_t:s0:c0         \
      tclass=file perms=ioctl,read,write,create,setattr,lock,append,unlink,link,rename

  * Then, type bounds prevents accesses to shadow_t
  type=UNKNOWN[1418] msg=audit(1245212024.689:39):      \
      op=security_compute_av masked=bounds              \
      scontext=system_u:system_r:user_webapp_t:s0       \
      tcontext=system_u:object_r:shadow_t:s0:c0         \
      tclass=file perms=getattr,open

 Signed-off-by: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
--
 include/linux/audit.h          |    1 +
 security/selinux/avc.c         |    2 +-
 security/selinux/include/avc.h |    3 -
 security/selinux/ss/services.c |  161 ++++++++++++++++++++++++++++++++++------
 4 files changed, 141 insertions(+), 26 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 4fa2810..6de6ef3 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -121,6 +121,7 @@
 #define AUDIT_MAC_IPSEC_EVENT	1415	/* Audit an IPSec event */
 #define AUDIT_MAC_UNLBL_STCADD	1416	/* NetLabel: add a static label */
 #define AUDIT_MAC_UNLBL_STCDEL	1417	/* NetLabel: del a static label */
+#define AUDIT_SELINUX_INFO	1418	/* Notifications from SE Linux */

 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 7f9b5fa..4bf5d08 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)
  * @tclass: target security class
  * @av: access vector
  */
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
+static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
 {
 	const char **common_pts = NULL;
 	u32 common_base = 0;
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index d12ff1a..46a940d 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,
 		     u32 events, u32 ssid, u32 tsid,
 		     u16 tclass, u32 perms);

-/* Shows permission in human readable form */
-void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
-
 /* Exported to selinuxfs */
 int avc_get_hash_stats(char *page);
 extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index deeec6c..5b19fd3 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -22,6 +22,11 @@
  *
  *  Added validation of kernel classes and permissions
  *
+ * Updated: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
+ *
+ *  Added support for bounds domain and audit messaged on masked permissions
+ *
+ * Copyright (C) 2008, 2009 NEC Corporation
  * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
@@ -279,6 +284,98 @@ mls_ops:
 }

 /*
+ * security_dump_masked_av - dumps masked permissions during
+ * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
+ */
+static int dump_masked_av_helper(void *k, void *d, void *args)
+{
+	struct perm_datum *pdatum = d;
+	char **permission_names = args;
+
+	BUG_ON(pdatum->value < 1 || pdatum->value > 32);
+
+	permission_names[pdatum->value - 1] = (char *)k;
+
+	return 0;
+}
+
+static void security_dump_masked_av(struct context *scontext,
+				    struct context *tcontext,
+				    u16 tclass,
+				    u32 permissions,
+				    const char *reason)
+{
+	struct common_datum *common_dat;
+	struct class_datum *tclass_dat;
+	struct audit_buffer *ab;
+	char *tclass_name;
+	char *scontext_name;
+	char *tcontext_name;
+	char *permission_names[32];
+	int index, length;
+	bool need_comma = false;
+
+	if (!permissions)
+		return;
+
+	tclass_name = policydb.p_class_val_to_name[tclass - 1];
+	tclass_dat = policydb.class_val_to_struct[tclass - 1];
+	common_dat = tclass_dat->comdatum;
+
+	/* init permission_names */
+	if (common_dat) {
+		if (hashtab_map(common_dat->permissions.table,
+				dump_masked_av_helper, permission_names) < 0)
+			goto out0;
+	}
+	if (hashtab_map(tclass_dat->permissions.table,
+			dump_masked_av_helper, permission_names) < 0)
+		goto out0;
+
+	/* get scontext/tcontext in text form */
+	if (context_struct_to_string(scontext,
+				     &scontext_name, &length) < 0)
+		goto out0;
+
+	if (context_struct_to_string(tcontext,
+				     &tcontext_name, &length) < 0)
+		goto out1;
+
+	/* audit a message */
+	ab = audit_log_start(current->audit_context,
+			     GFP_ATOMIC, AUDIT_SELINUX_INFO);
+	if (!ab)
+		goto out2;
+
+	audit_log_format(ab,
+			 "op=security_compute_av masked=%s "
+			 "scontext=%s tcontext=%s tclass=%s perms=",
+			 reason, scontext_name, tcontext_name, tclass_name);
+
+	for (index = 0; index < 32; index++) {
+		u32 mask = (1 << index);
+
+		if ((mask & permissions) == 0)
+			continue;
+
+		audit_log_format(ab, "%s%s",
+				 need_comma ? "," : "",
+				 permission_names[index]
+				 ? permission_names[index] : "????");
+		need_comma = true;
+	}
+	audit_log_end(ab);
+
+	/* release scontext/tcontext */
+out2:
+	kfree(tcontext_name);
+out1:
+	kfree(scontext_name);
+out0:
+	return;
+}
+
+/*
  * security_boundary_permission - drops violated permissions
  * on boundary constraint.
  */
@@ -347,28 +444,12 @@ static void type_attribute_bounds_av(struct context *scontext,
 	}

 	if (masked) {
-		struct audit_buffer *ab;
-		char *stype_name
-			= policydb.p_type_val_to_name[source->value - 1];
-		char *ttype_name
-			= policydb.p_type_val_to_name[target->value - 1];
-		char *tclass_name
-			= policydb.p_class_val_to_name[tclass - 1];
-
 		/* mask violated permissions */
 		avd->allowed &= ~masked;

-		/* notice to userspace via audit message */
-		ab = audit_log_start(current->audit_context,
-				     GFP_ATOMIC, AUDIT_SELINUX_ERR);
-		if (!ab)
-			return;
-
-		audit_log_format(ab, "av boundary violation: "
-				 "source=%s target=%s tclass=%s",
-				 stype_name, ttype_name, tclass_name);
-		avc_dump_av(ab, tclass, masked);
-		audit_log_end(ab);
+		/* audit masked permissions */
+		security_dump_masked_av(scontext, tcontext,
+					tclass, masked, "bounds");
 	}
 }

@@ -391,6 +472,7 @@ static int context_struct_compute_av(struct context *scontext,
 	struct ebitmap_node *snode, *tnode;
 	const struct selinux_class_perm *kdefs = &selinux_class_perm;
 	unsigned int i, j;
+	u32 masked;

 	/*
 	 * Remap extended Netlink classes for old policy versions.
@@ -475,15 +557,20 @@ static int context_struct_compute_av(struct context *scontext,
 	 * the MLS policy).
 	 */
 	constraint = tclass_datum->constraints;
+	masked = 0;
 	while (constraint) {
 		if ((constraint->permissions & (avd->allowed)) &&
 		    !constraint_expr_eval(scontext, tcontext, NULL,
 					  constraint->expr)) {
+			masked |= (avd->allowed & constraint->permissions);
 			avd->allowed = (avd->allowed) & ~(constraint->permissions);
 		}
 		constraint = constraint->next;
 	}

+	if (masked)
+		security_dump_masked_av(scontext, tcontext,
+					tclass, masked, "constraint");
 	/*
 	 * If checking process transition permission and the
 	 * role is changing, then check the (current_role, new_role)
@@ -497,9 +584,15 @@ static int context_struct_compute_av(struct context *scontext,
 			    tcontext->role == ra->new_role)
 				break;
 		}
-		if (!ra)
-			avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
-							PROCESS__DYNTRANSITION);
+		if (!ra) {
+			masked = avd->allowed & (PROCESS__TRANSITION |
+						 PROCESS__DYNTRANSITION);
+			avd->allowed &= ~(PROCESS__TRANSITION |
+					  PROCESS__DYNTRANSITION);
+			if (masked)
+				security_dump_masked_av(scontext, tcontext,
+							tclass, masked, "rbac");
+		}
 	}

 	/*
@@ -711,6 +804,30 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
 		}
 		index = type->bounds;
 	}
+
+	if (rc) {
+		char *old_name;
+		char *new_name;
+		int length;
+
+		if (context_struct_to_string(old_context,
+					     &old_name, &length) < 0)
+			goto out;
+		if (context_struct_to_string(new_context,
+					     &new_name, &length) < 0) {
+			kfree(old_name);
+			goto out;
+		}
+
+		audit_log(current->audit_context,
+			  GFP_ATOMIC, AUDIT_SELINUX_ERR,
+			  "security_bounded_transition: denied for "
+			  "oldcontext=%s newcontext=%s",
+			  old_name, new_name);
+
+		kfree(new_name);
+		kfree(old_name);
+	}
 out:
 	read_unlock(&policy_rwlock);


-- 
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@xxxxxxxxxxxxx>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux