Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f74972c authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

signal: Don't use structure initializers for struct siginfo



The siginfo structure has all manners of holes with the result that a
structure initializer is not guaranteed to initialize all of the bits.
As we have to copy the structure to userspace don't even try to use
a structure initializer.  Instead use clear_siginfo followed by initializing
selected fields.  This gives a guarantee that uninitialized kernel memory
is not copied to userspace.

Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 66e0f263
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -65,12 +65,14 @@ unhandled_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
#define DO_ERROR_INFO(signr, str, name, sicode) \
int name(unsigned long address, struct pt_regs *regs) \
{						\
	siginfo_t info = {			\
		.si_signo = signr,		\
		.si_errno = 0,			\
		.si_code  = sicode,		\
		.si_addr = (void __user *)address,	\
	};					\
	siginfo_t info;				\
						\
	clear_siginfo(&info);			\
	info.si_signo = signr;			\
	info.si_errno = 0;			\
	info.si_code  = sicode;			\
	info.si_addr = (void __user *)address;	\
						\
	return unhandled_exception(str, regs, &info);\
}

+7 −6
Original line number Diff line number Diff line
@@ -209,12 +209,13 @@ NOKPROBE_SYMBOL(call_step_hook);
static void send_user_sigtrap(int si_code)
{
	struct pt_regs *regs = current_pt_regs();
	siginfo_t info = {
		.si_signo	= SIGTRAP,
		.si_errno	= 0,
		.si_code	= si_code,
		.si_addr	= (void __user *)instruction_pointer(regs),
	};
	siginfo_t info;

	clear_siginfo(&info);
	info.si_signo	= SIGTRAP;
	info.si_errno	= 0;
	info.si_code	= si_code;
	info.si_addr	= (void __user *)instruction_pointer(regs);

	if (WARN_ON(!user_mode(regs)))
		return;
+7 −6
Original line number Diff line number Diff line
@@ -180,12 +180,13 @@ static void ptrace_hbptriggered(struct perf_event *bp,
				struct pt_regs *regs)
{
	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
	siginfo_t info = {
		.si_signo	= SIGTRAP,
		.si_errno	= 0,
		.si_code	= TRAP_HWBKPT,
		.si_addr	= (void __user *)(bkpt->trigger),
	};
	siginfo_t info;

	clear_siginfo(&info);
	info.si_signo	= SIGTRAP;
	info.si_errno	= 0;
	info.si_code	= TRAP_HWBKPT;
	info.si_addr	= (void __user *)(bkpt->trigger);

#ifdef CONFIG_COMPAT
	if (is_compat_task()) {
+2 −1
Original line number Diff line number Diff line
@@ -21,8 +21,9 @@ extern void die_if_kernel(char *, struct pt_regs *, long);

int send_fault_sig(struct pt_regs *regs)
{
	siginfo_t siginfo = { 0, 0, 0, };
	siginfo_t siginfo;

	clear_siginfo(&siginfo);
	siginfo.si_signo = current->thread.signo;
	siginfo.si_code = current->thread.code;
	siginfo.si_addr = (void *)current->thread.faddr;
+20 −9
Original line number Diff line number Diff line
@@ -699,11 +699,12 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
asmlinkage void do_ov(struct pt_regs *regs)
{
	enum ctx_state prev_state;
	siginfo_t info = {
		.si_signo = SIGFPE,
		.si_code = FPE_INTOVF,
		.si_addr = (void __user *)regs->cp0_epc,
	};
	siginfo_t info;

	clear_siginfo(&info);
	info.si_signo = SIGFPE;
	info.si_code = FPE_INTOVF;
	info.si_addr = (void __user *)regs->cp0_epc;

	prev_state = exception_enter();
	die_if_kernel("Integer overflow", regs);
@@ -721,7 +722,11 @@ asmlinkage void do_ov(struct pt_regs *regs)
void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
		     struct task_struct *tsk)
{
	struct siginfo si = { .si_addr = fault_addr, .si_signo = SIGFPE };
	struct siginfo si;

	clear_siginfo(&si);
	si.si_addr = fault_addr;
	si.si_signo = SIGFPE;

	if (fcr31 & FPU_CSR_INV_X)
		si.si_code = FPE_FLTINV;
@@ -739,9 +744,10 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,

int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
{
	struct siginfo si = { 0 };
	struct siginfo si;
	struct vm_area_struct *vma;

	clear_siginfo(&si);
	switch (sig) {
	case 0:
		return 0;
@@ -890,9 +896,10 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
	const char *str)
{
	siginfo_t info = { 0 };
	siginfo_t info;
	char b[40];

	clear_siginfo(&info);
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
	if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
			 SIGTRAP) == NOTIFY_STOP)
@@ -1499,9 +1506,13 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
 */
asmlinkage void do_watch(struct pt_regs *regs)
{
	siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
	siginfo_t info;
	enum ctx_state prev_state;

	clear_siginfo(&info);
	info.si_signo = SIGTRAP;
	info.si_code = TRAP_HWBKPT;

	prev_state = exception_enter();
	/*
	 * Clear WP (bit 22) bit of cause register so we don't loop
Loading