diff options
36 files changed, 351 insertions, 119 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index f6c6b345388c..b7ff9a318c31 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -22,6 +22,7 @@ config ALPHA | |||
22 | select GENERIC_SMP_IDLE_THREAD | 22 | select GENERIC_SMP_IDLE_THREAD |
23 | select GENERIC_STRNCPY_FROM_USER | 23 | select GENERIC_STRNCPY_FROM_USER |
24 | select GENERIC_STRNLEN_USER | 24 | select GENERIC_STRNLEN_USER |
25 | select HAVE_ARCH_AUDITSYSCALL | ||
25 | select HAVE_MOD_ARCH_SPECIFIC | 26 | select HAVE_MOD_ARCH_SPECIFIC |
26 | select MODULES_USE_ELF_RELA | 27 | select MODULES_USE_ELF_RELA |
27 | select ODD_RT_SIGACTION | 28 | select ODD_RT_SIGACTION |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5db05f6a0412..ab438cb5af55 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -24,6 +24,7 @@ config ARM | |||
24 | select GENERIC_STRNCPY_FROM_USER | 24 | select GENERIC_STRNCPY_FROM_USER |
25 | select GENERIC_STRNLEN_USER | 25 | select GENERIC_STRNLEN_USER |
26 | select HARDIRQS_SW_RESEND | 26 | select HARDIRQS_SW_RESEND |
27 | select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) | ||
27 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL | 28 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
28 | select HAVE_ARCH_KGDB | 29 | select HAVE_ARCH_KGDB |
29 | select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) | 30 | select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) |
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h index 73ddd7239b33..4651f6999b7d 100644 --- a/arch/arm/include/asm/syscall.h +++ b/arch/arm/include/asm/syscall.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #ifndef _ASM_ARM_SYSCALL_H | 7 | #ifndef _ASM_ARM_SYSCALL_H |
8 | #define _ASM_ARM_SYSCALL_H | 8 | #define _ASM_ARM_SYSCALL_H |
9 | 9 | ||
10 | #include <linux/audit.h> /* for AUDIT_ARCH_* */ | 10 | #include <uapi/linux/audit.h> /* for AUDIT_ARCH_* */ |
11 | #include <linux/elf.h> /* for ELF_EM */ | 11 | #include <linux/elf.h> /* for ELF_EM */ |
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
@@ -103,8 +103,7 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
103 | memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); | 103 | memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0])); |
104 | } | 104 | } |
105 | 105 | ||
106 | static inline int syscall_get_arch(struct task_struct *task, | 106 | static inline int syscall_get_arch(void) |
107 | struct pt_regs *regs) | ||
108 | { | 107 | { |
109 | /* ARM tasks don't change audit architectures on the fly. */ | 108 | /* ARM tasks don't change audit architectures on the fly. */ |
110 | return AUDIT_ARCH_ARM; | 109 | return AUDIT_ARCH_ARM; |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 1325c3bc58e1..12c3afee0f6f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -45,6 +45,7 @@ config IA64 | |||
45 | select HAVE_MOD_ARCH_SPECIFIC | 45 | select HAVE_MOD_ARCH_SPECIFIC |
46 | select MODULES_USE_ELF_RELA | 46 | select MODULES_USE_ELF_RELA |
47 | select ARCH_USE_CMPXCHG_LOCKREF | 47 | select ARCH_USE_CMPXCHG_LOCKREF |
48 | select HAVE_ARCH_AUDITSYSCALL | ||
48 | default y | 49 | default y |
49 | help | 50 | help |
50 | The Itanium Processor Family is Intel's 64-bit successor to | 51 | The Itanium Processor Family is Intel's 64-bit successor to |
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 6c488c85d791..c6e9cd2bca8d 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #define __ASM_MIPS_SYSCALL_H | 14 | #define __ASM_MIPS_SYSCALL_H |
15 | 15 | ||
16 | #include <linux/compiler.h> | 16 | #include <linux/compiler.h> |
17 | #include <linux/audit.h> | 17 | #include <uapi/linux/audit.h> |
18 | #include <linux/elf-em.h> | 18 | #include <linux/elf-em.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
@@ -127,12 +127,11 @@ extern const unsigned long sys_call_table[]; | |||
127 | extern const unsigned long sys32_call_table[]; | 127 | extern const unsigned long sys32_call_table[]; |
128 | extern const unsigned long sysn32_call_table[]; | 128 | extern const unsigned long sysn32_call_table[]; |
129 | 129 | ||
130 | static inline int syscall_get_arch(struct task_struct *task, | 130 | static inline int syscall_get_arch(void) |
131 | struct pt_regs *regs) | ||
132 | { | 131 | { |
133 | int arch = EM_MIPS; | 132 | int arch = EM_MIPS; |
134 | #ifdef CONFIG_64BIT | 133 | #ifdef CONFIG_64BIT |
135 | if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) | 134 | if (!test_thread_flag(TIF_32BIT_REGS)) |
136 | arch |= __AUDIT_ARCH_64BIT; | 135 | arch |= __AUDIT_ARCH_64BIT; |
137 | #endif | 136 | #endif |
138 | #if defined(__LITTLE_ENDIAN) | 137 | #if defined(__LITTLE_ENDIAN) |
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 7271e5a83081..71f85f427034 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -649,7 +649,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) | |||
649 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 649 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
650 | trace_sys_enter(regs, regs->regs[2]); | 650 | trace_sys_enter(regs, regs->regs[2]); |
651 | 651 | ||
652 | audit_syscall_entry(syscall_get_arch(current, regs), | 652 | audit_syscall_entry(syscall_get_arch(), |
653 | syscall, | 653 | syscall, |
654 | regs->regs[4], regs->regs[5], | 654 | regs->regs[4], regs->regs[5], |
655 | regs->regs[6], regs->regs[7]); | 655 | regs->regs[6], regs->regs[7]); |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index bb2a8ec440e7..1faefed32749 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -28,6 +28,7 @@ config PARISC | |||
28 | select CLONE_BACKWARDS | 28 | select CLONE_BACKWARDS |
29 | select TTY # Needed for pdc_cons.c | 29 | select TTY # Needed for pdc_cons.c |
30 | select HAVE_DEBUG_STACKOVERFLOW | 30 | select HAVE_DEBUG_STACKOVERFLOW |
31 | select HAVE_ARCH_AUDITSYSCALL | ||
31 | 32 | ||
32 | help | 33 | help |
33 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 34 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6c03a94991ad..e0998997943b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -144,6 +144,7 @@ config PPC | |||
144 | select HAVE_DEBUG_STACKOVERFLOW | 144 | select HAVE_DEBUG_STACKOVERFLOW |
145 | select HAVE_IRQ_EXIT_ON_IRQ_STACK | 145 | select HAVE_IRQ_EXIT_ON_IRQ_STACK |
146 | select ARCH_USE_CMPXCHG_LOCKREF if PPC64 | 146 | select ARCH_USE_CMPXCHG_LOCKREF if PPC64 |
147 | select HAVE_ARCH_AUDITSYSCALL | ||
147 | 148 | ||
148 | config GENERIC_CSUM | 149 | config GENERIC_CSUM |
149 | def_bool CPU_LITTLE_ENDIAN | 150 | def_bool CPU_LITTLE_ENDIAN |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 346d21678ffd..d68fe34799b0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -103,6 +103,7 @@ config S390 | |||
103 | select GENERIC_SMP_IDLE_THREAD | 103 | select GENERIC_SMP_IDLE_THREAD |
104 | select GENERIC_TIME_VSYSCALL | 104 | select GENERIC_TIME_VSYSCALL |
105 | select HAVE_ALIGNED_STRUCT_PAGE if SLUB | 105 | select HAVE_ALIGNED_STRUCT_PAGE if SLUB |
106 | select HAVE_ARCH_AUDITSYSCALL | ||
106 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 | 107 | select HAVE_ARCH_JUMP_LABEL if !MARCH_G5 |
107 | select HAVE_ARCH_SECCOMP_FILTER | 108 | select HAVE_ARCH_SECCOMP_FILTER |
108 | select HAVE_ARCH_TRACEHOOK | 109 | select HAVE_ARCH_TRACEHOOK |
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index cd29d2f4e4f3..777687055e7b 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #ifndef _ASM_SYSCALL_H | 12 | #ifndef _ASM_SYSCALL_H |
13 | #define _ASM_SYSCALL_H 1 | 13 | #define _ASM_SYSCALL_H 1 |
14 | 14 | ||
15 | #include <linux/audit.h> | 15 | #include <uapi/linux/audit.h> |
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
@@ -89,11 +89,10 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
89 | regs->orig_gpr2 = args[0]; | 89 | regs->orig_gpr2 = args[0]; |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline int syscall_get_arch(struct task_struct *task, | 92 | static inline int syscall_get_arch(void) |
93 | struct pt_regs *regs) | ||
94 | { | 93 | { |
95 | #ifdef CONFIG_COMPAT | 94 | #ifdef CONFIG_COMPAT |
96 | if (test_tsk_thread_flag(task, TIF_31BIT)) | 95 | if (test_tsk_thread_flag(current, TIF_31BIT)) |
97 | return AUDIT_ARCH_S390; | 96 | return AUDIT_ARCH_S390; |
98 | #endif | 97 | #endif |
99 | return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; | 98 | return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ba55e939a820..834b67c4db5a 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -42,6 +42,7 @@ config SUPERH | |||
42 | select MODULES_USE_ELF_RELA | 42 | select MODULES_USE_ELF_RELA |
43 | select OLD_SIGSUSPEND | 43 | select OLD_SIGSUSPEND |
44 | select OLD_SIGACTION | 44 | select OLD_SIGACTION |
45 | select HAVE_ARCH_AUDITSYSCALL | ||
45 | help | 46 | help |
46 | The SuperH is a RISC processor targeted for use in embedded systems | 47 | The SuperH is a RISC processor targeted for use in embedded systems |
47 | and consumer electronics; it was also used in the Sega Dreamcast | 48 | and consumer electronics; it was also used in the Sega Dreamcast |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 7d8b7e94b93b..29f2e988c56a 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -77,6 +77,7 @@ config SPARC64 | |||
77 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 77 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
78 | select HAVE_C_RECORDMCOUNT | 78 | select HAVE_C_RECORDMCOUNT |
79 | select NO_BOOTMEM | 79 | select NO_BOOTMEM |
80 | select HAVE_ARCH_AUDITSYSCALL | ||
80 | 81 | ||
81 | config ARCH_DEFCONFIG | 82 | config ARCH_DEFCONFIG |
82 | string | 83 | string |
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index 21ca44c4f6d5..6915d28cf118 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common | |||
@@ -1,6 +1,7 @@ | |||
1 | config UML | 1 | config UML |
2 | bool | 2 | bool |
3 | default y | 3 | default y |
4 | select HAVE_ARCH_AUDITSYSCALL | ||
4 | select HAVE_UID16 | 5 | select HAVE_UID16 |
5 | select GENERIC_IRQ_SHOW | 6 | select GENERIC_IRQ_SHOW |
6 | select GENERIC_CPU_DEVICES | 7 | select GENERIC_CPU_DEVICES |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5b8ec0f53b57..25d2c6f7325e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -129,6 +129,7 @@ config X86 | |||
129 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 | 129 | select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 |
130 | select HAVE_CC_STACKPROTECTOR | 130 | select HAVE_CC_STACKPROTECTOR |
131 | select GENERIC_CPU_AUTOPROBE | 131 | select GENERIC_CPU_AUTOPROBE |
132 | select HAVE_ARCH_AUDITSYSCALL | ||
132 | 133 | ||
133 | config INSTRUCTION_DECODER | 134 | config INSTRUCTION_DECODER |
134 | def_bool y | 135 | def_bool y |
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index aea284b41312..d6a756ae04c8 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h | |||
@@ -13,7 +13,7 @@ | |||
13 | #ifndef _ASM_X86_SYSCALL_H | 13 | #ifndef _ASM_X86_SYSCALL_H |
14 | #define _ASM_X86_SYSCALL_H | 14 | #define _ASM_X86_SYSCALL_H |
15 | 15 | ||
16 | #include <linux/audit.h> | 16 | #include <uapi/linux/audit.h> |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <asm/asm-offsets.h> /* For NR_syscalls */ | 19 | #include <asm/asm-offsets.h> /* For NR_syscalls */ |
@@ -91,8 +91,7 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
91 | memcpy(®s->bx + i, args, n * sizeof(args[0])); | 91 | memcpy(®s->bx + i, args, n * sizeof(args[0])); |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline int syscall_get_arch(struct task_struct *task, | 94 | static inline int syscall_get_arch(void) |
95 | struct pt_regs *regs) | ||
96 | { | 95 | { |
97 | return AUDIT_ARCH_I386; | 96 | return AUDIT_ARCH_I386; |
98 | } | 97 | } |
@@ -221,8 +220,7 @@ static inline void syscall_set_arguments(struct task_struct *task, | |||
221 | } | 220 | } |
222 | } | 221 | } |
223 | 222 | ||
224 | static inline int syscall_get_arch(struct task_struct *task, | 223 | static inline int syscall_get_arch(void) |
225 | struct pt_regs *regs) | ||
226 | { | 224 | { |
227 | #ifdef CONFIG_IA32_EMULATION | 225 | #ifdef CONFIG_IA32_EMULATION |
228 | /* | 226 | /* |
@@ -234,7 +232,7 @@ static inline int syscall_get_arch(struct task_struct *task, | |||
234 | * | 232 | * |
235 | * x32 tasks should be considered AUDIT_ARCH_X86_64. | 233 | * x32 tasks should be considered AUDIT_ARCH_X86_64. |
236 | */ | 234 | */ |
237 | if (task_thread_info(task)->status & TS_COMPAT) | 235 | if (task_thread_info(current)->status & TS_COMPAT) |
238 | return AUDIT_ARCH_I386; | 236 | return AUDIT_ARCH_I386; |
239 | #endif | 237 | #endif |
240 | /* Both x32 and x86_64 are considered "64-bit". */ | 238 | /* Both x32 and x86_64 are considered "64-bit". */ |
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index b0e540137e39..90ca082935f6 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c | |||
@@ -65,6 +65,7 @@ static void tty_audit_log(const char *description, int major, int minor, | |||
65 | { | 65 | { |
66 | struct audit_buffer *ab; | 66 | struct audit_buffer *ab; |
67 | struct task_struct *tsk = current; | 67 | struct task_struct *tsk = current; |
68 | pid_t pid = task_pid_nr(tsk); | ||
68 | uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); | 69 | uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); |
69 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); | 70 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); |
70 | unsigned int sessionid = audit_get_sessionid(tsk); | 71 | unsigned int sessionid = audit_get_sessionid(tsk); |
@@ -74,7 +75,7 @@ static void tty_audit_log(const char *description, int major, int minor, | |||
74 | char name[sizeof(tsk->comm)]; | 75 | char name[sizeof(tsk->comm)]; |
75 | 76 | ||
76 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" | 77 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" |
77 | " minor=%d comm=", description, tsk->pid, uid, | 78 | " minor=%d comm=", description, pid, uid, |
78 | loginuid, sessionid, major, minor); | 79 | loginuid, sessionid, major, minor); |
79 | get_task_comm(name, tsk); | 80 | get_task_comm(name, tsk); |
80 | audit_log_untrustedstring(ab, name); | 81 | audit_log_untrustedstring(ab, name); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 6b7087e2e8fb..2d696b0c93bf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -200,41 +200,9 @@ static int proc_root_link(struct dentry *dentry, struct path *path) | |||
200 | return result; | 200 | return result; |
201 | } | 201 | } |
202 | 202 | ||
203 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 203 | static int proc_pid_cmdline(struct task_struct *task, char *buffer) |
204 | { | 204 | { |
205 | int res = 0; | 205 | return get_cmdline(task, buffer, PAGE_SIZE); |
206 | unsigned int len; | ||
207 | struct mm_struct *mm = get_task_mm(task); | ||
208 | if (!mm) | ||
209 | goto out; | ||
210 | if (!mm->arg_end) | ||
211 | goto out_mm; /* Shh! No looking before we're done */ | ||
212 | |||
213 | len = mm->arg_end - mm->arg_start; | ||
214 | |||
215 | if (len > PAGE_SIZE) | ||
216 | len = PAGE_SIZE; | ||
217 | |||
218 | res = access_process_vm(task, mm->arg_start, buffer, len, 0); | ||
219 | |||
220 | // If the nul at the end of args has been overwritten, then | ||
221 | // assume application is using setproctitle(3). | ||
222 | if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) { | ||
223 | len = strnlen(buffer, res); | ||
224 | if (len < res) { | ||
225 | res = len; | ||
226 | } else { | ||
227 | len = mm->env_end - mm->env_start; | ||
228 | if (len > PAGE_SIZE - res) | ||
229 | len = PAGE_SIZE - res; | ||
230 | res += access_process_vm(task, mm->env_start, buffer+res, len, 0); | ||
231 | res = strnlen(buffer, res); | ||
232 | } | ||
233 | } | ||
234 | out_mm: | ||
235 | mmput(mm); | ||
236 | out: | ||
237 | return res; | ||
238 | } | 206 | } |
239 | 207 | ||
240 | static int proc_pid_auxv(struct task_struct *task, char *buffer) | 208 | static int proc_pid_auxv(struct task_struct *task, char *buffer) |
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h index 5b09392db673..d401e5463fb0 100644 --- a/include/asm-generic/syscall.h +++ b/include/asm-generic/syscall.h | |||
@@ -144,8 +144,6 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, | |||
144 | 144 | ||
145 | /** | 145 | /** |
146 | * syscall_get_arch - return the AUDIT_ARCH for the current system call | 146 | * syscall_get_arch - return the AUDIT_ARCH for the current system call |
147 | * @task: task of interest, must be in system call entry tracing | ||
148 | * @regs: task_pt_regs() of @task | ||
149 | * | 147 | * |
150 | * Returns the AUDIT_ARCH_* based on the system call convention in use. | 148 | * Returns the AUDIT_ARCH_* based on the system call convention in use. |
151 | * | 149 | * |
@@ -155,5 +153,5 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, | |||
155 | * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must | 153 | * Architectures which permit CONFIG_HAVE_ARCH_SECCOMP_FILTER must |
156 | * provide an implementation of this. | 154 | * provide an implementation of this. |
157 | */ | 155 | */ |
158 | int syscall_get_arch(struct task_struct *task, struct pt_regs *regs); | 156 | int syscall_get_arch(void); |
159 | #endif /* _ASM_SYSCALL_H */ | 157 | #endif /* _ASM_SYSCALL_H */ |
diff --git a/include/linux/audit.h b/include/linux/audit.h index ec1464df4c60..22cfddb75566 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -79,6 +79,14 @@ extern int is_audit_feature_set(int which); | |||
79 | extern int __init audit_register_class(int class, unsigned *list); | 79 | extern int __init audit_register_class(int class, unsigned *list); |
80 | extern int audit_classify_syscall(int abi, unsigned syscall); | 80 | extern int audit_classify_syscall(int abi, unsigned syscall); |
81 | extern int audit_classify_arch(int arch); | 81 | extern int audit_classify_arch(int arch); |
82 | /* only for compat system calls */ | ||
83 | extern unsigned compat_write_class[]; | ||
84 | extern unsigned compat_read_class[]; | ||
85 | extern unsigned compat_dir_class[]; | ||
86 | extern unsigned compat_chattr_class[]; | ||
87 | extern unsigned compat_signal_class[]; | ||
88 | |||
89 | extern int __weak audit_classify_compat_syscall(int abi, unsigned syscall); | ||
82 | 90 | ||
83 | /* audit_names->type values */ | 91 | /* audit_names->type values */ |
84 | #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ | 92 | #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ |
@@ -94,6 +102,12 @@ struct filename; | |||
94 | 102 | ||
95 | extern void audit_log_session_info(struct audit_buffer *ab); | 103 | extern void audit_log_session_info(struct audit_buffer *ab); |
96 | 104 | ||
105 | #ifdef CONFIG_AUDIT_COMPAT_GENERIC | ||
106 | #define audit_is_compat(arch) (!((arch) & __AUDIT_ARCH_64BIT)) | ||
107 | #else | ||
108 | #define audit_is_compat(arch) false | ||
109 | #endif | ||
110 | |||
97 | #ifdef CONFIG_AUDITSYSCALL | 111 | #ifdef CONFIG_AUDITSYSCALL |
98 | /* These are defined in auditsc.c */ | 112 | /* These are defined in auditsc.c */ |
99 | /* Public API */ | 113 | /* Public API */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index abc848412e3c..bf9811e1321a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1204,6 +1204,7 @@ void account_page_writeback(struct page *page); | |||
1204 | int set_page_dirty(struct page *page); | 1204 | int set_page_dirty(struct page *page); |
1205 | int set_page_dirty_lock(struct page *page); | 1205 | int set_page_dirty_lock(struct page *page); |
1206 | int clear_page_dirty_for_io(struct page *page); | 1206 | int clear_page_dirty_for_io(struct page *page); |
1207 | int get_cmdline(struct task_struct *task, char *buffer, int buflen); | ||
1207 | 1208 | ||
1208 | /* Is the vma a continuation of the stack vma above it? */ | 1209 | /* Is the vma a continuation of the stack vma above it? */ |
1209 | static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) | 1210 | static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 075b3056c0c0..25f54c79f757 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1719,6 +1719,24 @@ static inline pid_t task_tgid_vnr(struct task_struct *tsk) | |||
1719 | } | 1719 | } |
1720 | 1720 | ||
1721 | 1721 | ||
1722 | static inline int pid_alive(const struct task_struct *p); | ||
1723 | static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns) | ||
1724 | { | ||
1725 | pid_t pid = 0; | ||
1726 | |||
1727 | rcu_read_lock(); | ||
1728 | if (pid_alive(tsk)) | ||
1729 | pid = task_tgid_nr_ns(rcu_dereference(tsk->real_parent), ns); | ||
1730 | rcu_read_unlock(); | ||
1731 | |||
1732 | return pid; | ||
1733 | } | ||
1734 | |||
1735 | static inline pid_t task_ppid_nr(const struct task_struct *tsk) | ||
1736 | { | ||
1737 | return task_ppid_nr_ns(tsk, &init_pid_ns); | ||
1738 | } | ||
1739 | |||
1722 | static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, | 1740 | static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, |
1723 | struct pid_namespace *ns) | 1741 | struct pid_namespace *ns) |
1724 | { | 1742 | { |
@@ -1758,7 +1776,7 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk) | |||
1758 | * | 1776 | * |
1759 | * Return: 1 if the process is alive. 0 otherwise. | 1777 | * Return: 1 if the process is alive. 0 otherwise. |
1760 | */ | 1778 | */ |
1761 | static inline int pid_alive(struct task_struct *p) | 1779 | static inline int pid_alive(const struct task_struct *p) |
1762 | { | 1780 | { |
1763 | return p->pids[PIDTYPE_PID].pid != NULL; | 1781 | return p->pids[PIDTYPE_PID].pid != NULL; |
1764 | } | 1782 | } |
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 2d48fe1274ca..11917f747cb4 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
@@ -70,7 +70,6 @@ | |||
70 | #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ | 70 | #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ |
71 | #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ | 71 | #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ |
72 | #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ | 72 | #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ |
73 | #define AUDIT_FEATURE_CHANGE 1020 /* audit log listing feature changes */ | ||
74 | 73 | ||
75 | #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ | 74 | #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ |
76 | #define AUDIT_USER_AVC 1107 /* We filter this differently */ | 75 | #define AUDIT_USER_AVC 1107 /* We filter this differently */ |
@@ -109,6 +108,8 @@ | |||
109 | #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ | 108 | #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ |
110 | #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ | 109 | #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ |
111 | #define AUDIT_SECCOMP 1326 /* Secure Computing event */ | 110 | #define AUDIT_SECCOMP 1326 /* Secure Computing event */ |
111 | #define AUDIT_PROCTITLE 1327 /* Proctitle emit event */ | ||
112 | #define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */ | ||
112 | 113 | ||
113 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 114 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
114 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 115 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index ba478fa3012e..154dd6d3c8fe 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h | |||
@@ -308,8 +308,12 @@ struct vfs_cap_data { | |||
308 | 308 | ||
309 | #define CAP_LEASE 28 | 309 | #define CAP_LEASE 28 |
310 | 310 | ||
311 | /* Allow writing the audit log via unicast netlink socket */ | ||
312 | |||
311 | #define CAP_AUDIT_WRITE 29 | 313 | #define CAP_AUDIT_WRITE 29 |
312 | 314 | ||
315 | /* Allow configuration of audit via unicast netlink socket */ | ||
316 | |||
313 | #define CAP_AUDIT_CONTROL 30 | 317 | #define CAP_AUDIT_CONTROL 30 |
314 | 318 | ||
315 | #define CAP_SETFCAP 31 | 319 | #define CAP_SETFCAP 31 |
diff --git a/init/Kconfig b/init/Kconfig index 427ba60d638f..765018c24cf9 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -292,9 +292,12 @@ config AUDIT | |||
292 | logging of avc messages output). Does not do system-call | 292 | logging of avc messages output). Does not do system-call |
293 | auditing without CONFIG_AUDITSYSCALL. | 293 | auditing without CONFIG_AUDITSYSCALL. |
294 | 294 | ||
295 | config HAVE_ARCH_AUDITSYSCALL | ||
296 | bool | ||
297 | |||
295 | config AUDITSYSCALL | 298 | config AUDITSYSCALL |
296 | bool "Enable system-call auditing support" | 299 | bool "Enable system-call auditing support" |
297 | depends on AUDIT && (X86 || PARISC || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT) || ALPHA) | 300 | depends on AUDIT && HAVE_ARCH_AUDITSYSCALL |
298 | default y if SECURITY_SELINUX | 301 | default y if SECURITY_SELINUX |
299 | help | 302 | help |
300 | Enable low-overhead system-call auditing infrastructure that | 303 | Enable low-overhead system-call auditing infrastructure that |
diff --git a/kernel/audit.c b/kernel/audit.c index 95a20f3f52f1..7c2893602d06 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -182,7 +182,7 @@ struct audit_buffer { | |||
182 | 182 | ||
183 | struct audit_reply { | 183 | struct audit_reply { |
184 | __u32 portid; | 184 | __u32 portid; |
185 | struct net *net; | 185 | struct net *net; |
186 | struct sk_buff *skb; | 186 | struct sk_buff *skb; |
187 | }; | 187 | }; |
188 | 188 | ||
@@ -396,7 +396,7 @@ static void audit_printk_skb(struct sk_buff *skb) | |||
396 | if (printk_ratelimit()) | 396 | if (printk_ratelimit()) |
397 | pr_notice("type=%d %s\n", nlh->nlmsg_type, data); | 397 | pr_notice("type=%d %s\n", nlh->nlmsg_type, data); |
398 | else | 398 | else |
399 | audit_log_lost("printk limit exceeded\n"); | 399 | audit_log_lost("printk limit exceeded"); |
400 | } | 400 | } |
401 | 401 | ||
402 | audit_hold_skb(skb); | 402 | audit_hold_skb(skb); |
@@ -412,7 +412,7 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
412 | BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ | 412 | BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ |
413 | if (audit_pid) { | 413 | if (audit_pid) { |
414 | pr_err("*NO* daemon at audit_pid=%d\n", audit_pid); | 414 | pr_err("*NO* daemon at audit_pid=%d\n", audit_pid); |
415 | audit_log_lost("auditd disappeared\n"); | 415 | audit_log_lost("auditd disappeared"); |
416 | audit_pid = 0; | 416 | audit_pid = 0; |
417 | audit_sock = NULL; | 417 | audit_sock = NULL; |
418 | } | 418 | } |
@@ -607,7 +607,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
607 | { | 607 | { |
608 | int err = 0; | 608 | int err = 0; |
609 | 609 | ||
610 | /* Only support the initial namespaces for now. */ | 610 | /* Only support initial user namespace for now. */ |
611 | /* | 611 | /* |
612 | * We return ECONNREFUSED because it tricks userspace into thinking | 612 | * We return ECONNREFUSED because it tricks userspace into thinking |
613 | * that audit was not configured into the kernel. Lots of users | 613 | * that audit was not configured into the kernel. Lots of users |
@@ -618,8 +618,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
618 | * userspace will reject all logins. This should be removed when we | 618 | * userspace will reject all logins. This should be removed when we |
619 | * support non init namespaces!! | 619 | * support non init namespaces!! |
620 | */ | 620 | */ |
621 | if ((current_user_ns() != &init_user_ns) || | 621 | if (current_user_ns() != &init_user_ns) |
622 | (task_active_pid_ns(current) != &init_pid_ns)) | ||
623 | return -ECONNREFUSED; | 622 | return -ECONNREFUSED; |
624 | 623 | ||
625 | switch (msg_type) { | 624 | switch (msg_type) { |
@@ -639,6 +638,11 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
639 | case AUDIT_TTY_SET: | 638 | case AUDIT_TTY_SET: |
640 | case AUDIT_TRIM: | 639 | case AUDIT_TRIM: |
641 | case AUDIT_MAKE_EQUIV: | 640 | case AUDIT_MAKE_EQUIV: |
641 | /* Only support auditd and auditctl in initial pid namespace | ||
642 | * for now. */ | ||
643 | if ((task_active_pid_ns(current) != &init_pid_ns)) | ||
644 | return -EPERM; | ||
645 | |||
642 | if (!capable(CAP_AUDIT_CONTROL)) | 646 | if (!capable(CAP_AUDIT_CONTROL)) |
643 | err = -EPERM; | 647 | err = -EPERM; |
644 | break; | 648 | break; |
@@ -659,6 +663,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) | |||
659 | { | 663 | { |
660 | int rc = 0; | 664 | int rc = 0; |
661 | uid_t uid = from_kuid(&init_user_ns, current_uid()); | 665 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
666 | pid_t pid = task_tgid_nr(current); | ||
662 | 667 | ||
663 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) { | 668 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) { |
664 | *ab = NULL; | 669 | *ab = NULL; |
@@ -668,7 +673,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) | |||
668 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 673 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
669 | if (unlikely(!*ab)) | 674 | if (unlikely(!*ab)) |
670 | return rc; | 675 | return rc; |
671 | audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid); | 676 | audit_log_format(*ab, "pid=%d uid=%u", pid, uid); |
672 | audit_log_session_info(*ab); | 677 | audit_log_session_info(*ab); |
673 | audit_log_task_context(*ab); | 678 | audit_log_task_context(*ab); |
674 | 679 | ||
@@ -1097,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net) | |||
1097 | audit_sock = NULL; | 1102 | audit_sock = NULL; |
1098 | } | 1103 | } |
1099 | 1104 | ||
1100 | rcu_assign_pointer(aunet->nlsk, NULL); | 1105 | RCU_INIT_POINTER(aunet->nlsk, NULL); |
1101 | synchronize_net(); | 1106 | synchronize_net(); |
1102 | netlink_kernel_release(sock); | 1107 | netlink_kernel_release(sock); |
1103 | } | 1108 | } |
@@ -1829,11 +1834,11 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | |||
1829 | spin_unlock_irq(&tsk->sighand->siglock); | 1834 | spin_unlock_irq(&tsk->sighand->siglock); |
1830 | 1835 | ||
1831 | audit_log_format(ab, | 1836 | audit_log_format(ab, |
1832 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | 1837 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" |
1833 | " euid=%u suid=%u fsuid=%u" | 1838 | " euid=%u suid=%u fsuid=%u" |
1834 | " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", | 1839 | " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", |
1835 | sys_getppid(), | 1840 | task_ppid_nr(tsk), |
1836 | tsk->pid, | 1841 | task_pid_nr(tsk), |
1837 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), | 1842 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), |
1838 | from_kuid(&init_user_ns, cred->uid), | 1843 | from_kuid(&init_user_ns, cred->uid), |
1839 | from_kgid(&init_user_ns, cred->gid), | 1844 | from_kgid(&init_user_ns, cred->gid), |
diff --git a/kernel/audit.h b/kernel/audit.h index 8df132214606..7bb65730c890 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -106,6 +106,11 @@ struct audit_names { | |||
106 | bool should_free; | 106 | bool should_free; |
107 | }; | 107 | }; |
108 | 108 | ||
109 | struct audit_proctitle { | ||
110 | int len; /* length of the cmdline field. */ | ||
111 | char *value; /* the cmdline field */ | ||
112 | }; | ||
113 | |||
109 | /* The per-task audit context. */ | 114 | /* The per-task audit context. */ |
110 | struct audit_context { | 115 | struct audit_context { |
111 | int dummy; /* must be the first element */ | 116 | int dummy; /* must be the first element */ |
@@ -202,6 +207,7 @@ struct audit_context { | |||
202 | } execve; | 207 | } execve; |
203 | }; | 208 | }; |
204 | int fds[2]; | 209 | int fds[2]; |
210 | struct audit_proctitle proctitle; | ||
205 | 211 | ||
206 | #if AUDIT_DEBUG | 212 | #if AUDIT_DEBUG |
207 | int put_count; | 213 | int put_count; |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 92062fd6cc8c..8e9bc9c3dbb7 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
23 | #include <linux/audit.h> | 25 | #include <linux/audit.h> |
24 | #include <linux/kthread.h> | 26 | #include <linux/kthread.h> |
@@ -226,7 +228,7 @@ static int audit_match_signal(struct audit_entry *entry) | |||
226 | #endif | 228 | #endif |
227 | 229 | ||
228 | /* Common user-space to kernel rule translation. */ | 230 | /* Common user-space to kernel rule translation. */ |
229 | static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) | 231 | static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *rule) |
230 | { | 232 | { |
231 | unsigned listnr; | 233 | unsigned listnr; |
232 | struct audit_entry *entry; | 234 | struct audit_entry *entry; |
@@ -249,7 +251,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) | |||
249 | ; | 251 | ; |
250 | } | 252 | } |
251 | if (unlikely(rule->action == AUDIT_POSSIBLE)) { | 253 | if (unlikely(rule->action == AUDIT_POSSIBLE)) { |
252 | printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n"); | 254 | pr_err("AUDIT_POSSIBLE is deprecated\n"); |
253 | goto exit_err; | 255 | goto exit_err; |
254 | } | 256 | } |
255 | if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS) | 257 | if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS) |
@@ -403,7 +405,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
403 | int i; | 405 | int i; |
404 | char *str; | 406 | char *str; |
405 | 407 | ||
406 | entry = audit_to_entry_common((struct audit_rule *)data); | 408 | entry = audit_to_entry_common(data); |
407 | if (IS_ERR(entry)) | 409 | if (IS_ERR(entry)) |
408 | goto exit_nofree; | 410 | goto exit_nofree; |
409 | 411 | ||
@@ -431,6 +433,19 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
431 | f->val = 0; | 433 | f->val = 0; |
432 | } | 434 | } |
433 | 435 | ||
436 | if ((f->type == AUDIT_PID) || (f->type == AUDIT_PPID)) { | ||
437 | struct pid *pid; | ||
438 | rcu_read_lock(); | ||
439 | pid = find_vpid(f->val); | ||
440 | if (!pid) { | ||
441 | rcu_read_unlock(); | ||
442 | err = -ESRCH; | ||
443 | goto exit_free; | ||
444 | } | ||
445 | f->val = pid_nr(pid); | ||
446 | rcu_read_unlock(); | ||
447 | } | ||
448 | |||
434 | err = audit_field_valid(entry, f); | 449 | err = audit_field_valid(entry, f); |
435 | if (err) | 450 | if (err) |
436 | goto exit_free; | 451 | goto exit_free; |
@@ -479,8 +494,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
479 | /* Keep currently invalid fields around in case they | 494 | /* Keep currently invalid fields around in case they |
480 | * become valid after a policy reload. */ | 495 | * become valid after a policy reload. */ |
481 | if (err == -EINVAL) { | 496 | if (err == -EINVAL) { |
482 | printk(KERN_WARNING "audit rule for LSM " | 497 | pr_warn("audit rule for LSM \'%s\' is invalid\n", |
483 | "\'%s\' is invalid\n", str); | 498 | str); |
484 | err = 0; | 499 | err = 0; |
485 | } | 500 | } |
486 | if (err) { | 501 | if (err) { |
@@ -709,8 +724,8 @@ static inline int audit_dupe_lsm_field(struct audit_field *df, | |||
709 | /* Keep currently invalid fields around in case they | 724 | /* Keep currently invalid fields around in case they |
710 | * become valid after a policy reload. */ | 725 | * become valid after a policy reload. */ |
711 | if (ret == -EINVAL) { | 726 | if (ret == -EINVAL) { |
712 | printk(KERN_WARNING "audit rule for LSM \'%s\' is " | 727 | pr_warn("audit rule for LSM \'%s\' is invalid\n", |
713 | "invalid\n", df->lsm_str); | 728 | df->lsm_str); |
714 | ret = 0; | 729 | ret = 0; |
715 | } | 730 | } |
716 | 731 | ||
@@ -1240,12 +1255,14 @@ static int audit_filter_user_rules(struct audit_krule *rule, int type, | |||
1240 | 1255 | ||
1241 | for (i = 0; i < rule->field_count; i++) { | 1256 | for (i = 0; i < rule->field_count; i++) { |
1242 | struct audit_field *f = &rule->fields[i]; | 1257 | struct audit_field *f = &rule->fields[i]; |
1258 | pid_t pid; | ||
1243 | int result = 0; | 1259 | int result = 0; |
1244 | u32 sid; | 1260 | u32 sid; |
1245 | 1261 | ||
1246 | switch (f->type) { | 1262 | switch (f->type) { |
1247 | case AUDIT_PID: | 1263 | case AUDIT_PID: |
1248 | result = audit_comparator(task_pid_vnr(current), f->op, f->val); | 1264 | pid = task_pid_nr(current); |
1265 | result = audit_comparator(pid, f->op, f->val); | ||
1249 | break; | 1266 | break; |
1250 | case AUDIT_UID: | 1267 | case AUDIT_UID: |
1251 | result = audit_uid_comparator(current_uid(), f->op, f->uid); | 1268 | result = audit_uid_comparator(current_uid(), f->op, f->uid); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 7aef2f4b6c64..f251a5e8d17a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -42,6 +42,8 @@ | |||
42 | * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. | 42 | * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance. |
43 | */ | 43 | */ |
44 | 44 | ||
45 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
46 | |||
45 | #include <linux/init.h> | 47 | #include <linux/init.h> |
46 | #include <asm/types.h> | 48 | #include <asm/types.h> |
47 | #include <linux/atomic.h> | 49 | #include <linux/atomic.h> |
@@ -68,6 +70,7 @@ | |||
68 | #include <linux/capability.h> | 70 | #include <linux/capability.h> |
69 | #include <linux/fs_struct.h> | 71 | #include <linux/fs_struct.h> |
70 | #include <linux/compat.h> | 72 | #include <linux/compat.h> |
73 | #include <linux/ctype.h> | ||
71 | 74 | ||
72 | #include "audit.h" | 75 | #include "audit.h" |
73 | 76 | ||
@@ -79,6 +82,9 @@ | |||
79 | /* no execve audit message should be longer than this (userspace limits) */ | 82 | /* no execve audit message should be longer than this (userspace limits) */ |
80 | #define MAX_EXECVE_AUDIT_LEN 7500 | 83 | #define MAX_EXECVE_AUDIT_LEN 7500 |
81 | 84 | ||
85 | /* max length to print of cmdline/proctitle value during audit */ | ||
86 | #define MAX_PROCTITLE_AUDIT_LEN 128 | ||
87 | |||
82 | /* number of audit rules */ | 88 | /* number of audit rules */ |
83 | int audit_n_rules; | 89 | int audit_n_rules; |
84 | 90 | ||
@@ -451,15 +457,17 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
451 | struct audit_field *f = &rule->fields[i]; | 457 | struct audit_field *f = &rule->fields[i]; |
452 | struct audit_names *n; | 458 | struct audit_names *n; |
453 | int result = 0; | 459 | int result = 0; |
460 | pid_t pid; | ||
454 | 461 | ||
455 | switch (f->type) { | 462 | switch (f->type) { |
456 | case AUDIT_PID: | 463 | case AUDIT_PID: |
457 | result = audit_comparator(tsk->pid, f->op, f->val); | 464 | pid = task_pid_nr(tsk); |
465 | result = audit_comparator(pid, f->op, f->val); | ||
458 | break; | 466 | break; |
459 | case AUDIT_PPID: | 467 | case AUDIT_PPID: |
460 | if (ctx) { | 468 | if (ctx) { |
461 | if (!ctx->ppid) | 469 | if (!ctx->ppid) |
462 | ctx->ppid = sys_getppid(); | 470 | ctx->ppid = task_ppid_nr(tsk); |
463 | result = audit_comparator(ctx->ppid, f->op, f->val); | 471 | result = audit_comparator(ctx->ppid, f->op, f->val); |
464 | } | 472 | } |
465 | break; | 473 | break; |
@@ -805,7 +813,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) | |||
805 | rcu_read_unlock(); | 813 | rcu_read_unlock(); |
806 | } | 814 | } |
807 | 815 | ||
808 | static inline struct audit_context *audit_get_context(struct task_struct *tsk, | 816 | /* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */ |
817 | static inline struct audit_context *audit_take_context(struct task_struct *tsk, | ||
809 | int return_valid, | 818 | int return_valid, |
810 | long return_code) | 819 | long return_code) |
811 | { | 820 | { |
@@ -842,6 +851,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
842 | return context; | 851 | return context; |
843 | } | 852 | } |
844 | 853 | ||
854 | static inline void audit_proctitle_free(struct audit_context *context) | ||
855 | { | ||
856 | kfree(context->proctitle.value); | ||
857 | context->proctitle.value = NULL; | ||
858 | context->proctitle.len = 0; | ||
859 | } | ||
860 | |||
845 | static inline void audit_free_names(struct audit_context *context) | 861 | static inline void audit_free_names(struct audit_context *context) |
846 | { | 862 | { |
847 | struct audit_names *n, *next; | 863 | struct audit_names *n, *next; |
@@ -850,16 +866,15 @@ static inline void audit_free_names(struct audit_context *context) | |||
850 | if (context->put_count + context->ino_count != context->name_count) { | 866 | if (context->put_count + context->ino_count != context->name_count) { |
851 | int i = 0; | 867 | int i = 0; |
852 | 868 | ||
853 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" | 869 | pr_err("%s:%d(:%d): major=%d in_syscall=%d" |
854 | " name_count=%d put_count=%d" | 870 | " name_count=%d put_count=%d ino_count=%d" |
855 | " ino_count=%d [NOT freeing]\n", | 871 | " [NOT freeing]\n", __FILE__, __LINE__, |
856 | __FILE__, __LINE__, | ||
857 | context->serial, context->major, context->in_syscall, | 872 | context->serial, context->major, context->in_syscall, |
858 | context->name_count, context->put_count, | 873 | context->name_count, context->put_count, |
859 | context->ino_count); | 874 | context->ino_count); |
860 | list_for_each_entry(n, &context->names_list, list) { | 875 | list_for_each_entry(n, &context->names_list, list) { |
861 | printk(KERN_ERR "names[%d] = %p = %s\n", i++, | 876 | pr_err("names[%d] = %p = %s\n", i++, n->name, |
862 | n->name, n->name->name ?: "(null)"); | 877 | n->name->name ?: "(null)"); |
863 | } | 878 | } |
864 | dump_stack(); | 879 | dump_stack(); |
865 | return; | 880 | return; |
@@ -955,6 +970,7 @@ static inline void audit_free_context(struct audit_context *context) | |||
955 | audit_free_aux(context); | 970 | audit_free_aux(context); |
956 | kfree(context->filterkey); | 971 | kfree(context->filterkey); |
957 | kfree(context->sockaddr); | 972 | kfree(context->sockaddr); |
973 | audit_proctitle_free(context); | ||
958 | kfree(context); | 974 | kfree(context); |
959 | } | 975 | } |
960 | 976 | ||
@@ -1157,7 +1173,7 @@ static void audit_log_execve_info(struct audit_context *context, | |||
1157 | */ | 1173 | */ |
1158 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); | 1174 | buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL); |
1159 | if (!buf) { | 1175 | if (!buf) { |
1160 | audit_panic("out of memory for argv string\n"); | 1176 | audit_panic("out of memory for argv string"); |
1161 | return; | 1177 | return; |
1162 | } | 1178 | } |
1163 | 1179 | ||
@@ -1271,6 +1287,59 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
1271 | audit_log_end(ab); | 1287 | audit_log_end(ab); |
1272 | } | 1288 | } |
1273 | 1289 | ||
1290 | static inline int audit_proctitle_rtrim(char *proctitle, int len) | ||
1291 | { | ||
1292 | char *end = proctitle + len - 1; | ||
1293 | while (end > proctitle && !isprint(*end)) | ||
1294 | end--; | ||
1295 | |||
1296 | /* catch the case where proctitle is only 1 non-print character */ | ||
1297 | len = end - proctitle + 1; | ||
1298 | len -= isprint(proctitle[len-1]) == 0; | ||
1299 | return len; | ||
1300 | } | ||
1301 | |||
1302 | static void audit_log_proctitle(struct task_struct *tsk, | ||
1303 | struct audit_context *context) | ||
1304 | { | ||
1305 | int res; | ||
1306 | char *buf; | ||
1307 | char *msg = "(null)"; | ||
1308 | int len = strlen(msg); | ||
1309 | struct audit_buffer *ab; | ||
1310 | |||
1311 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE); | ||
1312 | if (!ab) | ||
1313 | return; /* audit_panic or being filtered */ | ||
1314 | |||
1315 | audit_log_format(ab, "proctitle="); | ||
1316 | |||
1317 | /* Not cached */ | ||
1318 | if (!context->proctitle.value) { | ||
1319 | buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL); | ||
1320 | if (!buf) | ||
1321 | goto out; | ||
1322 | /* Historically called this from procfs naming */ | ||
1323 | res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN); | ||
1324 | if (res == 0) { | ||
1325 | kfree(buf); | ||
1326 | goto out; | ||
1327 | } | ||
1328 | res = audit_proctitle_rtrim(buf, res); | ||
1329 | if (res == 0) { | ||
1330 | kfree(buf); | ||
1331 | goto out; | ||
1332 | } | ||
1333 | context->proctitle.value = buf; | ||
1334 | context->proctitle.len = res; | ||
1335 | } | ||
1336 | msg = context->proctitle.value; | ||
1337 | len = context->proctitle.len; | ||
1338 | out: | ||
1339 | audit_log_n_untrustedstring(ab, msg, len); | ||
1340 | audit_log_end(ab); | ||
1341 | } | ||
1342 | |||
1274 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1343 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
1275 | { | 1344 | { |
1276 | int i, call_panic = 0; | 1345 | int i, call_panic = 0; |
@@ -1388,6 +1457,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1388 | audit_log_name(context, n, NULL, i++, &call_panic); | 1457 | audit_log_name(context, n, NULL, i++, &call_panic); |
1389 | } | 1458 | } |
1390 | 1459 | ||
1460 | audit_log_proctitle(tsk, context); | ||
1461 | |||
1391 | /* Send end of event record to help user space know we are finished */ | 1462 | /* Send end of event record to help user space know we are finished */ |
1392 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1463 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
1393 | if (ab) | 1464 | if (ab) |
@@ -1406,7 +1477,7 @@ void __audit_free(struct task_struct *tsk) | |||
1406 | { | 1477 | { |
1407 | struct audit_context *context; | 1478 | struct audit_context *context; |
1408 | 1479 | ||
1409 | context = audit_get_context(tsk, 0, 0); | 1480 | context = audit_take_context(tsk, 0, 0); |
1410 | if (!context) | 1481 | if (!context) |
1411 | return; | 1482 | return; |
1412 | 1483 | ||
@@ -1500,7 +1571,7 @@ void __audit_syscall_exit(int success, long return_code) | |||
1500 | else | 1571 | else |
1501 | success = AUDITSC_FAILURE; | 1572 | success = AUDITSC_FAILURE; |
1502 | 1573 | ||
1503 | context = audit_get_context(tsk, success, return_code); | 1574 | context = audit_take_context(tsk, success, return_code); |
1504 | if (!context) | 1575 | if (!context) |
1505 | return; | 1576 | return; |
1506 | 1577 | ||
@@ -1550,7 +1621,7 @@ static inline void handle_one(const struct inode *inode) | |||
1550 | if (likely(put_tree_ref(context, chunk))) | 1621 | if (likely(put_tree_ref(context, chunk))) |
1551 | return; | 1622 | return; |
1552 | if (unlikely(!grow_tree_refs(context))) { | 1623 | if (unlikely(!grow_tree_refs(context))) { |
1553 | printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); | 1624 | pr_warn("out of memory, audit has lost a tree reference\n"); |
1554 | audit_set_auditable(context); | 1625 | audit_set_auditable(context); |
1555 | audit_put_chunk(chunk); | 1626 | audit_put_chunk(chunk); |
1556 | unroll_tree_refs(context, p, count); | 1627 | unroll_tree_refs(context, p, count); |
@@ -1609,8 +1680,7 @@ retry: | |||
1609 | goto retry; | 1680 | goto retry; |
1610 | } | 1681 | } |
1611 | /* too bad */ | 1682 | /* too bad */ |
1612 | printk(KERN_WARNING | 1683 | pr_warn("out of memory, audit has lost a tree reference\n"); |
1613 | "out of memory, audit has lost a tree reference\n"); | ||
1614 | unroll_tree_refs(context, p, count); | 1684 | unroll_tree_refs(context, p, count); |
1615 | audit_set_auditable(context); | 1685 | audit_set_auditable(context); |
1616 | return; | 1686 | return; |
@@ -1682,7 +1752,7 @@ void __audit_getname(struct filename *name) | |||
1682 | 1752 | ||
1683 | if (!context->in_syscall) { | 1753 | if (!context->in_syscall) { |
1684 | #if AUDIT_DEBUG == 2 | 1754 | #if AUDIT_DEBUG == 2 |
1685 | printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n", | 1755 | pr_err("%s:%d(:%d): ignoring getname(%p)\n", |
1686 | __FILE__, __LINE__, context->serial, name); | 1756 | __FILE__, __LINE__, context->serial, name); |
1687 | dump_stack(); | 1757 | dump_stack(); |
1688 | #endif | 1758 | #endif |
@@ -1721,15 +1791,15 @@ void audit_putname(struct filename *name) | |||
1721 | BUG_ON(!context); | 1791 | BUG_ON(!context); |
1722 | if (!name->aname || !context->in_syscall) { | 1792 | if (!name->aname || !context->in_syscall) { |
1723 | #if AUDIT_DEBUG == 2 | 1793 | #if AUDIT_DEBUG == 2 |
1724 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", | 1794 | pr_err("%s:%d(:%d): final_putname(%p)\n", |
1725 | __FILE__, __LINE__, context->serial, name); | 1795 | __FILE__, __LINE__, context->serial, name); |
1726 | if (context->name_count) { | 1796 | if (context->name_count) { |
1727 | struct audit_names *n; | 1797 | struct audit_names *n; |
1728 | int i = 0; | 1798 | int i = 0; |
1729 | 1799 | ||
1730 | list_for_each_entry(n, &context->names_list, list) | 1800 | list_for_each_entry(n, &context->names_list, list) |
1731 | printk(KERN_ERR "name[%d] = %p = %s\n", i++, | 1801 | pr_err("name[%d] = %p = %s\n", i++, n->name, |
1732 | n->name, n->name->name ?: "(null)"); | 1802 | n->name->name ?: "(null)"); |
1733 | } | 1803 | } |
1734 | #endif | 1804 | #endif |
1735 | final_putname(name); | 1805 | final_putname(name); |
@@ -1738,9 +1808,8 @@ void audit_putname(struct filename *name) | |||
1738 | else { | 1808 | else { |
1739 | ++context->put_count; | 1809 | ++context->put_count; |
1740 | if (context->put_count > context->name_count) { | 1810 | if (context->put_count > context->name_count) { |
1741 | printk(KERN_ERR "%s:%d(:%d): major=%d" | 1811 | pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" |
1742 | " in_syscall=%d putname(%p) name_count=%d" | 1812 | " name_count=%d put_count=%d\n", |
1743 | " put_count=%d\n", | ||
1744 | __FILE__, __LINE__, | 1813 | __FILE__, __LINE__, |
1745 | context->serial, context->major, | 1814 | context->serial, context->major, |
1746 | context->in_syscall, name->name, | 1815 | context->in_syscall, name->name, |
@@ -1981,12 +2050,10 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | |||
1981 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | 2050 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); |
1982 | if (!ab) | 2051 | if (!ab) |
1983 | return; | 2052 | return; |
1984 | audit_log_format(ab, "pid=%d uid=%u" | 2053 | audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid); |
1985 | " old-auid=%u new-auid=%u old-ses=%u new-ses=%u" | 2054 | audit_log_task_context(ab); |
1986 | " res=%d", | 2055 | audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d", |
1987 | current->pid, uid, | 2056 | oldloginuid, loginuid, oldsessionid, sessionid, !rc); |
1988 | oldloginuid, loginuid, oldsessionid, sessionid, | ||
1989 | !rc); | ||
1990 | audit_log_end(ab); | 2057 | audit_log_end(ab); |
1991 | } | 2058 | } |
1992 | 2059 | ||
@@ -2208,7 +2275,7 @@ void __audit_ptrace(struct task_struct *t) | |||
2208 | { | 2275 | { |
2209 | struct audit_context *context = current->audit_context; | 2276 | struct audit_context *context = current->audit_context; |
2210 | 2277 | ||
2211 | context->target_pid = t->pid; | 2278 | context->target_pid = task_pid_nr(t); |
2212 | context->target_auid = audit_get_loginuid(t); | 2279 | context->target_auid = audit_get_loginuid(t); |
2213 | context->target_uid = task_uid(t); | 2280 | context->target_uid = task_uid(t); |
2214 | context->target_sessionid = audit_get_sessionid(t); | 2281 | context->target_sessionid = audit_get_sessionid(t); |
@@ -2233,7 +2300,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2233 | 2300 | ||
2234 | if (audit_pid && t->tgid == audit_pid) { | 2301 | if (audit_pid && t->tgid == audit_pid) { |
2235 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { | 2302 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { |
2236 | audit_sig_pid = tsk->pid; | 2303 | audit_sig_pid = task_pid_nr(tsk); |
2237 | if (uid_valid(tsk->loginuid)) | 2304 | if (uid_valid(tsk->loginuid)) |
2238 | audit_sig_uid = tsk->loginuid; | 2305 | audit_sig_uid = tsk->loginuid; |
2239 | else | 2306 | else |
@@ -2247,7 +2314,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2247 | /* optimize the common case by putting first signal recipient directly | 2314 | /* optimize the common case by putting first signal recipient directly |
2248 | * in audit_context */ | 2315 | * in audit_context */ |
2249 | if (!ctx->target_pid) { | 2316 | if (!ctx->target_pid) { |
2250 | ctx->target_pid = t->tgid; | 2317 | ctx->target_pid = task_tgid_nr(t); |
2251 | ctx->target_auid = audit_get_loginuid(t); | 2318 | ctx->target_auid = audit_get_loginuid(t); |
2252 | ctx->target_uid = t_uid; | 2319 | ctx->target_uid = t_uid; |
2253 | ctx->target_sessionid = audit_get_sessionid(t); | 2320 | ctx->target_sessionid = audit_get_sessionid(t); |
@@ -2268,7 +2335,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
2268 | } | 2335 | } |
2269 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); | 2336 | BUG_ON(axp->pid_count >= AUDIT_AUX_PIDS); |
2270 | 2337 | ||
2271 | axp->target_pid[axp->pid_count] = t->tgid; | 2338 | axp->target_pid[axp->pid_count] = task_tgid_nr(t); |
2272 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); | 2339 | axp->target_auid[axp->pid_count] = audit_get_loginuid(t); |
2273 | axp->target_uid[axp->pid_count] = t_uid; | 2340 | axp->target_uid[axp->pid_count] = t_uid; |
2274 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); | 2341 | axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t); |
@@ -2368,7 +2435,7 @@ static void audit_log_task(struct audit_buffer *ab) | |||
2368 | from_kgid(&init_user_ns, gid), | 2435 | from_kgid(&init_user_ns, gid), |
2369 | sessionid); | 2436 | sessionid); |
2370 | audit_log_task_context(ab); | 2437 | audit_log_task_context(ab); |
2371 | audit_log_format(ab, " pid=%d comm=", current->pid); | 2438 | audit_log_format(ab, " pid=%d comm=", task_pid_nr(current)); |
2372 | audit_log_untrustedstring(ab, current->comm); | 2439 | audit_log_untrustedstring(ab, current->comm); |
2373 | if (mm) { | 2440 | if (mm) { |
2374 | down_read(&mm->mmap_sem); | 2441 | down_read(&mm->mmap_sem); |
diff --git a/kernel/seccomp.c b/kernel/seccomp.c index fd609bd9d6dd..d8d046c0726a 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c | |||
@@ -71,7 +71,7 @@ static void populate_seccomp_data(struct seccomp_data *sd) | |||
71 | struct pt_regs *regs = task_pt_regs(task); | 71 | struct pt_regs *regs = task_pt_regs(task); |
72 | 72 | ||
73 | sd->nr = syscall_get_nr(task, regs); | 73 | sd->nr = syscall_get_nr(task, regs); |
74 | sd->arch = syscall_get_arch(task, regs); | 74 | sd->arch = syscall_get_arch(); |
75 | 75 | ||
76 | /* Unroll syscall_get_args to help gcc on arm. */ | 76 | /* Unroll syscall_get_args to help gcc on arm. */ |
77 | syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]); | 77 | syscall_get_arguments(task, regs, 0, 1, (unsigned long *) &sd->args[0]); |
@@ -348,7 +348,7 @@ static void seccomp_send_sigsys(int syscall, int reason) | |||
348 | info.si_code = SYS_SECCOMP; | 348 | info.si_code = SYS_SECCOMP; |
349 | info.si_call_addr = (void __user *)KSTK_EIP(current); | 349 | info.si_call_addr = (void __user *)KSTK_EIP(current); |
350 | info.si_errno = reason; | 350 | info.si_errno = reason; |
351 | info.si_arch = syscall_get_arch(current, task_pt_regs(current)); | 351 | info.si_arch = syscall_get_arch(); |
352 | info.si_syscall = syscall; | 352 | info.si_syscall = syscall; |
353 | force_sig_info(SIGSYS, &info, current); | 353 | force_sig_info(SIGSYS, &info, current); |
354 | } | 354 | } |
diff --git a/lib/Kconfig b/lib/Kconfig index 5d4984c505f8..4771fb3f4da4 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -182,6 +182,15 @@ config AUDIT_GENERIC | |||
182 | depends on AUDIT && !AUDIT_ARCH | 182 | depends on AUDIT && !AUDIT_ARCH |
183 | default y | 183 | default y |
184 | 184 | ||
185 | config AUDIT_ARCH_COMPAT_GENERIC | ||
186 | bool | ||
187 | default n | ||
188 | |||
189 | config AUDIT_COMPAT_GENERIC | ||
190 | bool | ||
191 | depends on AUDIT_GENERIC && AUDIT_ARCH_COMPAT_GENERIC && COMPAT | ||
192 | default y | ||
193 | |||
185 | config RANDOM32_SELFTEST | 194 | config RANDOM32_SELFTEST |
186 | bool "PRNG perform self test on init" | 195 | bool "PRNG perform self test on init" |
187 | default n | 196 | default n |
diff --git a/lib/Makefile b/lib/Makefile index 48140e3ba73f..0cd7b68e1382 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -96,6 +96,7 @@ obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o | |||
96 | obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o | 96 | obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o |
97 | obj-$(CONFIG_SMP) += percpu_counter.o | 97 | obj-$(CONFIG_SMP) += percpu_counter.o |
98 | obj-$(CONFIG_AUDIT_GENERIC) += audit.o | 98 | obj-$(CONFIG_AUDIT_GENERIC) += audit.o |
99 | obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o | ||
99 | 100 | ||
100 | obj-$(CONFIG_SWIOTLB) += swiotlb.o | 101 | obj-$(CONFIG_SWIOTLB) += swiotlb.o |
101 | obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o | 102 | obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o |
diff --git a/lib/audit.c b/lib/audit.c index 76bbed4a20e5..1d726a22565b 100644 --- a/lib/audit.c +++ b/lib/audit.c | |||
@@ -30,11 +30,17 @@ static unsigned signal_class[] = { | |||
30 | 30 | ||
31 | int audit_classify_arch(int arch) | 31 | int audit_classify_arch(int arch) |
32 | { | 32 | { |
33 | return 0; | 33 | if (audit_is_compat(arch)) |
34 | return 1; | ||
35 | else | ||
36 | return 0; | ||
34 | } | 37 | } |
35 | 38 | ||
36 | int audit_classify_syscall(int abi, unsigned syscall) | 39 | int audit_classify_syscall(int abi, unsigned syscall) |
37 | { | 40 | { |
41 | if (audit_is_compat(abi)) | ||
42 | return audit_classify_compat_syscall(abi, syscall); | ||
43 | |||
38 | switch(syscall) { | 44 | switch(syscall) { |
39 | #ifdef __NR_open | 45 | #ifdef __NR_open |
40 | case __NR_open: | 46 | case __NR_open: |
@@ -57,6 +63,13 @@ int audit_classify_syscall(int abi, unsigned syscall) | |||
57 | 63 | ||
58 | static int __init audit_classes_init(void) | 64 | static int __init audit_classes_init(void) |
59 | { | 65 | { |
66 | #ifdef CONFIG_AUDIT_COMPAT_GENERIC | ||
67 | audit_register_class(AUDIT_CLASS_WRITE_32, compat_write_class); | ||
68 | audit_register_class(AUDIT_CLASS_READ_32, compat_read_class); | ||
69 | audit_register_class(AUDIT_CLASS_DIR_WRITE_32, compat_dir_class); | ||
70 | audit_register_class(AUDIT_CLASS_CHATTR_32, compat_chattr_class); | ||
71 | audit_register_class(AUDIT_CLASS_SIGNAL_32, compat_signal_class); | ||
72 | #endif | ||
60 | audit_register_class(AUDIT_CLASS_WRITE, write_class); | 73 | audit_register_class(AUDIT_CLASS_WRITE, write_class); |
61 | audit_register_class(AUDIT_CLASS_READ, read_class); | 74 | audit_register_class(AUDIT_CLASS_READ, read_class); |
62 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); | 75 | audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); |
diff --git a/lib/compat_audit.c b/lib/compat_audit.c new file mode 100644 index 000000000000..873f75b640ab --- /dev/null +++ b/lib/compat_audit.c | |||
@@ -0,0 +1,50 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/types.h> | ||
3 | #include <asm/unistd32.h> | ||
4 | |||
5 | unsigned compat_dir_class[] = { | ||
6 | #include <asm-generic/audit_dir_write.h> | ||
7 | ~0U | ||
8 | }; | ||
9 | |||
10 | unsigned compat_read_class[] = { | ||
11 | #include <asm-generic/audit_read.h> | ||
12 | ~0U | ||
13 | }; | ||
14 | |||
15 | unsigned compat_write_class[] = { | ||
16 | #include <asm-generic/audit_write.h> | ||
17 | ~0U | ||
18 | }; | ||
19 | |||
20 | unsigned compat_chattr_class[] = { | ||
21 | #include <asm-generic/audit_change_attr.h> | ||
22 | ~0U | ||
23 | }; | ||
24 | |||
25 | unsigned compat_signal_class[] = { | ||
26 | #include <asm-generic/audit_signal.h> | ||
27 | ~0U | ||
28 | }; | ||
29 | |||
30 | int audit_classify_compat_syscall(int abi, unsigned syscall) | ||
31 | { | ||
32 | switch (syscall) { | ||
33 | #ifdef __NR_open | ||
34 | case __NR_open: | ||
35 | return 2; | ||
36 | #endif | ||
37 | #ifdef __NR_openat | ||
38 | case __NR_openat: | ||
39 | return 3; | ||
40 | #endif | ||
41 | #ifdef __NR_socketcall | ||
42 | case __NR_socketcall: | ||
43 | return 4; | ||
44 | #endif | ||
45 | case __NR_execve: | ||
46 | return 5; | ||
47 | default: | ||
48 | return 1; | ||
49 | } | ||
50 | } | ||
@@ -446,6 +446,54 @@ unsigned long vm_commit_limit(void) | |||
446 | return allowed; | 446 | return allowed; |
447 | } | 447 | } |
448 | 448 | ||
449 | /** | ||
450 | * get_cmdline() - copy the cmdline value to a buffer. | ||
451 | * @task: the task whose cmdline value to copy. | ||
452 | * @buffer: the buffer to copy to. | ||
453 | * @buflen: the length of the buffer. Larger cmdline values are truncated | ||
454 | * to this length. | ||
455 | * Returns the size of the cmdline field copied. Note that the copy does | ||
456 | * not guarantee an ending NULL byte. | ||
457 | */ | ||
458 | int get_cmdline(struct task_struct *task, char *buffer, int buflen) | ||
459 | { | ||
460 | int res = 0; | ||
461 | unsigned int len; | ||
462 | struct mm_struct *mm = get_task_mm(task); | ||
463 | if (!mm) | ||
464 | goto out; | ||
465 | if (!mm->arg_end) | ||
466 | goto out_mm; /* Shh! No looking before we're done */ | ||
467 | |||
468 | len = mm->arg_end - mm->arg_start; | ||
469 | |||
470 | if (len > buflen) | ||
471 | len = buflen; | ||
472 | |||
473 | res = access_process_vm(task, mm->arg_start, buffer, len, 0); | ||
474 | |||
475 | /* | ||
476 | * If the nul at the end of args has been overwritten, then | ||
477 | * assume application is using setproctitle(3). | ||
478 | */ | ||
479 | if (res > 0 && buffer[res-1] != '\0' && len < buflen) { | ||
480 | len = strnlen(buffer, res); | ||
481 | if (len < res) { | ||
482 | res = len; | ||
483 | } else { | ||
484 | len = mm->env_end - mm->env_start; | ||
485 | if (len > buflen - res) | ||
486 | len = buflen - res; | ||
487 | res += access_process_vm(task, mm->env_start, | ||
488 | buffer+res, len, 0); | ||
489 | res = strnlen(buffer, res); | ||
490 | } | ||
491 | } | ||
492 | out_mm: | ||
493 | mmput(mm); | ||
494 | out: | ||
495 | return res; | ||
496 | } | ||
449 | 497 | ||
450 | /* Tracepoints definitions. */ | 498 | /* Tracepoints definitions. */ |
451 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); | 499 | EXPORT_TRACEPOINT_SYMBOL(kmalloc); |
diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c index aab9fa5a8231..90987d15b6fe 100644 --- a/security/integrity/integrity_audit.c +++ b/security/integrity/integrity_audit.c | |||
@@ -40,7 +40,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, | |||
40 | 40 | ||
41 | ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); | 41 | ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); |
42 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", | 42 | audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", |
43 | current->pid, | 43 | task_pid_nr(current), |
44 | from_kuid(&init_user_ns, current_cred()->uid), | 44 | from_kuid(&init_user_ns, current_cred()->uid), |
45 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 45 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
46 | audit_get_sessionid(current)); | 46 | audit_get_sessionid(current)); |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 9a62045e6282..69fdf3bc765b 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -220,7 +220,7 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
220 | */ | 220 | */ |
221 | BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); | 221 | BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); |
222 | 222 | ||
223 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | 223 | audit_log_format(ab, " pid=%d comm=", task_pid_nr(tsk)); |
224 | audit_log_untrustedstring(ab, tsk->comm); | 224 | audit_log_untrustedstring(ab, tsk->comm); |
225 | 225 | ||
226 | switch (a->type) { | 226 | switch (a->type) { |
@@ -278,9 +278,12 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
278 | } | 278 | } |
279 | case LSM_AUDIT_DATA_TASK: | 279 | case LSM_AUDIT_DATA_TASK: |
280 | tsk = a->u.tsk; | 280 | tsk = a->u.tsk; |
281 | if (tsk && tsk->pid) { | 281 | if (tsk) { |
282 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | 282 | pid_t pid = task_pid_nr(tsk); |
283 | audit_log_untrustedstring(ab, tsk->comm); | 283 | if (pid) { |
284 | audit_log_format(ab, " pid=%d comm=", pid); | ||
285 | audit_log_untrustedstring(ab, tsk->comm); | ||
286 | } | ||
284 | } | 287 | } |
285 | break; | 288 | break; |
286 | case LSM_AUDIT_DATA_NET: | 289 | case LSM_AUDIT_DATA_NET: |