From 316d4ef4f9624b4a55537fc299a403f84af52bff Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Tue, 10 Feb 2026 05:13:16 -0300 Subject: [PATCH] fix: audit and correct bugs in Fases 1-4 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Fase 1 (CPUID): - cpuid.c: Replace strict-aliasing-violating uint32_t* casts for vendor string with memcpy() to avoid UB - cpuid.c: Increase itoa tmp buffer from 4 to 12 bytes to prevent potential overflow with larger APIC IDs Fase 2 (Spinlock): No bugs found — TTAS + cpu_relax + barriers OK Fase 3 (SYSENTER): - sysenter.S: Add 'cld' at entry to clear direction flag. Userspace could leave DF=1 and SYSENTER doesn't reset EFLAGS, which would corrupt any kernel string/memory operations using rep movsb/stosb Fase 4 (ulibc): - stdio.c: Fix PUTC macro underflow — use 'pos+1 < size' instead of 'pos < size-1' which underflows to SIZE_MAX when size==0 - stdio.c: Fix vsnprintf(buf, 0, fmt) — was counting raw format chars instead of returning 0; now returns 0 immediately - stdlib.c: Use uintptr_t instead of unsigned int for brk() pointer comparison to be correct on all architectures - unistd.c: Replace 'hlt' with 'nop' in _exit() fallback loop — hlt is privileged and causes #GP in ring 3 Passes: make, ulibc build, cppcheck, QEMU smoke test. --- src/arch/x86/cpuid.c | 11 ++++++----- src/arch/x86/sysenter.S | 3 +++ user/ulibc/src/stdio.c | 7 +++---- user/ulibc/src/stdlib.c | 2 +- user/ulibc/src/unistd.c | 4 +++- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/arch/x86/cpuid.c b/src/arch/x86/cpuid.c index fa19226..1f590bd 100644 --- a/src/arch/x86/cpuid.c +++ b/src/arch/x86/cpuid.c @@ -3,6 +3,7 @@ #include "utils.h" #include +#include static inline void cpuid(uint32_t leaf, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { @@ -22,10 +23,10 @@ void x86_cpuid_detect(struct x86_cpu_features* out) { cpuid(0, &eax, &ebx, &ecx, &edx); out->max_leaf = eax; - /* Vendor: EBX-EDX-ECX */ - *(uint32_t*)&out->vendor[0] = ebx; - *(uint32_t*)&out->vendor[4] = edx; - *(uint32_t*)&out->vendor[8] = ecx; + /* Vendor: EBX-EDX-ECX (use memcpy to avoid strict-aliasing UB) */ + memcpy(&out->vendor[0], &ebx, 4); + memcpy(&out->vendor[4], &edx, 4); + memcpy(&out->vendor[8], &ecx, 4); out->vendor[12] = '\0'; if (out->max_leaf < 1) return; @@ -127,7 +128,7 @@ void x86_cpuid_print(const struct x86_cpu_features* f) { uart_print("\n"); uart_print("[CPUID] APIC ID: "); - char tmp[4]; + char tmp[12]; itoa(f->initial_apic_id, tmp, 10); uart_print(tmp); uart_print(", Logical CPUs: "); diff --git a/src/arch/x86/sysenter.S b/src/arch/x86/sysenter.S index c0f186e..8a4a704 100644 --- a/src/arch/x86/sysenter.S +++ b/src/arch/x86/sysenter.S @@ -51,6 +51,9 @@ sysenter_entry: * User stack: [return_eip, saved_edx(arg3), saved_ecx(arg2)] */ + /* Ensure direction flag is clear — userspace may have set DF=1 */ + cld + /* Build iret-style frame: ss, useresp, eflags, cs, eip */ push $0x23 /* ss = user data segment (GDT entry 4 | RPL 3) */ push %ecx /* useresp = user ESP */ diff --git a/user/ulibc/src/stdio.c b/user/ulibc/src/stdio.c index 87089a1..a01bc01 100644 --- a/user/ulibc/src/stdio.c +++ b/user/ulibc/src/stdio.c @@ -20,12 +20,11 @@ int puts(const char* s) { int vsnprintf(char* buf, size_t size, const char* fmt, va_list ap) { size_t pos = 0; -#define PUTC(c) do { if (pos < size - 1) buf[pos] = (c); pos++; } while(0) +#define PUTC(c) do { if (pos + 1 < size) buf[pos] = (c); pos++; } while(0) if (size == 0) { - /* Just count characters */ - while (*fmt) { pos++; fmt++; } - return (int)pos; + /* Cannot write anything; return 0 */ + return 0; } while (*fmt) { diff --git a/user/ulibc/src/stdlib.c b/user/ulibc/src/stdlib.c index 7afd02d..072ff02 100644 --- a/user/ulibc/src/stdlib.c +++ b/user/ulibc/src/stdlib.c @@ -25,7 +25,7 @@ void* malloc(size_t size) { void* new_end = (void*)((char*)heap_end + size); void* result = brk(new_end); - if ((unsigned int)result < (unsigned int)new_end) { + if ((uintptr_t)result < (uintptr_t)new_end) { return (void*)0; /* OOM */ } diff --git a/user/ulibc/src/unistd.c b/user/ulibc/src/unistd.c index 5114a75..3036f5c 100644 --- a/user/ulibc/src/unistd.c +++ b/user/ulibc/src/unistd.c @@ -88,5 +88,7 @@ void* brk(void* addr) { void _exit(int status) { _syscall1(SYS_EXIT, status); - for (;;) __asm__ volatile("hlt"); + /* If exit syscall somehow returns, loop forever. + * Cannot use hlt — it's privileged and causes #GP in ring 3. */ + for (;;) __asm__ volatile("nop"); } -- 2.43.0