From: Tulio A M Mendes Date: Tue, 10 Feb 2026 02:35:38 +0000 (-0300) Subject: fix: heap coalesce early-return, process_create_kernel leak, pipe double-free, path... X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=eed0331f44e9bdf22f1dfe5806bc8254e52b52b5;p=AdrOS.git fix: heap coalesce early-return, process_create_kernel leak, pipe double-free, path '..' resolution --- diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 2adbe02..7405a56 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -402,6 +402,7 @@ struct process* process_create_kernel(void (*entry_point)(void)) { void* stack = kmalloc(4096); if (!stack) { + kfree(proc); spin_unlock_irqrestore(&sched_lock, flags); return NULL; } diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 865e8bf..f9a0480 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -406,13 +406,15 @@ static int pipe_create_kfds(int kfds[2]) { fs_node_t* rnode = NULL; fs_node_t* wnode = NULL; - if (pipe_node_create(ps, 1, &rnode) < 0 || pipe_node_create(ps, 0, &wnode) < 0) { - if (rnode) vfs_close(rnode); - if (wnode) vfs_close(wnode); - if (ps->buf) kfree(ps->buf); + if (pipe_node_create(ps, 1, &rnode) < 0) { + kfree(ps->buf); kfree(ps); return -ENOMEM; } + if (pipe_node_create(ps, 0, &wnode) < 0) { + vfs_close(rnode); + return -ENOMEM; + } struct file* rf = (struct file*)kmalloc(sizeof(*rf)); struct file* wf = (struct file*)kmalloc(sizeof(*wf)); @@ -878,33 +880,72 @@ static int path_is_absolute(const char* p) { static void path_normalize_inplace(char* s) { if (!s) return; - // Collapse duplicate slashes and remove trailing slash (except for root). - char tmp[128]; - size_t w = 0; - size_t r = 0; if (s[0] == 0) { strcpy(s, "/"); return; } - while (s[r] != 0 && w + 1 < sizeof(tmp)) { - char c = s[r++]; - if (c == '/') { - if (w == 0 || tmp[w - 1] != '/') { - tmp[w++] = '/'; + // Phase 1: split into components, resolve '.' and '..' + char tmp[128]; + // Stack of component start offsets within tmp + size_t comp_start[32]; + int depth = 0; + size_t w = 0; + + const char* p = s; + int absolute = (*p == '/'); + if (absolute) { + tmp[w++] = '/'; + while (*p == '/') p++; + } + + while (*p != 0) { + // Extract next component + const char* seg = p; + while (*p != 0 && *p != '/') p++; + size_t seg_len = (size_t)(p - seg); + while (*p == '/') p++; + + if (seg_len == 1 && seg[0] == '.') { + continue; // skip '.' + } + + if (seg_len == 2 && seg[0] == '.' && seg[1] == '.') { + // Go up one level + if (depth > 0) { + depth--; + w = comp_start[depth]; } - } else { - tmp[w++] = c; + continue; + } + + // Record start of this component + if (depth < 32) { + comp_start[depth++] = w; + } + + // Append separator if needed + if (w > 1 || (w == 1 && tmp[0] != '/')) { + if (w + 1 < sizeof(tmp)) tmp[w++] = '/'; + } + + // Append component + for (size_t i = 0; i < seg_len && w + 1 < sizeof(tmp); i++) { + tmp[w++] = seg[i]; } } - tmp[w] = 0; - size_t l = strlen(tmp); - while (l > 1 && tmp[l - 1] == '/') { - tmp[l - 1] = 0; - l--; + // Handle empty result + if (w == 0) { + tmp[w++] = '/'; } + // Remove trailing slash (except root) + while (w > 1 && tmp[w - 1] == '/') { + w--; + } + + tmp[w] = 0; strcpy(s, tmp); } diff --git a/src/mm/heap.c b/src/mm/heap.c index 61208ea..e5c7315 100644 --- a/src/mm/heap.c +++ b/src/mm/heap.c @@ -173,18 +173,15 @@ void kfree(void* ptr) { // Only coalesce if physically adjacent. heap_header_t* expected_next = (heap_header_t*)((uint8_t*)header + sizeof(heap_header_t) + header->size); - if (next_block != expected_next) { - spin_unlock_irqrestore(&heap_lock, flags); - return; - } - - header->size += sizeof(heap_header_t) + next_block->size; - header->next = next_block->next; - - if (header->next) { - header->next->prev = header; - } else { - tail = header; // If next was tail, now current is tail + if (next_block == expected_next) { + header->size += sizeof(heap_header_t) + next_block->size; + header->next = next_block->next; + + if (header->next) { + header->next->prev = header; + } else { + tail = header; + } } } @@ -194,20 +191,16 @@ void kfree(void* ptr) { // Only coalesce if physically adjacent. heap_header_t* expected_hdr = (heap_header_t*)((uint8_t*)prev_block + sizeof(heap_header_t) + prev_block->size); - if (expected_hdr != header) { - spin_unlock_irqrestore(&heap_lock, flags); - return; - } - - prev_block->size += sizeof(heap_header_t) + header->size; - prev_block->next = header->next; - - if (header->next) { - header->next->prev = prev_block; - } else { - tail = prev_block; + if (expected_hdr == header) { + prev_block->size += sizeof(heap_header_t) + header->size; + prev_block->next = header->next; + + if (header->next) { + header->next->prev = prev_block; + } else { + tail = prev_block; + } } - // No need to update 'header' anymore, prev_block is the merged one } spin_unlock_irqrestore(&heap_lock, flags);