Skip to content

Commit

Permalink
all arches, signal: move restart_block to struct task_struct
Browse files Browse the repository at this point in the history
If an attacker can cause a controlled kernel stack overflow, overwriting
the restart block is a very juicy exploit target.  This is because the
restart_block is held in the same memory allocation as the kernel stack.

Moving the restart block to struct task_struct prevents this exploit by
making the restart_block harder to locate.

Note that there are other fields in thread_info that are also easy
targets, at least on some architectures.

It's also a decent simplification, since the restart code is more or less
identical on all architectures.

[[email protected]: metag: align thread_info::supervisor_stack]
Signed-off-by: Andy Lutomirski <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Al Viro <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: David Miller <[email protected]>
Acked-by: Richard Weinberger <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Ivan Kokshaysky <[email protected]>
Cc: Matt Turner <[email protected]>
Cc: Vineet Gupta <[email protected]>
Cc: Russell King <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Haavard Skinnemoen <[email protected]>
Cc: Hans-Christian Egtvedt <[email protected]>
Cc: Steven Miao <[email protected]>
Cc: Mark Salter <[email protected]>
Cc: Aurelien Jacquiot <[email protected]>
Cc: Mikael Starvik <[email protected]>
Cc: Jesper Nilsson <[email protected]>
Cc: David Howells <[email protected]>
Cc: Richard Kuo <[email protected]>
Cc: "Luck, Tony" <[email protected]>
Cc: Geert Uytterhoeven <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: Ralf Baechle <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Acked-by: Michael Ellerman <[email protected]> (powerpc)
Tested-by: Michael Ellerman <[email protected]> (powerpc)
Cc: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
Cc: Chen Liqin <[email protected]>
Cc: Lennox Wu <[email protected]>
Cc: Chris Metcalf <[email protected]>
Cc: Guan Xuetao <[email protected]>
Cc: Chris Zankel <[email protected]>
Cc: Max Filippov <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Guenter Roeck <[email protected]>
Signed-off-by: James Hogan <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
amluto authored and torvalds committed Feb 13, 2015
1 parent edc924e commit f56141e
Show file tree
Hide file tree
Showing 84 changed files with 62 additions and 194 deletions.
5 changes: 0 additions & 5 deletions arch/alpha/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ struct thread_info {
int bpt_nsaved;
unsigned long bpt_addr[2]; /* breakpoint handling */
unsigned int bpt_insn[2];

struct restart_block restart_block;
};

/*
Expand All @@ -40,9 +38,6 @@ struct thread_info {
.exec_domain = &default_exec_domain, \
.addr_limit = KERNEL_DS, \
.preempt_count = INIT_PREEMPT_COUNT, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
2 changes: 1 addition & 1 deletion arch/alpha/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
struct switch_stack *sw = (struct switch_stack *)regs - 1;
long i, err = __get_user(regs->pc, &sc->sc_pc);

current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

sw->r26 = (unsigned long) ret_from_sys_call;

Expand Down
4 changes: 0 additions & 4 deletions arch/arc/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ struct thread_info {
struct exec_domain *exec_domain;/* execution domain */
__u32 cpu; /* current CPU */
unsigned long thr_ptr; /* TLS ptr */
struct restart_block restart_block;
};

/*
Expand All @@ -62,9 +61,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
2 changes: 1 addition & 1 deletion arch/arc/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
struct pt_regs *regs = current_pt_regs();

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/* Since we stacked the signal on a word boundary,
* then 'sp' should be word aligned here. If it's
Expand Down
4 changes: 0 additions & 4 deletions arch/arm/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ struct thread_info {
#ifdef CONFIG_ARM_THUMBEE
unsigned long thumbee_state; /* ThumbEE Handler Base register */
#endif
struct restart_block restart_block;
};

#define INIT_THREAD_INFO(tsk) \
Expand All @@ -81,9 +80,6 @@ struct thread_info {
.cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT), \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
4 changes: 2 additions & 2 deletions arch/arm/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
struct sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a 64-bit boundary,
Expand Down Expand Up @@ -221,7 +221,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
struct rt_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a 64-bit boundary,
Expand Down
4 changes: 0 additions & 4 deletions arch/arm64/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct thread_info {
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
struct restart_block restart_block;
int preempt_count; /* 0 => preemptable, <0 => bug */
int cpu; /* cpu */
};
Expand All @@ -60,9 +59,6 @@ struct thread_info {
.flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
struct rt_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a 128-bit boundary, then 'sp' should
Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
struct compat_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a 64-bit boundary,
Expand Down Expand Up @@ -381,7 +381,7 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
struct compat_rt_sigframe __user *frame;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a 64-bit boundary,
Expand Down
4 changes: 0 additions & 4 deletions arch/avr32/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct thread_info {
saved by debug handler
when setting up
trampoline */
struct restart_block restart_block;
__u8 supervisor_stack[0];
};

Expand All @@ -41,9 +40,6 @@ struct thread_info {
.flags = 0, \
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.restart_block = { \
.fn = do_no_restart_syscall \
} \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
1 change: 0 additions & 1 deletion arch/avr32/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ void foo(void)
OFFSET(TI_preempt_count, thread_info, preempt_count);
OFFSET(TI_rar_saved, thread_info, rar_saved);
OFFSET(TI_rsr_saved, thread_info, rsr_saved);
OFFSET(TI_restart_block, thread_info, restart_block);
BLANK();
OFFSET(TSK_active_mm, task_struct, active_mm);
BLANK();
Expand Down
2 changes: 1 addition & 1 deletion arch/avr32/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
sigset_t set;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

frame = (struct rt_sigframe __user *)regs->sp;
pr_debug("SIG return: frame = %p\n", frame);
Expand Down
4 changes: 0 additions & 4 deletions arch/blackfin/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ struct thread_info {
int cpu; /* cpu we're on */
int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* address limit */
struct restart_block restart_block;
#ifndef CONFIG_SMP
struct l1_scratch_task_info l1_task_info;
#endif
Expand All @@ -58,9 +57,6 @@ struct thread_info {
.flags = 0, \
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
Expand Down
2 changes: 1 addition & 1 deletion arch/blackfin/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *p
int err = 0;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

#define RESTORE(x) err |= __get_user(regs->x, &sc->sc_##x)

Expand Down
4 changes: 0 additions & 4 deletions arch/c6x/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ struct thread_info {
int cpu; /* cpu we're on */
int preempt_count; /* 0 = preemptable, <0 = BUG */
mm_segment_t addr_limit; /* thread address space */
struct restart_block restart_block;
};

/*
Expand All @@ -61,9 +60,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
2 changes: 1 addition & 1 deletion arch/c6x/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
sigset_t set;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Since we stacked the signal on a dword boundary,
Expand Down
2 changes: 1 addition & 1 deletion arch/cris/arch-v10/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
unsigned long old_usp;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/* restore the regs from &sc->regs (same as sc, since regs is first)
* (sc is already checked for VERIFY_READ since the sigframe was
Expand Down
2 changes: 1 addition & 1 deletion arch/cris/arch-v32/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
unsigned long old_usp;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/*
* Restore the registers from &sc->regs. sc is already checked
Expand Down
4 changes: 0 additions & 4 deletions arch/cris/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ struct thread_info {
0-0xBFFFFFFF for user-thead
0-0xFFFFFFFF for kernel-thread
*/
struct restart_block restart_block;
__u8 supervisor_stack[0];
};

Expand All @@ -56,9 +55,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
4 changes: 0 additions & 4 deletions arch/frv/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ struct thread_info {
* 0-0xBFFFFFFF for user-thead
* 0-0xFFFFFFFF for kernel-thread
*/
struct restart_block restart_block;

__u8 supervisor_stack[0];
};
Expand All @@ -65,9 +64,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
1 change: 0 additions & 1 deletion arch/frv/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ void foo(void)
OFFSET(TI_CPU, thread_info, cpu);
OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count);
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
BLANK();

/* offsets into register file storage */
Expand Down
2 changes: 1 addition & 1 deletion arch/frv/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
unsigned long tbr, psr;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

tbr = user->i.tbr;
psr = user->i.psr;
Expand Down
4 changes: 0 additions & 4 deletions arch/hexagon/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ struct thread_info {
* used for syscalls somehow;
* seems to have a function pointer and four arguments
*/
struct restart_block restart_block;
/* Points to the current pt_regs frame */
struct pt_regs *regs;
/*
Expand All @@ -83,9 +82,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = 1, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
.sp = 0, \
.regs = NULL, \
}
Expand Down
2 changes: 1 addition & 1 deletion arch/hexagon/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ asmlinkage int sys_rt_sigreturn(void)
sigset_t blocked;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

frame = (struct rt_sigframe __user *)pt_psp(regs);
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
Expand Down
4 changes: 0 additions & 4 deletions arch/ia64/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ struct thread_info {
__u32 status; /* Thread synchronous flags */
mm_segment_t addr_limit; /* user-level address space limit */
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
struct restart_block restart_block;
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
__u64 ac_stamp;
__u64 ac_leave;
Expand All @@ -46,9 +45,6 @@ struct thread_info {
.cpu = 0, \
.addr_limit = KERNEL_DS, \
.preempt_count = INIT_PREEMPT_COUNT, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#ifndef ASM_OFFSETS_C
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
long err;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

/* restore scratch that always needs gets updated during signal delivery: */
err = __get_user(flags, &sc->sc_flags);
Expand Down
5 changes: 0 additions & 5 deletions arch/m32r/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ struct thread_info {
0-0xBFFFFFFF for user-thread
0-0xFFFFFFFF for kernel-thread
*/
struct restart_block restart_block;

__u8 supervisor_stack[0];
};
Expand All @@ -49,7 +48,6 @@ struct thread_info {
#define TI_CPU 0x00000010
#define TI_PRE_COUNT 0x00000014
#define TI_ADDR_LIMIT 0x00000018
#define TI_RESTART_BLOCK 0x000001C

#endif

Expand All @@ -68,9 +66,6 @@ struct thread_info {
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
}

#define init_thread_info (init_thread_union.thread_info)
Expand Down
2 changes: 1 addition & 1 deletion arch/m32r/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
unsigned int err = 0;

/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
current->restart_block.fn = do_no_restart_syscall;

#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
COPY(r4);
Expand Down
Loading

0 comments on commit f56141e

Please sign in to comment.