diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | apps/idle.c | 3 | ||||
-rw-r--r-- | kernel/drivers/cpu.c | 112 | ||||
-rw-r--r-- | kernel/drivers/fb.c | 3 | ||||
-rw-r--r-- | kernel/drivers/keyboard.c | 2 | ||||
-rw-r--r-- | kernel/drivers/mouse.c | 2 | ||||
-rw-r--r-- | kernel/features/fs.c | 50 | ||||
-rw-r--r-- | kernel/features/load.c | 13 | ||||
-rw-r--r-- | kernel/features/mm.c | 17 | ||||
-rw-r--r-- | kernel/features/proc.c | 75 | ||||
-rw-r--r-- | kernel/features/syscall.c | 8 | ||||
-rw-r--r-- | kernel/inc/cpu.h | 31 | ||||
-rw-r--r-- | libs/libc/inc/mem.h | 12 | ||||
-rw-r--r-- | libs/libc/inc/str.h | 22 | ||||
-rw-r--r-- | libs/libc/mem.c | 42 | ||||
-rw-r--r-- | libs/libc/print.c | 3 | ||||
-rw-r--r-- | libs/libc/random.c | 4 | ||||
-rw-r--r-- | libs/libc/str.c | 88 |
18 files changed, 379 insertions, 110 deletions
@@ -27,7 +27,7 @@ This project is somewhat of a coding playground for me. It doesn't have any usef - Fast boot time (< 1s) - TCP/IP stack and rtl8139 driver - Small size (< 100KiB) -- Sandboxed processes (paging, ring 3, iomap) +- Sandboxed processes (paging, ring 3, SMAP/SMEP protections) - Full UBSan support - Compiles with `-Wall -Wextra -Werror -pedantic-errors -std=c99 -Ofast` diff --git a/apps/idle.c b/apps/idle.c index 95731e2..43186ff 100644 --- a/apps/idle.c +++ b/apps/idle.c @@ -9,7 +9,8 @@ int main(int argc, char **argv) // Just chillin' while (1) - __asm__ volatile("hlt"); + ; + /* __asm__ volatile("hlt"); */ return 0; } diff --git a/kernel/drivers/cpu.c b/kernel/drivers/cpu.c index 774d9f7..86ae2be 100644 --- a/kernel/drivers/cpu.c +++ b/kernel/drivers/cpu.c @@ -1,8 +1,10 @@ // MIT License, Copyright (c) 2020 Marvin Borner // This file is a wrapper around some CPU asm calls +#include <assert.h> #include <cpu.h> #include <def.h> +#include <mem.h> #include <print.h> u8 inb(u16 port) @@ -41,26 +43,6 @@ void outl(u16 port, u32 data) __asm__ volatile("outl %0, %1" ::"a"(data), "Nd"(port)); } -CLEAR static void cpuid(int code, u32 *a, u32 *b, u32 *c, u32 *d) -{ - __asm__ volatile("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "a"(code)); -} - -CLEAR static char *cpu_string(char buf[16]) -{ - // wtf - cpuid(CPUID_VENDOR_STRING, (u32 *)(buf + 12), (u32 *)(buf), (u32 *)(buf + 8), - (u32 *)(buf + 4)); - - return buf; -} - -CLEAR void cpu_print(void) -{ - char buf[16] = { 0 }; - printf("CPU vendor: %s\n", cpu_string(buf)); -} - CLEAR u32 cr0_get(void) { u32 cr0; @@ -97,18 +79,6 @@ CLEAR void cr4_set(u32 cr4) __asm__ volatile("movl %%eax, %%cr4" ::"a"(cr4)); } -static u32 cpu_cfeatures = 0; -u8 cpu_has_cfeature(enum cpuid_features feature) -{ - return (cpu_cfeatures & feature) != 0; -} - -static u32 cpu_dfeatures = 0; -u8 cpu_has_dfeature(enum cpuid_features feature) -{ - return (cpu_dfeatures & feature) != 0; -} - static void fpu_handler(struct regs *r) { UNUSED(r); @@ -121,13 +91,44 @@ void fpu_restore(void) __asm__ volatile("fxrstor (%0)" ::"r"(fpu_state)); } -CLEAR void cpu_enable_features(void) +CLEAR static struct cpuid cpuid(u32 code) { u32 a, b, c, d; - cpuid(CPUID_FEATURES, &a, &b, &c, &d); - cpu_cfeatures = c; - cpu_dfeatures = d; - if (cpu_has_dfeature(CPUID_FEAT_EDX_SSE)) { + __asm__ volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(code), "c"(0)); + return (struct cpuid){ a, b, c, d }; +} + +CLEAR static char *cpu_string(char buf[16]) +{ + // wtf + struct cpuid id = cpuid(CPUID_VENDOR_STRING); + memcpy((u32 *)(buf + 12), &id.eax, 4); + memcpy((u32 *)(buf + 0), &id.ebx, 4); + memcpy((u32 *)(buf + 8), &id.ecx, 4); + memcpy((u32 *)(buf + 4), &id.edx, 4); + return buf; +} + +CLEAR void cpu_print(void) +{ + char buf[16] = { 0 }; + printf("CPU vendor: %s\n", cpu_string(buf)); +} + +PROTECTED struct cpuid cpu_features = { 0 }; +PROTECTED struct cpuid cpu_extended_information = { 0 }; +PROTECTED struct cpuid cpu_extended_features = { 0 }; + +CLEAR void cpu_enable_features(void) +{ + cpu_features = cpuid(CPUID_FEATURES); + u32 max = cpuid(0x80000000).eax; + assert(max >= 0x80000001); + cpu_extended_information = cpuid(0x80000001); + cpu_extended_features = cpuid(0x7); + + // Enable SSE + if (cpu_features.edx & CPUID_FEAT_EDX_SSE) { cr0_set(cr0_get() & ~(1 << 2)); cr0_set(cr0_get() | (1 << 1)); cr4_set(cr4_get() | (3 << 9)); @@ -135,13 +136,48 @@ CLEAR void cpu_enable_features(void) panic("No SSE support!\n"); } - if (cpu_has_dfeature(CPUID_FEAT_EDX_FPU)) { + // Enable FPU + if (cpu_features.edx & CPUID_FEAT_EDX_FPU) { __asm__ volatile("fninit"); __asm__ volatile("fxsave %0" : "=m"(fpu_state)); irq_install_handler(7, fpu_handler); } else { panic("No FPU support!\n"); } + + // Enable NX (IA32_EFER.NXE) + if (cpu_extended_information.edx & CPUID_EXT_INFO_EDX_NX) { + __asm__ volatile("movl $0xc0000080, %ecx\n" + "rdmsr\n" + "orl $0x800, %eax\n" + "wrmsr\n"); + } else { + print("No NX support :(\n"); + } + + // Enable SMEP + if (cpu_extended_features.ebx & CPUID_EXT_FEAT_EBX_SMEP) { + cr4_set(cr4_get() | 0x100000); + } else { + print("No SMEP support :(\n"); + } + + // Enable SMAP + if (cpu_extended_features.ebx & CPUID_EXT_FEAT_EBX_SMAP) { + cr4_set(cr4_get() | 0x200000); + } else { + print("No SMAP support :(\n"); + } +} + +void clac(void) +{ + __asm__ volatile("clac" ::: "cc"); +} + +void stac(void) +{ + __asm__ volatile("stac" ::: "cc"); } CLEAR void cli(void) diff --git a/kernel/drivers/fb.c b/kernel/drivers/fb.c index 577debf..3e333e8 100644 --- a/kernel/drivers/fb.c +++ b/kernel/drivers/fb.c @@ -1,6 +1,7 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include <assert.h> +#include <cpu.h> #include <def.h> #include <errno.h> #include <fb.h> @@ -44,7 +45,9 @@ static res fb_ioctl(u32 request, void *arg1, void *arg2, void *arg3, struct devi else fb_owner = proc_current()->pid; + stac(); memcpy(arg1, info->vbe, sizeof(struct vbe_basic)); + clac(); fb_map_buffer(proc_current()->page_dir, info); return EOK; } diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index b917e4e..95b8a21 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -68,7 +68,7 @@ static res keyboard_read(void *buf, u32 offset, u32 count, struct device *dev) return -EINVAL; struct event_keyboard *e = stack_pop(queue); - memcpy(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); + memcpy_user(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); free(e); return MIN(count, sizeof(*e)); } diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c index eb05d08..0440057 100644 --- a/kernel/drivers/mouse.c +++ b/kernel/drivers/mouse.c @@ -95,7 +95,7 @@ static res mouse_read(void *buf, u32 offset, u32 count, struct device *dev) return -EINVAL; struct event_mouse *e = stack_pop(queue); - memcpy(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); + memcpy_user(buf, (u8 *)e + offset, MIN(count, sizeof(*e))); free(e); return MIN(count, sizeof(*e)); } diff --git a/kernel/features/fs.c b/kernel/features/fs.c index cc9949e..47e7891 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -1,6 +1,7 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <assert.h> +#include <cpu.h> #include <crypto.h> #include <def.h> #include <errno.h> @@ -65,15 +66,24 @@ static struct mount_info *vfs_recursive_find(char *path) static struct mount_info *vfs_find_mount_info(const char *path) { - if (path[0] != '/') + stac(); + if (path[0] != '/') { + clac(); return NULL; - return vfs_recursive_find(strdup(path)); + } + clac(); + struct mount_info *ret = vfs_recursive_find(strdup_user(path)); + return ret; } struct device *vfs_find_dev(const char *path) { - if (path[0] != '/') + stac(); + if (path[0] != '/') { + clac(); return NULL; + } + clac(); struct mount_info *m = vfs_find_mount_info(path); if (m->dev->vfs->type == VFS_DEVFS) // TODO: ? return device_get_by_name(path + strlen(m->path) + 1); @@ -130,7 +140,6 @@ res vfs_mount(struct device *dev, const char *path) res vfs_read(const char *path, void *buf, u32 offset, u32 count) { - /* printf("%s READ: %s\n", proc_current() ? proc_current()->name : "Unknown", path); */ if (!memory_valid(path)) return -EFAULT; @@ -159,7 +168,6 @@ res vfs_read(const char *path, void *buf, u32 offset, u32 count) res vfs_write(const char *path, void *buf, u32 offset, u32 count) { - /* printf("%s WRITE: %s\n", proc_current() ? proc_current()->name : "Unknown", path); */ if (!memory_valid(path)) return -EFAULT; @@ -255,21 +263,31 @@ res vfs_block(const char *path, u32 func_ptr) return m->dev->vfs->block(path, func_ptr, m->dev); } +// TODO: Reduce stac clac? +// TODO: Fix page fault when called too often/fast res vfs_poll(const char **files) { if (!memory_valid(files)) return -EFAULT; + stac(); for (const char **p = files; *p && memory_valid(*p) && **p; p++) { res ready = vfs_ready(*p); + clac(); if (ready == 1) return p - files; else if (ready < 0) return ready; + stac(); } + clac(); - for (const char **p = files; *p && memory_valid(*p) && **p; p++) + stac(); + for (const char **p = files; *p && memory_valid(*p) && **p; p++) { vfs_block(*p, (u32)vfs_poll); + stac(); + } + clac(); return PROC_MAX_BLOCK_IDS + 1; } @@ -325,7 +343,7 @@ struct device *device_get_by_name(const char *name) { struct node *iterator = devices->head; while (iterator) { - if (!strcmp(((struct device *)iterator->data)->name, name)) + if (!strcmp_user(((struct device *)iterator->data)->name, name)) return iterator->data; iterator = iterator->next; } @@ -522,7 +540,7 @@ static res read_inode(struct ext2_inode *in, void *buf, u32 offset, u32 count, s u32 block_offset = (i == first_block) ? first_block_offset : 0; u32 byte_count = MIN(BLOCK_SIZE - block_offset, remaining); - memcpy((u8 *)buf + copied, data + block_offset, byte_count); + memcpy_user((u8 *)buf + copied, data + block_offset, byte_count); copied += byte_count; remaining -= byte_count; @@ -583,12 +601,14 @@ static u32 find_inode(const char *name, u32 dir_inode, struct device *dev) static struct ext2_inode *find_inode_by_path(const char *path, struct ext2_inode *in_buf, struct device *dev) { - if (path[0] != '/') - return NULL; - - char *path_cp = strdup(path); + char *path_cp = strdup_user(path); char *init = path_cp; // For freeing + if (path_cp[0] != '/') { + free(init); + return NULL; + } + path_cp++; u32 current_inode = EXT2_ROOT; @@ -623,9 +643,9 @@ static struct ext2_inode *find_inode_by_path(const char *path, struct ext2_inode res ext2_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) { struct ext2_inode in = { 0 }; - if (find_inode_by_path(path, &in, dev) == &in) + if (find_inode_by_path(path, &in, dev) == &in) { return read_inode(&in, buf, offset, count, dev); - else + } else return -ENOENT; } @@ -638,8 +658,10 @@ res ext2_stat(const char *path, struct stat *buf, struct device *dev) //u32 num_blocks = in.blocks / (BLOCK_SIZE / SECTOR_SIZE); //u32 sz = BLOCK_SIZE * num_blocks; + stac(); buf->dev_id = dev->id; buf->size = in.size; + clac(); return EOK; } diff --git a/kernel/features/load.c b/kernel/features/load.c index c5039ed..0439424 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -1,5 +1,6 @@ // MIT License, Copyright (c) 2020 Marvin Borner +#include <cpu.h> #include <errno.h> #include <fs.h> #include <load.h> @@ -9,6 +10,8 @@ #define PROC_STACK_SIZE 0x4000 +#include <print.h> + res elf_load(const char *path, struct proc *proc) { if (!memory_valid(path)) @@ -18,19 +21,23 @@ res elf_load(const char *path, struct proc *proc) memory_bypass_enable(); res stat = vfs_stat(path, &s); memory_bypass_disable(); - if (stat != 0) + if (stat != EOK) return stat; struct elf_header header = { 0 }; + stac(); memory_bypass_enable(); res read = vfs_read(path, &header, 0, sizeof(header)); memory_bypass_disable(); + clac(); if (read < 0) return read; if (read != sizeof(header)) return -ENOEXEC; + stac(); strlcpy(proc->name, path, sizeof(proc->name)); + clac(); // Valid? u8 *magic = header.ident; @@ -44,10 +51,12 @@ res elf_load(const char *path, struct proc *proc) for (u32 i = 0; i < header.phnum; i++) { struct elf_program program = { 0 }; + memory_bypass_enable(); if (vfs_read(path, &program, header.phoff + header.phentsize * i, sizeof(program)) != sizeof(program)) { memory_bypass_disable(); + clac(); return -ENOEXEC; } memory_bypass_disable(); @@ -82,11 +91,13 @@ res elf_load(const char *path, struct proc *proc) memory_backup_dir(&prev); memory_switch_dir(proc->page_dir); + stac(); u32 stack = (u32)memory_alloc(proc->page_dir, PROC_STACK_SIZE, MEMORY_USER | MEMORY_CLEAR); proc->regs.ebp = stack + PROC_STACK_SIZE; proc->regs.useresp = stack + PROC_STACK_SIZE; proc->regs.eip = header.entry; proc->entry = header.entry; + clac(); memory_switch_dir(prev); return EOK; diff --git a/kernel/features/mm.c b/kernel/features/mm.c index 86d33c7..75b64bd 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -56,11 +56,12 @@ void page_fault_handler(struct regs *r) } else { dir = &kernel_dir; } - u32 paddr = virtual_to_physical(dir, vaddr); // Print! + u32 paddr = virtual_to_physical(dir, vaddr); printf("%s process tried to %s a %s page at [vaddr=%x; paddr=%x]\n", super, operation, type, vaddr, paddr); + print_trace(5); isr_panic(r); } @@ -350,7 +351,7 @@ void *memory_alloc(struct page_dir *dir, u32 size, u32 flags) } if (flags & MEMORY_CLEAR) - memset((void *)vaddr, 0, size); + memset_user((void *)vaddr, 0, size); return (void *)vaddr; @@ -427,8 +428,10 @@ res memory_sys_alloc(struct page_dir *dir, u32 size, u32 *addr, u32 *id, u8 shar link->vrange = memory_range(vaddr, size); list_add(proc_current()->memory, link); + stac(); *addr = vaddr; *id = obj->id; + clac(); return EOK; } @@ -466,9 +469,6 @@ res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size) if (!memory_valid(addr) || !memory_valid(size)) return -EFAULT; - *addr = 0; - *size = 0; - struct node *iterator = memory_objects->head; while (iterator) { struct memory_object *obj = iterator->data; @@ -480,8 +480,10 @@ res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size) struct memory_range shrange = virtual_alloc(dir, obj->prange, MEMORY_CLEAR | MEMORY_USER); + stac(); *addr = shrange.base; *size = shrange.size; + clac(); struct memory_proc_link *link = zalloc(sizeof(*link)); link->obj = obj; @@ -493,6 +495,11 @@ res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size) iterator = iterator->next; } + stac(); + *addr = 0; + *size = 0; + clac(); + return -ENOENT; } diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 6d07945..21e63b3 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -305,7 +305,9 @@ void proc_stack_push(struct proc *proc, u32 data) memory_switch_dir(proc->page_dir); proc->regs.useresp -= sizeof(data); + stac(); *(u32 *)proc->regs.useresp = data; + clac(); memory_switch_dir(prev); } @@ -314,6 +316,7 @@ void proc_stack_push(struct proc *proc, u32 data) static const char *procfs_parse_path(const char **path, u32 *pid) { + stac(); while (**path == '/') (*path)++; @@ -326,19 +329,20 @@ static const char *procfs_parse_path(const char **path, u32 *pid) *pid = proc_current()->pid; *path += 4; } + clac(); return *path; } static enum stream_defaults procfs_stream(const char *path) { - if (!memcmp(path, "in", 3)) { + if (!memcmp_user(path, "in", 3)) { return STREAM_IN; - } else if (!memcmp(path, "out", 4)) { + } else if (!memcmp_user(path, "out", 4)) { return STREAM_OUT; - } else if (!memcmp(path, "err", 4)) { + } else if (!memcmp_user(path, "err", 4)) { return STREAM_ERR; - } else if (!memcmp(path, "log", 4)) { + } else if (!memcmp_user(path, "log", 4)) { return STREAM_LOG; } else { return STREAM_UNKNOWN; @@ -356,20 +360,24 @@ static res procfs_write(const char *path, void *buf, u32 offset, u32 count, stru procfs_parse_path(&path, &pid); if (pid) { struct proc *p = proc_from_pid(pid); - if (!p || path[0] != '/') + stac(); + if (!p || path[0] != '/') { + clac(); return -ENOENT; + } + clac(); path++; - if (!memcmp(path, "msg", 4)) { + if (!memcmp_user(path, "msg", 4)) { void *msg_data = malloc(count); - memcpy(msg_data, buf, count); + memcpy_user(msg_data, buf, count); struct procfs_message *msg = malloc(sizeof(*msg)); msg->data = msg_data; msg->size = count; stack_push_bot(p->messages, msg); // TODO: Use offset proc_unblock(pid, PROC_BLOCK_MSG); return count; - } else if (!memcmp(path, "io/", 3)) { + } else if (!memcmp_user(path, "io/", 3)) { path += 3; enum stream_defaults id = procfs_stream(path); if (id == STREAM_UNKNOWN) @@ -381,7 +389,7 @@ static res procfs_write(const char *path, void *buf, u32 offset, u32 count, stru struct stream *stream = &p->streams[id]; assert(stream->offset_write + count < STREAM_MAX_SIZE); // TODO: Resize - memcpy((char *)(stream->data + stream->offset_write), buf, count); + memcpy_user((char *)(stream->data + stream->offset_write), buf, count); stream->offset_write += count; proc_unblock(dev->id, PROC_BLOCK_DEV); return count; @@ -400,40 +408,46 @@ static res procfs_read(const char *path, void *buf, u32 offset, u32 count, struc if (pid) { struct proc *p = proc_from_pid(pid); - if (!p || path[0] != '/') + stac(); + if (!p || path[0] != '/') { + clac(); return -ENOENT; + } + clac(); path++; - if (!memcmp(path, "pid", 4)) { - //memcpy(buf, ((u8 *)p->pid) + offset, count); + if (!memcmp_user(path, "pid", 4)) { + /* memcpy_user(buf, ((u8 *)p->pid) + offset, count); */ + stac(); *(u32 *)buf = p->pid; + clac(); return count; - } else if (!memcmp(path, "name", 5)) { - memcpy(buf, p->name + offset, count); + } else if (!memcmp_user(path, "name", 5)) { + memcpy_user(buf, p->name + offset, count); return count; - } else if (!memcmp(path, "status", 7)) { + } else if (!memcmp_user(path, "status", 7)) { const char *status = p->state == PROC_RUNNING ? "running" : "sleeping"; - memcpy(buf, status + offset, count); + memcpy_user(buf, status + offset, count); return count; - } else if (!memcmp(path, "msg", 4)) { + } else if (!memcmp_user(path, "msg", 4)) { if (stack_empty(p->messages)) { return -EIO; // This shouldn't happen } else { struct procfs_message *msg = stack_pop(p->messages); if (!msg) return -EIO; - memcpy(buf, msg->data + offset, MIN(count, msg->size)); + memcpy_user(buf, msg->data + offset, MIN(count, msg->size)); free(msg->data); free(msg); return MIN(count, msg->size); } - } else if (!memcmp(path, "io/", 3)) { + } else if (!memcmp_user(path, "io/", 3)) { path += 3; enum stream_defaults id = procfs_stream(path); if (id == STREAM_UNKNOWN) return -ENOENT; struct stream *stream = &p->streams[id]; - memcpy(buf, stream->data + stream->offset_read, count); + memcpy_user(buf, stream->data + stream->offset_read, count); stream->offset_read += count; return count; } @@ -449,11 +463,15 @@ static res procfs_block(const char *path, u32 func_ptr, struct device *dev) if (pid) { struct proc *p = proc_from_pid(pid); - if (!p || path[0] != '/') + stac(); + if (!p || path[0] != '/') { + clac(); return -ENOENT; + } + clac(); path++; - if (!memcmp(path, "msg", 4)) { + if (!memcmp_user(path, "msg", 4)) { proc_block(pid, PROC_BLOCK_MSG, func_ptr); return EOK; } else { @@ -485,13 +503,17 @@ static res procfs_ready(const char *path, struct device *dev) if (pid) { struct proc *p = proc_from_pid(pid); - if (!p || path[0] != '/') + stac(); + if (!p || path[0] != '/') { + clac(); return -ENOENT; + } + clac(); path++; - if (!memcmp(path, "msg", 4)) { + if (!memcmp_user(path, "msg", 4)) { return stack_empty(p->messages) == 0; - } else if (!memcmp(path, "io/", 3)) { + } else if (!memcmp_user(path, "io/", 3)) { path += 3; enum stream_defaults id = procfs_stream(path); if (id == STREAM_UNKNOWN) @@ -535,7 +557,8 @@ NORETURN void proc_init(void) assert(vfs_mount(dev, "/proc/") == EOK); // Idle proc - struct proc *kernel_proc = proc_make(PROC_PRIV_KERNEL); + // TODO: Reimplement hlt privileges in idle proc (SMEP!) + struct proc *kernel_proc = proc_make(PROC_PRIV_NONE); assert(elf_load("/bin/idle", kernel_proc) == EOK); kernel_proc->state = PROC_BLOCKED; kernel_proc->quantum.val = 0; diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 6a64996..b5c08da 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -28,8 +28,8 @@ static void syscall_handler(struct regs *r) break; } case SYS_ALLOC: { - r->eax = (u32)memory_sys_alloc(proc_current()->page_dir, r->ebx, (u32 *)r->ecx, - (u32 *)r->edx, (u8)r->esi); + r->eax = memory_sys_alloc(proc_current()->page_dir, r->ebx, (u32 *)r->ecx, + (u32 *)r->edx, (u8)r->esi); break; } case SYS_FREE: { @@ -102,7 +102,7 @@ static void syscall_handler(struct regs *r) case SYS_BOOT_REBOOT: print("Rebooting...\n"); outb(0x64, 0xfe); - __asm__ volatile("ud2"); + __asm__ volatile("cli\nud2"); break; case SYS_BOOT_SHUTDOWN: print("Shutting down...\n"); @@ -110,7 +110,7 @@ static void syscall_handler(struct regs *r) outw(0x604, 0x2000); outw(0x4004, 0x3400); outb(0x64, 0xfe); - __asm__ volatile("ud2"); + __asm__ volatile("cli\nud2"); break; default: r->eax = -EINVAL; diff --git a/kernel/inc/cpu.h b/kernel/inc/cpu.h index a88d94e..e7a5f58 100644 --- a/kernel/inc/cpu.h +++ b/kernel/inc/cpu.h @@ -32,10 +32,27 @@ void cr3_set(u32 cr3); u32 cr4_get(void); void cr4_set(u32 cr4); +void clac(void); +void stac(void); + void cli(void); void sti(void); -enum cpuid_requests { CPUID_VENDOR_STRING, CPUID_FEATURES, CPUID_TLB, CPUID_SERIAL }; +struct cpuid { + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; +}; + +enum cpuid_requests { + CPUID_VENDOR_STRING, + CPUID_FEATURES, + CPUID_TLB, + CPUID_SERIAL, + CPUID_EXT_FEATURES = 7, +}; + enum cpuid_features { CPUID_FEAT_ECX_SSE3 = 1u << 0, CPUID_FEAT_ECX_PCLMUL = 1u << 1, @@ -95,9 +112,17 @@ enum cpuid_features { CPUID_FEAT_EDX_HTT = 1u << 28, CPUID_FEAT_EDX_TM1 = 1u << 29, CPUID_FEAT_EDX_IA64 = 1u << 30, + + CPUID_EXT_FEAT_EBX_UMIP = 1u << 2, + CPUID_EXT_FEAT_EBX_SMEP = 1u << 7, + CPUID_EXT_FEAT_EBX_RDSEED = 1u << 18, + CPUID_EXT_FEAT_EBX_SMAP = 1u << 20, + + CPUID_EXT_INFO_EDX_NX = 1u << 20, }; -u8 cpu_has_cfeature(enum cpuid_features feature); -u8 cpu_has_dfeature(enum cpuid_features feature); +extern struct cpuid cpu_features; +extern struct cpuid cpu_extended_information; +extern struct cpuid cpu_extended_features; #endif diff --git a/libs/libc/inc/mem.h b/libs/libc/inc/mem.h index 960ee86..7318c25 100644 --- a/libs/libc/inc/mem.h +++ b/libs/libc/inc/mem.h @@ -21,7 +21,15 @@ void *zalloc(u32 size); void *memcpy(void *dest, const void *src, u32 n) NONNULL; void *memset(void *dest, u32 val, u32 n) NONNULL; void *memchr(void *src, char c, u32 n) NONNULL; -int memcmp(const void *s1, const void *s2, u32 n) NONNULL; -int mememp(const u8 *buf, u32 n) NONNULL; +s32 memcmp(const void *s1, const void *s2, u32 n) NONNULL; +u8 mememp(const u8 *buf, u32 n) NONNULL; + +#ifdef KERNEL +void *memcpy_user(void *dest, const void *src, u32 n) NONNULL; +void *memset_user(void *dest, u32 val, u32 n) NONNULL; +void *memchr_user(void *src, char c, u32 n) NONNULL; +s32 memcmp_user(const void *s1, const void *s2, u32 n) NONNULL; +u8 mememp_user(const u8 *buf, u32 n) NONNULL; +#endif #endif diff --git a/libs/libc/inc/str.h b/libs/libc/inc/str.h index e77eeee..b00750b 100644 --- a/libs/libc/inc/str.h +++ b/libs/libc/inc/str.h @@ -7,14 +7,28 @@ u32 strlen(const char *s) NONNULL; u32 strlcpy(char *dst, const char *src, u32 size) NONNULL; -char *strchr(char *s, int c) NONNULL; -char *strrchr(char *s, int c) NONNULL; +char *strchr(char *s, char c) NONNULL; +char *strrchr(char *s, char c) NONNULL; u32 strlcat(char *dst, const char *src, u32 size) NONNULL; -int strcmp(const char *s1, const char *s2) NONNULL; -int strncmp(const char *s1, const char *s2, u32 n) NONNULL; +s32 strcmp(const char *s1, const char *s2) NONNULL; +s32 strncmp(const char *s1, const char *s2, u32 n) NONNULL; char *strinv(char *s) NONNULL; char *strdup(const char *s) NONNULL; +#ifdef KERNEL + +u32 strlen_user(const char *s) NONNULL; +u32 strlcpy_user(char *dst, const char *src, u32 size) NONNULL; +char *strchr_user(char *s, char c) NONNULL; +char *strrchr_user(char *s, char c) NONNULL; +u32 strlcat_user(char *dst, const char *src, u32 size) NONNULL; +s32 strcmp_user(const char *s1, const char *s2) NONNULL; +s32 strncmp_user(const char *s1, const char *s2, u32 n) NONNULL; +char *strinv_user(char *s) NONNULL; +char *strdup_user(const char *s) NONNULL; + +#endif + const char *strerror(u32 err); #endif diff --git a/libs/libc/mem.c b/libs/libc/mem.c index ad691ed..babec3a 100644 --- a/libs/libc/mem.c +++ b/libs/libc/mem.c @@ -102,7 +102,7 @@ void *memchr(void *src, char c, u32 n) return NULL; } -int memcmp(const void *s1, const void *s2, u32 n) +s32 memcmp(const void *s1, const void *s2, u32 n) { const u8 *a = (const u8 *)s1; const u8 *b = (const u8 *)s2; @@ -115,7 +115,45 @@ int memcmp(const void *s1, const void *s2, u32 n) return 0; } -int mememp(const u8 *buf, u32 n) +u8 mememp(const u8 *buf, u32 n) { return buf[0] == 0 && !memcmp(buf, buf + 1, n - 1); } + +#ifdef KERNEL + +#include <cpu.h> + +void *memcpy_user(void *dest, const void *src, u32 n) +{ + stac(); + void *ret = memcpy(dest, src, n); + clac(); + return ret; +} + +void *memset_user(void *dest, u32 val, u32 n) +{ + stac(); + void *ret = memset(dest, val, n); + clac(); + return ret; +} + +void *memchr_user(void *src, char c, u32 n) +{ + stac(); + void *ret = memchr(src, c, n); + clac(); + return ret; +} + +s32 memcmp_user(const void *s1, const void *s2, u32 n) +{ + stac(); + s32 ret = memcmp(s1, s2, n); + clac(); + return ret; +} + +#endif diff --git a/libs/libc/print.c b/libs/libc/print.c index 4c38cdc..dcaa8cb 100644 --- a/libs/libc/print.c +++ b/libs/libc/print.c @@ -164,6 +164,7 @@ int print(const char *str) // The kernel prints everything into the serial console +#include <cpu.h> #include <mm.h> #include <proc.h> #include <serial.h> @@ -211,7 +212,9 @@ int print_app(enum stream_defaults id, const char *proc_name, const char *str) serial_print(YEL "[ERR] to "); serial_print(proc_name); serial_print(": "); + stac(); serial_print(str); + clac(); serial_print(RES); return 1; } diff --git a/libs/libc/random.c b/libs/libc/random.c index 6e65959..6296407 100644 --- a/libs/libc/random.c +++ b/libs/libc/random.c @@ -18,7 +18,7 @@ void srand(u32 seed) u32 rdrand(void) { #ifdef KERNEL - if (!cpu_has_cfeature(CPUID_FEAT_ECX_RDRND)) + if (!(cpu_features.ecx & CPUID_FEAT_ECX_RDRND)) return rand(); u32 rd; @@ -35,7 +35,7 @@ u32 rdrand(void) u32 rdseed(void) { #ifdef KERNEL - if (!cpu_has_cfeature(CPUID_FEAT_ECX_RDRND)) + if (!(cpu_extended_features.ebx & CPUID_EXT_FEAT_EBX_RDSEED)) return rand(); u32 rd; diff --git a/libs/libc/str.c b/libs/libc/str.c index 3bc3aaf..52af5c4 100644 --- a/libs/libc/str.c +++ b/libs/libc/str.c @@ -33,7 +33,7 @@ u32 strlcpy(char *dst, const char *src, u32 size) return src - orig - 1; } -int strcmp(const char *s1, const char *s2) +s32 strcmp(const char *s1, const char *s2) { const u8 *c1 = (const u8 *)s1; const u8 *c2 = (const u8 *)s2; @@ -49,7 +49,7 @@ int strcmp(const char *s1, const char *s2) return d; } -int strncmp(const char *s1, const char *s2, u32 n) +s32 strncmp(const char *s1, const char *s2, u32 n) { const u8 *c1 = (const u8 *)s1; const u8 *c2 = (const u8 *)s2; @@ -65,9 +65,9 @@ int strncmp(const char *s1, const char *s2, u32 n) return d; } -char *strchr(char *s, int c) +char *strchr(char *s, char c) { - while (*s != (char)c) { + while (*s != c) { if (!*s) return NULL; s++; @@ -76,7 +76,7 @@ char *strchr(char *s, int c) return s; } -char *strrchr(char *s, int c) +char *strrchr(char *s, char c) { char *ret = 0; @@ -218,3 +218,81 @@ const char *strerror(u32 error) return "Unknown error"; } } + +#ifdef KERNEL + +#include <cpu.h> + +u32 strlen_user(const char *str) +{ + stac(); + u32 ret = strlen(str); + clac(); + return ret; +} + +u32 strlcpy_user(char *dst, const char *src, u32 size) +{ + stac(); + u32 ret = strlcpy(dst, src, size); + clac(); + return ret; +} + +s32 strcmp_user(const char *s1, const char *s2) +{ + stac(); + s32 ret = strcmp(s1, s2); + clac(); + return ret; +} + +s32 strncmp_user(const char *s1, const char *s2, u32 n) +{ + stac(); + s32 ret = strncmp(s1, s2, n); + clac(); + return ret; +} + +char *strchr_user(char *s, char c) +{ + stac(); + char *ret = strchr(s, c); + clac(); + return ret; +} + +char *strrchr_user(char *s, char c) +{ + stac(); + char *ret = strrchr(s, c); + clac(); + return ret; +} + +u32 strlcat_user(char *dst, const char *src, u32 size) +{ + stac(); + u32 ret = strlcat(dst, src, size); + clac(); + return ret; +} + +char *strinv_user(char *s) +{ + stac(); + char *ret = strinv(s); + clac(); + return ret; +} + +char *strdup_user(const char *s) +{ + stac(); + char *ret = strdup(s); + clac(); + return ret; +} + +#endif |