Skip to content

Commit 24e6dc3

Browse files
Brian Gerstsuryasaimadhu
authored andcommitted
x86/signal/32: Merge native and compat 32-bit signal code
There are significant differences between signal handling on 32-bit vs. 64-bit, like different structure layouts and legacy syscalls. Instead of duplicating that code for native and compat, merge both versions into one file. Signed-off-by: Brian Gerst <brgerst@gmail.com> Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Link: https://lore.kernel.org/r/20220606203802.158958-8-brgerst@gmail.com Signed-off-by: Borislav Petkov <bp@suse.de>
1 parent c461ae3 commit 24e6dc3

6 files changed

Lines changed: 60 additions & 227 deletions

File tree

arch/x86/ia32/Makefile

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@
33
# Makefile for the ia32 kernel emulation subsystem.
44
#
55

6-
obj-$(CONFIG_IA32_EMULATION) := ia32_signal.o
7-
86
audit-class-$(CONFIG_AUDIT) := audit.o
97
obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)

arch/x86/include/asm/segment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
136136
#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
137137
#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
138+
#define __USER32_CS __USER_CS
138139
#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8)
139140

140141
/* segment for calling fn: */

arch/x86/kernel/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ obj-y += setup.o x86_init.o i8259.o irqinit.o
5353
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
5454
obj-$(CONFIG_IRQ_WORK) += irq_work.o
5555
obj-y += probe_roms.o
56-
obj-$(CONFIG_X86_32) += sys_ia32.o
57-
obj-$(CONFIG_IA32_EMULATION) += sys_ia32.o
56+
obj-$(CONFIG_X86_32) += sys_ia32.o signal_32.o
57+
obj-$(CONFIG_IA32_EMULATION) += sys_ia32.o signal_32.o
5858
obj-$(CONFIG_X86_64) += sys_x86_64.o
5959
obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o
6060
obj-$(CONFIG_SYSFS) += ksysfs.o

arch/x86/kernel/signal.c

Lines changed: 6 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ static void force_valid_ss(struct pt_regs *regs)
9292
ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
9393
regs->ss = __USER_DS;
9494
}
95-
# define CONTEXT_COPY_SIZE offsetof(struct sigcontext, reserved1)
96-
#else
97-
# define CONTEXT_COPY_SIZE sizeof(struct sigcontext)
98-
#endif
9995

10096
static bool restore_sigcontext(struct pt_regs *regs,
10197
struct sigcontext __user *usc,
@@ -106,16 +102,9 @@ static bool restore_sigcontext(struct pt_regs *regs,
106102
/* Always make any pending restarted system calls return -EINTR */
107103
current->restart_block.fn = do_no_restart_syscall;
108104

109-
if (copy_from_user(&sc, usc, CONTEXT_COPY_SIZE))
105+
if (copy_from_user(&sc, usc, offsetof(struct sigcontext, reserved1)))
110106
return false;
111107

112-
#ifdef CONFIG_X86_32
113-
loadsegment(gs, sc.gs);
114-
regs->fs = sc.fs;
115-
regs->es = sc.es;
116-
regs->ds = sc.ds;
117-
#endif /* CONFIG_X86_32 */
118-
119108
regs->bx = sc.bx;
120109
regs->cx = sc.cx;
121110
regs->dx = sc.dx;
@@ -125,8 +114,6 @@ static bool restore_sigcontext(struct pt_regs *regs,
125114
regs->ax = sc.ax;
126115
regs->sp = sc.sp;
127116
regs->ip = sc.ip;
128-
129-
#ifdef CONFIG_X86_64
130117
regs->r8 = sc.r8;
131118
regs->r9 = sc.r9;
132119
regs->r10 = sc.r10;
@@ -135,7 +122,6 @@ static bool restore_sigcontext(struct pt_regs *regs,
135122
regs->r13 = sc.r13;
136123
regs->r14 = sc.r14;
137124
regs->r15 = sc.r15;
138-
#endif /* CONFIG_X86_64 */
139125

140126
/* Get CS/SS and force CPL3 */
141127
regs->cs = sc.cs | 0x03;
@@ -145,33 +131,20 @@ static bool restore_sigcontext(struct pt_regs *regs,
145131
/* disable syscall checks */
146132
regs->orig_ax = -1;
147133

148-
#ifdef CONFIG_X86_64
149134
/*
150135
* Fix up SS if needed for the benefit of old DOSEMU and
151136
* CRIU.
152137
*/
153138
if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
154139
force_valid_ss(regs);
155-
#endif
156140

157-
return fpu__restore_sig((void __user *)sc.fpstate,
158-
IS_ENABLED(CONFIG_X86_32));
141+
return fpu__restore_sig((void __user *)sc.fpstate, 0);
159142
}
160143

161144
static __always_inline int
162145
__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
163146
struct pt_regs *regs, unsigned long mask)
164147
{
165-
#ifdef CONFIG_X86_32
166-
unsigned int gs;
167-
savesegment(gs, gs);
168-
169-
unsafe_put_user(gs, (unsigned int __user *)&sc->gs, Efault);
170-
unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault);
171-
unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault);
172-
unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault);
173-
#endif /* CONFIG_X86_32 */
174-
175148
unsafe_put_user(regs->di, &sc->di, Efault);
176149
unsafe_put_user(regs->si, &sc->si, Efault);
177150
unsafe_put_user(regs->bp, &sc->bp, Efault);
@@ -180,7 +153,6 @@ __unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
180153
unsafe_put_user(regs->dx, &sc->dx, Efault);
181154
unsafe_put_user(regs->cx, &sc->cx, Efault);
182155
unsafe_put_user(regs->ax, &sc->ax, Efault);
183-
#ifdef CONFIG_X86_64
184156
unsafe_put_user(regs->r8, &sc->r8, Efault);
185157
unsafe_put_user(regs->r9, &sc->r9, Efault);
186158
unsafe_put_user(regs->r10, &sc->r10, Efault);
@@ -189,23 +161,15 @@ __unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
189161
unsafe_put_user(regs->r13, &sc->r13, Efault);
190162
unsafe_put_user(regs->r14, &sc->r14, Efault);
191163
unsafe_put_user(regs->r15, &sc->r15, Efault);
192-
#endif /* CONFIG_X86_64 */
193164

194165
unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault);
195166
unsafe_put_user(current->thread.error_code, &sc->err, Efault);
196167
unsafe_put_user(regs->ip, &sc->ip, Efault);
197-
#ifdef CONFIG_X86_32
198-
unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault);
199-
unsafe_put_user(regs->flags, &sc->flags, Efault);
200-
unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault);
201-
unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault);
202-
#else /* !CONFIG_X86_32 */
203168
unsafe_put_user(regs->flags, &sc->flags, Efault);
204169
unsafe_put_user(regs->cs, &sc->cs, Efault);
205170
unsafe_put_user(0, &sc->gs, Efault);
206171
unsafe_put_user(0, &sc->fs, Efault);
207172
unsafe_put_user(regs->ss, &sc->ss, Efault);
208-
#endif /* CONFIG_X86_32 */
209173

210174
unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault);
211175

@@ -228,6 +192,8 @@ do { \
228192
(__u64 __user *)&(frame)->uc.uc_sigmask, \
229193
label)
230194

195+
#endif /* CONFIG_X86_64 */
196+
231197
/*
232198
* Set up a signal frame.
233199
*/
@@ -313,148 +279,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,
313279
return (void __user *)sp;
314280
}
315281

316-
#ifdef CONFIG_X86_32
317-
static const struct {
318-
u16 poplmovl;
319-
u32 val;
320-
u16 int80;
321-
} __attribute__((packed)) retcode = {
322-
0xb858, /* popl %eax; movl $..., %eax */
323-
__NR_sigreturn,
324-
0x80cd, /* int $0x80 */
325-
};
326-
327-
static const struct {
328-
u8 movl;
329-
u32 val;
330-
u16 int80;
331-
u8 pad;
332-
} __attribute__((packed)) rt_retcode = {
333-
0xb8, /* movl $..., %eax */
334-
__NR_rt_sigreturn,
335-
0x80cd, /* int $0x80 */
336-
0
337-
};
338-
339-
int ia32_setup_frame(struct ksignal *ksig, struct pt_regs *regs)
340-
{
341-
sigset_t *set = sigmask_to_save();
342-
struct sigframe __user *frame;
343-
void __user *restorer;
344-
void __user *fp = NULL;
345-
346-
frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);
347-
348-
if (!user_access_begin(frame, sizeof(*frame)))
349-
return -EFAULT;
350-
351-
unsafe_put_user(ksig->sig, &frame->sig, Efault);
352-
unsafe_put_sigcontext(&frame->sc, fp, regs, set, Efault);
353-
unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);
354-
if (current->mm->context.vdso)
355-
restorer = current->mm->context.vdso +
356-
vdso_image_32.sym___kernel_sigreturn;
357-
else
358-
restorer = &frame->retcode;
359-
if (ksig->ka.sa.sa_flags & SA_RESTORER)
360-
restorer = ksig->ka.sa.sa_restorer;
361-
362-
/* Set up to return from userspace. */
363-
unsafe_put_user(restorer, &frame->pretcode, Efault);
364-
365-
/*
366-
* This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
367-
*
368-
* WE DO NOT USE IT ANY MORE! It's only left here for historical
369-
* reasons and because gdb uses it as a signature to notice
370-
* signal handler stack frames.
371-
*/
372-
unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault);
373-
user_access_end();
374-
375-
/* Set up registers for signal handler */
376-
regs->sp = (unsigned long)frame;
377-
regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
378-
regs->ax = (unsigned long)ksig->sig;
379-
regs->dx = 0;
380-
regs->cx = 0;
381-
382-
regs->ds = __USER_DS;
383-
regs->es = __USER_DS;
384-
regs->ss = __USER_DS;
385-
regs->cs = __USER_CS;
386-
387-
return 0;
388-
389-
Efault:
390-
user_access_end();
391-
return -EFAULT;
392-
}
393-
394-
int ia32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
395-
{
396-
sigset_t *set = sigmask_to_save();
397-
struct rt_sigframe __user *frame;
398-
void __user *restorer;
399-
void __user *fp = NULL;
400-
401-
frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);
402-
403-
if (!user_access_begin(frame, sizeof(*frame)))
404-
return -EFAULT;
405-
406-
unsafe_put_user(ksig->sig, &frame->sig, Efault);
407-
unsafe_put_user(&frame->info, &frame->pinfo, Efault);
408-
unsafe_put_user(&frame->uc, &frame->puc, Efault);
409-
410-
/* Create the ucontext. */
411-
if (static_cpu_has(X86_FEATURE_XSAVE))
412-
unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
413-
else
414-
unsafe_put_user(0, &frame->uc.uc_flags, Efault);
415-
unsafe_put_user(0, &frame->uc.uc_link, Efault);
416-
unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
417-
418-
/* Set up to return from userspace. */
419-
restorer = current->mm->context.vdso +
420-
vdso_image_32.sym___kernel_rt_sigreturn;
421-
if (ksig->ka.sa.sa_flags & SA_RESTORER)
422-
restorer = ksig->ka.sa.sa_restorer;
423-
unsafe_put_user(restorer, &frame->pretcode, Efault);
424-
425-
/*
426-
* This is movl $__NR_rt_sigreturn, %ax ; int $0x80
427-
*
428-
* WE DO NOT USE IT ANY MORE! It's only left here for historical
429-
* reasons and because gdb uses it as a signature to notice
430-
* signal handler stack frames.
431-
*/
432-
unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault);
433-
unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
434-
unsafe_put_sigmask(set, frame, Efault);
435-
user_access_end();
436-
437-
if (copy_siginfo_to_user(&frame->info, &ksig->info))
438-
return -EFAULT;
439-
440-
/* Set up registers for signal handler */
441-
regs->sp = (unsigned long)frame;
442-
regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
443-
regs->ax = (unsigned long)ksig->sig;
444-
regs->dx = (unsigned long)&frame->info;
445-
regs->cx = (unsigned long)&frame->uc;
446-
447-
regs->ds = __USER_DS;
448-
regs->es = __USER_DS;
449-
regs->ss = __USER_DS;
450-
regs->cs = __USER_CS;
451-
452-
return 0;
453-
Efault:
454-
user_access_end();
455-
return -EFAULT;
456-
}
457-
#else /* !CONFIG_X86_32 */
282+
#ifdef CONFIG_X86_64
458283
static unsigned long frame_uc_flags(struct pt_regs *regs)
459284
{
460285
unsigned long flags;
@@ -545,7 +370,6 @@ int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
545370
user_access_end();
546371
return -EFAULT;
547372
}
548-
#endif /* CONFIG_X86_32 */
549373

550374
#ifdef CONFIG_X86_X32_ABI
551375
static int x32_copy_siginfo_to_user(struct compat_siginfo __user *to,
@@ -631,38 +455,6 @@ int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
631455
/*
632456
* Do a signal return; undo the signal stack.
633457
*/
634-
#ifdef CONFIG_X86_32
635-
SYSCALL_DEFINE0(sigreturn)
636-
{
637-
struct pt_regs *regs = current_pt_regs();
638-
struct sigframe __user *frame;
639-
sigset_t set;
640-
641-
frame = (struct sigframe __user *)(regs->sp - 8);
642-
643-
if (!access_ok(frame, sizeof(*frame)))
644-
goto badframe;
645-
if (__get_user(set.sig[0], &frame->sc.oldmask) ||
646-
__get_user(set.sig[1], &frame->extramask[0]))
647-
goto badframe;
648-
649-
set_current_blocked(&set);
650-
651-
/*
652-
* x86_32 has no uc_flags bits relevant to restore_sigcontext.
653-
* Save a few cycles by skipping the __get_user.
654-
*/
655-
if (!restore_sigcontext(regs, &frame->sc, 0))
656-
goto badframe;
657-
return regs->ax;
658-
659-
badframe:
660-
signal_fault(regs, frame, "sigreturn");
661-
662-
return 0;
663-
}
664-
#endif /* CONFIG_X86_32 */
665-
666458
SYSCALL_DEFINE0(rt_sigreturn)
667459
{
668460
struct pt_regs *regs = current_pt_regs();
@@ -692,6 +484,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
692484
signal_fault(regs, frame, "rt_sigreturn");
693485
return 0;
694486
}
487+
#endif /* CONFIG_X86_64 */
695488

696489
/*
697490
* There are four different struct types for signal frame: sigframe_ia32,

0 commit comments

Comments
 (0)