aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/audit.c28
-rw-r--r--arch/ia64/ia32/audit.c26
-rw-r--r--arch/ia64/kernel/audit.c35
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/audit.c66
-rw-r--r--arch/powerpc/kernel/compat_audit.c38
-rw-r--r--arch/s390/kernel/Makefile4
-rw-r--r--arch/s390/kernel/audit.c66
-rw-r--r--arch/s390/kernel/compat_audit.c38
-rw-r--r--arch/x86_64/ia32/audit.c26
-rw-r--r--arch/x86_64/kernel/audit.c35
-rw-r--r--include/asm-generic/audit_read.h8
-rw-r--r--include/asm-generic/audit_write.h11
-rw-r--r--include/linux/audit.h11
-rw-r--r--kernel/audit.c6
-rw-r--r--kernel/audit.h1
-rw-r--r--kernel/auditfilter.c37
-rw-r--r--kernel/auditsc.c51
18 files changed, 483 insertions, 6 deletions
diff --git a/arch/i386/kernel/audit.c b/arch/i386/kernel/audit.c
index 5a53c6f371ff..3b97cff41549 100644
--- a/arch/i386/kernel/audit.c
+++ b/arch/i386/kernel/audit.c
@@ -8,13 +8,41 @@ static unsigned dir_class[] = {
8~0U 8~0U
9}; 9};
10 10
11static unsigned read_class[] = {
12#include <asm-generic/audit_read.h>
13~0U
14};
15
16static unsigned write_class[] = {
17#include <asm-generic/audit_write.h>
18~0U
19};
20
11static unsigned chattr_class[] = { 21static unsigned chattr_class[] = {
12#include <asm-generic/audit_change_attr.h> 22#include <asm-generic/audit_change_attr.h>
13~0U 23~0U
14}; 24};
15 25
26int audit_classify_syscall(int abi, unsigned syscall)
27{
28 switch(syscall) {
29 case __NR_open:
30 return 2;
31 case __NR_openat:
32 return 3;
33 case __NR_socketcall:
34 return 4;
35 case __NR_execve:
36 return 5;
37 default:
38 return 0;
39 }
40}
41
16static int __init audit_classes_init(void) 42static int __init audit_classes_init(void)
17{ 43{
44 audit_register_class(AUDIT_CLASS_WRITE, write_class);
45 audit_register_class(AUDIT_CLASS_READ, read_class);
18 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 46 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
19 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 47 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
20 return 0; 48 return 0;
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
index ab94f2e58cdd..92d7d0c8d93f 100644
--- a/arch/ia64/ia32/audit.c
+++ b/arch/ia64/ia32/audit.c
@@ -9,3 +9,29 @@ unsigned ia32_chattr_class[] = {
9#include <asm-generic/audit_change_attr.h> 9#include <asm-generic/audit_change_attr.h>
10~0U 10~0U
11}; 11};
12
13unsigned ia32_write_class[] = {
14#include <asm-generic/audit_write.h>
15~0U
16};
17
18unsigned ia32_read_class[] = {
19#include <asm-generic/audit_read.h>
20~0U
21};
22
23int ia32_classify_syscall(unsigned syscall)
24{
25 switch(syscall) {
26 case __NR_open:
27 return 2;
28 case __NR_openat:
29 return 3;
30 case __NR_socketcall:
31 return 4;
32 case __NR_execve:
33 return 5;
34 default:
35 return 1;
36 }
37}
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
index f2512931ccaf..04682555a28c 100644
--- a/arch/ia64/kernel/audit.c
+++ b/arch/ia64/kernel/audit.c
@@ -8,19 +8,54 @@ static unsigned dir_class[] = {
8~0U 8~0U
9}; 9};
10 10
11static unsigned read_class[] = {
12#include <asm-generic/audit_read.h>
13~0U
14};
15
16static unsigned write_class[] = {
17#include <asm-generic/audit_write.h>
18~0U
19};
20
11static unsigned chattr_class[] = { 21static unsigned chattr_class[] = {
12#include <asm-generic/audit_change_attr.h> 22#include <asm-generic/audit_change_attr.h>
13~0U 23~0U
14}; 24};
15 25
26int audit_classify_syscall(int abi, unsigned syscall)
27{
28#ifdef CONFIG_IA32_SUPPORT
29 extern int ia32_classify_syscall(unsigned);
30 if (abi == AUDIT_ARCH_I386)
31 return ia32_classify_syscall(syscall);
32#endif
33 switch(syscall) {
34 case __NR_open:
35 return 2;
36 case __NR_openat:
37 return 3;
38 case __NR_execve:
39 return 5;
40 default:
41 return 0;
42 }
43}
44
16static int __init audit_classes_init(void) 45static int __init audit_classes_init(void)
17{ 46{
18#ifdef CONFIG_IA32_SUPPORT 47#ifdef CONFIG_IA32_SUPPORT
19 extern __u32 ia32_dir_class[]; 48 extern __u32 ia32_dir_class[];
49 extern __u32 ia32_write_class[];
50 extern __u32 ia32_read_class[];
20 extern __u32 ia32_chattr_class[]; 51 extern __u32 ia32_chattr_class[];
52 audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
53 audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
21 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); 54 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
22 audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); 55 audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
23#endif 56#endif
57 audit_register_class(AUDIT_CLASS_WRITE, write_class);
58 audit_register_class(AUDIT_CLASS_READ, read_class);
24 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 59 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
25 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 60 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
26 return 0; 61 return 0;
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 956c2e5564b7..7d32ad0194a4 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -70,6 +70,8 @@ obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
70kexec-$(CONFIG_PPC64) := machine_kexec_64.o 70kexec-$(CONFIG_PPC64) := machine_kexec_64.o
71kexec-$(CONFIG_PPC32) := machine_kexec_32.o 71kexec-$(CONFIG_PPC32) := machine_kexec_32.o
72obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y) 72obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o $(kexec-y)
73obj-$(CONFIG_AUDIT) += audit.o
74obj64-$(CONFIG_AUDIT) += compat_audit.o
73 75
74ifeq ($(CONFIG_PPC_ISERIES),y) 76ifeq ($(CONFIG_PPC_ISERIES),y)
75$(obj)/head_64.o: $(obj)/lparmap.s 77$(obj)/head_64.o: $(obj)/lparmap.s
diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c
new file mode 100644
index 000000000000..7fe5e6300e9a
--- /dev/null
+++ b/arch/powerpc/kernel/audit.c
@@ -0,0 +1,66 @@
1#include <linux/init.h>
2#include <linux/types.h>
3#include <linux/audit.h>
4#include <asm/unistd.h>
5
6static unsigned dir_class[] = {
7#include <asm-generic/audit_dir_write.h>
8~0U
9};
10
11static unsigned read_class[] = {
12#include <asm-generic/audit_read.h>
13~0U
14};
15
16static unsigned write_class[] = {
17#include <asm-generic/audit_write.h>
18~0U
19};
20
21static unsigned chattr_class[] = {
22#include <asm-generic/audit_change_attr.h>
23~0U
24};
25
26int audit_classify_syscall(int abi, unsigned syscall)
27{
28#ifdef CONFIG_PPC64
29 extern int ppc32_classify_syscall(unsigned);
30 if (abi == AUDIT_ARCH_PPC)
31 return ppc32_classify_syscall(syscall);
32#endif
33 switch(syscall) {
34 case __NR_open:
35 return 2;
36 case __NR_openat:
37 return 3;
38 case __NR_socketcall:
39 return 4;
40 case __NR_execve:
41 return 5;
42 default:
43 return 0;
44 }
45}
46
47static int __init audit_classes_init(void)
48{
49#ifdef CONFIG_PPC64
50 extern __u32 ppc32_dir_class[];
51 extern __u32 ppc32_write_class[];
52 extern __u32 ppc32_read_class[];
53 extern __u32 ppc32_chattr_class[];
54 audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
55 audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
56 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
57 audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
58#endif
59 audit_register_class(AUDIT_CLASS_WRITE, write_class);
60 audit_register_class(AUDIT_CLASS_READ, read_class);
61 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
62 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
63 return 0;
64}
65
66__initcall(audit_classes_init);
diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c
new file mode 100644
index 000000000000..640d4bb29321
--- /dev/null
+++ b/arch/powerpc/kernel/compat_audit.c
@@ -0,0 +1,38 @@
1#undef __powerpc64__
2#include <asm/unistd.h>
3
4unsigned ppc32_dir_class[] = {
5#include <asm-generic/audit_dir_write.h>
6~0U
7};
8
9unsigned ppc32_chattr_class[] = {
10#include <asm-generic/audit_change_attr.h>
11~0U
12};
13
14unsigned ppc32_write_class[] = {
15#include <asm-generic/audit_write.h>
16~0U
17};
18
19unsigned ppc32_read_class[] = {
20#include <asm-generic/audit_read.h>
21~0U
22};
23
24int ppc32_classify_syscall(unsigned syscall)
25{
26 switch(syscall) {
27 case __NR_open:
28 return 2;
29 case __NR_openat:
30 return 3;
31 case __NR_socketcall:
32 return 4;
33 case __NR_execve:
34 return 5;
35 default:
36 return 1;
37 }
38}
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 86601a945709..9a33ed6ca696 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -16,9 +16,11 @@ extra-y += head.o init_task.o vmlinux.lds
16obj-$(CONFIG_MODULES) += s390_ksyms.o module.o 16obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
17obj-$(CONFIG_SMP) += smp.o 17obj-$(CONFIG_SMP) += smp.o
18 18
19obj-$(CONFIG_AUDIT) += audit.o
20compat-obj-$(CONFIG_AUDIT) += compat_audit.o
19obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ 21obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \
20 compat_wrapper.o compat_exec_domain.o \ 22 compat_wrapper.o compat_exec_domain.o \
21 binfmt_elf32.o 23 binfmt_elf32.o $(compat-obj-y)
22 24
23obj-$(CONFIG_VIRT_TIMER) += vtime.o 25obj-$(CONFIG_VIRT_TIMER) += vtime.o
24obj-$(CONFIG_STACKTRACE) += stacktrace.o 26obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
new file mode 100644
index 000000000000..0741d9193390
--- /dev/null
+++ b/arch/s390/kernel/audit.c
@@ -0,0 +1,66 @@
1#include <linux/init.h>
2#include <linux/types.h>
3#include <linux/audit.h>
4#include <asm/unistd.h>
5
6static unsigned dir_class[] = {
7#include <asm-generic/audit_dir_write.h>
8~0U
9};
10
11static unsigned read_class[] = {
12#include <asm-generic/audit_read.h>
13~0U
14};
15
16static unsigned write_class[] = {
17#include <asm-generic/audit_write.h>
18~0U
19};
20
21static unsigned chattr_class[] = {
22#include <asm-generic/audit_change_attr.h>
23~0U
24};
25
26int audit_classify_syscall(int abi, unsigned syscall)
27{
28#ifdef CONFIG_COMPAT
29 extern int s390_classify_syscall(unsigned);
30 if (abi == AUDIT_ARCH_S390)
31 return s390_classify_syscall(syscall);
32#endif
33 switch(syscall) {
34 case __NR_open:
35 return 2;
36 case __NR_openat:
37 return 3;
38 case __NR_socketcall:
39 return 4;
40 case __NR_execve:
41 return 5;
42 default:
43 return 0;
44 }
45}
46
47static int __init audit_classes_init(void)
48{
49#ifdef CONFIG_COMPAT
50 extern __u32 s390_dir_class[];
51 extern __u32 s390_write_class[];
52 extern __u32 s390_read_class[];
53 extern __u32 s390_chattr_class[];
54 audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
55 audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
56 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
57 audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
58#endif
59 audit_register_class(AUDIT_CLASS_WRITE, write_class);
60 audit_register_class(AUDIT_CLASS_READ, read_class);
61 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
62 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
63 return 0;
64}
65
66__initcall(audit_classes_init);
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
new file mode 100644
index 000000000000..16d9436bfa91
--- /dev/null
+++ b/arch/s390/kernel/compat_audit.c
@@ -0,0 +1,38 @@
1#undef __s390x__
2#include <asm/unistd.h>
3
4unsigned s390_dir_class[] = {
5#include <asm-generic/audit_dir_write.h>
6~0U
7};
8
9unsigned s390_chattr_class[] = {
10#include <asm-generic/audit_change_attr.h>
11~0U
12};
13
14unsigned s390_write_class[] = {
15#include <asm-generic/audit_write.h>
16~0U
17};
18
19unsigned s390_read_class[] = {
20#include <asm-generic/audit_read.h>
21~0U
22};
23
24int s390_classify_syscall(unsigned syscall)
25{
26 switch(syscall) {
27 case __NR_open:
28 return 2;
29 case __NR_openat:
30 return 3;
31 case __NR_socketcall:
32 return 4;
33 case __NR_execve:
34 return 5;
35 default:
36 return 1;
37 }
38}
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
index ab94f2e58cdd..92d7d0c8d93f 100644
--- a/arch/x86_64/ia32/audit.c
+++ b/arch/x86_64/ia32/audit.c
@@ -9,3 +9,29 @@ unsigned ia32_chattr_class[] = {
9#include <asm-generic/audit_change_attr.h> 9#include <asm-generic/audit_change_attr.h>
10~0U 10~0U
11}; 11};
12
13unsigned ia32_write_class[] = {
14#include <asm-generic/audit_write.h>
15~0U
16};
17
18unsigned ia32_read_class[] = {
19#include <asm-generic/audit_read.h>
20~0U
21};
22
23int ia32_classify_syscall(unsigned syscall)
24{
25 switch(syscall) {
26 case __NR_open:
27 return 2;
28 case __NR_openat:
29 return 3;
30 case __NR_socketcall:
31 return 4;
32 case __NR_execve:
33 return 5;
34 default:
35 return 1;
36 }
37}
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
index a067aa468a85..21f33387bef3 100644
--- a/arch/x86_64/kernel/audit.c
+++ b/arch/x86_64/kernel/audit.c
@@ -8,19 +8,54 @@ static unsigned dir_class[] = {
8~0U 8~0U
9}; 9};
10 10
11static unsigned read_class[] = {
12#include <asm-generic/audit_read.h>
13~0U
14};
15
16static unsigned write_class[] = {
17#include <asm-generic/audit_write.h>
18~0U
19};
20
11static unsigned chattr_class[] = { 21static unsigned chattr_class[] = {
12#include <asm-generic/audit_change_attr.h> 22#include <asm-generic/audit_change_attr.h>
13~0U 23~0U
14}; 24};
15 25
26int audit_classify_syscall(int abi, unsigned syscall)
27{
28#ifdef CONFIG_IA32_EMULATION
29 extern int ia32_classify_syscall(unsigned);
30 if (abi == AUDIT_ARCH_I386)
31 return ia32_classify_syscall(syscall);
32#endif
33 switch(syscall) {
34 case __NR_open:
35 return 2;
36 case __NR_openat:
37 return 3;
38 case __NR_execve:
39 return 5;
40 default:
41 return 0;
42 }
43}
44
16static int __init audit_classes_init(void) 45static int __init audit_classes_init(void)
17{ 46{
18#ifdef CONFIG_IA32_EMULATION 47#ifdef CONFIG_IA32_EMULATION
19 extern __u32 ia32_dir_class[]; 48 extern __u32 ia32_dir_class[];
49 extern __u32 ia32_write_class[];
50 extern __u32 ia32_read_class[];
20 extern __u32 ia32_chattr_class[]; 51 extern __u32 ia32_chattr_class[];
52 audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
53 audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
21 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); 54 audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
22 audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); 55 audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
23#endif 56#endif
57 audit_register_class(AUDIT_CLASS_WRITE, write_class);
58 audit_register_class(AUDIT_CLASS_READ, read_class);
24 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); 59 audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
25 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); 60 audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
26 return 0; 61 return 0;
diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h
new file mode 100644
index 000000000000..0e87464d9847
--- /dev/null
+++ b/include/asm-generic/audit_read.h
@@ -0,0 +1,8 @@
1__NR_readlink,
2__NR_quotactl,
3__NR_listxattr,
4__NR_llistxattr,
5__NR_flistxattr,
6__NR_getxattr,
7__NR_lgetxattr,
8__NR_fgetxattr,
diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h
new file mode 100644
index 000000000000..f10d367fb2a5
--- /dev/null
+++ b/include/asm-generic/audit_write.h
@@ -0,0 +1,11 @@
1#include <asm-generic/audit_dir_write.h>
2__NR_acct,
3__NR_swapon,
4__NR_quotactl,
5__NR_truncate,
6#ifdef __NR_truncate64
7__NR_truncate64,
8#endif
9#ifdef __NR_bind
10__NR_bind, /* bind can affect fs object only in one way... */
11#endif
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 64f9f9e56ac5..40a6c26294ae 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -132,6 +132,10 @@
132#define AUDIT_CLASS_DIR_WRITE_32 1 132#define AUDIT_CLASS_DIR_WRITE_32 1
133#define AUDIT_CLASS_CHATTR 2 133#define AUDIT_CLASS_CHATTR 2
134#define AUDIT_CLASS_CHATTR_32 3 134#define AUDIT_CLASS_CHATTR_32 3
135#define AUDIT_CLASS_READ 4
136#define AUDIT_CLASS_READ_32 5
137#define AUDIT_CLASS_WRITE 6
138#define AUDIT_CLASS_WRITE_32 7
135 139
136/* This bitmask is used to validate user input. It represents all bits that 140/* This bitmask is used to validate user input. It represents all bits that
137 * are currently used in an audit field constant understood by the kernel. 141 * are currently used in an audit field constant understood by the kernel.
@@ -177,6 +181,7 @@
177#define AUDIT_EXIT 103 181#define AUDIT_EXIT 103
178#define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */ 182#define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */
179#define AUDIT_WATCH 105 183#define AUDIT_WATCH 105
184#define AUDIT_PERM 106
180 185
181#define AUDIT_ARG0 200 186#define AUDIT_ARG0 200
182#define AUDIT_ARG1 (AUDIT_ARG0+1) 187#define AUDIT_ARG1 (AUDIT_ARG0+1)
@@ -252,6 +257,11 @@
252#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE) 257#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)
253#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) 258#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
254 259
260#define AUDIT_PERM_EXEC 1
261#define AUDIT_PERM_WRITE 2
262#define AUDIT_PERM_READ 4
263#define AUDIT_PERM_ATTR 8
264
255struct audit_status { 265struct audit_status {
256 __u32 mask; /* Bit mask for valid entries */ 266 __u32 mask; /* Bit mask for valid entries */
257 __u32 enabled; /* 1 = enabled, 0 = disabled */ 267 __u32 enabled; /* 1 = enabled, 0 = disabled */
@@ -314,6 +324,7 @@ struct mqstat;
314#define AUDITSC_FAILURE 2 324#define AUDITSC_FAILURE 2
315#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) 325#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
316extern int __init audit_register_class(int class, unsigned *list); 326extern int __init audit_register_class(int class, unsigned *list);
327extern int audit_classify_syscall(int abi, unsigned syscall);
317#ifdef CONFIG_AUDITSYSCALL 328#ifdef CONFIG_AUDITSYSCALL
318/* These are defined in auditsc.c */ 329/* These are defined in auditsc.c */
319 /* Public API */ 330 /* Public API */
diff --git a/kernel/audit.c b/kernel/audit.c
index 0a36091ed712..963fd15c9621 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1028,6 +1028,9 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
1028 struct sk_buff *skb; 1028 struct sk_buff *skb;
1029 static const unsigned char *hex = "0123456789ABCDEF"; 1029 static const unsigned char *hex = "0123456789ABCDEF";
1030 1030
1031 if (!ab)
1032 return;
1033
1031 BUG_ON(!ab->skb); 1034 BUG_ON(!ab->skb);
1032 skb = ab->skb; 1035 skb = ab->skb;
1033 avail = skb_tailroom(skb); 1036 avail = skb_tailroom(skb);
@@ -1060,6 +1063,9 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
1060 unsigned char *ptr; 1063 unsigned char *ptr;
1061 struct sk_buff *skb; 1064 struct sk_buff *skb;
1062 1065
1066 if (!ab)
1067 return;
1068
1063 BUG_ON(!ab->skb); 1069 BUG_ON(!ab->skb);
1064 skb = ab->skb; 1070 skb = ab->skb;
1065 avail = skb_tailroom(skb); 1071 avail = skb_tailroom(skb);
diff --git a/kernel/audit.h b/kernel/audit.h
index 6aa33b848cf2..a3370232a390 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -104,6 +104,7 @@ static inline int audit_hash_ino(u32 ino)
104 return (ino & (AUDIT_INODE_BUCKETS-1)); 104 return (ino & (AUDIT_INODE_BUCKETS-1));
105} 105}
106 106
107extern int audit_match_class(int class, unsigned syscall);
107extern int audit_comparator(const u32 left, const u32 op, const u32 right); 108extern int audit_comparator(const u32 left, const u32 op, const u32 right);
108extern int audit_compare_dname_path(const char *dname, const char *path, 109extern int audit_compare_dname_path(const char *dname, const char *path,
109 int *dirlen); 110 int *dirlen);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 6a9a5c5a4e7d..a44879b0c72f 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -302,6 +302,15 @@ int __init audit_register_class(int class, unsigned *list)
302 return 0; 302 return 0;
303} 303}
304 304
305int audit_match_class(int class, unsigned syscall)
306{
307 if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32)))
308 return 0;
309 if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class]))
310 return 0;
311 return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
312}
313
305/* Common user-space to kernel rule translation. */ 314/* Common user-space to kernel rule translation. */
306static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) 315static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
307{ 316{
@@ -404,6 +413,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
404 case AUDIT_PERS: 413 case AUDIT_PERS:
405 case AUDIT_ARCH: 414 case AUDIT_ARCH:
406 case AUDIT_MSGTYPE: 415 case AUDIT_MSGTYPE:
416 case AUDIT_PPID:
407 case AUDIT_DEVMAJOR: 417 case AUDIT_DEVMAJOR:
408 case AUDIT_DEVMINOR: 418 case AUDIT_DEVMINOR:
409 case AUDIT_EXIT: 419 case AUDIT_EXIT:
@@ -413,6 +423,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
413 case AUDIT_ARG2: 423 case AUDIT_ARG2:
414 case AUDIT_ARG3: 424 case AUDIT_ARG3:
415 break; 425 break;
426 case AUDIT_PERM:
427 if (f->val & ~15)
428 goto exit_free;
429 break;
416 case AUDIT_INODE: 430 case AUDIT_INODE:
417 err = audit_to_inode(&entry->rule, f); 431 err = audit_to_inode(&entry->rule, f);
418 if (err) 432 if (err)
@@ -567,6 +581,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
567 entry->rule.buflen += f->val; 581 entry->rule.buflen += f->val;
568 entry->rule.filterkey = str; 582 entry->rule.filterkey = str;
569 break; 583 break;
584 case AUDIT_PERM:
585 if (f->val & ~15)
586 goto exit_free;
587 break;
570 default: 588 default:
571 goto exit_free; 589 goto exit_free;
572 } 590 }
@@ -913,7 +931,7 @@ static void audit_update_watch(struct audit_parent *parent,
913 } 931 }
914 932
915 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 933 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
916 audit_log_format(ab, "audit updated rules specifying watch="); 934 audit_log_format(ab, "audit updated rules specifying path=");
917 audit_log_untrustedstring(ab, owatch->path); 935 audit_log_untrustedstring(ab, owatch->path);
918 audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); 936 audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
919 audit_log_end(ab); 937 audit_log_end(ab);
@@ -936,19 +954,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
936 struct audit_watch *w, *nextw; 954 struct audit_watch *w, *nextw;
937 struct audit_krule *r, *nextr; 955 struct audit_krule *r, *nextr;
938 struct audit_entry *e; 956 struct audit_entry *e;
957 struct audit_buffer *ab;
939 958
940 mutex_lock(&audit_filter_mutex); 959 mutex_lock(&audit_filter_mutex);
941 parent->flags |= AUDIT_PARENT_INVALID; 960 parent->flags |= AUDIT_PARENT_INVALID;
942 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { 961 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
943 list_for_each_entry_safe(r, nextr, &w->rules, rlist) { 962 list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
944 e = container_of(r, struct audit_entry, rule); 963 e = container_of(r, struct audit_entry, rule);
964
965 ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
966 audit_log_format(ab, "audit implicitly removed rule path=");
967 audit_log_untrustedstring(ab, w->path);
968 if (r->filterkey) {
969 audit_log_format(ab, " key=");
970 audit_log_untrustedstring(ab, r->filterkey);
971 } else
972 audit_log_format(ab, " key=(null)");
973 audit_log_format(ab, " list=%d", r->listnr);
974 audit_log_end(ab);
975
945 list_del(&r->rlist); 976 list_del(&r->rlist);
946 list_del_rcu(&e->list); 977 list_del_rcu(&e->list);
947 call_rcu(&e->rcu, audit_free_rule_rcu); 978 call_rcu(&e->rcu, audit_free_rule_rcu);
948
949 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
950 "audit implicitly removed rule from list=%d\n",
951 AUDIT_FILTER_EXIT);
952 } 979 }
953 audit_remove_watch(w); 980 audit_remove_watch(w);
954 } 981 }
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index efc1b74bebf3..1bd8827a0102 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -209,6 +209,54 @@ struct audit_context {
209#endif 209#endif
210}; 210};
211 211
212#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])
213static inline int open_arg(int flags, int mask)
214{
215 int n = ACC_MODE(flags);
216 if (flags & (O_TRUNC | O_CREAT))
217 n |= AUDIT_PERM_WRITE;
218 return n & mask;
219}
220
221static int audit_match_perm(struct audit_context *ctx, int mask)
222{
223 unsigned n = ctx->major;
224 switch (audit_classify_syscall(ctx->arch, n)) {
225 case 0: /* native */
226 if ((mask & AUDIT_PERM_WRITE) &&
227 audit_match_class(AUDIT_CLASS_WRITE, n))
228 return 1;
229 if ((mask & AUDIT_PERM_READ) &&
230 audit_match_class(AUDIT_CLASS_READ, n))
231 return 1;
232 if ((mask & AUDIT_PERM_ATTR) &&
233 audit_match_class(AUDIT_CLASS_CHATTR, n))
234 return 1;
235 return 0;
236 case 1: /* 32bit on biarch */
237 if ((mask & AUDIT_PERM_WRITE) &&
238 audit_match_class(AUDIT_CLASS_WRITE_32, n))
239 return 1;
240 if ((mask & AUDIT_PERM_READ) &&
241 audit_match_class(AUDIT_CLASS_READ_32, n))
242 return 1;
243 if ((mask & AUDIT_PERM_ATTR) &&
244 audit_match_class(AUDIT_CLASS_CHATTR_32, n))
245 return 1;
246 return 0;
247 case 2: /* open */
248 return mask & ACC_MODE(ctx->argv[1]);
249 case 3: /* openat */
250 return mask & ACC_MODE(ctx->argv[2]);
251 case 4: /* socketcall */
252 return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
253 case 5: /* execve */
254 return mask & AUDIT_PERM_EXEC;
255 default:
256 return 0;
257 }
258}
259
212/* Determine if any context name data matches a rule's watch data */ 260/* Determine if any context name data matches a rule's watch data */
213/* Compare a task_struct with an audit_rule. Return 1 on match, 0 261/* Compare a task_struct with an audit_rule. Return 1 on match, 0
214 * otherwise. */ 262 * otherwise. */
@@ -397,6 +445,9 @@ static int audit_filter_rules(struct task_struct *tsk,
397 /* ignore this field for filtering */ 445 /* ignore this field for filtering */
398 result = 1; 446 result = 1;
399 break; 447 break;
448 case AUDIT_PERM:
449 result = audit_match_perm(ctx, f->val);
450 break;
400 } 451 }
401 452
402 if (!result) 453 if (!result)