All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amy Griffis <amy.griffis@hp.com>
To: linux-audit@redhat.com
Subject: [PATCH 2/2] audit signal recipients (v2)
Date: Fri, 23 Feb 2007 17:51:51 -0500	[thread overview]
Message-ID: <20070223225151.GB993@fc.hp.com> (raw)
In-Reply-To: <20070223225003.GA993@fc.hp.com>

When auditing syscalls that send signals, log the pid and security
context for each target process. Optimize the data collection by
adding a counter for signal-related rules, and avoiding allocating an
aux struct unless we have more than one target process. Move the
audit_signal_info() hook up in check_kill_permission() so we audit
attempts where permission is denied.

Signed-off-by: Amy Griffis <amy.griffis@hp.com>
---
 include/linux/audit.h |    3 ++
 kernel/audit.h        |   12 ++++---
 kernel/auditfilter.c  |   14 ++++++++-
 kernel/auditsc.c      |   76 ++++++++++++++++++++++++++++++++++++++++++++++--
 kernel/signal.c       |   10 ++++--
 5 files changed, 100 insertions(+), 15 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 0194a9b..b1daf3c 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -90,6 +90,7 @@
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
+#define AUDIT_TARGET_PID	1318    /* audit record for a pid arg */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -443,6 +444,7 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
 	return 0;
 }
 extern int audit_n_rules;
+extern int audit_signals;
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -472,6 +474,7 @@ extern int audit_n_rules;
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
 #define audit_n_rules 0
+#define audit_signals 0
 #endif
 
 #ifdef CONFIG_AUDIT
diff --git a/kernel/audit.h b/kernel/audit.h
index a337023..36960f7 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -131,17 +131,19 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
 extern int selinux_audit_rule_update(void);
 
 #ifdef CONFIG_AUDITSYSCALL
-extern void __audit_signal_info(int sig, struct task_struct *t);
-static inline void audit_signal_info(int sig, struct task_struct *t)
+extern int __audit_signal_info(int sig, struct task_struct *t);
+static inline int audit_signal_info(int sig, struct task_struct *t)
 {
-	if (unlikely(audit_pid && t->tgid == audit_pid))
-		__audit_signal_info(sig, t);
+	if (unlikely((audit_pid && t->tgid == audit_pid) ||
+		     (audit_signals && !audit_dummy_context())))
+		return __audit_signal_info(sig, t);
+	return 0;
 }
 extern enum audit_state audit_filter_inodes(struct task_struct *,
 					    struct audit_context *);
 extern void audit_set_auditable(struct audit_context *);
 #else
-#define audit_signal_info(s,t)
+#define audit_signal_info(s,t) AUDIT_DISABLED
 #define audit_filter_inodes(t,c) AUDIT_DISABLED
 #define audit_set_auditable(c)
 #endif
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3749193..b90d121 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1171,7 +1171,7 @@ static inline int audit_add_rule(struct audit_entry *entry,
 	struct nameidata *ndp, *ndw;
 	int h, err, putnd_needed = 0;
 #ifdef CONFIG_AUDITSYSCALL
-	int dont_count = 0;
+	int i, dont_count = 0;
 
 	/* If either of these, don't count towards total */
 	if (entry->rule.listnr == AUDIT_FILTER_USER ||
@@ -1221,6 +1221,11 @@ static inline int audit_add_rule(struct audit_entry *entry,
 #ifdef CONFIG_AUDITSYSCALL
 	if (!dont_count)
 		audit_n_rules++;
+
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+		if ((entry->rule.mask[i] & classes[AUDIT_CLASS_SIGNAL][i]) ||
+		    (entry->rule.mask[i] & classes[AUDIT_CLASS_SIGNAL_32][i]))
+			audit_signals++;
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
@@ -1247,7 +1252,7 @@ static inline int audit_del_rule(struct audit_entry *entry,
 	LIST_HEAD(inotify_list);
 	int h, ret = 0;
 #ifdef CONFIG_AUDITSYSCALL
-	int dont_count = 0;
+	int i, dont_count = 0;
 
 	/* If either of these, don't count towards total */
 	if (entry->rule.listnr == AUDIT_FILTER_USER ||
@@ -1294,6 +1299,11 @@ static inline int audit_del_rule(struct audit_entry *entry,
 #ifdef CONFIG_AUDITSYSCALL
 	if (!dont_count)
 		audit_n_rules--;
+
+	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+		if ((entry->rule.mask[i] & classes[AUDIT_CLASS_SIGNAL][i]) ||
+		    (entry->rule.mask[i] & classes[AUDIT_CLASS_SIGNAL_32][i]))
+			audit_signals--;
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 1b427d9..2da8c2c 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -84,6 +84,9 @@ extern int audit_enabled;
 /* number of audit rules */
 int audit_n_rules;
 
+/* determines whether we collect data for signals sent */
+int audit_signals;
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -176,6 +179,12 @@ struct audit_aux_data_path {
 	struct vfsmount		*mnt;
 };
 
+struct audit_aux_data_pid {
+	struct audit_aux_data	d;
+	pid_t			opid;
+	u32			osid;
+};
+
 /* The per-task audit context. */
 struct audit_context {
 	int		    dummy;	/* must be the first element */
@@ -204,6 +213,10 @@ struct audit_context {
 	unsigned long	    personality;
 	int		    arch;
 
+				/* optimize collection for single target pid */
+	pid_t		    opid;
+	u32		    osid;
+
 #if AUDIT_DEBUG
 	int		    put_count;
 	int		    ino_count;
@@ -860,6 +873,21 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 		audit_log_format(ab, " key=(null)");
 	audit_log_end(ab);
 
+	if (context->opid) {
+	    char *sectx = NULL;
+	    u32 len;
+
+	    ab = audit_log_start(context, GFP_KERNEL, AUDIT_TARGET_PID);
+	    audit_log_format(ab, "opid=%d ", context->opid);
+	    if (selinux_sid_to_string(context->osid, &sectx, &len)) {
+		    audit_log_format(ab, "osid=%u", context->osid);
+		    call_panic = 2;
+	    } else
+		    audit_log_format(ab, " obj=%s", sectx);
+	    kfree(sectx);
+	    audit_log_end(ab);
+	}
+
 	for (aux = context->aux; aux; aux = aux->next) {
 
 		ab = audit_log_start(context, GFP_KERNEL, aux->type);
@@ -867,6 +895,20 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 			continue; /* audit_panic has been called */
 
 		switch (aux->type) {
+		case AUDIT_TARGET_PID: {
+			struct audit_aux_data_pid *axi = (void *)aux;
+			char *sectx = NULL;
+			u32 len;
+
+			audit_log_format(ab, "opid=%d ", axi->opid);
+			if (selinux_sid_to_string(axi->osid, &sectx, &len)) {
+				audit_log_format(ab, "osid=%u", axi->osid);
+				call_panic = 2;
+			} else
+				audit_log_format(ab, " obj=%s", sectx);
+			kfree(sectx);
+			break; }
+
 		case AUDIT_MQ_OPEN: {
 			struct audit_aux_data_mq_open *axi = (void *)aux;
 			audit_log_format(ab,
@@ -1916,15 +1958,17 @@ int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
  * If the audit subsystem is being terminated, record the task (pid)
  * and uid that is doing that.
  */
-void __audit_signal_info(int sig, struct task_struct *t)
+int __audit_signal_info(int sig, struct task_struct *t)
 {
+	struct audit_aux_data_pid *ax;
+	struct task_struct *tsk = current;
+	struct audit_context *ctx = tsk->audit_context;
 	extern pid_t audit_sig_pid;
 	extern uid_t audit_sig_uid;
 	extern u32 audit_sig_sid;
 
-	if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
-		struct task_struct *tsk = current;
-		struct audit_context *ctx = tsk->audit_context;
+	if (audit_pid && t->tgid == audit_pid &&
+	    (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) {
 		audit_sig_pid = tsk->pid;
 		if (ctx)
 			audit_sig_uid = ctx->loginuid;
@@ -1932,4 +1976,28 @@ void __audit_signal_info(int sig, struct task_struct *t)
 			audit_sig_uid = tsk->uid;
 		selinux_get_task_sid(tsk, &audit_sig_sid);
 	}
+
+	if (!audit_signals) /* audit_context checked in wrapper */
+		return 0;
+
+	/* optimize the common case by putting first signal recipient directly
+	 * in audit_context */
+	if (!ctx->opid) {
+		ctx->opid = t->tgid;
+		selinux_get_task_sid(t, &ctx->osid);
+		return 0;
+	}
+
+	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+	if (!ax) {
+		return -ENOMEM;
+	}
+
+	ax->opid = t->tgid;
+	selinux_get_task_sid(t, &ax->osid);
+
+	ax->d.type = AUDIT_TARGET_PID;
+	ax->d.next = ctx->aux;
+	ctx->aux = (void *)ax;
+	return 0;
 }
diff --git a/kernel/signal.c b/kernel/signal.c
index e2a7d4b..10c183a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -607,6 +607,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
 	int error = -EINVAL;
 	if (!valid_signal(sig))
 		return error;
+
+	error = audit_signal_info(sig, t); /* Let audit system see the signal */
+	if (error)
+		return error;
+
 	error = -EPERM;
 	if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
 	    && ((sig != SIGCONT) ||
@@ -616,10 +621,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
 	    && !capable(CAP_KILL))
 		return error;
 
-	error = security_task_kill(t, info, sig, 0);
-	if (!error)
-		audit_signal_info(sig, t); /* Let audit system see the signal */
-	return error;
+	return security_task_kill(t, info, sig, 0);
 }
 
 /* forward decl */
-- 
1.4.4.4

  reply	other threads:[~2007-02-23 22:55 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-23 22:50 [PATCH 1/2] add SIGNAL syscall class (v2) Amy Griffis
2007-02-23 22:51 ` Amy Griffis [this message]
2007-02-27 20:41   ` [PATCH 2/2] audit signal recipients (v2) Eric Paris

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=20070223225151.GB993@fc.hp.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.