Skip to content

Commit 63004af

Browse files
committed
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull straggler x86 fixes from Peter Anvin: "Three groups of patches: - EFI boot stub documentation and the ability to print error messages; - Removal for PTRACE_ARCH_PRCTL for x32 (obsolete interface which should never have been ported, and the port is broken and potentially dangerous.) - ftrace stack corruption fixes. I'm not super-happy about the technical implementation, but it is probably the least invasive in the short term. In the future I would like a single method for nesting the debug stack, however." * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, x32, ptrace: Remove PTRACE_ARCH_PRCTL for x32 x86, efi: Add EFI boot stub documentation x86, efi; Add EFI boot stub console support x86, efi: Only close open files in error path ftrace/x86: Do not change stacks in DEBUG when calling lockdep x86: Allow nesting of the debug stack IDT setting x86: Reset the debug_stack update counter ftrace: Use breakpoint method to update ftrace caller ftrace: Synchronize variable setting with breakpoints
2 parents f309532 + 40b46a7 commit 63004af

File tree

11 files changed

+297
-39
lines changed

11 files changed

+297
-39
lines changed

Documentation/x86/efi-stub.txt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
The EFI Boot Stub
2+
---------------------------
3+
4+
On the x86 platform, a bzImage can masquerade as a PE/COFF image,
5+
thereby convincing EFI firmware loaders to load it as an EFI
6+
executable. The code that modifies the bzImage header, along with the
7+
EFI-specific entry point that the firmware loader jumps to are
8+
collectively known as the "EFI boot stub", and live in
9+
arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c,
10+
respectively.
11+
12+
By using the EFI boot stub it's possible to boot a Linux kernel
13+
without the use of a conventional EFI boot loader, such as grub or
14+
elilo. Since the EFI boot stub performs the jobs of a boot loader, in
15+
a certain sense it *IS* the boot loader.
16+
17+
The EFI boot stub is enabled with the CONFIG_EFI_STUB kernel option.
18+
19+
20+
**** How to install bzImage.efi
21+
22+
The bzImage located in arch/x86/boot/bzImage must be copied to the EFI
23+
System Partiion (ESP) and renamed with the extension ".efi". Without
24+
the extension the EFI firmware loader will refuse to execute it. It's
25+
not possible to execute bzImage.efi from the usual Linux file systems
26+
because EFI firmware doesn't have support for them.
27+
28+
29+
**** Passing kernel parameters from the EFI shell
30+
31+
Arguments to the kernel can be passed after bzImage.efi, e.g.
32+
33+
fs0:> bzImage.efi console=ttyS0 root=/dev/sda4
34+
35+
36+
**** The "initrd=" option
37+
38+
Like most boot loaders, the EFI stub allows the user to specify
39+
multiple initrd files using the "initrd=" option. This is the only EFI
40+
stub-specific command line parameter, everything else is passed to the
41+
kernel when it boots.
42+
43+
The path to the initrd file must be an absolute path from the
44+
beginning of the ESP, relative path names do not work. Also, the path
45+
is an EFI-style path and directory elements must be separated with
46+
backslashes (\). For example, given the following directory layout,
47+
48+
fs0:>
49+
Kernels\
50+
bzImage.efi
51+
initrd-large.img
52+
53+
Ramdisks\
54+
initrd-small.img
55+
initrd-medium.img
56+
57+
to boot with the initrd-large.img file if the current working
58+
directory is fs0:\Kernels, the following command must be used,
59+
60+
fs0:\Kernels> bzImage.efi initrd=\Kernels\initrd-large.img
61+
62+
Notice how bzImage.efi can be specified with a relative path. That's
63+
because the image we're executing is interpreted by the EFI shell,
64+
which understands relative paths, whereas the rest of the command line
65+
is passed to bzImage.efi.

arch/x86/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ config EFI_STUB
15061506
This kernel feature allows a bzImage to be loaded directly
15071507
by EFI firmware without the use of a bootloader.
15081508

1509+
See Documentation/x86/efi-stub.txt for more information.
1510+
15091511
config SECCOMP
15101512
def_bool y
15111513
prompt "Enable seccomp to safely compute untrusted bytecode"

arch/x86/boot/compressed/eboot.c

Lines changed: 70 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@
1616

1717
static efi_system_table_t *sys_table;
1818

19+
static void efi_printk(char *str)
20+
{
21+
char *s8;
22+
23+
for (s8 = str; *s8; s8++) {
24+
struct efi_simple_text_output_protocol *out;
25+
efi_char16_t ch[2] = { 0 };
26+
27+
ch[0] = *s8;
28+
out = (struct efi_simple_text_output_protocol *)sys_table->con_out;
29+
30+
if (*s8 == '\n') {
31+
efi_char16_t nl[2] = { '\r', 0 };
32+
efi_call_phys2(out->output_string, out, nl);
33+
}
34+
35+
efi_call_phys2(out->output_string, out, ch);
36+
}
37+
}
38+
1939
static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size,
2040
unsigned long *desc_size)
2141
{
@@ -531,8 +551,10 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
531551
EFI_LOADER_DATA,
532552
nr_initrds * sizeof(*initrds),
533553
&initrds);
534-
if (status != EFI_SUCCESS)
554+
if (status != EFI_SUCCESS) {
555+
efi_printk("Failed to alloc mem for initrds\n");
535556
goto fail;
557+
}
536558

537559
str = (char *)(unsigned long)hdr->cmd_line_ptr;
538560
for (i = 0; i < nr_initrds; i++) {
@@ -575,32 +597,42 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
575597

576598
status = efi_call_phys3(boottime->handle_protocol,
577599
image->device_handle, &fs_proto, &io);
578-
if (status != EFI_SUCCESS)
600+
if (status != EFI_SUCCESS) {
601+
efi_printk("Failed to handle fs_proto\n");
579602
goto free_initrds;
603+
}
580604

581605
status = efi_call_phys2(io->open_volume, io, &fh);
582-
if (status != EFI_SUCCESS)
606+
if (status != EFI_SUCCESS) {
607+
efi_printk("Failed to open volume\n");
583608
goto free_initrds;
609+
}
584610
}
585611

586612
status = efi_call_phys5(fh->open, fh, &h, filename_16,
587613
EFI_FILE_MODE_READ, (u64)0);
588-
if (status != EFI_SUCCESS)
614+
if (status != EFI_SUCCESS) {
615+
efi_printk("Failed to open initrd file\n");
589616
goto close_handles;
617+
}
590618

591619
initrd->handle = h;
592620

593621
info_sz = 0;
594622
status = efi_call_phys4(h->get_info, h, &info_guid,
595623
&info_sz, NULL);
596-
if (status != EFI_BUFFER_TOO_SMALL)
624+
if (status != EFI_BUFFER_TOO_SMALL) {
625+
efi_printk("Failed to get initrd info size\n");
597626
goto close_handles;
627+
}
598628

599629
grow:
600630
status = efi_call_phys3(sys_table->boottime->allocate_pool,
601631
EFI_LOADER_DATA, info_sz, &info);
602-
if (status != EFI_SUCCESS)
632+
if (status != EFI_SUCCESS) {
633+
efi_printk("Failed to alloc mem for initrd info\n");
603634
goto close_handles;
635+
}
604636

605637
status = efi_call_phys4(h->get_info, h, &info_guid,
606638
&info_sz, info);
@@ -612,8 +644,10 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
612644
file_sz = info->file_size;
613645
efi_call_phys1(sys_table->boottime->free_pool, info);
614646

615-
if (status != EFI_SUCCESS)
647+
if (status != EFI_SUCCESS) {
648+
efi_printk("Failed to get initrd info\n");
616649
goto close_handles;
650+
}
617651

618652
initrd->size = file_sz;
619653
initrd_total += file_sz;
@@ -629,11 +663,14 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
629663
*/
630664
status = high_alloc(initrd_total, 0x1000,
631665
&initrd_addr, hdr->initrd_addr_max);
632-
if (status != EFI_SUCCESS)
666+
if (status != EFI_SUCCESS) {
667+
efi_printk("Failed to alloc highmem for initrds\n");
633668
goto close_handles;
669+
}
634670

635671
/* We've run out of free low memory. */
636672
if (initrd_addr > hdr->initrd_addr_max) {
673+
efi_printk("We've run out of free low memory\n");
637674
status = EFI_INVALID_PARAMETER;
638675
goto free_initrd_total;
639676
}
@@ -652,8 +689,10 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
652689
status = efi_call_phys3(fh->read,
653690
initrds[j].handle,
654691
&chunksize, addr);
655-
if (status != EFI_SUCCESS)
692+
if (status != EFI_SUCCESS) {
693+
efi_printk("Failed to read initrd\n");
656694
goto free_initrd_total;
695+
}
657696
addr += chunksize;
658697
size -= chunksize;
659698
}
@@ -674,7 +713,7 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image,
674713
low_free(initrd_total, initrd_addr);
675714

676715
close_handles:
677-
for (k = j; k < nr_initrds; k++)
716+
for (k = j; k < i; k++)
678717
efi_call_phys1(fh->close, initrds[k].handle);
679718
free_initrds:
680719
efi_call_phys1(sys_table->boottime->free_pool, initrds);
@@ -732,8 +771,10 @@ static efi_status_t make_boot_params(struct boot_params *boot_params,
732771
options_size++; /* NUL termination */
733772

734773
status = low_alloc(options_size, 1, &cmdline);
735-
if (status != EFI_SUCCESS)
774+
if (status != EFI_SUCCESS) {
775+
efi_printk("Failed to alloc mem for cmdline\n");
736776
goto fail;
777+
}
737778

738779
s1 = (u8 *)(unsigned long)cmdline;
739780
s2 = (u16 *)options;
@@ -895,12 +936,16 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
895936

896937
status = efi_call_phys3(sys_table->boottime->handle_protocol,
897938
handle, &proto, (void *)&image);
898-
if (status != EFI_SUCCESS)
939+
if (status != EFI_SUCCESS) {
940+
efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
899941
goto fail;
942+
}
900943

901944
status = low_alloc(0x4000, 1, (unsigned long *)&boot_params);
902-
if (status != EFI_SUCCESS)
945+
if (status != EFI_SUCCESS) {
946+
efi_printk("Failed to alloc lowmem for boot params\n");
903947
goto fail;
948+
}
904949

905950
memset(boot_params, 0x0, 0x4000);
906951

@@ -933,8 +978,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
933978
if (status != EFI_SUCCESS) {
934979
status = low_alloc(hdr->init_size, hdr->kernel_alignment,
935980
&start);
936-
if (status != EFI_SUCCESS)
981+
if (status != EFI_SUCCESS) {
982+
efi_printk("Failed to alloc mem for kernel\n");
937983
goto fail;
984+
}
938985
}
939986

940987
hdr->code32_start = (__u32)start;
@@ -945,19 +992,25 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table)
945992
status = efi_call_phys3(sys_table->boottime->allocate_pool,
946993
EFI_LOADER_DATA, sizeof(*gdt),
947994
(void **)&gdt);
948-
if (status != EFI_SUCCESS)
995+
if (status != EFI_SUCCESS) {
996+
efi_printk("Failed to alloc mem for gdt structure\n");
949997
goto fail;
998+
}
950999

9511000
gdt->size = 0x800;
9521001
status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address);
953-
if (status != EFI_SUCCESS)
1002+
if (status != EFI_SUCCESS) {
1003+
efi_printk("Failed to alloc mem for gdt\n");
9541004
goto fail;
1005+
}
9551006

9561007
status = efi_call_phys3(sys_table->boottime->allocate_pool,
9571008
EFI_LOADER_DATA, sizeof(*idt),
9581009
(void **)&idt);
959-
if (status != EFI_SUCCESS)
1010+
if (status != EFI_SUCCESS) {
1011+
efi_printk("Failed to alloc mem for idt structure\n");
9601012
goto fail;
1013+
}
9611014

9621015
idt->size = 0;
9631016
idt->address = 0;

arch/x86/boot/compressed/eboot.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@ struct efi_uga_draw_protocol {
5858
void *blt;
5959
};
6060

61+
struct efi_simple_text_output_protocol {
62+
void *reset;
63+
void *output_string;
64+
void *test_string;
65+
};
66+
6167
#endif /* BOOT_COMPRESSED_EBOOT_H */

arch/x86/include/asm/ftrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
#ifndef __ASSEMBLY__
3636
extern void mcount(void);
37-
extern int modifying_ftrace_code;
37+
extern atomic_t modifying_ftrace_code;
3838

3939
static inline unsigned long ftrace_call_adjust(unsigned long addr)
4040
{

arch/x86/kernel/cpu/common.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,14 +1101,20 @@ int is_debug_stack(unsigned long addr)
11011101
addr > (__get_cpu_var(debug_stack_addr) - DEBUG_STKSZ));
11021102
}
11031103

1104+
static DEFINE_PER_CPU(u32, debug_stack_use_ctr);
1105+
11041106
void debug_stack_set_zero(void)
11051107
{
1108+
this_cpu_inc(debug_stack_use_ctr);
11061109
load_idt((const struct desc_ptr *)&nmi_idt_descr);
11071110
}
11081111

11091112
void debug_stack_reset(void)
11101113
{
1111-
load_idt((const struct desc_ptr *)&idt_descr);
1114+
if (WARN_ON(!this_cpu_read(debug_stack_use_ctr)))
1115+
return;
1116+
if (this_cpu_dec_return(debug_stack_use_ctr) == 0)
1117+
load_idt((const struct desc_ptr *)&idt_descr);
11121118
}
11131119

11141120
#else /* CONFIG_X86_64 */

arch/x86/kernel/entry_64.S

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,44 @@ ENDPROC(native_usergs_sysret64)
190190
#endif
191191
.endm
192192

193+
/*
194+
* When dynamic function tracer is enabled it will add a breakpoint
195+
* to all locations that it is about to modify, sync CPUs, update
196+
* all the code, sync CPUs, then remove the breakpoints. In this time
197+
* if lockdep is enabled, it might jump back into the debug handler
198+
* outside the updating of the IST protection. (TRACE_IRQS_ON/OFF).
199+
*
200+
* We need to change the IDT table before calling TRACE_IRQS_ON/OFF to
201+
* make sure the stack pointer does not get reset back to the top
202+
* of the debug stack, and instead just reuses the current stack.
203+
*/
204+
#if defined(CONFIG_DYNAMIC_FTRACE) && defined(CONFIG_TRACE_IRQFLAGS)
205+
206+
.macro TRACE_IRQS_OFF_DEBUG
207+
call debug_stack_set_zero
208+
TRACE_IRQS_OFF
209+
call debug_stack_reset
210+
.endm
211+
212+
.macro TRACE_IRQS_ON_DEBUG
213+
call debug_stack_set_zero
214+
TRACE_IRQS_ON
215+
call debug_stack_reset
216+
.endm
217+
218+
.macro TRACE_IRQS_IRETQ_DEBUG offset=ARGOFFSET
219+
bt $9,EFLAGS-\offset(%rsp) /* interrupts off? */
220+
jnc 1f
221+
TRACE_IRQS_ON_DEBUG
222+
1:
223+
.endm
224+
225+
#else
226+
# define TRACE_IRQS_OFF_DEBUG TRACE_IRQS_OFF
227+
# define TRACE_IRQS_ON_DEBUG TRACE_IRQS_ON
228+
# define TRACE_IRQS_IRETQ_DEBUG TRACE_IRQS_IRETQ
229+
#endif
230+
193231
/*
194232
* C code is not supposed to know about undefined top of stack. Every time
195233
* a C function with an pt_regs argument is called from the SYSCALL based
@@ -1098,7 +1136,7 @@ ENTRY(\sym)
10981136
subq $ORIG_RAX-R15, %rsp
10991137
CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
11001138
call save_paranoid
1101-
TRACE_IRQS_OFF
1139+
TRACE_IRQS_OFF_DEBUG
11021140
movq %rsp,%rdi /* pt_regs pointer */
11031141
xorl %esi,%esi /* no error code */
11041142
subq $EXCEPTION_STKSZ, INIT_TSS_IST(\ist)
@@ -1393,7 +1431,7 @@ paranoidzeroentry machine_check *machine_check_vector(%rip)
13931431
ENTRY(paranoid_exit)
13941432
DEFAULT_FRAME
13951433
DISABLE_INTERRUPTS(CLBR_NONE)
1396-
TRACE_IRQS_OFF
1434+
TRACE_IRQS_OFF_DEBUG
13971435
testl %ebx,%ebx /* swapgs needed? */
13981436
jnz paranoid_restore
13991437
testl $3,CS(%rsp)
@@ -1404,7 +1442,7 @@ paranoid_swapgs:
14041442
RESTORE_ALL 8
14051443
jmp irq_return
14061444
paranoid_restore:
1407-
TRACE_IRQS_IRETQ 0
1445+
TRACE_IRQS_IRETQ_DEBUG 0
14081446
RESTORE_ALL 8
14091447
jmp irq_return
14101448
paranoid_userspace:

0 commit comments

Comments
 (0)