aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2012-01-03 14:23:06 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-17 16:16:56 -0500
commitd7e7528bcd456f5c36ad4a202ccfb43c5aa98bc4 (patch)
treeef49503b1dc52c52102e728dbd979c9309d5756b /arch
parent85e7bac33b8d5edafc4e219c7dfdb3d48e0b4e31 (diff)
Audit: push audit success and retcode into arch ptrace.h
The audit system previously expected arches calling to audit_syscall_exit to supply as arguments if the syscall was a success and what the return code was. Audit also provides a helper AUDITSC_RESULT which was supposed to simplify things by converting from negative retcodes to an audit internal magic value stating success or failure. This helper was wrong and could indicate that a valid pointer returned to userspace was a failed syscall. The fix is to fix the layering foolishness. We now pass audit_syscall_exit a struct pt_reg and it in turns calls back into arch code to collect the return value and to determine if the syscall was a success or failure. We also define a generic is_syscall_success() macro which determines success/failure based on if the value is < -MAX_ERRNO. This works for arches like x86 which do not use a separate mechanism to indicate syscall failure. We make both the is_syscall_success() and regs_return_value() static inlines instead of macros. The reason is because the audit function must take a void* for the regs. (uml calls theirs struct uml_pt_regs instead of just struct pt_regs so audit_syscall_exit can't take a struct pt_regs). Since the audit function takes a void* we need to use static inlines to cast it back to the arch correct structure to dereference it. The other major change is that on some arches, like ia64, MIPS and ppc, we change regs_return_value() to give us the negative value on syscall failure. THE only other user of this macro, kretprobe_example.c, won't notice and it makes the value signed consistently for the audit functions across all archs. In arch/sh/kernel/ptrace_64.c I see that we were using regs[9] in the old audit code as the return value. But the ptrace_64.h code defined the macro regs_return_value() as regs[3]. I have no idea which one is correct, but this patch now uses the regs_return_value() function, so it now uses regs[3]. For powerpc we previously used regs->result but now use the regs_return_value() function which uses regs->gprs[3]. regs->gprs[3] is always positive so the regs_return_value(), much like ia64 makes it negative before calling the audit code when appropriate. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: H. Peter Anvin <hpa@zytor.com> [for x86 portion] Acked-by: Tony Luck <tony.luck@intel.com> [for ia64] Acked-by: Richard Weinberger <richard@nod.at> [for uml] Acked-by: David S. Miller <davem@davemloft.net> [for sparc] Acked-by: Ralf Baechle <ralf@linux-mips.org> [for mips] Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [for ppc]
Diffstat (limited to 'arch')
-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
23 files changed, 96 insertions, 62 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}