diff options
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) | 249 | static inline int is_syscall_success(struct pt_regs *regs) |
250 | { | ||
251 | return regs->r10 != -1; | ||
252 | } | ||
253 | |||
254 | static 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(®s); |
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 | ||
64 | static 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]) | 140 | static inline int is_syscall_success(struct pt_regs *regs) |
141 | { | ||
142 | return !regs->regs[7]; | ||
143 | } | ||
144 | |||
145 | static 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 | */ |
573 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 573 | asmlinkage 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]) | 89 | static inline int is_syscall_success(struct pt_regs *regs) |
90 | { | ||
91 | return !(regs->ccr & 0x10000000); | ||
92 | } | ||
93 | |||
94 | static 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 |
92 | extern unsigned long profile_pc(struct pt_regs *regs); | 103 | extern 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 | ||
546 | static inline long regs_return_value(struct pt_regs *regs) | ||
547 | { | ||
548 | return regs->gprs[2]; | ||
549 | } | ||
550 | |||
547 | int regs_query_register_offset(const char *name); | 551 | int regs_query_register_offset(const char *name); |
548 | const char *regs_query_register_name(unsigned int offset); | 552 | const char *regs_query_register_name(unsigned int offset); |
549 | unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); | 553 | unsigned 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 | ||
752 | asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) | 752 | asmlinkage 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]) | 79 | static 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]) | 16 | static 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]) | 210 | static inline int is_syscall_success(struct pt_regs *regs) |
211 | { | ||
212 | return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)); | ||
213 | } | ||
214 | |||
215 | static 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 |
212 | extern unsigned long profile_pc(struct pt_regs *); | 220 | extern 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 | ||
1087 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | 1087 | asmlinkage 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 | */ |
570 | sysret_audit: | 571 | sysret_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 | |||
7 | static 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 ) | ||
415 | extern int __init audit_register_class(int class, unsigned *list); | 412 | extern int __init audit_register_class(int class, unsigned *list); |
416 | extern int audit_classify_syscall(int abi, unsigned syscall); | 413 | extern int audit_classify_syscall(int abi, unsigned syscall); |
417 | extern int audit_classify_arch(int arch); | 414 | extern int audit_classify_arch(int arch); |
@@ -424,7 +421,7 @@ extern void audit_free(struct task_struct *task); | |||
424 | extern void audit_syscall_entry(int arch, | 421 | extern 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); |
427 | extern void audit_syscall_exit(int failed, long return_code); | 424 | extern void __audit_syscall_exit(int ret_success, long ret_value); |
428 | extern void __audit_getname(const char *name); | 425 | extern void __audit_getname(const char *name); |
429 | extern void audit_putname(const char *name); | 426 | extern void audit_putname(const char *name); |
430 | extern void __audit_inode(const char *name, const struct dentry *dentry); | 427 | extern 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 | } |
438 | static 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 | } | ||
441 | static inline void audit_getname(const char *name) | 447 | static 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 | ||
552 | extern int audit_n_rules; | 558 | extern int audit_n_rules; |
553 | extern int audit_signals; | 559 | extern 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 | ||
117 | extern long arch_ptrace(struct task_struct *child, long request, | 118 | extern 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 | */ |
1736 | void audit_syscall_exit(int valid, long return_code) | 1740 | void __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 | ||