diff options
author | Nathaniel Husted <nhusted@gmail.com> | 2012-01-03 14:23:09 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-17 16:17:01 -0500 |
commit | 29ef73b7a823b77a7cd0bdd7d7cded3fb6c2587b (patch) | |
tree | 4edfccf0b4d2b24c8e6069113eb69bb8c7a9b037 | |
parent | 4043cde8ecf7f7d880eb1133c201a3d392fd68c3 (diff) |
Kernel: Audit Support For The ARM Platform
This patch provides functionality to audit system call events on the
ARM platform. The implementation was based off the structure of the
MIPS platform and information in this
(http://lists.fedoraproject.org/pipermail/arm/2009-October/000382.html)
mailing list thread. The required audit_syscall_exit and
audit_syscall_entry checks were added to ptrace using the standard
registers for system call values (r0 through r3). A thread information
flag was added for auditing (TIF_SYSCALL_AUDIT) and a meta-flag was
added (_TIF_SYSCALL_WORK) to simplify modifications to the syscall
entry/exit. Now, if either the TRACE flag is set or the AUDIT flag is
set, the syscall_trace function will be executed. The prober changes
were made to Kconfig to allow CONFIG_AUDITSYSCALL to be enabled.
Due to platform availability limitations, this patch was only tested
on the Android platform running the modified "android-goldfish-2.6.29"
kernel. A test compile was performed using Code Sourcery's
cross-compilation toolset and the current linux-3.0 stable kernel. The
changes compile without error. I'm hoping, due to the simple modifications,
the patch is "obviously correct".
Signed-off-by: Nathaniel Husted <nhusted@gmail.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r-- | arch/arm/include/asm/kprobes.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/ptrace.h | 5 | ||||
-rw-r--r-- | arch/arm/include/asm/thread_info.h | 6 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 4 | ||||
-rw-r--r-- | arch/arm/kernel/ptrace.c | 16 | ||||
-rw-r--r-- | init/Kconfig | 2 |
6 files changed, 25 insertions, 9 deletions
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index feec86768f9c..f82ec22eeb11 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h | |||
@@ -24,7 +24,6 @@ | |||
24 | #define MAX_INSN_SIZE 2 | 24 | #define MAX_INSN_SIZE 2 |
25 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ | 25 | #define MAX_STACK_SIZE 64 /* 32 would probably be OK */ |
26 | 26 | ||
27 | #define regs_return_value(regs) ((regs)->ARM_r0) | ||
28 | #define flush_insn_slot(p) do { } while (0) | 27 | #define flush_insn_slot(p) do { } while (0) |
29 | #define kretprobe_blacklist_size 0 | 28 | #define kretprobe_blacklist_size 0 |
30 | 29 | ||
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 96187ff58c24..451808ba1211 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
@@ -189,6 +189,11 @@ static inline int valid_user_regs(struct pt_regs *regs) | |||
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
191 | 191 | ||
192 | static inline long regs_return_value(struct pt_regs *regs) | ||
193 | { | ||
194 | return regs->ARM_r0; | ||
195 | } | ||
196 | |||
192 | #define instruction_pointer(regs) (regs)->ARM_pc | 197 | #define instruction_pointer(regs) (regs)->ARM_pc |
193 | 198 | ||
194 | #ifdef CONFIG_SMP | 199 | #ifdef CONFIG_SMP |
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 0f30c3a78fc1..d4c24d412a8d 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h | |||
@@ -129,6 +129,7 @@ extern void vfp_flush_hwstate(struct thread_info *); | |||
129 | /* | 129 | /* |
130 | * thread information flags: | 130 | * thread information flags: |
131 | * TIF_SYSCALL_TRACE - syscall trace active | 131 | * TIF_SYSCALL_TRACE - syscall trace active |
132 | * TIF_SYSCAL_AUDIT - syscall auditing active | ||
132 | * TIF_SIGPENDING - signal pending | 133 | * TIF_SIGPENDING - signal pending |
133 | * TIF_NEED_RESCHED - rescheduling necessary | 134 | * TIF_NEED_RESCHED - rescheduling necessary |
134 | * TIF_NOTIFY_RESUME - callback before returning to user | 135 | * TIF_NOTIFY_RESUME - callback before returning to user |
@@ -139,6 +140,7 @@ extern void vfp_flush_hwstate(struct thread_info *); | |||
139 | #define TIF_NEED_RESCHED 1 | 140 | #define TIF_NEED_RESCHED 1 |
140 | #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ | 141 | #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ |
141 | #define TIF_SYSCALL_TRACE 8 | 142 | #define TIF_SYSCALL_TRACE 8 |
143 | #define TIF_SYSCALL_AUDIT 9 | ||
142 | #define TIF_POLLING_NRFLAG 16 | 144 | #define TIF_POLLING_NRFLAG 16 |
143 | #define TIF_USING_IWMMXT 17 | 145 | #define TIF_USING_IWMMXT 17 |
144 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ | 146 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ |
@@ -149,11 +151,15 @@ extern void vfp_flush_hwstate(struct thread_info *); | |||
149 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 151 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
150 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 152 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
151 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 153 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
154 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | ||
152 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 155 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
153 | #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) | 156 | #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT) |
154 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) | 157 | #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) |
155 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 158 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
156 | 159 | ||
160 | /* Checks for any syscall work in entry-common.S */ | ||
161 | #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT) | ||
162 | |||
157 | /* | 163 | /* |
158 | * Change these and you break ASM code in entry-common.S | 164 | * Change these and you break ASM code in entry-common.S |
159 | */ | 165 | */ |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index b2a27b6b0046..520889cf1b5b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
@@ -87,7 +87,7 @@ ENTRY(ret_from_fork) | |||
87 | get_thread_info tsk | 87 | get_thread_info tsk |
88 | ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing | 88 | ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing |
89 | mov why, #1 | 89 | mov why, #1 |
90 | tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? | 90 | tst r1, #_TIF_SYSCALL_WORK @ are we tracing syscalls? |
91 | beq ret_slow_syscall | 91 | beq ret_slow_syscall |
92 | mov r1, sp | 92 | mov r1, sp |
93 | mov r0, #1 @ trace exit [IP = 1] | 93 | mov r0, #1 @ trace exit [IP = 1] |
@@ -443,7 +443,7 @@ ENTRY(vector_swi) | |||
443 | 1: | 443 | 1: |
444 | #endif | 444 | #endif |
445 | 445 | ||
446 | tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? | 446 | tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? |
447 | bne __sys_trace | 447 | bne __sys_trace |
448 | 448 | ||
449 | cmp scno, #NR_syscalls @ check upper syscall limit | 449 | cmp scno, #NR_syscalls @ check upper syscall limit |
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 483727ad6892..e1d5e1929fbd 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
@@ -906,11 +906,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) | |||
906 | { | 906 | { |
907 | unsigned long ip; | 907 | unsigned long ip; |
908 | 908 | ||
909 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
910 | return scno; | ||
911 | if (!(current->ptrace & PT_PTRACED)) | ||
912 | return scno; | ||
913 | |||
914 | /* | 909 | /* |
915 | * Save IP. IP is used to denote syscall entry/exit: | 910 | * Save IP. IP is used to denote syscall entry/exit: |
916 | * IP = 0 -> entry, = 1 -> exit | 911 | * IP = 0 -> entry, = 1 -> exit |
@@ -918,6 +913,17 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) | |||
918 | ip = regs->ARM_ip; | 913 | ip = regs->ARM_ip; |
919 | regs->ARM_ip = why; | 914 | regs->ARM_ip = why; |
920 | 915 | ||
916 | if (!ip) | ||
917 | audit_syscall_exit(regs); | ||
918 | else | ||
919 | audit_syscall_entry(AUDIT_ARCH_ARMEB, scno, regs->ARM_r0, | ||
920 | regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); | ||
921 | |||
922 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | ||
923 | return scno; | ||
924 | if (!(current->ptrace & PT_PTRACED)) | ||
925 | return scno; | ||
926 | |||
921 | current_thread_info()->syscall = scno; | 927 | current_thread_info()->syscall = scno; |
922 | 928 | ||
923 | /* the 0x80 provides a way for the tracing parent to distinguish | 929 | /* the 0x80 provides a way for the tracing parent to distinguish |
diff --git a/init/Kconfig b/init/Kconfig index 5ad8b775f2ac..fe25ffbe818b 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -355,7 +355,7 @@ config AUDIT | |||
355 | 355 | ||
356 | config AUDITSYSCALL | 356 | config AUDITSYSCALL |
357 | bool "Enable system-call auditing support" | 357 | bool "Enable system-call auditing support" |
358 | depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH) | 358 | depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || ARM) |
359 | default y if SECURITY_SELINUX | 359 | default y if SECURITY_SELINUX |
360 | help | 360 | help |
361 | Enable low-overhead system-call auditing infrastructure that | 361 | Enable low-overhead system-call auditing infrastructure that |