[PATCH 2/2] SELinux Context Label based audit filtering

Dustin Kirkland dustin.kirkland at us.ibm.com
Fri Feb 17 06:18:23 UTC 2006


Updated patch.

Only changes from the last one is that:

AUDIT_SE_SENS became AUDIT_SE_SEN
and
AUDIT_SE_CAT became AUDIT_SE_CLR

These reflect Darrel's more knowledgeable naming of these SELinux
context label components.

Still, this is not going to be acceptable to mainline, Steve, as it doesn't
preserve backward compatibility.  But it does work in allowing one to test
the SELinux context label filtering provided in the kernel space sibling
patch.



:-Dustin



diff -urpN audit-1.1.3/lib/fieldtab.h audit-1.1.3.dustin/lib/fieldtab.h
--- audit-1.1.3/lib/fieldtab.h	2006-01-05 14:30:40.000000000 -0600
+++ audit-1.1.3.dustin/lib/fieldtab.h	2006-02-16 23:20:03.000000000 -0600
@@ -34,6 +34,11 @@ _S(AUDIT_LOGINUID, "loginuid" )
 _S(AUDIT_PERS,     "pers"     )
 _S(AUDIT_ARCH,     "arch"     )
 _S(AUDIT_MSGTYPE,  "msgtype"  )
+_S(AUDIT_SE_USER,  "se_user"  )
+_S(AUDIT_SE_ROLE,  "se_role"  )
+_S(AUDIT_SE_TYPE,  "se_type"  )
+_S(AUDIT_SE_SEN,   "se_sen"   )
+_S(AUDIT_SE_CLR,   "se_clr"  )
 
 _S(AUDIT_DEVMAJOR, "devmajor" )
 _S(AUDIT_DEVMINOR, "devminor" )
diff -urpN audit-1.1.3/lib/libaudit.c audit-1.1.3.dustin/lib/libaudit.c
--- audit-1.1.3/lib/libaudit.c	2006-02-02 11:02:12.000000000 -0600
+++ audit-1.1.3.dustin/lib/libaudit.c	2006-02-16 23:19:27.000000000 -0600
@@ -48,6 +48,7 @@ int audit_syscalladded = 0;
 unsigned int audit_elf = 0U;
 static int name_to_uid(const char *name, uid_t *uid);
 static int name_to_gid(const char *name, gid_t *gid);
+static void print_audit_rule_data(struct audit_rule_data *rd);
 
 
 int audit_request_status(int fd)
@@ -580,7 +581,7 @@ int audit_log_if_enabled(int fd, int typ
 	return rc;
 }
 
-int audit_rule_syscall(struct audit_rule *rule, int scall)
+int audit_rule_syscall(struct audit_rule_data *rule, int scall)
 {
 	int word = AUDIT_WORD(scall);
 	int bit  = AUDIT_BIT(scall);
@@ -591,7 +592,7 @@ int audit_rule_syscall(struct audit_rule
 	return 0;
 }
 
-int audit_rule_syscallbyname(struct audit_rule *rule,
+int audit_rule_syscallbyname(struct audit_rule_data *rule,
                              const char *scall)
 {
 	int nr, i;
@@ -602,7 +603,10 @@ int audit_rule_syscallbyname(struct audi
 			rule->mask[i] = ~0;
 		return 0;
 	}
-	machine = audit_elf_to_machine(audit_elf);
+	if (!audit_elf)
+		machine = audit_detect_machine();
+	else
+		machine = audit_elf_to_machine(audit_elf);
 	if (machine < 0)
 		return -2;
 	nr = audit_name_to_syscall(scall, machine);
@@ -626,44 +630,58 @@ int audit_rule_field(struct audit_rule *
 	return 0;
 }
 
-int audit_rule_fieldpair(struct audit_rule *rule, const char *pair, int flags)
+int audit_get_operator(const char *pair, char **v)
+{
+	/* look for 2-char operators first
+	   then look for 1-char operators afterwards
+	   when found, null out the bytes under the operators to split
+	   and set value pointer just past operator bytes
+	 */
+	if ( (*v = strstr(pair, "!=")) ) {
+		*(*v)++ = '\0';
+		*(*v)++ = '\0';
+		return AUDIT_NOT_EQUAL;
+	} 
+	if ( (*v = strstr(pair, ">=")) ) {
+		*(*v)++ = '\0';
+		*(*v)++ = '\0';
+		return AUDIT_GREATER_THAN_OR_EQUAL;
+	} 
+	if ( (*v = strstr(pair, "<=")) ) {
+		*(*v)++ = '\0';
+		*(*v)++ = '\0';
+		return AUDIT_LESS_THAN_OR_EQUAL;
+	} 	
+	if ( (*v = strstr(pair, "=")) ) {
+		*(*v)++ = '\0';
+		return AUDIT_EQUAL;
+	} 
+	if ( (*v = strstr(pair, ">")) ) {
+		*(*v)++ = '\0';
+		return AUDIT_GREATER_THAN;
+	} 
+	if ( (*v = strstr(pair, "<")) ) {
+		*(*v)++ = '\0';
+		return AUDIT_LESS_THAN;
+	}
+	return 0;
+}
+
+int audit_rule_fieldpair(struct audit_rule_data *rule, 
+			      const char *pair, int flags)
 {
 	const char *f = pair;
 	char       *v;
 	int        op;
 	int        field;
 	int        vlen;
+	int	   total_size;
+	int	   offset;
     
 	if (f == NULL)
 		return -1;
 
-	/* look for 2-char operators first
-	   then look for 1-char operators afterwards
-	   when found, null out the bytes under the operators to split
-	   and set value pointer just past operator bytes
-	*/
-	if ( (v = strstr(pair, "!=")) ) {
-		*v++ = '\0';
-		*v++ = '\0';
-		op = AUDIT_NOT_EQUAL;
-	} else if ( (v = strstr(pair, ">=")) ) {
-		*v++ = '\0';
-		*v++ = '\0';
-		op = AUDIT_GREATER_THAN_OR_EQUAL;
-	} else if ( (v = strstr(pair, "<=")) ) {
-		*v++ = '\0';
-		*v++ = '\0';
-		op = AUDIT_LESS_THAN_OR_EQUAL;
-	} else if ( (v = strstr(pair, "=")) ) {
-		*v++ = '\0';
-		op = AUDIT_EQUAL;
-	} else if ( (v = strstr(pair, ">")) ) {
-		*v++ = '\0';
-		op = AUDIT_GREATER_THAN;
-	} else if ( (v = strstr(pair, "<")) ) {
-		*v++ = '\0';
-		op = AUDIT_LESS_THAN;
-	}
+	op = audit_get_operator(pair, &v);
 
 	if (v == NULL || f == v)
 		return -1;
@@ -673,7 +691,9 @@ int audit_rule_fieldpair(struct audit_ru
 		return -2;
 
 	audit_msg(LOG_DEBUG,"f%d%s%s\n", field, audit_operator_to_symbol(op),v);
-	rule->fields[rule->field_count] = field | op;
+        rule->fields[rule->field_count] = field;
+        rule->fieldflags[rule->field_count] = op;
+
 	switch (field)
 	{
 		case AUDIT_UID:
@@ -819,6 +839,22 @@ int audit_rule_fieldpair(struct audit_ru
 		case AUDIT_DEVMAJOR...AUDIT_SUCCESS:
 			if (flags == AUDIT_FILTER_ENTRY)
 				return -7;
+		case AUDIT_SE_USER:
+		case AUDIT_SE_ROLE:
+		case AUDIT_SE_TYPE:
+		case AUDIT_SE_SEN:
+		case AUDIT_SE_CLR:
+			rule->values[rule->field_count] = strlen(v);
+			rule->buflen += strlen(v);
+			total_size = sizeof(*rule) + rule->buflen;
+			if (realloc(rule, total_size) == NULL) {
+				printf("Cannot realloc memory!\n");
+				return -3;
+			}
+			offset = total_size - sizeof(*rule) - strlen(v);
+			strncpy(&rule->buf[offset], v, strlen(v));
+                        break;
+
 			/* fallthrough */
 		default:
 			rule->values[rule->field_count] = strtol(v, NULL, 0);
@@ -828,6 +864,30 @@ int audit_rule_fieldpair(struct audit_ru
 	return 0;
 }
 
+/*
+ * Debug function useful to sanity check the contents of this new
+ * audit_rule_data structure, and in particular the variable length
+ * strings
+ */
+void print_audit_rule_data(struct audit_rule_data *rd) {
+	int i;
+	printf("====================================\n");
+	printf("flags       = [0x%x]\n", rd->flags);
+	printf("action      = [%d]\n", rd->action);
+	printf("field_count = [%d]\n", rd->field_count);
+	for (i=0; i<AUDIT_BITMASK_SIZE; i++)
+		if (rd->mask[i])
+			printf("mask[%d] = [0x%x]\n", i, rd->mask[i]);
+	for (i=0; i<AUDIT_MAX_FIELDS; i++) {
+		if (rd->fields[i] || rd->values[i] || rd->fieldflags[i]) 
+			printf("fields[%d] = [%d], values[%d] = [%d], fieldflags[%d] = [0x%x]\n", i, rd->fields[i], i, rd->values[i], i, rd->fieldflags[i]);
+	}
+	printf("buflen      = [%d]\n", rd->buflen);
+	printf("buf         = [%s]\n", rd->buf);
+	printf("TOTAL_SIZE  = [%d]\n", sizeof(*rd) + rd->buflen);
+	printf("====================================\n");
+}
+
 void audit_rule_free(struct audit_rule *rule)
 {
 	if (rule) 
diff -urpN audit-1.1.3/lib/libaudit.h audit-1.1.3.dustin/lib/libaudit.h
--- audit-1.1.3/lib/libaudit.h	2006-02-02 11:02:12.000000000 -0600
+++ audit-1.1.3.dustin/lib/libaudit.h	2006-02-16 23:18:59.000000000 -0600
@@ -182,6 +182,13 @@ extern "C" {
 #ifndef AUDIT_MSGTYPE
 #define AUDIT_MSGTYPE 12
 #endif
+#ifndef AUDIT_SE_USER
+#define AUDIT_SE_USER 13
+#define AUDIT_SE_ROLE 14
+#define AUDIT_SE_TYPE 15
+#define AUDIT_SE_SEN  16
+#define AUDIT_SE_CLR  17
+#endif
 
 /* This is new list defines from audit.h */
 #ifndef AUDIT_FILTER_USER
@@ -236,6 +243,30 @@ struct watch_transport {
 };
 #endif
 
+
+#ifndef AUDIT_ADD_RULE
+#define AUDIT_ADD_RULE          1011    /* Add syscall filtering rule */
+#define AUDIT_DEL_RULE          1012    /* Delete syscall filtering rule */
+#define AUDIT_LIST_RULES        1013    /* List syscall filtering rules */
+/* audit_rule_data supports filter rules with both integer and string
+ * fields.  It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and
+ * AUDIT_LIST_RULES requests.
+ */
+struct audit_rule_data {
+        __u32           flags;  /* AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND */
+        __u32           action; /* AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS */
+        __u32           field_count;
+        __u32           mask[AUDIT_BITMASK_SIZE];
+        __u32           fields[AUDIT_MAX_FIELDS];
+        __u32           values[AUDIT_MAX_FIELDS];
+        __u32           fieldflags[AUDIT_MAX_FIELDS];
+        __u32           buflen; /* total length of string fields */
+        char            buf[0]; /* string fields buffer */
+};
+#endif
+
+
+
 struct audit_watch {
 	uint32_t dev_major;
 	uint32_t dev_minor;
@@ -386,12 +417,12 @@ extern int audit_log_user_avc_message(in
 	const char *tty, uid_t uid);
 
 /* Rule-building helper functions */
-extern int  audit_rule_syscall(struct audit_rule *rule, int scall);
-extern int  audit_rule_syscallbyname(struct audit_rule *rule,
+extern int  audit_rule_syscall(struct audit_rule_data *rule, int scall);
+extern int  audit_rule_syscallbyname(struct audit_rule_data *rule,
                                      const char *scall);
 extern int  audit_rule_field(struct audit_rule *rule, int field,
                              unsigned int value);
-extern int  audit_rule_fieldpair(struct audit_rule *rule, const char *pair, 
+extern int  audit_rule_fieldpair(struct audit_rule_data *rule, const char *pair, 
 		int flags);
 extern void audit_rule_free(struct audit_rule *rule);
 
diff -urpN audit-1.1.3/src/auditctl.c audit-1.1.3.dustin/src/auditctl.c
--- audit-1.1.3/src/auditctl.c	2006-01-04 16:19:55.000000000 -0600
+++ audit-1.1.3.dustin/src/auditctl.c	2006-02-02 13:15:09.000000000 -0600
@@ -70,6 +70,7 @@ static int list_requested = 0;
 static int add = AUDIT_FILTER_UNSET, del = AUDIT_FILTER_UNSET, action = 0;
 static int ins = 0, rem = 0, ignore = 0;
 static struct audit_rule  rule;
+static struct audit_rule_data  *rule_data;
 static struct audit_watch watch;
 
 extern int audit_archadded;
@@ -92,6 +93,7 @@ static int reset_vars(void)
 	ins = 0;
 	rem = 0;
 
+        rule_data = calloc(1, sizeof(*rule_data));
 	memset(&rule, 0, sizeof(rule));
 	memset(&watch, 0, sizeof(watch));
 	if ((fd = audit_open()) < 0) {
@@ -158,6 +160,8 @@ static int audit_rule_setup(const char *
 		*act = AUDIT_ALWAYS;
 	else
 		return 1;
+	rule_data->flags = *flags;
+	rule_data->action = *act;
 	return 0;
 }
 
@@ -498,7 +502,7 @@ static int setopt(int count, char *vars[
 				audit_elf = elf;
 			}
 		}
-		switch (audit_rule_syscallbyname(&rule, optarg))
+		switch (audit_rule_syscallbyname(rule_data, optarg))
 		{
 			case 0:
 				audit_syscalladded = 1;
@@ -527,8 +531,8 @@ static int setopt(int count, char *vars[
 			fprintf(stderr, "List must be given before field\n");
 			retval = -1;
 			break;
-		}	
-		switch (audit_rule_fieldpair(&rule, optarg, flags))
+		}
+		switch (audit_rule_fieldpair(rule_data, optarg, flags))
 		{
 			case 0:
 				break;
@@ -863,14 +867,14 @@ static int handle_request(int status)
 			// if !task add syscall any if not specified
 			if ((add & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && 
 					audit_syscalladded != 1)
-				audit_rule_syscallbyname(&rule, "all");
-			rc = audit_add_rule(fd, &rule, add, action);
+				audit_rule_syscallbyname(rule_data, "all");
+			rc = audit_add_rule_data(fd, rule_data);
 		}
 		else if (del != AUDIT_FILTER_UNSET) {
 			if ((del & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && 
 					audit_syscalladded != 1)
-				audit_rule_syscallbyname(&rule, "all");
-			rc = audit_delete_rule(fd, &rule, del, action);
+				audit_rule_syscallbyname(rule_data, "all");
+			rc = audit_del_rule_data(fd, rule_data);
 		}
 		else if (ins && !rem) 
 			rc = audit_insert_watch(fd, &watch);





More information about the Linux-audit mailing list