Ring 3 works: user GDT descriptors (sysret-ready layout), TSS.rsp0, U/S-bit user mappings (W^X preserved), an int 0x80 syscall gate with a mutable trap frame, and a setjmp-style enter/exit path. /sbin/init is a real freestanding Zig binary built from sbin/, shipped on the ESP, loaded by the bootloader (BootInfo.init_base/len), validated and mapped by an in-kernel user-ELF loader, and run at CPL 3 — syscalls: exit, ping, write. Tests: user, user-pf (U/S isolation proof, error code 0x5), init. Suite 27/27. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
46 lines
1.1 KiB
Plaintext
46 lines
1.1 KiB
Plaintext
/* /sbin/init link layout.
|
|
*
|
|
* Linked at a fixed user-space virtual base (set by `image_base` in build.zig,
|
|
* inside the kernel's user region). Same discipline as the kernel's script:
|
|
* one PT_LOAD per permission set, every section page-aligned, so the kernel's
|
|
* user-ELF loader can map each segment with exact W^X permissions. Note the
|
|
* linker also emits a read-only PT_LOAD covering the ELF headers at the image
|
|
* base, so the entry point comes from e_entry, not the base address.
|
|
*/
|
|
|
|
ENTRY(_start)
|
|
|
|
/* FLAGS bits: 1=X, 2=W, 4=R. */
|
|
PHDRS {
|
|
text PT_LOAD FLAGS(5); /* R + X */
|
|
rodata PT_LOAD FLAGS(4); /* R */
|
|
data PT_LOAD FLAGS(6); /* R + W */
|
|
}
|
|
|
|
SECTIONS {
|
|
.text ALIGN(4K) : {
|
|
*(.text .text.*)
|
|
} :text
|
|
|
|
.rodata ALIGN(4K) : {
|
|
*(.rodata .rodata.*)
|
|
} :rodata
|
|
|
|
.data ALIGN(4K) : {
|
|
*(.data .data.*)
|
|
} :data
|
|
|
|
/* .bss occupies memory but not file space; the loader zeroes the
|
|
* filesz..memsz gap. */
|
|
.bss ALIGN(4K) : {
|
|
*(.bss .bss.*)
|
|
*(COMMON)
|
|
} :data
|
|
|
|
/DISCARD/ : {
|
|
*(.comment)
|
|
*(.note .note.*)
|
|
*(.eh_frame .eh_frame_hdr)
|
|
}
|
|
}
|