Skip to content

Commit 44a1d99

Browse files
author
Al Viro
committed
x86: ia32_setup_sigcontext(): lift user_access_{begin,end}() into the callers
What's left is just a sequence of stores to userland addresses, with all error handling, etc. done out of line. Calling that from user_access block is safe, but rather than teaching objtool to recognize it as such we can just make it always_inline - it is small enough and has few enough callers, for the space savings not to be an issue. Rename the sucker to __unsafe_setup_sigcontext32() and provide unsafe_put_sigcontext32() with usual kind of semantics. Signed-off-by: Al Viro <[email protected]>
1 parent 39f16c1 commit 44a1d99

File tree

1 file changed

+28
-16
lines changed

1 file changed

+28
-16
lines changed

arch/x86/ia32/ia32_signal.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,11 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
154154

155155
#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
156156

157-
static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
158-
void __user *fpstate,
159-
struct pt_regs *regs, unsigned int mask)
157+
static __always_inline int
158+
__unsafe_setup_sigcontext32(struct sigcontext_32 __user *sc,
159+
void __user *fpstate,
160+
struct pt_regs *regs, unsigned int mask)
160161
{
161-
if (!user_access_begin(sc, sizeof(struct sigcontext_32)))
162-
return -EFAULT;
163-
164162
unsafe_put_user(get_user_seg(gs), (unsigned int __user *)&sc->gs, Efault);
165163
unsafe_put_user(get_user_seg(fs), (unsigned int __user *)&sc->fs, Efault);
166164
unsafe_put_user(get_user_seg(ds), (unsigned int __user *)&sc->ds, Efault);
@@ -187,13 +185,18 @@ static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
187185
/* non-iBCS2 extensions.. */
188186
unsafe_put_user(mask, &sc->oldmask, Efault);
189187
unsafe_put_user(current->thread.cr2, &sc->cr2, Efault);
190-
user_access_end();
191188
return 0;
189+
192190
Efault:
193-
user_access_end();
194191
return -EFAULT;
195192
}
196193

194+
#define unsafe_put_sigcontext32(sc, fp, regs, set, label) \
195+
do { \
196+
if (__unsafe_setup_sigcontext32(sc, fp, regs, set->sig[0])) \
197+
goto label; \
198+
} while(0)
199+
197200
/*
198201
* Determine which stack to use..
199202
*/
@@ -234,7 +237,7 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
234237
struct sigframe_ia32 __user *frame;
235238
void __user *restorer;
236239
int err = 0;
237-
void __user *fpstate = NULL;
240+
void __user *fp = NULL;
238241

239242
/* copy_to_user optimizes that into a single 8 byte store */
240243
static const struct {
@@ -247,17 +250,20 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
247250
0x80cd, /* int $0x80 */
248251
};
249252

250-
frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
253+
frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);
251254

252255
if (!access_ok(frame, sizeof(*frame)))
253256
return -EFAULT;
254257

255258
if (__put_user(sig, &frame->sig))
256259
return -EFAULT;
257260

258-
if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
261+
if (!user_access_begin(&frame->sc, sizeof(struct sigcontext_32)))
259262
return -EFAULT;
260263

264+
unsafe_put_sigcontext32(&frame->sc, fp, regs, set, Efault);
265+
user_access_end();
266+
261267
if (__put_user(set->sig[1], &frame->extramask[0]))
262268
return -EFAULT;
263269

@@ -301,6 +307,9 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
301307
regs->ss = __USER32_DS;
302308

303309
return 0;
310+
Efault:
311+
user_access_end();
312+
return -EFAULT;
304313
}
305314

306315
int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
@@ -309,7 +318,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
309318
struct rt_sigframe_ia32 __user *frame;
310319
void __user *restorer;
311320
int err = 0;
312-
void __user *fpstate = NULL;
321+
void __user *fp = NULL;
313322

314323
/* __copy_to_user optimizes that into a single 8 byte store */
315324
static const struct {
@@ -324,7 +333,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
324333
0,
325334
};
326335

327-
frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);
336+
frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);
328337

329338
if (!user_access_begin(frame, sizeof(*frame)))
330339
return -EFAULT;
@@ -355,9 +364,12 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
355364
unsafe_put_user(*((u64 *)&code), (u64 __user *)frame->retcode, Efault);
356365
user_access_end();
357366

358-
err |= __copy_siginfo_to_user32(&frame->info, &ksig->info, false);
359-
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
360-
regs, set->sig[0]);
367+
if (__copy_siginfo_to_user32(&frame->info, &ksig->info, false))
368+
return -EFAULT;
369+
if (!user_access_begin(&frame->uc.uc_mcontext, sizeof(struct sigcontext_32)))
370+
return -EFAULT;
371+
unsafe_put_sigcontext32(&frame->uc.uc_mcontext, fp, regs, set, Efault);
372+
user_access_end();
361373
err |= __put_user(*(__u64 *)set, (__u64 __user *)&frame->uc.uc_sigmask);
362374

363375
if (err)

0 commit comments

Comments
 (0)