aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/entry64.S
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 10:16:47 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2011-10-30 10:16:43 -0400
commit20b40a794baf3b4b0320c0a77ce944d5d1a01f25 (patch)
treefb5eb62f8f75d8f6a31aae4c3cff3371f41cdd6d /arch/s390/kernel/entry64.S
parent3ee49c8f123257c72b74f398ef99ac3348c493cc (diff)
[S390] signal race with restarting system calls
For a ERESTARTNOHAND/ERESTARTSYS/ERESTARTNOINTR restarting system call do_signal will prepare the restart of the system call with a rewind of the PSW before calling get_signal_to_deliver (where the debugger might take control). For A ERESTART_RESTARTBLOCK restarting system call do_signal will set -EINTR as return code. There are two issues with this approach: 1) strace never sees ERESTARTNOHAND, ERESTARTSYS, ERESTARTNOINTR or ERESTART_RESTARTBLOCK as the rewinding already took place or the return code has been changed to -EINTR 2) if get_signal_to_deliver does not return with a signal to deliver the restart via the repeat of the svc instruction is left in place. This opens a race if another signal is made pending before the system call instruction can be reexecuted. The original system call will be restarted even if the second signal would have ended the system call with -EINTR. These two issues can be solved by dropping the early rewind of the system call before get_signal_to_deliver has been called and by using the TIF_RESTART_SVC magic to do the restart if no signal has to be delivered. The only situation where the system call restart via the repeat of the svc instruction is appropriate is when a SA_RESTART signal is delivered to user space. Unfortunately this breaks inferior calls by the debugger again. The system call number and the length of the system call instruction is lost over the inferior call and user space will see ERESTARTNOHAND/ ERESTARTSYS/ERESTARTNOINTR/ERESTART_RESTARTBLOCK. To correct this a new ptrace interface is added to save/restore the system call number and system call instruction length. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/entry64.S')
-rw-r--r--arch/s390/kernel/entry64.S30
1 files changed, 15 insertions, 15 deletions
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 3257f7f55551..7ff07d3a29c1 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -43,8 +43,7 @@ SP_R13 = STACK_FRAME_OVERHEAD + __PT_GPRS + 104
43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112 43SP_R14 = STACK_FRAME_OVERHEAD + __PT_GPRS + 112
44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120 44SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120
45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2 45SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2
46SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC 46SP_SVC_CODE = STACK_FRAME_OVERHEAD + __PT_SVC_CODE
47SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR
48SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE 47SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
49 48
50STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER 49STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
@@ -250,7 +249,7 @@ sysc_saveall:
250 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 249 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
251 CREATE_STACK_FRAME __LC_SAVE_AREA 250 CREATE_STACK_FRAME __LC_SAVE_AREA
252 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 251 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
253 mvc SP_ILC(4,%r15),__LC_SVC_ILC 252 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
254 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 253 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
255sysc_vtime: 254sysc_vtime:
256 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 255 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -260,14 +259,14 @@ sysc_update:
260 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 259 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
261 LAST_BREAK 260 LAST_BREAK
262sysc_do_svc: 261sysc_do_svc:
263 llgh %r7,SP_SVCNR(%r15) 262 llgh %r7,SP_SVC_CODE+2(%r15)
264 slag %r7,%r7,2 # shift and test for svc 0 263 slag %r7,%r7,2 # shift and test for svc 0
265 jnz sysc_nr_ok 264 jnz sysc_nr_ok
266 # svc 0: system call number in %r1 265 # svc 0: system call number in %r1
267 llgfr %r1,%r1 # clear high word in r1 266 llgfr %r1,%r1 # clear high word in r1
268 cghi %r1,NR_syscalls 267 cghi %r1,NR_syscalls
269 jnl sysc_nr_ok 268 jnl sysc_nr_ok
270 sth %r1,SP_SVCNR(%r15) 269 sth %r1,SP_SVC_CODE+2(%r15)
271 slag %r7,%r1,2 # shift and test for svc 0 270 slag %r7,%r1,2 # shift and test for svc 0
272sysc_nr_ok: 271sysc_nr_ok:
273 larl %r10,sys_call_table 272 larl %r10,sys_call_table
@@ -358,11 +357,12 @@ sysc_notify_resume:
358# 357#
359sysc_restart: 358sysc_restart:
360 ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC 359 ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
361 lg %r7,SP_R2(%r15) # load new svc number
362 mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
363 lmg %r2,%r6,SP_R2(%r15) # load svc arguments 360 lmg %r2,%r6,SP_R2(%r15) # load svc arguments
364 sth %r7,SP_SVCNR(%r15) 361 lghi %r7,0 # svc 0 returns -ENOSYS
365 slag %r7,%r7,2 362 lh %r1,SP_SVC_CODE+2(%r15) # load new svc number
363 cghi %r1,NR_syscalls
364 jnl sysc_nr_ok # invalid svc number -> do svc 0
365 slag %r7,%r1,2
366 j sysc_nr_ok # restart svc 366 j sysc_nr_ok # restart svc
367 367
368# 368#
@@ -370,7 +370,7 @@ sysc_restart:
370# 370#
371sysc_singlestep: 371sysc_singlestep:
372 ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP 372 ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP
373 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 373 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15) # clear svc code
374 la %r2,SP_PTREGS(%r15) # address of register-save area 374 la %r2,SP_PTREGS(%r15) # address of register-save area
375 larl %r14,sysc_return # load adr. of system return 375 larl %r14,sysc_return # load adr. of system return
376 jg do_per_trap 376 jg do_per_trap
@@ -382,7 +382,7 @@ sysc_singlestep:
382sysc_tracesys: 382sysc_tracesys:
383 la %r2,SP_PTREGS(%r15) # load pt_regs 383 la %r2,SP_PTREGS(%r15) # load pt_regs
384 la %r3,0 384 la %r3,0
385 llgh %r0,SP_SVCNR(%r15) 385 llgh %r0,SP_SVC_CODE+2(%r15)
386 stg %r0,SP_R2(%r15) 386 stg %r0,SP_R2(%r15)
387 brasl %r14,do_syscall_trace_enter 387 brasl %r14,do_syscall_trace_enter
388 lghi %r0,NR_syscalls 388 lghi %r0,NR_syscalls
@@ -470,7 +470,7 @@ ENTRY(pgm_check_handler)
470 jnz pgm_per # got per exception -> special case 470 jnz pgm_per # got per exception -> special case
471 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA 471 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
472 CREATE_STACK_FRAME __LC_SAVE_AREA 472 CREATE_STACK_FRAME __LC_SAVE_AREA
473 xc SP_ILC(4,%r15),SP_ILC(%r15) 473 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15)
474 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW 474 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
475 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 475 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
476 HANDLE_SIE_INTERCEPT 476 HANDLE_SIE_INTERCEPT
@@ -551,7 +551,7 @@ pgm_svcper:
551 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA 551 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
552 CREATE_STACK_FRAME __LC_SAVE_AREA 552 CREATE_STACK_FRAME __LC_SAVE_AREA
553 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 553 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
554 mvc SP_ILC(4,%r15),__LC_SVC_ILC 554 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
555 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct 555 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
556 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 556 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
557 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 557 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
@@ -571,7 +571,7 @@ pgm_svcper:
571# 571#
572kernel_per: 572kernel_per:
573 REENABLE_IRQS 573 REENABLE_IRQS
574 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 574 xc SP_SVC_CODE(4,%r15),SP_SVC_CODE(%r15) # clear svc number
575 la %r2,SP_PTREGS(%r15) # address of register-save area 575 la %r2,SP_PTREGS(%r15) # address of register-save area
576 brasl %r14,do_per_trap 576 brasl %r14,do_per_trap
577 j pgm_exit 577 j pgm_exit
@@ -973,7 +973,7 @@ cleanup_system_call:
973 stg %r11,0(%r12) 973 stg %r11,0(%r12)
974 CREATE_STACK_FRAME __LC_SAVE_AREA 974 CREATE_STACK_FRAME __LC_SAVE_AREA
975 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW 975 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
976 mvc SP_ILC(4,%r15),__LC_SVC_ILC 976 mvc SP_SVC_CODE(4,%r15),__LC_SVC_ILC
977 mvc 8(8,%r12),__LC_THREAD_INFO 977 mvc 8(8,%r12),__LC_THREAD_INFO
978cleanup_vtime: 978cleanup_vtime:
979 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) 979 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)