Skip to contentSkip to conversation

add SIGNAL syscall class

PATCH In review Amy Griffis 2 participants 6 messages Feb 14, 2007

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 add SIGNAL syscall class

Add a syscall class for sending signals.

---
 arch/ia64/ia32/audit.c             |    5 +++++
 arch/ia64/kernel/audit.c           |    8 ++++++++
 arch/powerpc/kernel/audit.c        |    8 ++++++++
 arch/s390/kernel/audit.c           |    8 ++++++++
 arch/sparc64/kernel/audit.c        |    8 ++++++++
 arch/x86_64/ia32/audit.c           |    5 +++++
 arch/x86_64/kernel/audit.c         |    8 ++++++++
 include/asm-generic/audit_signal.h |    3 +++
 include/linux/audit.h              |    2 ++
 lib/audit.c                        |    6 ++++++
 10 files changed, 61 insertions(+), 0 deletions(-)
arch/ia64/ia32/audit.c +5 -0
index 92d7d0c..8850fe4 100644
@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = {
 ~0U
 };
 
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int ia32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
arch/ia64/kernel/audit.c +8 -0
index 0468255..538312a 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_IA32_SUPPORT
@@ -49,15 +54,18 @@ static int __init audit_classes_init(void)
 	extern __u32 ia32_write_class[];
 	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	extern __u32 ia32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
arch/powerpc/kernel/audit.c +8 -0
index 7fe5e63..66d54ba 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_PPC64
@@ -51,15 +56,18 @@ static int __init audit_classes_init(void)
 	extern __u32 ppc32_write_class[];
 	extern __u32 ppc32_read_class[];
 	extern __u32 ppc32_chattr_class[];
+	extern __u32 ppc32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
arch/s390/kernel/audit.c +8 -0
index 0741d91..7affafe 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_COMPAT
@@ -51,15 +56,18 @@ static int __init audit_classes_init(void)
 	extern __u32 s390_write_class[];
 	extern __u32 s390_read_class[];
 	extern __u32 s390_chattr_class[];
+	extern __u32 s390_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, s390_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
arch/sparc64/kernel/audit.c +8 -0
index aef19cc..d57a9da 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_SPARC32_COMPAT
@@ -51,15 +56,18 @@ static int __init audit_classes_init(void)
 	extern __u32 sparc32_write_class[];
 	extern __u32 sparc32_read_class[];
 	extern __u32 sparc32_chattr_class[];
+	extern __u32 sparc32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, sparc32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
arch/x86_64/ia32/audit.c +5 -0
index 92d7d0c..8850fe4 100644
@@ -20,6 +20,11 @@ unsigned ia32_read_class[] = {
 ~0U
 };
 
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int ia32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
arch/x86_64/kernel/audit.c +8 -0
index 21f3338..b970de6 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_IA32_EMULATION
@@ -49,15 +54,18 @@ static int __init audit_classes_init(void)
 	extern __u32 ia32_write_class[];
 	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	extern __u32 ia32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
include/asm-generic/audit_signal.h new file +3 -0
new file mode 100644
index 0000000..6feab7f
@@ -0,0 +1,3 @@
+__NR_kill,
+__NR_tgkill,
+__NR_tkill,
include/linux/audit.h +2 -0
index aa205cd..0194a9b 100644
@@ -147,6 +147,8 @@
 #define AUDIT_CLASS_READ_32 5
 #define AUDIT_CLASS_WRITE 6
 #define AUDIT_CLASS_WRITE_32 7
+#define AUDIT_CLASS_SIGNAL 8
+#define AUDIT_CLASS_SIGNAL_32 9
 
 /* This bitmask is used to validate user input.  It represents all bits that
  * are currently used in an audit field constant understood by the kernel.
lib/audit.c +6 -0
index 3b1289f..50e9152 100644
@@ -23,6 +23,11 @@ static unsigned chattr_class[] = {
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 	switch(syscall) {
@@ -49,6 +54,7 @@ static int __init audit_classes_init(void)
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
Signature · 1 line
1.4.4.4
#1 lore raw

PATCH 2/2 audit signal recipients

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.

---
 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(-)
include/linux/audit.h +3 -0
index 0194a9b..b1daf3c 100644
@@ -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
kernel/audit.h +7 -5
index a337023..36960f7 100644
@@ -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
kernel/auditfilter.c +12 -2
index 3749193..b90d121 100644
@@ -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);
 
kernel/auditsc.c +72 -4

121 lines not on this page · raw message

kernel/signal.c +6 -4
index 8072e56..1a4f602 100644
@@ -583,6 +583,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) ||
@@ -592,10 +597,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 */
Signature · 1 line
1.4.4.4
#2 lore raw
In reply to Amy Griffis
Quoted 1 line · On Wednesday 14 February 2007 13:24:31 Amy Griffis wrote:

Add a syscall class for sending signals.

The intent of the syscall classes had been to make an update independent way of being able to specify audit rules for filesystem auditing where new syscalls could be added. I don't know if this grouping would be useful in practice. <shrug>

What I have been thinking about is a grouping for delete and close. That would align with requirements on security standards people have to meet.

-Steve

#3 lore raw

Steve Grubb wrote: [Wed Feb 14 2007, 02:04:07PM EST]

Quoted 6 lines · On Wednesday 14 February 2007 13:24:31 Amy Griffis wrote:
Quoted 1 line

Add a syscall class for sending signals.

The intent of the syscall classes had been to make an update independent way of being able to specify audit rules for filesystem auditing where new syscalls could be added.

Yeah, I know I used it in a different way from the original purpose. But I think this is still a valid use... When we are adding or removing a rule, we need a way to determine if the rule specified one of the syscalls for sending signals.

Quoted 1 line

I don't know if this grouping would be useful in practice. <shrug>

Yeah I wasn't sure either, so I didn't add the filtering part.

Quoted 3 lines

What I have been thinking about is a grouping for delete and close. That would align with requirements on security standards people have to meet.

Makes sense. Do you think we're in danger of running out of slots for syscall classes?

Amy

#4 lore raw
Quoted 10 lines · On Wednesday 14 February 2007 15:12:05 Amy Griffis wrote:

Steve Grubb wrote: [Wed Feb 14 2007, 02:04:07PM EST]

Quoted 6 lines · On Wednesday 14 February 2007 13:24:31 Amy Griffis wrote:
Quoted 1 line

Add a syscall class for sending signals.

The intent of the syscall classes had been to make an update independent way of being able to specify audit rules for filesystem auditing where new syscalls could be added.

Yeah, I know I used it in a different way from the original purpose.

So, how does this work from a user perspective? Do you need to patch auditctl?

Quoted 3 lines

But I think this is still a valid use... When we are adding or removing a rule, we need a way to determine if the rule specified one of the syscalls for sending signals.

Could you show a sample use? (Just so I understand what its doing.)

Quoted 2 lines

Makes sense. Do you think we're in danger of running out of slots for syscall classes?

I think we should be fairly conservative. I hadn't quite got to the point of saying we needed close and delete since I am still thinking about the requirements.

Thanks,
-Steve

#5 lore raw

Steve Grubb wrote: [Wed Feb 14 2007, 03:32:02PM EST]

Quoted 10 lines · On Wednesday 14 February 2007 15:12:05 Amy Griffis wrote:
Quoted 9 lines

Steve Grubb wrote: [Wed Feb 14 2007, 02:04:07PM EST]

Quoted 6 lines · On Wednesday 14 February 2007 13:24:31 Amy Griffis wrote:
Quoted 1 line

Add a syscall class for sending signals.

The intent of the syscall classes had been to make an update independent way of being able to specify audit rules for filesystem auditing where new syscalls could be added.

Quoted 5 lines
Quoted 2 lines

Yeah, I know I used it in a different way from the original purpose.

So, how does this work from a user perspective? Do you need to patch auditctl?

For now, only the kernel is using the signal syscall class. You wouldn't need to do anything in userspace.

For the other signal audit patch, you would only need to add an entry for AUDIT_TARGET_PID in msg_typetab.h so the new record type is not logged as UNKNOWN.

This reminds me, do we want/need to be able to filter on target pid?

Quoted 5 lines
Quoted 3 lines

But I think this is still a valid use... When we are adding or removing a rule, we need a way to determine if the rule specified one of the syscalls for sending signals.

Could you show a sample use? (Just so I understand what its doing.)

It works like the audit_n_rules counter. When you add a rule specifying kill, tkill or tgkill the counter goes up. When you remove one of them, the counter goes down. If the counter is 0 when we hit the audit_signal_info hook, we don't collect the info about the target pid(s). That way we don't add unnecessary overhead to the call path.

The signal class exists so we can see if the rule being added/removed contains any of those particular syscalls.

Amy