Skip to content

Commit fbe0d45

Browse files
committed
Merge tag 'x86-urgent-2020-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into master
Pull x86 fixes from Ingo Molnar: "Misc fixes: - Fix a section end page alignment assumption that was causing crashes - Fix ORC unwinding on freshly forked tasks which haven't executed yet and which have empty user task stacks - Fix the debug.exception-trace=1 sysctl dumping of user stacks, which was broken by recent maccess changes" * tag 'x86-urgent-2020-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/dumpstack: Dump user space code correctly again x86/stacktrace: Fix reliable check for empty user task stacks x86/unwind/orc: Fix ORC for newly forked tasks x86, vmlinux.lds: Page-align end of ..page_aligned sections
2 parents 78b1afe + d181d2d commit fbe0d45

File tree

5 files changed

+28
-18
lines changed

5 files changed

+28
-18
lines changed

arch/x86/kernel/dumpstack.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,22 @@ static void printk_stack_address(unsigned long address, int reliable,
7171
printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
7272
}
7373

74+
static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
75+
unsigned int nbytes)
76+
{
77+
if (!user_mode(regs))
78+
return copy_from_kernel_nofault(buf, (u8 *)src, nbytes);
79+
80+
/*
81+
* Make sure userspace isn't trying to trick us into dumping kernel
82+
* memory by pointing the userspace instruction pointer at it.
83+
*/
84+
if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
85+
return -EINVAL;
86+
87+
return copy_from_user_nmi(buf, (void __user *)src, nbytes);
88+
}
89+
7490
/*
7591
* There are a couple of reasons for the 2/3rd prologue, courtesy of Linus:
7692
*
@@ -97,17 +113,8 @@ void show_opcodes(struct pt_regs *regs, const char *loglvl)
97113
#define OPCODE_BUFSIZE (PROLOGUE_SIZE + 1 + EPILOGUE_SIZE)
98114
u8 opcodes[OPCODE_BUFSIZE];
99115
unsigned long prologue = regs->ip - PROLOGUE_SIZE;
100-
bool bad_ip;
101-
102-
/*
103-
* Make sure userspace isn't trying to trick us into dumping kernel
104-
* memory by pointing the userspace instruction pointer at it.
105-
*/
106-
bad_ip = user_mode(regs) &&
107-
__chk_range_not_ok(prologue, OPCODE_BUFSIZE, TASK_SIZE_MAX);
108116

109-
if (bad_ip || copy_from_kernel_nofault(opcodes, (u8 *)prologue,
110-
OPCODE_BUFSIZE)) {
117+
if (copy_code(regs, opcodes, prologue, sizeof(opcodes))) {
111118
printk("%sCode: Bad RIP value.\n", loglvl);
112119
} else {
113120
printk("%sCode: %" __stringify(PROLOGUE_SIZE) "ph <%02x> %"

arch/x86/kernel/stacktrace.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
5858
* or a page fault), which can make frame pointers
5959
* unreliable.
6060
*/
61-
6261
if (IS_ENABLED(CONFIG_FRAME_POINTER))
6362
return -EINVAL;
6463
}
@@ -81,10 +80,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
8180
if (unwind_error(&state))
8281
return -EINVAL;
8382

84-
/* Success path for non-user tasks, i.e. kthreads and idle tasks */
85-
if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
86-
return -EINVAL;
87-
8883
return 0;
8984
}
9085

arch/x86/kernel/unwind_orc.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,11 @@ bool unwind_next_frame(struct unwind_state *state)
440440
/*
441441
* Find the orc_entry associated with the text address.
442442
*
443-
* Decrement call return addresses by one so they work for sibling
444-
* calls and calls to noreturn functions.
443+
* For a call frame (as opposed to a signal frame), state->ip points to
444+
* the instruction after the call. That instruction's stack layout
445+
* could be different from the call instruction's layout, for example
446+
* if the call was to a noreturn function. So get the ORC data for the
447+
* call instruction itself.
445448
*/
446449
orc = orc_find(state->signal ? state->ip : state->ip - 1);
447450
if (!orc) {
@@ -662,6 +665,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
662665
state->sp = task->thread.sp;
663666
state->bp = READ_ONCE_NOCHECK(frame->bp);
664667
state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
668+
state->signal = (void *)state->ip == ret_from_fork;
665669
}
666670

667671
if (get_stack_info((unsigned long *)state->sp, state->task,

arch/x86/kernel/vmlinux.lds.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ SECTIONS
358358
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
359359
__bss_start = .;
360360
*(.bss..page_aligned)
361+
. = ALIGN(PAGE_SIZE);
361362
*(BSS_MAIN)
362363
BSS_DECRYPTED
363364
. = ALIGN(PAGE_SIZE);

include/asm-generic/vmlinux.lds.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@
341341

342342
#define PAGE_ALIGNED_DATA(page_align) \
343343
. = ALIGN(page_align); \
344-
*(.data..page_aligned)
344+
*(.data..page_aligned) \
345+
. = ALIGN(page_align);
345346

346347
#define READ_MOSTLY_DATA(align) \
347348
. = ALIGN(align); \
@@ -737,7 +738,9 @@
737738
. = ALIGN(bss_align); \
738739
.bss : AT(ADDR(.bss) - LOAD_OFFSET) { \
739740
BSS_FIRST_SECTIONS \
741+
. = ALIGN(PAGE_SIZE); \
740742
*(.bss..page_aligned) \
743+
. = ALIGN(PAGE_SIZE); \
741744
*(.dynbss) \
742745
*(BSS_MAIN) \
743746
*(COMMON) \

0 commit comments

Comments
 (0)