arch/x86/kernel/signal_32.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/signal_32.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/signal_32.c
Extension
.c
Size
15824 bytes
Lines
536
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
 *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
 *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
 */

#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/personality.h>
#include <linux/compat.h>
#include <linux/binfmts.h>
#include <linux/syscalls.h>
#include <asm/ucontext.h>
#include <linux/uaccess.h>
#include <asm/fpu/signal.h>
#include <asm/ptrace.h>
#include <asm/user32.h>
#include <uapi/asm/sigcontext.h>
#include <asm/proto.h>
#include <asm/vdso.h>
#include <asm/sigframe.h>
#include <asm/sighandling.h>
#include <asm/smap.h>
#include <asm/gsseg.h>

/*
 * The first GDT descriptor is reserved as 'NULL descriptor'.  As bits 0
 * and 1 of a segment selector, i.e., the RPL bits, are NOT used to index
 * GDT, selector values 0~3 all point to the NULL descriptor, thus values
 * 0, 1, 2 and 3 are all valid NULL selector values.
 *
 * However IRET zeros ES, FS, GS, and DS segment registers if any of them
 * is found to have any nonzero NULL selector value, which can be used by
 * userspace in pre-FRED systems to spot any interrupt/exception by loading
 * a nonzero NULL selector and waiting for it to become zero.  Before FRED
 * there was nothing software could do to prevent such an information leak.
 *
 * ERETU, the only legit instruction to return to userspace from kernel
 * under FRED, by design does NOT zero any segment register to avoid this
 * problem behavior.
 *
 * As such, leave NULL selector values 0~3 unchanged.
 */
static inline u16 fixup_rpl(u16 sel)
{
	return sel <= 3 ? sel : sel | 3;
}

#ifdef CONFIG_IA32_EMULATION
#include <asm/unistd_32_ia32.h>

static inline void reload_segments(struct sigcontext_32 *sc)
{
	u16 cur;

	/*
	 * Reload fs and gs if they have changed in the signal
	 * handler.  This does not handle long fs/gs base changes in
	 * the handler, but does not clobber them at least in the
	 * normal case.
	 */
	savesegment(gs, cur);
	if (fixup_rpl(sc->gs) != cur)
		load_gs_index(fixup_rpl(sc->gs));
	savesegment(fs, cur);
	if (fixup_rpl(sc->fs) != cur)
		loadsegment(fs, fixup_rpl(sc->fs));

	savesegment(ds, cur);
	if (fixup_rpl(sc->ds) != cur)
		loadsegment(ds, fixup_rpl(sc->ds));
	savesegment(es, cur);
	if (fixup_rpl(sc->es) != cur)
		loadsegment(es, fixup_rpl(sc->es));
}

#define sigset32_t			compat_sigset_t
#define siginfo32_t			compat_siginfo_t
#define restore_altstack32		compat_restore_altstack
#define unsafe_save_altstack32		unsafe_compat_save_altstack

Annotation

Implementation Notes