aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ia64/include/asm/ptrace.h13
-rw-r--r--arch/ia64/kernel/ptrace.c9
-rw-r--r--arch/microblaze/include/asm/ptrace.h5
-rw-r--r--arch/microblaze/kernel/ptrace.c3
-rw-r--r--arch/mips/include/asm/ptrace.h14
-rw-r--r--arch/mips/kernel/ptrace.c4
-rw-r--r--arch/powerpc/include/asm/ptrace.h13
-rw-r--r--arch/powerpc/kernel/ptrace.c4
-rw-r--r--arch/s390/include/asm/ptrace.h6
-rw-r--r--arch/s390/kernel/ptrace.c4
-rw-r--r--arch/sh/include/asm/ptrace_32.h5
-rw-r--r--arch/sh/include/asm/ptrace_64.h5
-rw-r--r--arch/sh/kernel/ptrace_32.c4
-rw-r--r--arch/sh/kernel/ptrace_64.c4
-rw-r--r--arch/sparc/include/asm/ptrace.h10
-rw-r--r--arch/sparc/kernel/ptrace_64.c11
-rw-r--r--arch/um/kernel/ptrace.c4
-rw-r--r--arch/x86/ia32/ia32entry.S10
-rw-r--r--arch/x86/kernel/entry_32.S8
-rw-r--r--arch/x86/kernel/entry_64.S10
-rw-r--r--arch/x86/kernel/ptrace.c3
-rw-r--r--arch/x86/kernel/vm86_32.c4
-rw-r--r--arch/x86/um/shared/sysdep/ptrace.h5
-rw-r--r--include/linux/audit.h22
-rw-r--r--include/linux/ptrace.h10
-rw-r--r--kernel/auditsc.c16
26 files changed, 132 insertions, 74 deletions
diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h
index f5cb27614e35..68c98f5b3ca6 100644
--- a/arch/ia64/include/asm/ptrace.h
+++ b/arch/ia64/include/asm/ptrace.h
@@ -246,7 +246,18 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
246 return regs->ar_bspstore; 246 return regs->ar_bspstore;
247} 247}
248 248
249#define regs_return_value(regs) ((regs)->r8) 249static inline int is_syscall_success(struct pt_regs *regs)
250{
251 return regs->r10 != -1;
252}
253
254static inline long regs_return_value(struct pt_regs *regs)
255{
256 if (is_syscall_success(regs))
257 return regs->r8;
258 else
259 return -regs->r8;
260}
250 261
251/* Conserve space in histogram by encoding slot bits in address 262/* Conserve space in histogram by encoding slot bits in address
252 * bits 2 and 3 rather than bits 0 and 1. 263 * bits 2 and 3 rather than bits 0 and 1.
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 8848f43d819e..2c154088cce7 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1268,14 +1268,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
1268{ 1268{
1269 int step; 1269 int step;
1270 1270
1271 if (unlikely(current->audit_context)) { 1271 audit_syscall_exit(&regs);
1272 int success = AUDITSC_RESULT(regs.r10);
1273 long result = regs.r8;
1274
1275 if (success != AUDITSC_SUCCESS)
1276 result = -result;
1277 audit_syscall_exit(success, result);
1278 }
1279 1272
1280 step = test_thread_flag(TIF_SINGLESTEP); 1273 step = test_thread_flag(TIF_SINGLESTEP);
1281 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 1274 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index 816bee64b196..94e92c805859 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -61,6 +61,11 @@ struct pt_regs {
61#define instruction_pointer(regs) ((regs)->pc) 61#define instruction_pointer(regs) ((regs)->pc)
62#define profile_pc(regs) instruction_pointer(regs) 62#define profile_pc(regs) instruction_pointer(regs)
63 63
64static inline long regs_return_value(struct pt_regs *regs)
65{
66 return regs->r3;
67}
68
64#else /* __KERNEL__ */ 69#else /* __KERNEL__ */
65 70
66/* pt_regs offsets used by gdbserver etc in ptrace syscalls */ 71/* pt_regs offsets used by gdbserver etc in ptrace syscalls */
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 043cb58f9c44..f564b1bfd386 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -159,8 +159,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
159{ 159{
160 int step; 160 int step;
161 161
162 if (unlikely(current->audit_context)) 162 audit_syscall_exit(regs);
163 audit_syscall_exit(AUDITSC_RESULT(regs->r3), regs->r3);
164 163
165 step = test_thread_flag(TIF_SINGLESTEP); 164 step = test_thread_flag(TIF_SINGLESTEP);
166 if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 165 if (step || test_thread_flag(TIF_SYSCALL_TRACE))
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index de39b1f343ea..7d409505df2d 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -137,7 +137,19 @@ extern int ptrace_set_watch_regs(struct task_struct *child,
137 */ 137 */
138#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER) 138#define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
139 139
140#define regs_return_value(_regs) ((_regs)->regs[2]) 140static inline int is_syscall_success(struct pt_regs *regs)
141{
142 return !regs->regs[7];
143}
144
145static inline long regs_return_value(struct pt_regs *regs)
146{
147 if (is_syscall_success(regs))
148 return regs->regs[2];
149 else
150 return -regs->regs[2];
151}
152
141#define instruction_pointer(regs) ((regs)->cp0_epc) 153#define instruction_pointer(regs) ((regs)->cp0_epc)
142#define profile_pc(regs) instruction_pointer(regs) 154#define profile_pc(regs) instruction_pointer(regs)
143 155
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4e6ea1ffad46..ab0f1963a7bd 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -572,9 +572,7 @@ out:
572 */ 572 */
573asmlinkage void syscall_trace_leave(struct pt_regs *regs) 573asmlinkage void syscall_trace_leave(struct pt_regs *regs)
574{ 574{
575 if (unlikely(current->audit_context)) 575 audit_syscall_exit(regs);
576 audit_syscall_exit(AUDITSC_RESULT(regs->regs[7]),
577 -regs->regs[2]);
578 576
579 if (!(current->ptrace & PT_PTRACED)) 577 if (!(current->ptrace & PT_PTRACED))
580 return; 578 return;
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 48223f9b8728..78a205162fd7 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -86,7 +86,18 @@ struct pt_regs {
86#define instruction_pointer(regs) ((regs)->nip) 86#define instruction_pointer(regs) ((regs)->nip)
87#define user_stack_pointer(regs) ((regs)->gpr[1]) 87#define user_stack_pointer(regs) ((regs)->gpr[1])
88#define kernel_stack_pointer(regs) ((regs)->gpr[1]) 88#define kernel_stack_pointer(regs) ((regs)->gpr[1])
89#define regs_return_value(regs) ((regs)->gpr[3]) 89static inline int is_syscall_success(struct pt_regs *regs)
90{
91 return !(regs->ccr & 0x10000000);
92}
93
94static inline long regs_return_value(struct pt_regs *regs)
95{
96 if (is_syscall_success(regs))
97 return regs->gpr[3];
98 else
99 return -regs->gpr[3];
100}
90 101
91#ifdef CONFIG_SMP 102#ifdef CONFIG_SMP
92extern unsigned long profile_pc(struct pt_regs *regs); 103extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 5de73dbd15c7..09d31c12a5e3 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -1748,9 +1748,7 @@ void do_syscall_trace_leave(struct pt_regs *regs)
1748{ 1748{
1749 int step; 1749 int step;
1750 1750
1751 if (unlikely(current->audit_context)) 1751 audit_syscall_exit(regs);
1752 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
1753 regs->result);
1754 1752
1755 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1753 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1756 trace_sys_exit(regs, regs->result); 1754 trace_sys_exit(regs, regs->result);
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 56da355678f4..aeb77f017985 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -541,9 +541,13 @@ struct user_regs_struct
541#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) 541#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
542#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) 542#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
543#define user_stack_pointer(regs)((regs)->gprs[15]) 543#define user_stack_pointer(regs)((regs)->gprs[15])
544#define regs_return_value(regs)((regs)->gprs[2])
545#define profile_pc(regs) instruction_pointer(regs) 544#define profile_pc(regs) instruction_pointer(regs)
546 545
546static inline long regs_return_value(struct pt_regs *regs)
547{
548 return regs->gprs[2];
549}
550
547int regs_query_register_offset(const char *name); 551int regs_query_register_offset(const char *name);
548const char *regs_query_register_name(unsigned int offset); 552const char *regs_query_register_name(unsigned int offset);
549unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); 553unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset);
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 573bc29551ef..f52758600980 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -751,9 +751,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
751 751
752asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) 752asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
753{ 753{
754 if (unlikely(current->audit_context)) 754 audit_syscall_exit(regs);
755 audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
756 regs->gprs[2]);
757 755
758 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 756 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
759 trace_sys_exit(regs, regs->gprs[2]); 757 trace_sys_exit(regs, regs->gprs[2]);
diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h
index 6c2239cca1a2..2d3e906aa722 100644
--- a/arch/sh/include/asm/ptrace_32.h
+++ b/arch/sh/include/asm/ptrace_32.h
@@ -76,7 +76,10 @@ struct pt_dspregs {
76#ifdef __KERNEL__ 76#ifdef __KERNEL__
77 77
78#define MAX_REG_OFFSET offsetof(struct pt_regs, tra) 78#define MAX_REG_OFFSET offsetof(struct pt_regs, tra)
79#define regs_return_value(_regs) ((_regs)->regs[0]) 79static inline long regs_return_value(struct pt_regs *regs)
80{
81 return regs->regs[0];
82}
80 83
81#endif /* __KERNEL__ */ 84#endif /* __KERNEL__ */
82 85
diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h
index bf9be7764d69..eb3fcceaf64b 100644
--- a/arch/sh/include/asm/ptrace_64.h
+++ b/arch/sh/include/asm/ptrace_64.h
@@ -13,7 +13,10 @@ struct pt_regs {
13#ifdef __KERNEL__ 13#ifdef __KERNEL__
14 14
15#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) 15#define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7])
16#define regs_return_value(_regs) ((_regs)->regs[3]) 16static inline long regs_return_value(struct pt_regs *regs)
17{
18 return regs->regs[3];
19}
17 20
18#endif /* __KERNEL__ */ 21#endif /* __KERNEL__ */
19 22
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index 92b3c276339a..c0b5c179d27b 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -530,9 +530,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
530{ 530{
531 int step; 531 int step;
532 532
533 if (unlikely(current->audit_context)) 533 audit_syscall_exit(regs);
534 audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]),
535 regs->regs[0]);
536 534
537 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 535 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
538 trace_sys_exit(regs, regs->regs[0]); 536 trace_sys_exit(regs, regs->regs[0]);
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c
index c8f97649f354..ba720d686435 100644
--- a/arch/sh/kernel/ptrace_64.c
+++ b/arch/sh/kernel/ptrace_64.c
@@ -548,9 +548,7 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
548{ 548{
549 int step; 549 int step;
550 550
551 if (unlikely(current->audit_context)) 551 audit_syscall_exit(regs);
552 audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
553 regs->regs[9]);
554 552
555 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 553 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
556 trace_sys_exit(regs, regs->regs[9]); 554 trace_sys_exit(regs, regs->regs[9]);
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index a0e1bcf843a1..c00c3b5c2806 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -207,7 +207,15 @@ do { current_thread_info()->syscall_noerror = 1; \
207#define instruction_pointer(regs) ((regs)->tpc) 207#define instruction_pointer(regs) ((regs)->tpc)
208#define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) 208#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
209#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) 209#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
210#define regs_return_value(regs) ((regs)->u_regs[UREG_I0]) 210static inline int is_syscall_success(struct pt_regs *regs)
211{
212 return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY));
213}
214
215static inline long regs_return_value(struct pt_regs *regs)
216{
217 return regs->u_regs[UREG_I0];
218}
211#ifdef CONFIG_SMP 219#ifdef CONFIG_SMP
212extern unsigned long profile_pc(struct pt_regs *); 220extern unsigned long profile_pc(struct pt_regs *);
213#else 221#else
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 96ee50a80661..c73c8c50f117 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1086,17 +1086,8 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1086 1086
1087asmlinkage void syscall_trace_leave(struct pt_regs *regs) 1087asmlinkage void syscall_trace_leave(struct pt_regs *regs)
1088{ 1088{
1089#ifdef CONFIG_AUDITSYSCALL 1089 audit_syscall_exit(regs);
1090 if (unlikely(current->audit_context)) {
1091 unsigned long tstate = regs->tstate;
1092 int result = AUDITSC_SUCCESS;
1093 1090
1094 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
1095 result = AUDITSC_FAILURE;
1096
1097 audit_syscall_exit(result, regs->u_regs[UREG_I0]);
1098 }
1099#endif
1100 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1091 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1101 trace_sys_exit(regs, regs->u_regs[UREG_G1]); 1092 trace_sys_exit(regs, regs->u_regs[UREG_G1]);
1102 1093
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index c9da32b0c707..2ccf25c42feb 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -175,8 +175,8 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit)
175 UPT_SYSCALL_ARG2(regs), 175 UPT_SYSCALL_ARG2(regs),
176 UPT_SYSCALL_ARG3(regs), 176 UPT_SYSCALL_ARG3(regs),
177 UPT_SYSCALL_ARG4(regs)); 177 UPT_SYSCALL_ARG4(regs));
178 else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), 178 else
179 UPT_SYSCALL_RET(regs)); 179 audit_syscall_exit(regs);
180 } 180 }
181 181
182 /* Fake a debug trap */ 182 /* Fake a debug trap */
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 3e274564f6bf..64ced0b8f8fd 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -14,6 +14,7 @@
14#include <asm/segment.h> 14#include <asm/segment.h>
15#include <asm/irqflags.h> 15#include <asm/irqflags.h>
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17#include <linux/err.h>
17 18
18/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ 19/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
19#include <linux/elf-em.h> 20#include <linux/elf-em.h>
@@ -208,12 +209,11 @@ sysexit_from_sys_call:
208 TRACE_IRQS_ON 209 TRACE_IRQS_ON
209 sti 210 sti
210 movl %eax,%esi /* second arg, syscall return value */ 211 movl %eax,%esi /* second arg, syscall return value */
211 cmpl $0,%eax /* is it < 0? */ 212 cmpl $-MAX_ERRNO,%eax /* is it an error ? */
212 setl %al /* 1 if so, 0 if not */ 213 setbe %al /* 1 if so, 0 if not */
213 movzbl %al,%edi /* zero-extend that into %edi */ 214 movzbl %al,%edi /* zero-extend that into %edi */
214 inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */ 215 call __audit_syscall_exit
215 call audit_syscall_exit 216 movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */
216 movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall return value */
217 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi 217 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
218 cli 218 cli
219 TRACE_IRQS_OFF 219 TRACE_IRQS_OFF
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 22d0e21b4dd7..a22facf06f0e 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -42,6 +42,7 @@
42 */ 42 */
43 43
44#include <linux/linkage.h> 44#include <linux/linkage.h>
45#include <linux/err.h>
45#include <asm/thread_info.h> 46#include <asm/thread_info.h>
46#include <asm/irqflags.h> 47#include <asm/irqflags.h>
47#include <asm/errno.h> 48#include <asm/errno.h>
@@ -466,11 +467,10 @@ sysexit_audit:
466 TRACE_IRQS_ON 467 TRACE_IRQS_ON
467 ENABLE_INTERRUPTS(CLBR_ANY) 468 ENABLE_INTERRUPTS(CLBR_ANY)
468 movl %eax,%edx /* second arg, syscall return value */ 469 movl %eax,%edx /* second arg, syscall return value */
469 cmpl $0,%eax /* is it < 0? */ 470 cmpl $-MAX_ERRNO,%eax /* is it an error ? */
470 setl %al /* 1 if so, 0 if not */ 471 setbe %al /* 1 if so, 0 if not */
471 movzbl %al,%eax /* zero-extend that */ 472 movzbl %al,%eax /* zero-extend that */
472 inc %eax /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */ 473 call __audit_syscall_exit
473 call audit_syscall_exit
474 DISABLE_INTERRUPTS(CLBR_ANY) 474 DISABLE_INTERRUPTS(CLBR_ANY)
475 TRACE_IRQS_OFF 475 TRACE_IRQS_OFF
476 movl TI_flags(%ebp), %ecx 476 movl TI_flags(%ebp), %ecx
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index a20e1cb9dc87..e51393dd93a3 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -55,6 +55,7 @@
55#include <asm/paravirt.h> 55#include <asm/paravirt.h>
56#include <asm/ftrace.h> 56#include <asm/ftrace.h>
57#include <asm/percpu.h> 57#include <asm/percpu.h>
58#include <linux/err.h>
58 59
59/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ 60/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */
60#include <linux/elf-em.h> 61#include <linux/elf-em.h>
@@ -563,17 +564,16 @@ auditsys:
563 jmp system_call_fastpath 564 jmp system_call_fastpath
564 565
565 /* 566 /*
566 * Return fast path for syscall audit. Call audit_syscall_exit() 567 * Return fast path for syscall audit. Call __audit_syscall_exit()
567 * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT 568 * directly and then jump back to the fast path with TIF_SYSCALL_AUDIT
568 * masked off. 569 * masked off.
569 */ 570 */
570sysret_audit: 571sysret_audit:
571 movq RAX-ARGOFFSET(%rsp),%rsi /* second arg, syscall return value */ 572 movq RAX-ARGOFFSET(%rsp),%rsi /* second arg, syscall return value */
572 cmpq $0,%rsi /* is it < 0? */ 573 cmpq $-MAX_ERRNO,%rsi /* is it < -MAX_ERRNO? */
573 setl %al /* 1 if so, 0 if not */ 574 setbe %al /* 1 if so, 0 if not */
574 movzbl %al,%edi /* zero-extend that into %edi */ 575 movzbl %al,%edi /* zero-extend that into %edi */
575 inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */ 576 call __audit_syscall_exit
576 call audit_syscall_exit
577 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi 577 movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
578 jmp sysret_check 578 jmp sysret_check
579#endif /* CONFIG_AUDITSYSCALL */ 579#endif /* CONFIG_AUDITSYSCALL */
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 89a04c7b5bb6..8b0218758775 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1414,8 +1414,7 @@ void syscall_trace_leave(struct pt_regs *regs)
1414{ 1414{
1415 bool step; 1415 bool step;
1416 1416
1417 if (unlikely(current->audit_context)) 1417 audit_syscall_exit(regs);
1418 audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax);
1419 1418
1420 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 1419 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
1421 trace_sys_exit(regs, regs->ax); 1420 trace_sys_exit(regs, regs->ax);
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 863f8753ab0a..af17e1c966dc 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -335,9 +335,9 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
335 if (info->flags & VM86_SCREEN_BITMAP) 335 if (info->flags & VM86_SCREEN_BITMAP)
336 mark_screen_rdonly(tsk->mm); 336 mark_screen_rdonly(tsk->mm);
337 337
338 /*call audit_syscall_exit since we do not exit via the normal paths */ 338 /*call __audit_syscall_exit since we do not exit via the normal paths */
339 if (unlikely(current->audit_context)) 339 if (unlikely(current->audit_context))
340 audit_syscall_exit(AUDITSC_RESULT(0), 0); 340 __audit_syscall_exit(1, 0);
341 341
342 __asm__ __volatile__( 342 __asm__ __volatile__(
343 "movl %0,%%esp\n\t" 343 "movl %0,%%esp\n\t"
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
index 711b1621747f..5ef9344a8b24 100644
--- a/arch/x86/um/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -3,3 +3,8 @@
3#else 3#else
4#include "ptrace_64.h" 4#include "ptrace_64.h"
5#endif 5#endif
6
7static inline long regs_return_value(struct uml_pt_regs *regs)
8{
9 return UPT_SYSCALL_RET(regs);
10}
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6e1c533f9b46..3d65e4b3ba06 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
26 26
27#include <linux/types.h> 27#include <linux/types.h>
28#include <linux/elf-em.h> 28#include <linux/elf-em.h>
29#include <linux/ptrace.h>
29 30
30/* The netlink messages for the audit system is divided into blocks: 31/* The netlink messages for the audit system is divided into blocks:
31 * 1000 - 1099 are for commanding the audit system 32 * 1000 - 1099 are for commanding the audit system
@@ -408,10 +409,6 @@ struct audit_field {
408 void *lsm_rule; 409 void *lsm_rule;
409}; 410};
410 411
411#define AUDITSC_INVALID 0
412#define AUDITSC_SUCCESS 1
413#define AUDITSC_FAILURE 2
414#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
415extern int __init audit_register_class(int class, unsigned *list); 412extern int __init audit_register_class(int class, unsigned *list);
416extern int audit_classify_syscall(int abi, unsigned syscall); 413extern int audit_classify_syscall(int abi, unsigned syscall);
417extern int audit_classify_arch(int arch); 414extern int audit_classify_arch(int arch);
@@ -424,7 +421,7 @@ extern void audit_free(struct task_struct *task);
424extern void audit_syscall_entry(int arch, 421extern void audit_syscall_entry(int arch,
425 int major, unsigned long a0, unsigned long a1, 422 int major, unsigned long a0, unsigned long a1,
426 unsigned long a2, unsigned long a3); 423 unsigned long a2, unsigned long a3);
427extern void audit_syscall_exit(int failed, long return_code); 424extern void __audit_syscall_exit(int ret_success, long ret_value);
428extern void __audit_getname(const char *name); 425extern void __audit_getname(const char *name);
429extern void audit_putname(const char *name); 426extern void audit_putname(const char *name);
430extern void __audit_inode(const char *name, const struct dentry *dentry); 427extern void __audit_inode(const char *name, const struct dentry *dentry);
@@ -438,6 +435,15 @@ static inline int audit_dummy_context(void)
438 void *p = current->audit_context; 435 void *p = current->audit_context;
439 return !p || *(int *)p; 436 return !p || *(int *)p;
440} 437}
438static inline void audit_syscall_exit(void *pt_regs)
439{
440 if (unlikely(current->audit_context)) {
441 int success = is_syscall_success(pt_regs);
442 int return_code = regs_return_value(pt_regs);
443
444 __audit_syscall_exit(success, return_code);
445 }
446}
441static inline void audit_getname(const char *name) 447static inline void audit_getname(const char *name)
442{ 448{
443 if (unlikely(!audit_dummy_context())) 449 if (unlikely(!audit_dummy_context()))
@@ -551,12 +557,12 @@ static inline void audit_mmap_fd(int fd, int flags)
551 557
552extern int audit_n_rules; 558extern int audit_n_rules;
553extern int audit_signals; 559extern int audit_signals;
554#else 560#else /* CONFIG_AUDITSYSCALL */
555#define audit_finish_fork(t) 561#define audit_finish_fork(t)
556#define audit_alloc(t) ({ 0; }) 562#define audit_alloc(t) ({ 0; })
557#define audit_free(t) do { ; } while (0) 563#define audit_free(t) do { ; } while (0)
558#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0) 564#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
559#define audit_syscall_exit(f,r) do { ; } while (0) 565#define audit_syscall_exit(r) do { ; } while (0)
560#define audit_dummy_context() 1 566#define audit_dummy_context() 1
561#define audit_getname(n) do { ; } while (0) 567#define audit_getname(n) do { ; } while (0)
562#define audit_putname(n) do { ; } while (0) 568#define audit_putname(n) do { ; } while (0)
@@ -587,7 +593,7 @@ extern int audit_signals;
587#define audit_ptrace(t) ((void)0) 593#define audit_ptrace(t) ((void)0)
588#define audit_n_rules 0 594#define audit_n_rules 0
589#define audit_signals 0 595#define audit_signals 0
590#endif 596#endif /* CONFIG_AUDITSYSCALL */
591 597
592#ifdef CONFIG_AUDIT 598#ifdef CONFIG_AUDIT
593/* These are defined in audit.c */ 599/* These are defined in audit.c */
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 800f113bea66..dd4cefa6519d 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -112,6 +112,7 @@
112 112
113#include <linux/compiler.h> /* For unlikely. */ 113#include <linux/compiler.h> /* For unlikely. */
114#include <linux/sched.h> /* For struct task_struct. */ 114#include <linux/sched.h> /* For struct task_struct. */
115#include <linux/err.h> /* for IS_ERR_VALUE */
115 116
116 117
117extern long arch_ptrace(struct task_struct *child, long request, 118extern long arch_ptrace(struct task_struct *child, long request,
@@ -265,6 +266,15 @@ static inline void ptrace_release_task(struct task_struct *task)
265#define force_successful_syscall_return() do { } while (0) 266#define force_successful_syscall_return() do { } while (0)
266#endif 267#endif
267 268
269#ifndef is_syscall_success
270/*
271 * On most systems we can tell if a syscall is a success based on if the retval
272 * is an error value. On some systems like ia64 and powerpc they have different
273 * indicators of success/failure and must define their own.
274 */
275#define is_syscall_success(regs) (!IS_ERR_VALUE((unsigned long)(regs_return_value(regs))))
276#endif
277
268/* 278/*
269 * <asm/ptrace.h> should define the following things inside #ifdef __KERNEL__. 279 * <asm/ptrace.h> should define the following things inside #ifdef __KERNEL__.
270 * 280 *
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e9bcb93800d8..3d2853808185 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -70,6 +70,11 @@
70 70
71#include "audit.h" 71#include "audit.h"
72 72
73/* flags stating the success for a syscall */
74#define AUDITSC_INVALID 0
75#define AUDITSC_SUCCESS 1
76#define AUDITSC_FAILURE 2
77
73/* AUDIT_NAMES is the number of slots we reserve in the audit_context 78/* AUDIT_NAMES is the number of slots we reserve in the audit_context
74 * for saving names from getname(). If we get more names we will allocate 79 * for saving names from getname(). If we get more names we will allocate
75 * a name dynamically and also add those to the list anchored by names_list. */ 80 * a name dynamically and also add those to the list anchored by names_list. */
@@ -1724,8 +1729,7 @@ void audit_finish_fork(struct task_struct *child)
1724 1729
1725/** 1730/**
1726 * audit_syscall_exit - deallocate audit context after a system call 1731 * audit_syscall_exit - deallocate audit context after a system call
1727 * @valid: success/failure flag 1732 * @pt_regs: syscall registers
1728 * @return_code: syscall return value
1729 * 1733 *
1730 * Tear down after system call. If the audit context has been marked as 1734 * Tear down after system call. If the audit context has been marked as
1731 * auditable (either because of the AUDIT_RECORD_CONTEXT state from 1735 * auditable (either because of the AUDIT_RECORD_CONTEXT state from
@@ -1733,13 +1737,17 @@ void audit_finish_fork(struct task_struct *child)
1733 * message), then write out the syscall information. In call cases, 1737 * message), then write out the syscall information. In call cases,
1734 * free the names stored from getname(). 1738 * free the names stored from getname().
1735 */ 1739 */
1736void audit_syscall_exit(int valid, long return_code) 1740void __audit_syscall_exit(int success, long return_code)
1737{ 1741{
1738 struct task_struct *tsk = current; 1742 struct task_struct *tsk = current;
1739 struct audit_context *context; 1743 struct audit_context *context;
1740 1744
1741 context = audit_get_context(tsk, valid, return_code); 1745 if (success)
1746 success = AUDITSC_SUCCESS;
1747 else
1748 success = AUDITSC_FAILURE;
1742 1749
1750 context = audit_get_context(tsk, success, return_code);
1743 if (likely(!context)) 1751 if (likely(!context))
1744 return; 1752 return;
1745 1753