tOS ELF Loader — Privilege Escalation via Arbitrary Kernel Memory Write
In elf_load_dynamic of elf.c, there is a possible arbitrary kernel memory write due to a missing bounds check on the p_vaddr field of a PT_LOAD segment. This could lead to local escalation of privilege with no additional execution privileges needed.
While doing a routine code review of tOS kernel's filesystem and process-loading code, we noticed that elf_load_dynamic performed no address bounds checking when processing PT_LOAD segments. The segment's p_vaddr field was read directly from the file and used as the memcpy() destination address.
elf_load_dynamic() processed each PT_LOAD segment as follows: (1) the segment's p_vaddr value is read, (2) if the pages corresponding to that address are already mapped, memcpy() writes directly onto them, (3) whether p_vaddr belongs to kernel or user address space is never checked. Additionally, the boot-time code in kernel/core/paging.c marked all physical RAM — including kernel code, GDT, IDT, and page tables — as PTE_USER accessible, meaning no kernel/user memory isolation existed at all.
An attacker crafts a malicious ELF file with p_vaddr set to point into kernel memory (e.g. the syscall table or page directories). This file is placed on the system by any means and executed via the exec command or the SYS_EXECVE syscall. The kernel writes the file's contents directly to the target kernel address; modifying the syscall table or page tables allows full kernel takeover. No special bypass technique is required — simply executing the crafted file is enough.
Two architectural gaps combine here: (1) the loader placed no trust boundary on address/size fields coming from the file, (2) by design the kernel kept user and kernel memory in the same flat address space with the same access permissions.
Our first attempt — adding a check for 'writing to an already-mapped page' — broke the system entirely, because being already mapped is normal in this kernel; everything gets mapped at boot. A partial patch would have given a false sense of security without fixing the underlying architectural issue. So we removed ELF loading support entirely: kernel/fs/elf.c and elf.h were deleted, the exec shell command was removed, SYS_EXECVE now always returns -1, and the related sample binaries (hello.elf, hello_dyn.elf, libc.so) were deleted.
CWE-787, CWE-284, CWE-269
Artfical DT Developer Talha Berk Arslan