feat: Growable heap, GUI-by-default run, live sysmon, SUB/SUB default login

Kernel / memory:
- mm/kmalloc.c: fix "Heap: Out of memory" under the GUI. The desktop allocates
  three full-screen 32-bit buffers (~11MB) which overflowed the fixed 16MB pool.
  The heap now starts at 32MB and grows on demand from the PMM (16MB regions),
  with region-safe coalescing (only merges physically adjacent blocks) so growth
  never corrupts across separate PMM allocations. Adds heap_get_grow_count().

Build / run:
- Makefile: merge `run-gui` into `run` so `make run` boots into the graphical
  desktop; add `run-headless` (serial-only via QEMU_CMD), bump guest RAM to
  256M, update .PHONY and help.

Configure:
- scripts/kconfig/menuconfig.py: gate the curses UI behind isatty() on stdin and
  stdout so non-interactive `make configure` stops emitting "nocbreak() returned
  ERR" and falls cleanly through to the non-interactive writer.

GUI / userland:
- gui/gui_apps.c: rebuild the System Monitor from hardcoded values into live
  telemetry -- real heap used/total/free with a colour-shifting bar, a scrolling
  heap-utilisation graph, the grow counter, and real PMM RAM figures.
- lazybox `free`: report how many times the heap has grown.

Auth:
- Default login is now SUB / SUB (Kali-style username==password), seeded first
  as the primary uid-0 account and set as the logged-in user; root kept for
  compatibility. Hardcoded "root" defaults (whoami, su, passwd, ssh, sshd
  session) updated to SUB.

Verified: clean build on x86_64/aarch64/armv8i; GUI boots with 0 OOM/0 panic;
auth engine initialises cleanly; `make configure` fallback is clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
This commit is contained in:
subhobhai943andClaude Opus 4.8 committed 2026-08-25 17:34:50 +05:30
1 parent 65fa4dd049
commit 71ad6aca3d
8 files changed
+203 -64

No files matched your search

+17 -9
View File
@@ -330,7 +330,7 @@ DEPS = $(C_OBJS:.o=.d) $(CPP_OBJS:.o=.d) $(S_OBJS:.o=.d)
.DEFAULT_GOAL := all .DEFAULT_GOAL := all
.PHONY: all clean run run-fullscreen debug info configure menuconfig config tui nconfig defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig qemu help .PHONY: all clean run run-headless run-fullscreen run-vnc run-server debug info configure menuconfig config tui nconfig defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig qemu help
all: $(TARGET) all: $(TARGET)
@@ -448,24 +448,29 @@ $(IMAGE): $(BUILD_DIR)/boot/boot.bin $(BUILD_DIR)/boot/stage2.bin $(BUILD_DIR)/k
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Execution & Emulation Targets # Execution & Emulation Targets
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
run qemu: $(TARGET)
$(QEMU_CMD)
# -vga std gives the Bochs VBE adapter the kernel drives. vgamem_mb is raised # -vga std gives the Bochs VBE adapter the kernel drives. vgamem_mb is raised
# because a 1280x720 32-bit framebuffer needs more than the 8 MB default. # because a 1280x720 32-bit framebuffer needs more than the 8 MB default.
QEMU_VGA = -device VGA,vgamem_mb=32 QEMU_VGA = -device VGA,vgamem_mb=32
run-gui: $(TARGET) # `make run` boots straight into the SUB-OS Graphical Desktop Environment. The
# guest window scales with zoom-to-fit; pass `nogui`/`text` on the kernel
# command line for the emergency TTY. Use `make run-headless` for serial only.
run qemu: $(TARGET)
ifeq ($(ARCH), x86_64) ifeq ($(ARCH), x86_64)
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \ qemu-system-x86_64 -drive format=raw,file=$(IMAGE) -m 256M \
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \ -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
-device e1000,netdev=net0 $(QEMU_VGA) -display gtk,zoom-to-fit=on -serial stdio -device e1000,netdev=net0 $(QEMU_VGA) -display gtk,zoom-to-fit=on -serial stdio
else ifneq ($(filter $(ARCH), aarch64 arm64),) else ifneq ($(filter $(ARCH), aarch64 arm64),)
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio qemu-system-aarch64 -M virt -cpu cortex-a57 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
else else
qemu-system-arm -M virt -cpu cortex-a15 -m 128M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio qemu-system-arm -M virt -cpu cortex-a15 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
endif endif
# Headless: no graphical window, kernel console on the serial line only. Boot
# with `nogui` on the kernel command line to reach the TTY in this mode.
run-headless: $(TARGET)
$(QEMU_CMD)
# Fullscreen without distortion: zoom-to-fit scales the guest while preserving # Fullscreen without distortion: zoom-to-fit scales the guest while preserving
# its aspect ratio, letterboxing rather than stretching on a wider panel. # its aspect ratio, letterboxing rather than stretching on a wider panel.
run-fullscreen: $(TARGET) run-fullscreen: $(TARGET)
@@ -521,7 +526,10 @@ help:
@echo " make aarch64_defconfig- Load AArch64 default configuration" @echo " make aarch64_defconfig- Load AArch64 default configuration"
@echo " make armv8i_defconfig - Load ARMv8i (32-bit ARM) default configuration" @echo " make armv8i_defconfig - Load ARMv8i (32-bit ARM) default configuration"
@echo " make all [ARCH=...] - Compile kernel image for selected architecture" @echo " make all [ARCH=...] - Compile kernel image for selected architecture"
@echo " make qemu [ARCH=...] - Boot the compiled kernel in QEMU emulator" @echo " make run [ARCH=...] - Boot into the SUB-OS Graphical Desktop in QEMU"
@echo " make run-headless - Boot in QEMU with serial console only (no window)"
@echo " make run-fullscreen - Boot the desktop in a full-screen QEMU window"
@echo " make run-vnc - Boot the desktop and expose it over VNC :0"
@echo " make clean - Remove all compiled objects and disk images" @echo " make clean - Remove all compiled objects and disk images"
@echo " make info - Display build configuration and source metrics" @echo " make info - Display build configuration and source metrics"
+46 -18
View File
@@ -26,19 +26,41 @@ static int simple_atoi(const char* s) {
// ================================================================= // =================================================================
// 1. System Performance Monitor App (High-Res 320x240) // 1. System Performance Monitor App (High-Res 320x240)
// ================================================================= // =================================================================
static uint8_t g_cpu_history[60] = { /* Rolling trace of live heap utilisation (percent), newest sample on the right.
12, 15, 18, 22, 30, 25, 20, 35, 45, 50, 42, 38, 55, 60, 48, 52, 35, 30, 25, 20, * Seeded flat and advanced one sample per repaint from real allocator stats. */
28, 32, 45, 60, 55, 40, 30, 25, 20, 18, 22, 25, 15, 18, 22, 30, 35, 40, 38, 42, static uint8_t g_heap_history[60];
30, 25, 20, 18, 15, 22, 28, 35, 40, 48, 52, 45, 38, 30, 25, 20, 18, 15, 20, 24 static bool g_heap_history_seeded = false;
};
static void sysmon_sample_heap(uint8_t pct) {
if (!g_heap_history_seeded) {
for (int i = 0; i < 60; i++) g_heap_history[i] = pct;
g_heap_history_seeded = true;
return;
}
for (int i = 0; i < 59; i++) g_heap_history[i] = g_heap_history[i + 1];
g_heap_history[59] = pct;
}
static void sysmon_paint(gui_window_t* win) { static void sysmon_paint(gui_window_t* win) {
int cx = win->x + 12; int cx = win->x + 12;
int cy = win->y + GUI_TITLEBAR_HEIGHT + 10; int cy = win->y + GUI_TITLEBAR_HEIGHT + 10;
gui_gfx_draw_string_16_shadow(cx, cy, "CPU Load History (Real-Time)", GUI_THEME_PRIMARY, GUI_COLOR_BLACK); /* Pull live figures straight from the kernel allocators. */
uint64_t heap_used = (uint64_t)heap_get_used_bytes();
uint64_t heap_total = (uint64_t)heap_get_total_bytes();
uint64_t heap_free = (uint64_t)heap_get_free_bytes();
uint64_t heap_grows = (uint64_t)heap_get_grow_count();
uint32_t heap_pct = heap_total ? (uint32_t)((heap_used * 100) / heap_total) : 0;
if (heap_pct > 100) heap_pct = 100;
// CPU Graph Box uint64_t ram_free_mb = (pmm_get_free_pages() * PMM_PAGE_SIZE) / (1024 * 1024);
uint64_t ram_total_mb = pmm_get_usable_memory() / (1024 * 1024);
sysmon_sample_heap((uint8_t)heap_pct);
gui_gfx_draw_string_16_shadow(cx, cy, "Heap Utilization History (Live)", GUI_THEME_PRIMARY, GUI_COLOR_BLACK);
// Heap Graph Box
int graph_x = cx; int graph_x = cx;
int graph_y = cy + 20; int graph_y = cy + 20;
int graph_w = win->width - 24; int graph_w = win->width - 24;
@@ -54,31 +76,37 @@ static void sysmon_paint(gui_window_t* win) {
gui_gfx_draw_line(gx, graph_y + 1, gx, graph_y + graph_h - 2, 0xFF1E293B); gui_gfx_draw_line(gx, graph_y + 1, gx, graph_y + graph_h - 2, 0xFF1E293B);
} }
// Plot Waveform // Plot Waveform from the live heap trace
for (int i = 0; i < 59 && (i * 5 + 5) < graph_w; i++) { for (int i = 0; i < 59 && (i * 5 + 5) < graph_w; i++) {
int y1 = graph_y + graph_h - 3 - (g_cpu_history[i] * (graph_h - 6)) / 100; int y1 = graph_y + graph_h - 3 - (g_heap_history[i] * (graph_h - 6)) / 100;
int y2 = graph_y + graph_h - 3 - (g_cpu_history[i + 1] * (graph_h - 6)) / 100; int y2 = graph_y + graph_h - 3 - (g_heap_history[i + 1] * (graph_h - 6)) / 100;
gui_gfx_draw_line(graph_x + 4 + i * 5, y1, graph_x + 4 + (i + 1) * 5, y2, GUI_THEME_SUCCESS); gui_gfx_draw_line(graph_x + 4 + i * 5, y1, graph_x + 4 + (i + 1) * 5, y2, GUI_THEME_SUCCESS);
} }
// Memory Usage Bar // Heap Usage Bar (real used / total)
char buf[80];
int mem_y = graph_y + graph_h + 12; int mem_y = graph_y + graph_h + 12;
gui_gfx_draw_string_16(cx, mem_y, "RAM Usage: 24 MB / 128 MB (18% Heap)", GUI_THEME_TEXT_MAIN); snprintf(buf, sizeof(buf), "Heap: %llu / %llu KB (%u%%)",
(unsigned long long)(heap_used / 1024),
(unsigned long long)(heap_total / 1024), heap_pct);
gui_gfx_draw_string_16(cx, mem_y, buf, GUI_THEME_TEXT_MAIN);
int bar_y = mem_y + 20; int bar_y = mem_y + 20;
int bar_w = win->width - 24; int bar_w = win->width - 24;
gui_gfx_fill_rect(cx, bar_y, bar_w, 12, GUI_THEME_BG_DARK); gui_gfx_fill_rect(cx, bar_y, bar_w, 12, GUI_THEME_BG_DARK);
gui_gfx_fill_rect(cx, bar_y, (bar_w * 24) / 128, 12, GUI_THEME_ACCENT); gui_gfx_fill_rect(cx, bar_y, (int)((uint64_t)bar_w * heap_pct / 100), 12,
(heap_pct >= 90) ? GUI_THEME_DANGER : GUI_THEME_ACCENT);
gui_gfx_draw_rect(cx, bar_y, bar_w, 12, GUI_THEME_BORDER); gui_gfx_draw_rect(cx, bar_y, bar_w, 12, GUI_THEME_BORDER);
// System Telemetry Metrics // System Telemetry Metrics (live)
char buf[64];
cpufreq_stats_t stats = cpufreq_get_stats(); cpufreq_stats_t stats = cpufreq_get_stats();
snprintf(buf, sizeof(buf), "Clock: %u.%03u GHz | Governor: ondemand", snprintf(buf, sizeof(buf), "Clock: %u.%03u GHz | Heap free: %llu KB | Grows: %llu",
stats.current_khz / 1000000, (stats.current_khz % 1000000) / 1000); stats.current_khz / 1000000, (stats.current_khz % 1000000) / 1000,
(unsigned long long)(heap_free / 1024), (unsigned long long)heap_grows);
gui_gfx_draw_string(cx, bar_y + 20, buf, GUI_THEME_TEXT_MUTED); gui_gfx_draw_string(cx, bar_y + 20, buf, GUI_THEME_TEXT_MUTED);
snprintf(buf, sizeof(buf), "Core Tasks: 6 Active | VFS Cache: 98.4%% Hit", 0); snprintf(buf, sizeof(buf), "System RAM: %llu MB free / %llu MB usable",
(unsigned long long)ram_free_mb, (unsigned long long)ram_total_mb);
gui_gfx_draw_string(cx, bar_y + 32, buf, GUI_THEME_TEXT_DIM); gui_gfx_draw_string(cx, bar_y + 32, buf, GUI_THEME_TEXT_DIM);
} }
+1
View File
@@ -14,6 +14,7 @@ void kfree(void* ptr);
size_t heap_get_used_bytes(void); size_t heap_get_used_bytes(void);
size_t heap_get_free_bytes(void); size_t heap_get_free_bytes(void);
size_t heap_get_total_bytes(void); size_t heap_get_total_bytes(void);
size_t heap_get_grow_count(void); // Number of on-demand PMM growth events
static inline size_t kmalloc_get_used(void) { return heap_get_used_bytes(); } static inline size_t kmalloc_get_used(void) { return heap_get_used_bytes(); }
static inline size_t kmalloc_get_free(void) { return heap_get_free_bytes(); } static inline size_t kmalloc_get_free(void) { return heap_get_free_bytes(); }
+113 -28
View File
@@ -5,7 +5,8 @@
#include <kernel/printk.h> #include <kernel/printk.h>
#define HEAP_MAGIC 0x53554248 // "SUBH" #define HEAP_MAGIC 0x53554248 // "SUBH"
#define HEAP_INITIAL_PAGES 4096 // 16 MB initial kernel heap #define HEAP_INITIAL_PAGES 8192 // 32 MB initial kernel heap
#define HEAP_GROW_PAGES 4096 // Grow the heap 16 MB at a time on demand
typedef struct heap_block { typedef struct heap_block {
uint32_t magic; uint32_t magic;
@@ -18,11 +19,21 @@ typedef struct heap_block {
#define BLOCK_HEADER_SIZE sizeof(heap_block_t) #define BLOCK_HEADER_SIZE sizeof(heap_block_t)
static heap_block_t* heap_start = NULL; static heap_block_t* heap_start = NULL;
static heap_block_t* heap_tail = NULL; // last block in address order, for O(1) growth
static size_t heap_used_bytes = 0; static size_t heap_used_bytes = 0;
static size_t heap_free_bytes = 0; static size_t heap_free_bytes = 0;
static size_t heap_total_bytes = 0; static size_t heap_total_bytes = 0;
static size_t heap_grow_count = 0;
static spinlock_t heap_lock = SPINLOCK_INIT; static spinlock_t heap_lock = SPINLOCK_INIT;
/* Two blocks may only be coalesced when they are physically adjacent. The heap
* is made of one or more regions carved from the PMM; a region boundary shows
* up as a gap between a block and its list successor, so this guard keeps the
* free-list merge from ever spanning two independent PMM allocations. */
static inline bool blocks_adjacent(heap_block_t* a, heap_block_t* b) {
return (heap_block_t*)((uint8_t*)a + BLOCK_HEADER_SIZE + a->size) == b;
}
void heap_init(void) { void heap_init(void) {
void* initial_mem = pmm_alloc_pages(HEAP_INITIAL_PAGES); void* initial_mem = pmm_alloc_pages(HEAP_INITIAL_PAGES);
if (!initial_mem) { if (!initial_mem) {
@@ -31,7 +42,7 @@ void heap_init(void) {
} }
heap_start = (heap_block_t*)initial_mem; heap_start = (heap_block_t*)initial_mem;
heap_total_bytes = HEAP_INITIAL_PAGES * PMM_PAGE_SIZE; heap_total_bytes = (size_t)HEAP_INITIAL_PAGES * PMM_PAGE_SIZE;
heap_start->magic = HEAP_MAGIC; heap_start->magic = HEAP_MAGIC;
heap_start->is_free = true; heap_start->is_free = true;
@@ -39,28 +50,63 @@ void heap_init(void) {
heap_start->next = NULL; heap_start->next = NULL;
heap_start->prev = NULL; heap_start->prev = NULL;
heap_tail = heap_start;
heap_used_bytes = 0; heap_used_bytes = 0;
heap_free_bytes = heap_start->size; heap_free_bytes = heap_start->size;
} }
void* kmalloc(size_t size) { /* Append a fresh region from the PMM to the tail of the free list. Must be
if (size == 0) return NULL; * called with heap_lock held. Returns the new free block, or NULL if the PMM
* cannot satisfy a contiguous run large enough for the request. */
static heap_block_t* heap_grow(size_t need) {
size_t need_pages = (need + BLOCK_HEADER_SIZE + PMM_PAGE_SIZE - 1) / PMM_PAGE_SIZE;
size_t grow_pages = need_pages > HEAP_GROW_PAGES ? need_pages : HEAP_GROW_PAGES;
// Align size to 16 bytes for SIMD/64-bit performance void* mem = pmm_alloc_pages(grow_pages);
size = (size + 15) & ~15; if (!mem && grow_pages != need_pages) {
/* Could not get the generous chunk; fall back to exactly what is needed. */
spin_lock(&heap_lock); grow_pages = need_pages;
mem = pmm_alloc_pages(grow_pages);
heap_block_t* curr = heap_start; }
while (curr) { if (!mem) {
if (curr->magic != HEAP_MAGIC) {
printk(KERN_ERR "Heap Corruption detected at %p!\n", curr);
spin_unlock(&heap_lock);
return NULL; return NULL;
} }
if (curr->is_free && curr->size >= size) { heap_block_t* region = (heap_block_t*)mem;
// Check if block can be split region->magic = HEAP_MAGIC;
region->is_free = true;
region->size = (size_t)grow_pages * PMM_PAGE_SIZE - BLOCK_HEADER_SIZE;
region->next = NULL;
region->prev = heap_tail;
if (heap_tail) {
heap_tail->next = region;
}
heap_tail = region;
if (!heap_start) {
heap_start = region;
}
heap_total_bytes += (size_t)grow_pages * PMM_PAGE_SIZE;
heap_free_bytes += region->size;
heap_grow_count++;
/* A PMM run handed back right after the previous tail is a real neighbour;
* fuse it so the heap does not fragment purely from growing. */
if (region->prev && region->prev->is_free && blocks_adjacent(region->prev, region)) {
heap_block_t* prev = region->prev;
prev->size += BLOCK_HEADER_SIZE + region->size;
prev->next = region->next; // NULL
heap_tail = prev;
region = prev;
}
return region;
}
/* Carve `size` bytes out of a free block, splitting off the remainder. Must be
* called with heap_lock held; `curr` must be free and large enough. */
static void* heap_take(heap_block_t* curr, size_t size) {
if (curr->size >= size + BLOCK_HEADER_SIZE + 16) { if (curr->size >= size + BLOCK_HEADER_SIZE + 16) {
heap_block_t* new_block = (heap_block_t*)((uint8_t*)curr + BLOCK_HEADER_SIZE + size); heap_block_t* new_block = (heap_block_t*)((uint8_t*)curr + BLOCK_HEADER_SIZE + size);
new_block->magic = HEAP_MAGIC; new_block->magic = HEAP_MAGIC;
@@ -71,6 +117,8 @@ void* kmalloc(size_t size) {
if (curr->next) { if (curr->next) {
curr->next->prev = new_block; curr->next->prev = new_block;
} else {
heap_tail = new_block;
} }
curr->next = new_block; curr->next = new_block;
curr->size = size; curr->size = size;
@@ -80,15 +128,44 @@ void* kmalloc(size_t size) {
heap_used_bytes += curr->size; heap_used_bytes += curr->size;
heap_free_bytes -= curr->size; heap_free_bytes -= curr->size;
spin_unlock(&heap_lock);
return (void*)((uint8_t*)curr + BLOCK_HEADER_SIZE); return (void*)((uint8_t*)curr + BLOCK_HEADER_SIZE);
}
void* kmalloc(size_t size) {
if (size == 0) return NULL;
// Align size to 16 bytes for SIMD/64-bit performance
size = (size + 15) & ~15;
spin_lock(&heap_lock);
for (int attempt = 0; attempt < 2; attempt++) {
heap_block_t* curr = heap_start;
while (curr) {
if (curr->magic != HEAP_MAGIC) {
printk(KERN_ERR "Heap Corruption detected at %p!\n", curr);
spin_unlock(&heap_lock);
return NULL;
}
if (curr->is_free && curr->size >= size) {
void* ptr = heap_take(curr, size);
spin_unlock(&heap_lock);
return ptr;
} }
curr = curr->next; curr = curr->next;
} }
/* No block fit. Pull a new region from the PMM and try once more. */
if (attempt == 0 && heap_grow(size)) {
continue;
}
break;
}
spin_unlock(&heap_lock); spin_unlock(&heap_lock);
printk(KERN_WARNING "Heap: Out of memory for size %llu bytes!\n", size); printk(KERN_WARNING "Heap: Out of memory for size %llu bytes!\n", (uint64_t)size);
return NULL; return NULL;
} }
@@ -116,21 +193,27 @@ void kfree(void* ptr) {
heap_used_bytes -= block->size; heap_used_bytes -= block->size;
heap_free_bytes += block->size; heap_free_bytes += block->size;
// Coalesce with next block if free // Coalesce with next block if free AND physically adjacent (same region).
if (block->next && block->next->is_free) { if (block->next && block->next->is_free && blocks_adjacent(block, block->next)) {
block->size += BLOCK_HEADER_SIZE + block->next->size; heap_block_t* nxt = block->next;
block->next = block->next->next; block->size += BLOCK_HEADER_SIZE + nxt->size;
block->next = nxt->next;
if (block->next) { if (block->next) {
block->next->prev = block; block->next->prev = block;
} else {
heap_tail = block;
} }
} }
// Coalesce with prev block if free // Coalesce with prev block if free AND physically adjacent (same region).
if (block->prev && block->prev->is_free) { if (block->prev && block->prev->is_free && blocks_adjacent(block->prev, block)) {
block->prev->size += BLOCK_HEADER_SIZE + block->size; heap_block_t* prev = block->prev;
block->prev->next = block->next; prev->size += BLOCK_HEADER_SIZE + block->size;
prev->next = block->next;
if (block->next) { if (block->next) {
block->next->prev = block->prev; block->next->prev = prev;
} else {
heap_tail = prev;
} }
} }
@@ -151,9 +234,10 @@ void* krealloc(void* ptr, size_t new_size) {
return ptr; return ptr;
} }
size_t old_size = block->size;
void* new_ptr = kmalloc(new_size); void* new_ptr = kmalloc(new_size);
if (new_ptr) { if (new_ptr) {
memcpy(new_ptr, ptr, block->size); memcpy(new_ptr, ptr, old_size);
kfree(ptr); kfree(ptr);
} }
return new_ptr; return new_ptr;
@@ -162,3 +246,4 @@ void* krealloc(void* ptr, size_t new_size) {
size_t heap_get_used_bytes(void) { return heap_used_bytes; } size_t heap_get_used_bytes(void) { return heap_used_bytes; }
size_t heap_get_free_bytes(void) { return heap_free_bytes; } size_t heap_get_free_bytes(void) { return heap_free_bytes; }
size_t heap_get_total_bytes(void) { return heap_total_bytes; } size_t heap_get_total_bytes(void) { return heap_total_bytes; }
size_t heap_get_grow_count(void) { return heap_grow_count; }
+1 -1
View File
@@ -30,7 +30,7 @@ int sshd_start(uint16_t port) {
ssh_sessions[0].in_use = true; ssh_sessions[0].in_use = true;
ssh_sessions[0].state = SSH_STATE_SHELL_ACTIVE; ssh_sessions[0].state = SSH_STATE_SHELL_ACTIVE;
ssh_sessions[0].authenticated = true; ssh_sessions[0].authenticated = true;
strcpy(ssh_sessions[0].username, "root"); strcpy(ssh_sessions[0].username, "SUB");
ssh_sessions[0].client_ip = 0x0A000202; // 10.0.2.2 (QEMU Host Gateway) ssh_sessions[0].client_ip = 0x0A000202; // 10.0.2.2 (QEMU Host Gateway)
ssh_sessions[0].client_port = 52341; ssh_sessions[0].client_port = 52341;
ssh_sessions[0].connect_time = pit_get_ticks() / 100; ssh_sessions[0].connect_time = pit_get_ticks() / 100;
+11 -2
View File
@@ -829,7 +829,12 @@ def main():
print(f"menuconfig: lxdialog front-end failed ({exc}); " print(f"menuconfig: lxdialog front-end failed ({exc}); "
f"falling back to the curses UI.", file=sys.stderr) f"falling back to the curses UI.", file=sys.stderr)
# Fallback to Curses GUI replica # Fallback to the curses GUI replica, but only when we genuinely have an
# interactive terminal on both ends. Probing curses without a real TTY makes
# it fail deep inside the wrapper's teardown (e.g. "nocbreak() returned
# ERR"), which looked like a crash; gate on isatty so a piped or CI
# invocation drops straight to the non-interactive writer instead.
if sys.stdin.isatty() and sys.stdout.isatty():
try: try:
import curses import curses
curses.wrapper(run_curses_gui) curses.wrapper(run_curses_gui)
@@ -838,8 +843,12 @@ def main():
except Exception as exc: except Exception as exc:
print(f"menuconfig: curses UI unavailable ({exc}); " print(f"menuconfig: curses UI unavailable ({exc}); "
f"writing the current configuration non-interactively.", file=sys.stderr) f"writing the current configuration non-interactively.", file=sys.stderr)
else:
print("menuconfig: no interactive terminal detected; "
"writing the current configuration non-interactively.", file=sys.stderr)
# Last resort: no usable TTY at all. # Last resort: no usable TTY at all. Preserve an existing .config if present,
# otherwise fall back to the architecture default so the build never stalls.
cfg = load_config() cfg = load_config()
save_config(cfg) save_config(cfg)
print(f"*** Configuration written to {CONFIG_FILE} and {AUTOCONF_HEADER} ***") print(f"*** Configuration written to {CONFIG_FILE} and {AUTOCONF_HEADER} ***")
+8 -2
View File
@@ -23,11 +23,17 @@ void auth_init(void) {
user_count = 0; user_count = 0;
current_uid = 0; current_uid = 0;
// Seed default users // Seed default users. SUB/SUB is the primary superuser account -- the way
auth_add_user("root", "root", 0, 0, "/root", "/bin/sh"); // Kali ships with kali/kali -- so the username and password both default to
// "SUB". It is seeded first, so uid 0 resolves to it as the logged-in user.
auth_add_user("SUB", "SUB", 0, 0, "/root", "/bin/sh");
auth_add_user("root", "root", 0, 0, "/root", "/bin/sh"); // kept for compatibility
auth_add_user("admin", "admin123", 1000, 1000, "/home/admin", "/bin/sh"); auth_add_user("admin", "admin123", 1000, 1000, "/home/admin", "/bin/sh");
auth_add_user("guest", "guest", 1001, 1001, "/home/guest", "/bin/sh"); auth_add_user("guest", "guest", 1001, 1001, "/home/guest", "/bin/sh");
// Log in as SUB by default.
auth_set_current_user("SUB");
printk(KERN_INFO "AUTH: Pluggable Authentication & SHA-256 Shadow Password engine active\n"); printk(KERN_INFO "AUTH: Pluggable Authentication & SHA-256 Shadow Password engine active\n");
} }
+6 -4
View File
@@ -709,6 +709,8 @@ static int applet_free(int argc, char** argv) {
total_kb, used_kb, free_kb, free_kb); total_kb, used_kb, free_kb, free_kb);
printk("Heap: %8llu %8llu %8llu\n", printk("Heap: %8llu %8llu %8llu\n",
kmalloc_get_total() / 1024, kmalloc_get_used() / 1024, kmalloc_get_free() / 1024); kmalloc_get_total() / 1024, kmalloc_get_used() / 1024, kmalloc_get_free() / 1024);
printk(" (dynamic kernel heap, grown on demand %llu time(s))\n",
(unsigned long long)heap_get_grow_count());
return 0; return 0;
} }
@@ -1137,7 +1139,7 @@ static int applet_aead(int argc, char** argv) {
static int applet_whoami(int argc, char** argv) { static int applet_whoami(int argc, char** argv) {
(void)argc; (void)argv; (void)argc; (void)argv;
const user_account_t* u = auth_get_current_user(); const user_account_t* u = auth_get_current_user();
printk("%s\n", u ? u->username : "root"); printk("%s\n", u ? u->username : "SUB");
return 0; return 0;
} }
@@ -1652,7 +1654,7 @@ static int applet_ssh(int argc, char** argv) {
return 1; return 1;
} }
char username[32] = "root"; char username[32] = "SUB";
char host[64] = "localhost"; char host[64] = "localhost";
uint16_t port = 22; uint16_t port = 22;
@@ -1774,7 +1776,7 @@ static int applet_logread(int argc, char** argv) {
} }
static int applet_su(int argc, char** argv) { static int applet_su(int argc, char** argv) {
const char* target = (argc >= 2) ? argv[1] : "root"; const char* target = (argc >= 2) ? argv[1] : "SUB";
if (auth_set_current_user(target) == 0) { if (auth_set_current_user(target) == 0) {
printk(KERN_INFO "Switched to user '%s'\n", target); printk(KERN_INFO "Switched to user '%s'\n", target);
return 0; return 0;
@@ -1784,7 +1786,7 @@ static int applet_su(int argc, char** argv) {
} }
static int applet_passwd(int argc, char** argv) { static int applet_passwd(int argc, char** argv) {
const char* user = (argc >= 2) ? argv[1] : "root"; const char* user = (argc >= 2) ? argv[1] : "SUB";
const char* new_pass = (argc >= 3) ? argv[2] : "password"; const char* new_pass = (argc >= 3) ? argv[2] : "password";
if (auth_change_password(user, new_pass) == 0) { if (auth_change_password(user, new_pass) == 0) {
printk(KERN_INFO "passwd: password updated successfully for '%s'\n", user); printk(KERN_INFO "passwd: password updated successfully for '%s'\n", user);