kernel: experiment with static-pie

This commit is contained in:
K. Lange 2023-11-10 15:40:41 +09:00
parent b724489609
commit a8b506ad33
9 changed files with 131 additions and 27 deletions

View File

@ -79,7 +79,7 @@ LC = $(BASE)/lib/libc.so $(GCC_SHARED)
.PHONY: all system clean run shell
$(BASE)/mod/%.ko: modules/%.c | dirs
${CC} -c ${KERNEL_CFLAGS} -mcmodel=large -o $@ $<
${CC} -c ${KERNEL_CFLAGS} -fno-pie -mcmodel=large -o $@ $<
ramdisk.igz: $(wildcard $(BASE)/* $(BASE)/*/* $(BASE)/*/*/* $(BASE)/*/*/*/* $(BASE)/*/*/*/*/*) $(APPS_X) $(LIBS_X) $(KRK_MODS_X) $(BASE)/bin/kuroko $(BASE)/lib/ld.so $(BASE)/lib/libm.so $(APPS_KRK_X) $(KRK_MODS) $(APPS_SH_X) $(MODULES)
python3 util/createramdisk.py

View File

@ -63,12 +63,13 @@ uintptr_t _xmain = 0;
static int load_aout(uint32_t * hdr) {
uintptr_t base_offset = (uintptr_t)hdr - (uintptr_t)kernel_load_start;
uintptr_t hdr_offset = hdr[3] - base_offset;
size_t xtra = 0x100000;
memcpy((void*)(uintptr_t)hdr[4], kernel_load_start + (hdr[4] - hdr_offset), (hdr[5] - hdr[4]));
memset((void*)(uintptr_t)hdr[5], 0, (hdr[6] - hdr[5]));
_xmain = (uintptr_t)hdr[7];
memcpy((void*)(uintptr_t)hdr[4] + xtra, kernel_load_start + (hdr[4] - hdr_offset), (hdr[5] - hdr[4]));
memset((void*)(uintptr_t)hdr[5] + xtra, 0, (hdr[6] - hdr[5]));
_xmain = (uintptr_t)hdr[7] + xtra;
if (hdr[6] > final_offset) final_offset = hdr[6];
if (hdr[6] + xtra > final_offset) final_offset = hdr[6] + xtra;
final_offset = (final_offset & ~(0xFFF)) + ((final_offset & 0xFFF) ? 0x1000 : 0);
return 1;

View File

@ -1,6 +1,6 @@
ARCH=x86_64
ARCH_KERNEL_CFLAGS = -mno-red-zone -fno-omit-frame-pointer -mfsgsbase
ARCH_KERNEL_CFLAGS = -mno-red-zone -fno-omit-frame-pointer -mfsgsbase -fPIE
ARCH_KERNEL_CFLAGS += -mgeneral-regs-only -z max-page-size=0x1000 -nostdlib
ARCH_USER_CFLAGS += -z max-page-size=0x1000
@ -66,15 +66,15 @@ shell: system
-fw_cfg name=opt/org.toaruos.bootmode,string=headless
misaka-kernel: ${KERNEL_ASMOBJS} ${KERNEL_OBJS} kernel/symbols.o
${CC} -g -T kernel/arch/${ARCH}/link.ld ${KERNEL_CFLAGS} -o $@.64 ${KERNEL_ASMOBJS} ${KERNEL_OBJS} kernel/symbols.o
${OC} --strip-debug -I elf64-x86-64 -O elf32-i386 $@.64 $@
${CC} -g -T kernel/arch/${ARCH}/link.ld ${KERNEL_CFLAGS} -Wl,-static,-pie,--no-dynamic-linker,-z,notext,-z,norelro -o $@.64 ${KERNEL_ASMOBJS} ${KERNEL_OBJS} kernel/symbols.o
cp $@.64 $@
${STRIP} $@
# Loader stuff, legacy CDs
fatbase/ramdisk.igz: ramdisk.igz
cp $< $@
fatbase/kernel: misaka-kernel
cp $< $@
strip $@
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel fatbase/efi/boot/bootx64.efi util/mkdisk.sh | dirs
util/mkdisk.sh $@ fatbase

View File

@ -75,7 +75,7 @@ mb2_tag_entry:
.word 3
.word 0
.long 12
.long start
.long start_mbi2
/* Framebuffer tag */
.align 8
@ -99,6 +99,15 @@ mb2_tag_fb:
.word 0
.long 8
.align 8
.word 10
.word 0
.long 24
.long 0x200000
.long 0x1000000
.long 4096
.long 1
/* End tag */
.align 8
.word 0
@ -124,12 +133,34 @@ stack_top:
.extern kmain
.type kmain, @function
.global start_mbi2
.type start_mbi2, @function
start_mbi2:
/* Use reserved 0 space of boot information struct to thunk eip */
movl %ebx, %ecx
addl $8, %ecx
jmp good_to_go
.global start
.type start, @function
start:
/* Use boot_drive as a temporary place to thunk eip */
movl %ebx, %ecx
addl $16, %ecx
good_to_go:
mov %ecx, %esp
call _forward
_forward:
popl %ecx
subl $_forward, %ecx
/* Setup our stack */
mov $stack_top, %esp
addl %ecx, %esp
/* Make sure our stack is 16-byte aligned */
and $-16, %esp
@ -151,6 +182,8 @@ jmp_to_long:
/* Set up initial page region, which was zero'd for us by the loader */
mov $init_page_region, %edi
addl %ecx, %edi
pushl %ecx
/* PML4[0] = &PDP[0] | (PRESENT, WRITABLE, USER) */
mov $0x1007, %eax
@ -179,6 +212,9 @@ jmp_to_long:
loop .set_entry
mov $init_page_region, %edi
popl %ecx
addl %ecx, %edi
pushl %ecx
mov %edi, %cr3
/* Enable PAE */
@ -203,8 +239,31 @@ jmp_to_long:
or $0x80000000, %eax
mov %eax, %cr0
super_duper_bullshit:
popl %ecx
lea (_lgdt_instr+3)(%ecx), %eax
movl (%eax), %ebx
addl %ecx, %ebx
movl %ebx, (%eax)
lea (gdtr+2)(%ecx), %eax
movl (%eax), %ebx
addl %ecx, %ebx
movl %ebx, (%eax)
lea (_ljmp_instr+1)(%ecx), %eax
movl (%eax), %ebx
addl %ecx, %ebx
movl %ebx, (%eax)
pushl $0
pushl %ecx
_lgdt_instr:
lgdt gdtr
_ljmp_instr:
ljmp $0x08,$realm64
.align 8
@ -247,6 +306,7 @@ realm64:
.continue:
cli
pop %rcx
pop %rdi
pop %rsi
pop %rdx

View File

@ -94,7 +94,7 @@ ISR_NOERR 127
_isr123:
/* Acknowledge IPI */
pushq %r12
mov (lapic_final), %r12
mov (lapic_final)(%rip), %r12
add $0xb0, %r12
movl $0, (%r12)
popq %r12
@ -116,7 +116,7 @@ _isr124:
pushq %r12
mov %cr3, %r12
mov %r12, %cr3
mov (lapic_final), %r12
mov (lapic_final)(%rip), %r12
add $0xb0, %r12
movl $0, (%r12)
popq %r12
@ -128,7 +128,7 @@ _isr124:
.type _isr126, @function
_isr126:
pushq %r12
mov (lapic_final), %r12
mov (lapic_final)(%rip), %r12
add $0xb0, %r12
movl $0, (%r12)
popq %r12

View File

@ -12,12 +12,30 @@ SECTIONS
*(.bootstrap)
code = .;
*(.text)
*(.shit)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.rela.dyn BLOCK(4K) : ALIGN(4K)
{
_rela_start = .;
*(.rela)
*(.rela.text)
*(.rela.got)
*(.rela.plt)
*(.rela.bss)
*(.rela.ifunc)
*(.rela.text.*)
*(.rela.data)
*(.rela.data.*)
*(.rela.rodata)
*(.rela.rodata*)
*(.rela.dyn)
_rela_end = .;
}
.data BLOCK(4K) : ALIGN(4K)
{
@ -26,11 +44,11 @@ SECTIONS
*(.symbols)
PROVIDE(kernel_symbols_start = .);
PROVIDE(kernel_symbols_end = .);
PROVIDE(bss_start = .);
}
.bss BLOCK(4K) : ALIGN(4K)
{
PROVIDE(bss_start = .);
bss = .;
*(COMMON)
*(.bss)

View File

@ -23,6 +23,7 @@
#include <kernel/ksym.h>
#include <kernel/misc.h>
#include <kernel/version.h>
#include <kernel/elf.h>
#include <kernel/arch/x86_64/ports.h>
#include <kernel/arch/x86_64/cmos.h>
@ -76,6 +77,7 @@ struct MB2_TagHeader {
void * mboot2_find_next(char * current, uint32_t type) {
char * header = current;
while ((uintptr_t)header & 7) header++;
struct MB2_TagHeader * tag = (void*)header;
while (1) {
if (tag->type == 0) return NULL;
@ -219,11 +221,11 @@ void mboot_unmark_valid_memory(void) {
}
}
static void symbols_install(void) {
static void symbols_install(uint64_t base) {
ksym_install();
kernel_symbol_t * k = (kernel_symbol_t *)&kernel_symbols_start;
while ((uintptr_t)k < (uintptr_t)&kernel_symbols_end) {
ksym_bind(k->name, (void*)k->addr);
ksym_bind(k->name, (void*)(k->addr + base));
k = (kernel_symbol_t *)((uintptr_t)k + sizeof *k + strlen(k->name) + 1);
}
}
@ -284,6 +286,7 @@ static void mount_ramdisk(uintptr_t addr, size_t len) {
uint32_t decompressedSize = *(uint32_t*)mmu_map_from_physical(addr + len - sizeof(uint32_t));
size_t pageCount = (((size_t)decompressedSize + 0xFFF) & ~(0xFFF)) >> 12;
uintptr_t physicalAddress = mmu_allocate_n_frames(pageCount) << 12;
if (physicalAddress == (uintptr_t)-1) {
dprintf("gzip: failed to allocate pages\n");
return;
@ -408,7 +411,16 @@ void arch_framebuffer_initialize(void) {
*
* Called by the x86-64 longmode bootstrap.
*/
int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) {
int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp, uint64_t base) {
extern Elf64_Rela _rela_start[], _rela_end[];
for (Elf64_Rela * rela = _rela_start; rela < _rela_end; ++rela) {
switch (ELF64_R_TYPE(rela->r_info)) {
case R_X86_64_RELATIVE:
*(uint64_t*)(rela->r_offset + base) = base + rela->r_addend;
break;
}
}
/* The debug log is over /dev/ttyS0, but skips the PTY interface; it's available
* as soon as we can call printf(), which is as soon as we get to long mode. */
early_log_initialize();
@ -443,7 +455,7 @@ int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) {
/* With the MMU initialized, set up things required for the scheduler. */
pat_initialize();
symbols_install();
symbols_install(base);
gdt_install();
idt_install();
fpu_initialize();

View File

@ -24,6 +24,7 @@ __attribute__((used))
__attribute__((naked))
static void __ap_bootstrap(void) {
asm volatile (
".section .shit\n"
".code16\n"
".org 0x0\n"
".global _ap_bootstrap_start\n"
@ -34,8 +35,7 @@ static void __ap_bootstrap(void) {
"mov %%eax, %%cr4\n"
/* Kernel base PML4 */
".global init_page_region\n"
"mov $init_page_region, %%edx\n"
"mov $0x77777777, %%edx\n"
"mov %%edx, %%cr3\n"
/* Set LME */
@ -52,7 +52,7 @@ static void __ap_bootstrap(void) {
"addr32 lgdtl %%cs:_ap_bootstrap_gdtp-_ap_bootstrap_start\n"
/* Jump... */
"data32 jmp $0x08,$ap_premain\n"
"data32 jmp $0x08,$0x5A5A5A5A\n"
".global _ap_bootstrap_gdtp\n"
".align 16\n"
@ -60,21 +60,30 @@ static void __ap_bootstrap(void) {
".word 0\n"
".quad 0\n"
".global _ap_bootstrap_end\n"
"_ap_bootstrap_end:\n"
".section .text\n"
: : : "memory"
);
}
__attribute__((used))
__attribute__((naked))
static void __ap_bootstrap_landing(void) {
asm volatile (
".code64\n"
".align 16\n"
"ap_premain:\n"
".global _ap_premain\n"
"_ap_premain:\n"
"mov $0x10, %%ax\n"
"mov %%ax, %%ds\n"
"mov %%ax, %%ss\n"
"mov $0x33, %%ax\n" /* TSS offset in gdt */
"ltr %%ax\n"
".extern _ap_stack_base\n"
"mov _ap_stack_base,%%rsp\n"
"mov _ap_stack_base(%%rip),%%rsp\n"
".extern ap_main\n"
"callq ap_main\n"
".global _ap_bootstrap_end\n"
"_ap_bootstrap_end:\n"
: : : "memory"
);
}
@ -82,6 +91,7 @@ static void __ap_bootstrap(void) {
extern char _ap_bootstrap_start[];
extern char _ap_bootstrap_end[];
extern char _ap_bootstrap_gdtp[];
extern char _ap_premain[];
extern size_t arch_cpu_mhz(void);
extern void gdt_copy_to_trampoline(int ap, char * trampoline);
extern void arch_set_core_base(uintptr_t base);
@ -422,6 +432,9 @@ _toomany:
uintptr_t tmp_space = mmu_allocate_a_frame() << 12;
memcpy(mmu_map_from_physical(tmp_space), mmu_map_from_physical(0x1000), 0x1000);
*(uint32_t*)(&_ap_bootstrap_start[0xb]) = (void*)&init_page_region;
*(uint32_t*)(&_ap_bootstrap_start[0x37]) = (void*)&_ap_premain;
/* Map the bootstrap code */
memcpy(mmu_map_from_physical(0x1000), &_ap_bootstrap_start, (uintptr_t)&_ap_bootstrap_end - (uintptr_t)&_ap_bootstrap_start);

View File

@ -14,7 +14,7 @@ def entry(sym):
print(f'.{size} {sym}')
print(f'.asciz "{sym}"')
let ignore = ['abs','kernel_symbols_start','kernel_symbols_end']
let ignore = ['abs','kernel_symbols_start','kernel_symbols_end','_GLOBAL_OFFSET_TABLE_']
let source = (x.strip() for x in fileio.stdin.readlines())
let symbols = set(x.split()[0] for x in source if not x.endswith(':'))
let lines = sorted(x for x in symbols if x not in ignore)