All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amy Griffis <amy.griffis@hp.com>
To: linux-audit@redhat.com
Subject: [PATCH] add rule filterkey
Date: Wed, 14 Jun 2006 18:45:21 -0400	[thread overview]
Message-ID: <20060614224521.GA2268@zk3.dec.com> (raw)

Add support for a rule key, which can be used to tie audit records to audit
rules.  This is useful when a watched file is accessed through a link or
symlink, as well as for general audit log analysis.

Because this patch uses a string key instead of an integer key, there is a bit
of extra overhead to do the kstrdup() when a rule fires.  However, we're also
allocating memory for the audit record buffer, so it's probably not that
significant.  I went ahead with a string key because it seems more
user-friendly.

Note that the user must ensure that filterkeys are unique.  The kernel only
checks for duplicate rules.

Signed-off-by: Amy Griffis <amy.griffis@hpd.com>
---
 include/linux/audit.h |    3 ++
 kernel/audit.h        |    1 +
 kernel/auditfilter.c  |   95 ++++++++++++++++++++++++++++++-------------------
 kernel/auditsc.c      |   15 ++++++++
 4 files changed, 78 insertions(+), 36 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index e1c1dbd..f7883ec 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -123,6 +123,7 @@ #define AUDIT_ALWAYS   2	/* Generate aud
 /* Rule structure sizes -- if these change, different AUDIT_ADD and
  * AUDIT_LIST commands must be implemented. */
 #define AUDIT_MAX_FIELDS   64
+#define AUDIT_MAX_KEY_LEN  32
 #define AUDIT_BITMASK_SIZE 64
 #define AUDIT_WORD(nr) ((__u32)((nr)/32))
 #define AUDIT_BIT(nr)  (1 << ((nr) - AUDIT_WORD(nr)*32))
@@ -172,6 +173,8 @@ #define AUDIT_ARG1      (AUDIT_ARG0+1)
 #define AUDIT_ARG2      (AUDIT_ARG0+2)
 #define AUDIT_ARG3      (AUDIT_ARG0+3)
 
+#define AUDIT_FILTERKEY	210
+
 #define AUDIT_NEGATE			0x80000000
 
 /* These are the supported operators.
diff --git a/kernel/audit.h b/kernel/audit.h
index 38e62b7..0381640 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -81,6 +81,7 @@ struct audit_krule {
 	u32			mask[AUDIT_BITMASK_SIZE];
 	u32			buflen; /* for data alloc on list rules */
 	u32			field_count;
+	char			*filterkey; /* ties events to rules */
 	struct audit_field	*fields;
 	struct audit_field	*inode_f; /* quick access to an inode field */
 	struct audit_watch	*watch;	/* associated watch */
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 4c99d2c..e98db08 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -141,6 +141,7 @@ static inline void audit_free_rule(struc
 			selinux_audit_rule_free(f->se_rule);
 		}
 	kfree(e->rule.fields);
+	kfree(e->rule.filterkey);
 	kfree(e);
 }
 
@@ -511,6 +512,16 @@ static struct audit_entry *audit_data_to
 			if (err)
 				goto exit_free;
 			break;
+		case AUDIT_FILTERKEY:
+			err = -EINVAL;
+			if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
+				goto exit_free;
+			str = audit_unpack_string(&bufp, &remain, f->val);
+			if (IS_ERR(str))
+				goto exit_free;
+			entry->rule.buflen += f->val;
+			entry->rule.filterkey = str;
+			break;
 		default:
 			goto exit_free;
 		}
@@ -612,6 +623,10 @@ static struct audit_rule_data *audit_kru
 			data->buflen += data->values[i] =
 				audit_pack_string(&bufp, krule->watch->path);
 			break;
+		case AUDIT_FILTERKEY:
+			data->buflen += data->values[i] =
+				audit_pack_string(&bufp, krule->filterkey);
+			break;
 		default:
 			data->values[i] = f->val;
 		}
@@ -651,6 +666,11 @@ static int audit_compare_rule(struct aud
 			if (strcmp(a->watch->path, b->watch->path))
 				return 1;
 			break;
+		case AUDIT_FILTERKEY:
+			/* both filterkeys exist based on above type compare */
+			if (strcmp(a->filterkey, b->filterkey))
+				return 1;
+			break;
 		default:
 			if (a->fields[i].val != b->fields[i].val)
 				return 1;
@@ -730,6 +750,7 @@ static struct audit_entry *audit_dupe_ru
 	u32 fcount = old->field_count;
 	struct audit_entry *entry;
 	struct audit_krule *new;
+	char *fk;
 	int i, err = 0;
 
 	entry = audit_init_entry(fcount);
@@ -760,6 +781,13 @@ static struct audit_entry *audit_dupe_ru
 		case AUDIT_SE_CLR:
 			err = audit_dupe_selinux_field(&new->fields[i],
 						       &old->fields[i]);
+			break;
+		case AUDIT_FILTERKEY:
+			fk = kstrdup(old->filterkey, GFP_KERNEL);
+			if (unlikely(!fk))
+				err = -ENOMEM;
+			else
+				new->filterkey = fk;
 		}
 		if (err) {
 			audit_free_rule(entry);
@@ -1245,6 +1273,34 @@ static void audit_list_rules(int pid, in
 		skb_queue_tail(q, skb);
 }
 
+/* Log rule additions and removals */
+static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
+				  struct audit_krule *rule, int res)
+{
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	if (!ab)
+		return;
+	audit_log_format(ab, "auid=%u", loginuid);
+	if (sid) {
+		char *ctx = NULL;
+		u32 len;
+		if (selinux_ctxid_to_string(sid, &ctx, &len))
+			audit_log_format(ab, " ssid=%u", sid);
+		else
+			audit_log_format(ab, " subj=%s", ctx);
+		kfree(ctx);
+	}
+	audit_log_format(ab, " %s rule key=", action);
+	if (rule->filterkey)
+		audit_log_untrustedstring(ab, rule->filterkey);
+	else
+		audit_log_format(ab, "(null)");
+	audit_log_format(ab, " list=%d res=%d", rule->listnr, res);
+	audit_log_end(ab);
+}
+
 /**
  * audit_receive_filter - apply all rules to the specified message type
  * @type: audit message type
@@ -1304,24 +1360,7 @@ int audit_receive_filter(int type, int p
 
 		err = audit_add_rule(entry,
 				     &audit_filter_list[entry->rule.listnr]);
-
-		if (sid) {
-			char *ctx = NULL;
-			u32 len;
-			if (selinux_ctxid_to_string(sid, &ctx, &len)) {
-				/* Maybe call audit_panic? */
-				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				 "auid=%u ssid=%u add rule to list=%d res=%d",
-				 loginuid, sid, entry->rule.listnr, !err);
-			} else
-				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				 "auid=%u subj=%s add rule to list=%d res=%d",
-				 loginuid, ctx, entry->rule.listnr, !err);
-			kfree(ctx);
-		} else
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"auid=%u add rule to list=%d res=%d",
-				loginuid, entry->rule.listnr, !err);
+		audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err);
 
 		if (err)
 			audit_free_rule(entry);
@@ -1337,24 +1376,8 @@ int audit_receive_filter(int type, int p
 
 		err = audit_del_rule(entry,
 				     &audit_filter_list[entry->rule.listnr]);
-
-		if (sid) {
-			char *ctx = NULL;
-			u32 len;
-			if (selinux_ctxid_to_string(sid, &ctx, &len)) {
-				/* Maybe call audit_panic? */
-				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-					"auid=%u ssid=%u remove rule from list=%d res=%d",
-					 loginuid, sid, entry->rule.listnr, !err);
-			} else
-				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-					"auid=%u subj=%s remove rule from list=%d res=%d",
-					 loginuid, ctx, entry->rule.listnr, !err);
-			kfree(ctx);
-		} else
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				"auid=%u remove rule from list=%d res=%d",
-				loginuid, entry->rule.listnr, !err);
+		audit_log_rule_change(loginuid, sid, "remove", &entry->rule,
+				      !err);
 
 		audit_free_rule(entry);
 		break;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 1c43dba..b32ccfa 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -186,6 +186,7 @@ struct audit_context {
 	int		    auditable;  /* 1 if record should be written */
 	int		    name_count;
 	struct audit_names  names[AUDIT_NAMES];
+	char *		    filterkey;	/* key for rule that triggered record */
 	struct dentry *	    pwd;
 	struct vfsmount *   pwdmnt;
 	struct audit_context *previous; /* For nested syscalls */
@@ -348,11 +349,17 @@ static int audit_filter_rules(struct tas
 			if (ctx)
 				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
 			break;
+		case AUDIT_FILTERKEY:
+			/* ignore this field for filtering */
+			result = 1;
+			break;
 		}
 
 		if (!result)
 			return 0;
 	}
+	if (rule->filterkey)
+		ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
 	switch (rule->action) {
 	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
 	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
@@ -627,6 +634,7 @@ static inline void audit_free_context(st
 		}
 		audit_free_names(context);
 		audit_free_aux(context);
+		kfree(context->filterkey);
 		kfree(context);
 		context  = previous;
 	} while (context);
@@ -736,6 +744,11 @@ static void audit_log_exit(struct audit_
 		  context->euid, context->suid, context->fsuid,
 		  context->egid, context->sgid, context->fsgid, tty);
 	audit_log_task_info(ab, tsk);
+	if (context->filterkey) {
+		audit_log_format(ab, " key=");
+		audit_log_untrustedstring(ab, context->filterkey);
+	} else
+		audit_log_format(ab, " key=(null)");
 	audit_log_end(ab);
 
 	for (aux = context->aux; aux; aux = aux->next) {
@@ -1061,6 +1074,8 @@ void audit_syscall_exit(int valid, long 
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
+		kfree(context->filterkey);
+		context->filterkey = NULL;
 		tsk->audit_context = context;
 	}
 }
-- 
1.4.0

                 reply	other threads:[~2006-06-14 22:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060614224521.GA2268@zk3.dec.com \
    --to=amy.griffis@hp.com \
    --cc=linux-audit@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.