Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/kernel/drivers/ahci.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,16 @@ force_inline bool ahciCmdIssue(ahci *ahciPtr, HBA_PORT *port, int slot) {
ahciPtr->cmdSlotsPreping &= ~(1 << slot);

// Wait for completion
uint64_t deadline = timerTicks + 5000;
while (1) {
// In some longer duration reads, it may be helpful to spin on the DPS bit
// in the PxIS port field as well (1 << 5)
if ((port->ci & (1 << slot)) == 0)
break;
if (timerTicks >= deadline) {
debugf("[ahci] Command timeout on slot %d!\n", slot);
return false;
}
}

return true;
Expand Down
9 changes: 8 additions & 1 deletion src/kernel/filesystems/ext2/ext2_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,15 @@ size_t ext2Write(OpenFile *fd, uint8_t *buff, size_t limit) {

ext2CachePush(ext2, dir);

// todo! memory leak!
spinlockCntWriteAcquire(&dir->globalObject->WLOCK_CACHE);
Ext2CacheObject *cacheBrowse = dir->globalObject->firstCacheObj;
while (cacheBrowse) {
Ext2CacheObject *next = cacheBrowse->next;
VirtualFree(cacheBrowse->buff,
DivRoundUp((cacheBrowse->blocks + 1) * ext2->blockSize, BLOCK_SIZE));
free(cacheBrowse);
cacheBrowse = next;
}
dir->globalObject->firstCacheObj = 0;
spinlockCntWriteRelease(&dir->globalObject->WLOCK_CACHE);

Expand Down
4 changes: 3 additions & 1 deletion src/kernel/filesystems/vfs/vfs_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,13 @@ size_t fsUserSeek(void *task, uint32_t fd, int offset, int whence) {
}

size_t fsReadlink(void *task, char *path, char *buf, int size) {
if (size <= 0)
return ERR(EINVAL);
if (strlength(path) == 14 && memcmp(path, "/proc/self/exe", 15) == 0 &&
currentTask->execname) {
// todo: hack-y, needs to be done properly sometime!
size_t total = strlength(currentTask->execname);
size_t toCopy = MIN(size, total);
size_t toCopy = MIN((size_t)size, total);
memcpy(buf, currentTask->execname, toCopy);
return toCopy;
// memcpy(buf, "/usr/libexec/webkit2gtk-4.1/MiniBrowser", 40);
Expand Down
3 changes: 1 addition & 2 deletions src/kernel/memory/malloc_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@

#define DEBUG_DLMALLOC_GLUE 0

void *last = 0;
void *sbrk(long increment) {
#if DEBUG_DLMALLOC_GLUE
debugf("[dlmalloc::sbrk] size{%lx}\n", increment);
#endif
if (increment < 0)
return 0; // supposed to release, whatever.
return (void *)-1; // supposed to release, whatever.
if (!increment)
return last;
// return 0;
Expand Down
38 changes: 30 additions & 8 deletions src/kernel/memory/paging.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ size_t VirtualToPhysicalL(uint64_t *pagedir, size_t virt_addr) {
uint32_t pd_index = PDE(virt_addr);
uint32_t pt_index = PTE(virt_addr);

// spinlockCntReadAcquire(&WLOCK_PAGING);
spinlockCntReadAcquire(&WLOCK_PAGING);
if (!(pagedir[pml4_index] & PF_PRESENT))
goto error;
/*else if (pagedir[pml4_index] & PF_PRESENT &&
Expand All @@ -273,13 +273,13 @@ size_t VirtualToPhysicalL(uint64_t *pagedir, size_t virt_addr) {
size_t *pt = (size_t *)(PTE_GET_ADDR(pd[pd_index]) + HHDMoffset);

if (pt[pt_index] & PF_PRESENT) {
// spinlockCntReadRelease(&WLOCK_PAGING);
spinlockCntReadRelease(&WLOCK_PAGING);
return (size_t)(PTE_GET_ADDR(pt[pt_index]) +
((size_t)virt_addr_init & 0xFFF));
}

error:
// spinlockCntReadRelease(&WLOCK_PAGING);
spinlockCntReadRelease(&WLOCK_PAGING);
return 0;
}

Expand Down Expand Up @@ -348,7 +348,7 @@ void PageDirectoryFree(uint64_t *page_dir) {
}

void PageDirectoryUserDuplicate(uint64_t *source, uint64_t *target) {
spinlockCntReadAcquire(&WLOCK_PAGING);
spinlockCntWriteAcquire(&WLOCK_PAGING);
for (int pml4_index = 0; pml4_index < 512; pml4_index++) {
if (!(source[pml4_index] & PF_PRESENT) || source[pml4_index] & PF_PS)
continue;
Expand Down Expand Up @@ -384,13 +384,35 @@ void PageDirectoryUserDuplicate(uint64_t *source, uint64_t *target) {

memcpy(ptrTarget, ptrSource, PAGE_SIZE);

spinlockCntReadRelease(&WLOCK_PAGING);
VirtualMapL(target, virt, physTarget, PF_RW | PF_USER);
spinlockCntReadAcquire(&WLOCK_PAGING);
// manually map into target (lock already held as write)
uint64_t tvirt = AMD64_MM_STRIPSX(virt);
uint32_t tpml4 = PML4E(tvirt);
uint32_t tpdp = PDPTE(tvirt);
uint32_t tpd = PDE(tvirt);
uint32_t tpt = PTE(tvirt);

if (!(target[tpml4] & PF_PRESENT)) {
size_t targ = PagingPhysAllocate();
target[tpml4] = targ | PF_PRESENT | PF_RW | PF_USER;
}
size_t *tpdpPT = (size_t *)(PTE_GET_ADDR(target[tpml4]) + HHDMoffset);
if (!(tpdpPT[tpdp] & PF_PRESENT)) {
size_t targ = PagingPhysAllocate();
tpdpPT[tpdp] = targ | PF_PRESENT | PF_RW | PF_USER;
}
size_t *tpdPT = (size_t *)(PTE_GET_ADDR(tpdpPT[tpdp]) + HHDMoffset);
if (!(tpdPT[tpd] & PF_PRESENT)) {
size_t targ = PagingPhysAllocate();
tpdPT[tpd] = targ | PF_PRESENT | PF_RW | PF_USER;
}
size_t *tptPT = (size_t *)(PTE_GET_ADDR(tpdPT[tpd]) + HHDMoffset);
tptPT[tpt] = (P_PHYS_ADDR(physTarget)) | PF_PRESENT | PF_RW | PF_USER;

invalidate(virt);
}
}
}
}

spinlockCntReadRelease(&WLOCK_PAGING);
spinlockCntWriteRelease(&WLOCK_PAGING);
}
9 changes: 7 additions & 2 deletions src/kernel/memory/pmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ size_t PhysicalAllocate(int pages) {
}

void PhysicalFree(size_t ptr, int pages) {
// maybe verify no double-frees are occuring..

spinlockAcquire(&LOCK_PMM);
for (int i = 0; i < pages; i++) {
size_t block = (ptr / BLOCK_SIZE) + i;
if (!BitmapGet(&physical, block)) {
debugf("[pmm] Double-free detected! ptr{%lx} block{%ld}\n", ptr, block);
panic();
}
}
MarkRegion(&physical, (void *)ptr, pages * BLOCK_SIZE, 0);
spinlockRelease(&LOCK_PMM);
}
14 changes: 4 additions & 10 deletions src/kernel/multitasking/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,23 +239,17 @@ void taskKill(uint32_t id, uint16_t ret) {
// close any left open files
taskInfoFilesDiscard(task->infoFiles, task);

// if (!parentVfork)
// PageDirectoryFree(task->pagedir);
task->state = TASK_STATE_DEAD;

taskInfoPdDiscard(task->infoPd);
// ^ only changes userspace locations so we don't need to change our pagedir

// the "reaper" thread will finish everything in a safe context
taskCallReaper(task);
task->state = TASK_STATE_DEAD;

if (currentTask == task) {
// we're most likely in a syscall context, so...
// taskKillCleanup(task); // left for sched
asm volatile("sti");
// wait until we're outta here
while (1) {
// debugf("GET ME OUT ");
}
while (1)
handControl();
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/kernel/multitasking/task_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,8 @@ void taskInfoPdDiscard(TaskInfoPagedir *target) {
target->utilizedBy--;
if (!target->utilizedBy) {
PageDirectoryFree(target->pagedir);
// todo: find a safe way to free target
// cannot be done w/the current layout as it's done inside taskKill and the
// scheduler needs it in case it's switched in between (will point to
// invalid/unsafe memory). maybe with overrides but we'll see later when the
// system is more stable.
spinlockRelease(&target->LOCK_PD);
free(target);
} else
spinlockRelease(&target->LOCK_PD);
}
Expand Down
1 change: 1 addition & 0 deletions src/kernel/syscalls/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ size_t readHandler(OpenFile *fd, uint8_t *in, size_t limit) {
// finalise
uint32_t fr = currentTask->tmpRecV;
memcpy(in, kernelBuff, fr);
free(kernelBuff);
if (currentTask->term.c_lflag & ICANON && fr < limit)
in[fr++] = '\n';
// only add newline if we can!
Expand Down
148 changes: 86 additions & 62 deletions src/kernel/syscalls/linux/syscalls_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,70 +169,94 @@ void freeArgvIfNeeded(char **argv) {
}

#define SYSCALL_EXECVE 59
static size_t syscallExecve(char *filename, char **argv, char **envp) {
// todo: also check for leader & kill the whole thread group for this
assert(currentTask->id == currentTask->tgid);

assert(argv[0]); // shebang support depends on it atm. check (dep)
dbgSysExtraf("filename{%s}", filename);
spinlockAcquire(&currentTask->infoFs->LOCK_FS);
char *filenameSanitized = fsSanitize(currentTask->infoFs->cwd, filename);
spinlockRelease(&currentTask->infoFs->LOCK_FS);
uint8_t *buff = calloc(256, 1);

// do a read to check for alternatives, elfExecute() still does its checks
OpenFile *preScan = fsKernelOpen(filenameSanitized, O_RDONLY, 0);
if (!preScan) {
free(filenameSanitized);
return ERR(ENOENT);
}
size_t max = fsRead(preScan, buff, 255); // 1 less so there's always a \0
fsKernelClose(preScan);
if (RET_IS_ERR(max)) {
free(filenameSanitized);
return max;
}

if (max > 2 && buff[0] == '#' && buff[1] == '!') {
// shebang detected!
char *arg2 = (char *)0;
int spaces = 0;
for (int i = 0; i < max; i++) {
if (buff[i] == ' ') {
if (spaces == 0) {
buff[i] = '\0'; // needs to be null terminated
arg2 = (char *)&buff[i + 1];
#define SHEBANG_MAX_DEPTH 8

static size_t syscallExecve(char *filename, char **argvOriginal, char **envp) {
char **argv = argvOriginal;
int shebangDepth = 0;
char *filenameSanitized = NULL;

while (1) {
// todo: also check for leader & kill the whole thread group for this
assert(currentTask->id == currentTask->tgid);

assert(argv[0]); // shebang support depends on it atm. check (dep)
dbgSysExtraf("filename{%s}", filename);
spinlockAcquire(&currentTask->infoFs->LOCK_FS);
filenameSanitized = fsSanitize(currentTask->infoFs->cwd, filename);
spinlockRelease(&currentTask->infoFs->LOCK_FS);
uint8_t *buff = calloc(256, 1);

OpenFile *preScan = fsKernelOpen(filenameSanitized, O_RDONLY, 0);
if (!preScan) {
free(buff);
free(filenameSanitized);
return ERR(ENOENT);
}
size_t max = fsRead(preScan, buff, 255);
fsKernelClose(preScan);
if (RET_IS_ERR(max)) {
free(buff);
free(filenameSanitized);
return max;
}

if (max > 2 && buff[0] == '#' && buff[1] == '!') {
if (shebangDepth >= SHEBANG_MAX_DEPTH) {
free(buff);
free(filenameSanitized);
freeItemsIfNeeded(argv);
freeArgvIfNeeded(argv);
return ERR(ELOOP);
}
shebangDepth++;

char *arg2 = (char *)0;
int spaces = 0;
for (int i = 0; i < max; i++) {
if (buff[i] == ' ') {
if (spaces == 0) {
buff[i] = '\0';
arg2 = (char *)&buff[i + 1];
}
spaces++;
} else if (buff[i] == '\n') {
buff[i] = '\0';
break;
}
spaces++;
} else if (buff[i] == '\n') {
buff[i] = '\0'; // for the last arg (if none, 256-255=1 calloc)
break; // no longer needed + don't risk above
}

int argc = 0;
while (argv[argc++]);
int amnt = arg2 ? 2 : 1;
char **injectedArgv = calloc((amnt + argc + 1) * sizeof(char *), 1);
memcpy(&injectedArgv[amnt], argv, argc * sizeof(char *));
injectedArgv[amnt] = strdup(filename);

freeArgvIfNeeded(argv);

char *arg1 = (char *)&buff[2];
if (arg2 && arg2[0] != '\0')
injectedArgv[1] = strdup(arg2);
injectedArgv[0] = strdup(arg1);

free(buff);
free(filenameSanitized);
filename = injectedArgv[0];
argv = injectedArgv;
continue;
}
int argc = 0;
while (argv[argc++])
; // why not just pass argc. truly beyond me...
int amnt = arg2 ? 2 : 1;
char **injectedArgv = calloc((amnt + argc + 1) * sizeof(char *), 1);
memcpy(&injectedArgv[amnt], argv, argc * sizeof(char *));
injectedArgv[amnt] = strdup(filename); // replace [0] w/original (dep)

freeArgvIfNeeded(argv); // ! don't use argv anymore

char *arg1 = (char *)&buff[2];
if (arg2 && arg2[0] != '\0')
injectedArgv[1] = strdup(arg2);
injectedArgv[0] = strdup(arg1);

free(buff); // ! don't use anything defined before after this
syscallExecve(injectedArgv[0], injectedArgv, envp);
assert(false); // won't return, injectedArgv & buff are above HHDM
} else if (max > 4 && buff[EI_MAG0] == ELFMAG0 && buff[EI_MAG1] == ELFMAG1 &&
buff[EI_MAG2] == ELFMAG2 && buff[EI_MAG3] == ELFMAG3) {
// standard elf executable, go on
} else {
// both unnecessary, won't do anything w/them :^)
freeItemsIfNeeded(argv); // depends on the argv so NEEDS to be first

if (max > 4 && buff[EI_MAG0] == ELFMAG0 && buff[EI_MAG1] == ELFMAG1 &&
buff[EI_MAG2] == ELFMAG2 && buff[EI_MAG3] == ELFMAG3) {
free(buff);
break;
}

free(buff);
free(filenameSanitized);
freeItemsIfNeeded(argv);
freeArgvIfNeeded(argv);
return ERR(ENOEXEC);
}
Expand All @@ -247,8 +271,8 @@ static size_t syscallExecve(char *filename, char **argv, char **envp) {
free(arguments.valPlace);
free(environment.ptrPlace);
free(environment.valPlace);
freeItemsIfNeeded(argv); // depends on the argv so NEEDS to be first
freeArgvIfNeeded(argv); // ! don't use ANY argv after this
freeItemsIfNeeded(argv);
freeArgvIfNeeded(argv);
if (!ret)
return ERR(ENOENT);

Expand Down
Loading