Kernel: Support execute disable bit
We will now map executable memory explicitly as executable.
This commit is contained in:
		
							parent
							
								
									bca7e9a1e8
								
							
						
					
					
						commit
						7d00c2670f
					
				|  | @ -1,5 +1,6 @@ | |||
| #include <BAN/Errors.h> | ||||
| #include <kernel/Arch.h> | ||||
| #include <kernel/CPUID.h> | ||||
| #include <kernel/LockGuard.h> | ||||
| #include <kernel/Memory/kmalloc.h> | ||||
| #include <kernel/Memory/PageTable.h> | ||||
|  | @ -7,11 +8,15 @@ | |||
| extern uint8_t g_kernel_start[]; | ||||
| extern uint8_t g_kernel_end[]; | ||||
| 
 | ||||
| extern uint8_t g_kernel_execute_start[]; | ||||
| extern uint8_t g_kernel_execute_end[]; | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
| 	 | ||||
| 	static PageTable* s_kernel = nullptr; | ||||
| 	static PageTable* s_current = nullptr; | ||||
| 	static bool s_has_nxe = false; | ||||
| 
 | ||||
| 	// Page Directories for kernel memory (KERNEL_OFFSET -> 0xFFFFFFFFFFFFFFFF)
 | ||||
| 	static paddr_t s_global[(0xFFFFFFFFFFFFFFFF - KERNEL_OFFSET + 1) / (4096ull * 512ull * 512ull)] { }; | ||||
|  | @ -40,6 +45,17 @@ namespace Kernel | |||
| 
 | ||||
| 	void PageTable::initialize() | ||||
| 	{ | ||||
| 		if (CPUID::has_nxe()) | ||||
| 		{ | ||||
| 			asm volatile( | ||||
| 				"movl $0xC0000080, %ecx;" | ||||
| 				"rdmsr;" | ||||
| 				"orl $0x800, %eax;" | ||||
| 				"wrmsr" | ||||
| 			); | ||||
| 			s_has_nxe = true; | ||||
| 		} | ||||
| 
 | ||||
| 		ASSERT(s_kernel == nullptr); | ||||
| 		s_kernel = new PageTable(); | ||||
| 		ASSERT(s_kernel); | ||||
|  | @ -78,6 +94,14 @@ namespace Kernel | |||
| 
 | ||||
| 		// Map (0 -> phys_kernel_end) to (KERNEL_OFFSET -> virt_kernel_end)
 | ||||
| 		map_range_at(0, KERNEL_OFFSET, (uintptr_t)g_kernel_end - KERNEL_OFFSET, Flags::ReadWrite | Flags::Present); | ||||
| 		 | ||||
| 		// Map executable kernel memory as executable
 | ||||
| 		map_range_at( | ||||
| 			V2P(g_kernel_execute_start), | ||||
| 			(vaddr_t)g_kernel_execute_start, | ||||
| 			g_kernel_execute_end - g_kernel_execute_start, | ||||
| 			Flags::Execute | Flags::ReadWrite | Flags::Present | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<PageTable*> PageTable::create_userspace() | ||||
|  | @ -207,6 +231,10 @@ namespace Kernel | |||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		uint64_t xd_bit = 0; | ||||
| 		if (s_has_nxe && !(flags & Flags::Execute)) | ||||
| 			xd_bit = 1ull << 63; | ||||
| 
 | ||||
| 		if (vaddr && (vaddr >= KERNEL_OFFSET) != (this == s_kernel)) | ||||
| 			Kernel::panic("mapping {8H} to {8H}, kernel: {}", paddr, vaddr, this == s_kernel); | ||||
| 
 | ||||
|  | @ -248,7 +276,7 @@ namespace Kernel | |||
| 		} | ||||
| 
 | ||||
| 		uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK); | ||||
| 		pt[pte] = paddr | flags; | ||||
| 		pt[pte] = xd_bit | paddr | flags; | ||||
| 
 | ||||
| 		invalidate(canonicalize(vaddr)); | ||||
| 	} | ||||
|  | @ -304,12 +332,14 @@ namespace Kernel | |||
| 
 | ||||
| 	PageTable::flags_t PageTable::get_page_flags(vaddr_t addr) const | ||||
| 	{ | ||||
| 		return get_page_data(addr) & PAGE_FLAG_MASK; | ||||
| 		uint64_t page_data = get_page_data(addr); | ||||
| 		return (page_data & (1ull << 63) ? Flags::Execute : 0) | (page_data & PAGE_FLAG_MASK); | ||||
| 	} | ||||
| 
 | ||||
| 	paddr_t PageTable::physical_address_of(vaddr_t addr) const | ||||
| 	{ | ||||
| 		return get_page_data(addr) & PAGE_ADDR_MASK; | ||||
| 		uint64_t page_data = get_page_data(addr); | ||||
| 		return (page_data & PAGE_ADDR_MASK) & ~(1ull << 63); | ||||
| 	} | ||||
| 
 | ||||
| 	vaddr_t PageTable::get_free_page(vaddr_t first_address) const | ||||
|  |  | |||
|  | @ -9,12 +9,14 @@ SECTIONS | |||
| 	g_kernel_start = .; | ||||
| 	.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) | ||||
| 	{ | ||||
| 		g_kernel_execute_start = .; | ||||
| 		*(.multiboot) | ||||
| 		*(.text) | ||||
| 	} | ||||
| 	.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) | ||||
| 	{ | ||||
| 		*(.rodata.*) | ||||
| 		g_kernel_execute_end = .; | ||||
| 	} | ||||
| 	.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) | ||||
| 	{ | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ namespace Kernel | |||
| 			Present = 1, | ||||
| 			ReadWrite = 2, | ||||
| 			UserSupervisor = 4, | ||||
| 			Execute = 8, | ||||
| 		}; | ||||
| 
 | ||||
| 	public: | ||||
|  |  | |||
|  | @ -458,6 +458,8 @@ namespace Kernel | |||
| 				uint8_t flags = PageTable::Flags::UserSupervisor | PageTable::Flags::Present; | ||||
| 				if (elf_program_header.p_flags & LibELF::PF_W) | ||||
| 					flags |= PageTable::Flags::ReadWrite; | ||||
| 				if (elf_program_header.p_flags & LibELF::PF_X) | ||||
| 					flags |= PageTable::Flags::Execute; | ||||
| 
 | ||||
| 				size_t page_start = elf_program_header.p_vaddr / PAGE_SIZE; | ||||
| 				size_t page_end = BAN::Math::div_round_up<size_t>(elf_program_header.p_vaddr + elf_program_header.p_memsz, PAGE_SIZE); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue