]>
Commit | Line | Data |
---|---|---|
4d1e5b62 AF |
1 | Subject: [PATCH] fix syscall_get_nr. |
2 | ||
3 | From: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
4 | ||
5 | syscall_get_nr() currently returns a valid result only if the call | |
6 | chain of the traced process includes do_syscall_trace_enter(). But | |
7 | collect_syscall() can be called for any sleeping task, the result of | |
8 | syscall_get_nr() in general is completely bogus. | |
9 | ||
10 | To make syscall_get_nr() work for any sleeping task the traps field | |
11 | in pt_regs is replace with svcnr - the system call number the process | |
12 | is executing. If svcnr == 0 the process is not on a system call path. | |
13 | ||
14 | Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
15 | Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
16 | Acked-by: John Jolly <jjolly@novell.com> | |
17 | --- | |
18 | ||
19 | arch/s390/include/asm/ptrace.h | 2 +- | |
20 | arch/s390/include/asm/syscall.h | 4 +--- | |
21 | arch/s390/kernel/asm-offsets.c | 2 +- | |
22 | arch/s390/kernel/compat_signal.c | 2 +- | |
23 | arch/s390/kernel/entry.S | 21 +++++++++++---------- | |
24 | arch/s390/kernel/entry64.S | 23 ++++++++++------------- | |
25 | arch/s390/kernel/ptrace.c | 2 +- | |
26 | arch/s390/kernel/signal.c | 6 +++--- | |
27 | 8 files changed, 29 insertions(+), 33 deletions(-) | |
28 | ||
29 | --- a/arch/s390/include/asm/ptrace.h | |
30 | +++ b/arch/s390/include/asm/ptrace.h | |
31 | @@ -321,8 +321,8 @@ struct pt_regs | |
32 | psw_t psw; | |
33 | unsigned long gprs[NUM_GPRS]; | |
34 | unsigned long orig_gpr2; | |
35 | + unsigned short svcnr; | |
36 | unsigned short ilc; | |
37 | - unsigned short trap; | |
38 | }; | |
39 | #endif | |
40 | ||
41 | --- a/arch/s390/include/asm/syscall.h | |
42 | +++ b/arch/s390/include/asm/syscall.h | |
43 | @@ -17,9 +17,7 @@ | |
44 | static inline long syscall_get_nr(struct task_struct *task, | |
45 | struct pt_regs *regs) | |
46 | { | |
47 | - if (regs->trap != __LC_SVC_OLD_PSW) | |
48 | - return -1; | |
49 | - return regs->gprs[2]; | |
50 | + return regs->svcnr ? regs->svcnr : -1; | |
51 | } | |
52 | ||
53 | static inline void syscall_rollback(struct task_struct *task, | |
54 | --- a/arch/s390/kernel/asm-offsets.c | |
55 | +++ b/arch/s390/kernel/asm-offsets.c | |
56 | @@ -32,7 +32,7 @@ int main(void) | |
57 | DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); | |
58 | DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); | |
59 | DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc)); | |
60 | - DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap)); | |
61 | + DEFINE(__PT_SVCNR, offsetof(struct pt_regs, svcnr)); | |
62 | DEFINE(__PT_SIZE, sizeof(struct pt_regs)); | |
63 | BLANK(); | |
64 | DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); | |
65 | --- a/arch/s390/kernel/compat_signal.c | |
66 | +++ b/arch/s390/kernel/compat_signal.c | |
67 | @@ -340,7 +340,7 @@ static int restore_sigregs32(struct pt_r | |
68 | return err; | |
69 | ||
70 | restore_fp_regs(¤t->thread.fp_regs); | |
71 | - regs->trap = -1; /* disable syscall checks */ | |
72 | + regs->svcnr = 0; /* disable syscall checks */ | |
73 | return 0; | |
74 | } | |
75 | ||
76 | --- a/arch/s390/kernel/entry64.S | |
77 | +++ b/arch/s390/kernel/entry64.S | |
78 | @@ -46,7 +46,7 @@ SP_R14 = STACK_FRAME_OVERHEAD + __P | |
79 | SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 120 | |
80 | SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2 | |
81 | SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC | |
82 | -SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP | |
83 | +SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR | |
84 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | |
85 | ||
86 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | |
87 | @@ -168,11 +168,10 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_ | |
88 | .macro CREATE_STACK_FRAME psworg,savearea | |
89 | aghi %r15,-SP_SIZE # make room for registers & psw | |
90 | mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack | |
91 | - la %r12,\psworg | |
92 | stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | |
93 | - icm %r12,12,__LC_SVC_ILC | |
94 | + icm %r12,3,__LC_SVC_ILC | |
95 | stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack | |
96 | - st %r12,SP_ILC(%r15) | |
97 | + st %r12,SP_SVCNR(%r15) | |
98 | mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack | |
99 | la %r12,0 | |
100 | stg %r12,__SF_BACKCHAIN(%r15) | |
101 | @@ -247,16 +246,17 @@ sysc_update: | |
102 | #endif | |
103 | sysc_do_svc: | |
104 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | |
105 | - slag %r7,%r7,2 # *4 and test for svc 0 | |
106 | + ltgr %r7,%r7 # test for svc 0 | |
107 | jnz sysc_nr_ok | |
108 | # svc 0: system call number in %r1 | |
109 | cl %r1,BASED(.Lnr_syscalls) | |
110 | jnl sysc_nr_ok | |
111 | lgfr %r7,%r1 # clear high word in r1 | |
112 | - slag %r7,%r7,2 # svc 0: system call number in %r1 | |
113 | sysc_nr_ok: | |
114 | mvc SP_ARGS(8,%r15),SP_R7(%r15) | |
115 | sysc_do_restart: | |
116 | + sth %r7,SP_SVCNR(%r15) | |
117 | + sllg %r7,%r7,2 # svc number * 4 | |
118 | larl %r10,sys_call_table | |
119 | #ifdef CONFIG_COMPAT | |
120 | tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? | |
121 | @@ -360,7 +360,6 @@ sysc_notify_resume: | |
122 | sysc_restart: | |
123 | ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC | |
124 | lg %r7,SP_R2(%r15) # load new svc number | |
125 | - slag %r7,%r7,2 # *4 | |
126 | mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument | |
127 | lmg %r2,%r6,SP_R2(%r15) # load svc arguments | |
128 | j sysc_do_restart # restart svc | |
129 | @@ -369,9 +368,8 @@ sysc_restart: | |
130 | # _TIF_SINGLE_STEP is set, call do_single_step | |
131 | # | |
132 | sysc_singlestep: | |
133 | - ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | |
134 | - lhi %r0,__LC_PGM_OLD_PSW | |
135 | - sth %r0,SP_TRAP(%r15) # set trap indication to pgm check | |
136 | + ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | |
137 | + xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | |
138 | la %r2,SP_PTREGS(%r15) # address of register-save area | |
139 | larl %r14,sysc_return # load adr. of system return | |
140 | jg do_single_step # branch to do_sigtrap | |
141 | @@ -389,7 +387,7 @@ sysc_tracesys: | |
142 | lghi %r0,NR_syscalls | |
143 | clgr %r0,%r2 | |
144 | jnh sysc_tracenogo | |
145 | - slag %r7,%r2,2 # *4 | |
146 | + sllg %r7,%r2,2 # svc number *4 | |
147 | lgf %r8,0(%r7,%r10) | |
148 | sysc_tracego: | |
149 | lmg %r3,%r6,SP_R3(%r15) | |
150 | @@ -564,8 +562,7 @@ pgm_svcper: | |
151 | # per was called from kernel, must be kprobes | |
152 | # | |
153 | kernel_per: | |
154 | - lhi %r0,__LC_PGM_OLD_PSW | |
155 | - sth %r0,SP_TRAP(%r15) # set trap indication to pgm check | |
156 | + xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number | |
157 | la %r2,SP_PTREGS(%r15) # address of register-save area | |
158 | larl %r14,sysc_restore # load adr. of system ret, no work | |
159 | jg do_single_step # branch to do_single_step | |
160 | --- a/arch/s390/kernel/entry.S | |
161 | +++ b/arch/s390/kernel/entry.S | |
162 | @@ -46,7 +46,7 @@ SP_R14 = STACK_FRAME_OVERHEAD + __P | |
163 | SP_R15 = STACK_FRAME_OVERHEAD + __PT_GPRS + 60 | |
164 | SP_ORIG_R2 = STACK_FRAME_OVERHEAD + __PT_ORIG_GPR2 | |
165 | SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC | |
166 | -SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP | |
167 | +SP_SVCNR = STACK_FRAME_OVERHEAD + __PT_SVCNR | |
168 | SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE | |
169 | ||
170 | _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |
171 | @@ -180,11 +180,10 @@ STACK_SIZE = 1 << STACK_SHIFT | |
172 | .macro CREATE_STACK_FRAME psworg,savearea | |
173 | s %r15,BASED(.Lc_spsize) # make room for registers & psw | |
174 | mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack | |
175 | - la %r12,\psworg | |
176 | st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 | |
177 | - icm %r12,12,__LC_SVC_ILC | |
178 | + icm %r12,3,__LC_SVC_ILC | |
179 | stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack | |
180 | - st %r12,SP_ILC(%r15) | |
181 | + st %r12,SP_SVCNR(%r15) | |
182 | mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack | |
183 | la %r12,0 | |
184 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain | |
185 | @@ -261,16 +260,17 @@ sysc_update: | |
186 | #endif | |
187 | sysc_do_svc: | |
188 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | |
189 | - sla %r7,2 # *4 and test for svc 0 | |
190 | + ltr %r7,%r7 # test for svc 0 | |
191 | bnz BASED(sysc_nr_ok) # svc number > 0 | |
192 | # svc 0: system call number in %r1 | |
193 | cl %r1,BASED(.Lnr_syscalls) | |
194 | bnl BASED(sysc_nr_ok) | |
195 | lr %r7,%r1 # copy svc number to %r7 | |
196 | - sla %r7,2 # *4 | |
197 | sysc_nr_ok: | |
198 | mvc SP_ARGS(4,%r15),SP_R7(%r15) | |
199 | sysc_do_restart: | |
200 | + sth %r7,SP_SVCNR(%r15) | |
201 | + sll %r7,2 # svc number *4 | |
202 | l %r8,BASED(.Lsysc_table) | |
203 | tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) | |
204 | l %r8,0(%r7,%r8) # get system call addr. | |
205 | @@ -373,7 +373,6 @@ sysc_notify_resume: | |
206 | sysc_restart: | |
207 | ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC | |
208 | l %r7,SP_R2(%r15) # load new svc number | |
209 | - sla %r7,2 | |
210 | mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument | |
211 | lm %r2,%r6,SP_R2(%r15) # load svc arguments | |
212 | b BASED(sysc_do_restart) # restart svc | |
213 | @@ -383,7 +382,8 @@ sysc_restart: | |
214 | # | |
215 | sysc_singlestep: | |
216 | ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP | |
217 | - mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check | |
218 | + mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check | |
219 | + mvi SP_SVCNR+1(%r15),0xff | |
220 | la %r2,SP_PTREGS(%r15) # address of register-save area | |
221 | l %r1,BASED(.Lhandle_per) # load adr. of per handler | |
222 | la %r14,BASED(sysc_return) # load adr. of system return | |
223 | @@ -404,7 +404,7 @@ sysc_tracesys: | |
224 | bnl BASED(sysc_tracenogo) | |
225 | l %r8,BASED(.Lsysc_table) | |
226 | lr %r7,%r2 | |
227 | - sll %r7,2 # *4 | |
228 | + sll %r7,2 # svc number *4 | |
229 | l %r8,0(%r7,%r8) | |
230 | sysc_tracego: | |
231 | lm %r3,%r6,SP_R3(%r15) | |
232 | @@ -583,7 +583,8 @@ pgm_svcper: | |
233 | # per was called from kernel, must be kprobes | |
234 | # | |
235 | kernel_per: | |
236 | - mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check | |
237 | + mvi SP_SVCNR(%r15),0xff # set trap indication to pgm check | |
238 | + mvi SP_SVCNR+1(%r15),0xff | |
239 | la %r2,SP_PTREGS(%r15) # address of register-save area | |
240 | l %r1,BASED(.Lhandle_per) # load adr. of per handler | |
241 | la %r14,BASED(sysc_restore)# load adr. of system return | |
242 | --- a/arch/s390/kernel/ptrace.c | |
243 | +++ b/arch/s390/kernel/ptrace.c | |
244 | @@ -671,7 +671,7 @@ asmlinkage long do_syscall_trace_enter(s | |
245 | * debugger stored an invalid system call number. Skip | |
246 | * the system call and the system call restart handling. | |
247 | */ | |
248 | - regs->trap = -1; | |
249 | + regs->svcnr = 0; | |
250 | ret = -1; | |
251 | } | |
252 | ||
253 | --- a/arch/s390/kernel/signal.c | |
254 | +++ b/arch/s390/kernel/signal.c | |
255 | @@ -157,7 +157,7 @@ static int restore_sigregs(struct pt_reg | |
256 | current->thread.fp_regs.fpc &= FPC_VALID_MASK; | |
257 | ||
258 | restore_fp_regs(¤t->thread.fp_regs); | |
259 | - regs->trap = -1; /* disable syscall checks */ | |
260 | + regs->svcnr = 0; /* disable syscall checks */ | |
261 | return 0; | |
262 | } | |
263 | ||
264 | @@ -442,7 +442,7 @@ void do_signal(struct pt_regs *regs) | |
265 | oldset = ¤t->blocked; | |
266 | ||
267 | /* Are we from a system call? */ | |
268 | - if (regs->trap == __LC_SVC_OLD_PSW) { | |
269 | + if (regs->svcnr) { | |
270 | continue_addr = regs->psw.addr; | |
271 | restart_addr = continue_addr - regs->ilc; | |
272 | retval = regs->gprs[2]; | |
273 | @@ -459,7 +459,7 @@ void do_signal(struct pt_regs *regs) | |
274 | case -ERESTART_RESTARTBLOCK: | |
275 | regs->gprs[2] = -EINTR; | |
276 | } | |
277 | - regs->trap = -1; /* Don't deal with this again. */ | |
278 | + regs->svcnr = 0; /* Don't deal with this again. */ | |
279 | } | |
280 | ||
281 | /* Get signal to deliver. When running under ptrace, at this point |