diff options
| author | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-08-27 05:23:46 -0400 |
|---|---|---|
| committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-08-27 05:23:46 -0400 |
| commit | 17888225c2f392bfdbac6c7f0713cbd9a4d02b05 (patch) | |
| tree | cf11f005d3a973be9fd06eec243ded4b776c1502 | |
| parent | 3c789a19054034847afe80af2f23ebb0eebfbad6 (diff) | |
Fix missing audit_syscall_exit() on ppc64 sigsuspend exit path
When we leave sigsuspend() directly into a signal handler, we don't want
to go via the normal syscall exit path -- it'll corrupt r4 and r5 which
are supposed to be giving information to the signal handler, and it'll
give us one more single-step SIGTRAP than we need if single-stepping is
in operation.
However, we _should_ be calling audit_syscall_exit(), which would
normally get invoked in that patch. It's not wonderfully pretty, but I
suspect the best answer is just to call it directly...
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
| -rw-r--r-- | arch/ppc64/kernel/asm-offsets.c | 1 | ||||
| -rw-r--r-- | arch/ppc64/kernel/entry.S | 16 |
2 files changed, 13 insertions, 4 deletions
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index abb9e5b5da03..6f910fa2746f 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c | |||
| @@ -68,6 +68,7 @@ int main(void) | |||
| 68 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); | 68 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); |
| 69 | #endif /* CONFIG_ALTIVEC */ | 69 | #endif /* CONFIG_ALTIVEC */ |
| 70 | DEFINE(MM, offsetof(struct task_struct, mm)); | 70 | DEFINE(MM, offsetof(struct task_struct, mm)); |
| 71 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); | ||
| 71 | 72 | ||
| 72 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); | 73 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); |
| 73 | DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); | 74 | DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); |
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S index b61572eb2a71..ae5d563ad93a 100644 --- a/arch/ppc64/kernel/entry.S +++ b/arch/ppc64/kernel/entry.S | |||
| @@ -276,12 +276,20 @@ _GLOBAL(ppc64_rt_sigsuspend) | |||
| 276 | _GLOBAL(ppc32_rt_sigsuspend) | 276 | _GLOBAL(ppc32_rt_sigsuspend) |
| 277 | bl .save_nvgprs | 277 | bl .save_nvgprs |
| 278 | bl .sys32_rt_sigsuspend | 278 | bl .sys32_rt_sigsuspend |
| 279 | /* If sigsuspend() returns zero, we are going into a signal handler */ | ||
| 280 | 70: cmpdi 0,r3,0 | 279 | 70: cmpdi 0,r3,0 |
| 281 | beq .ret_from_except | 280 | /* If it returned an error, we need to return via syscall_exit to set |
| 282 | /* If it returned -EINTR, we need to return via syscall_exit to set | ||
| 283 | the SO bit in cr0 and potentially stop for ptrace. */ | 281 | the SO bit in cr0 and potentially stop for ptrace. */ |
| 284 | b syscall_exit | 282 | bne syscall_exit |
| 283 | /* If sigsuspend() returns zero, we are going into a signal handler. We | ||
| 284 | may need to call audit_syscall_exit() to mark the exit from sigsuspend() */ | ||
| 285 | ld r3,PACACURRENT(r13) | ||
| 286 | ld r4,AUDITCONTEXT(r3) | ||
| 287 | cmpdi 0,r4,0 | ||
| 288 | beq .ret_from_except /* No audit_context: Leave immediately. */ | ||
| 289 | li r4, 2 /* AUDITSC_FAILURE */ | ||
| 290 | li r5,-4 /* It's always -EINTR */ | ||
| 291 | bl .audit_syscall_exit | ||
| 292 | b .ret_from_except | ||
| 285 | 293 | ||
| 286 | _GLOBAL(ppc_fork) | 294 | _GLOBAL(ppc_fork) |
| 287 | bl .save_nvgprs | 295 | bl .save_nvgprs |
