summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/init/syscalls.c8
-rw-r--r--src/kernel/proc.h2
-rw-r--r--src/kernel/syscalls.c7
-rw-r--r--src/kernel/util.h6
-rw-r--r--src/kernel/vfs/request.h4
-rw-r--r--src/kernel/vfs/root.c19
-rw-r--r--src/shared/syscalls.h8
8 files changed, 26 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index 3d913d4..44bcfc0 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ PATH := $(shell pwd)/toolchain/bin/:$(PATH)
AS = i686-elf-as
CC = i686-elf-gcc
CHECK = sparse
-CFLAGS = -std=gnu99 -ffreestanding -O2 -Wall -Wextra -Wold-style-definition -Werror=implicit-function-declaration
+CFLAGS += -std=gnu99 -ffreestanding -O2 -Wall -Wextra -Wold-style-definition -Werror=implicit-function-declaration -ftrack-macro-expansion=0
CFLAGS += -mgeneral-regs-only
CFLAGS += -Isrc/
LFLAGS = -ffreestanding -O2 -nostdlib -lgcc
diff --git a/src/init/syscalls.c b/src/init/syscalls.c
index 99f68f3..15acd1c 100644
--- a/src/init/syscalls.c
+++ b/src/init/syscalls.c
@@ -22,12 +22,12 @@ int _syscall_mount(handle_t handle, const char __user *path, int len) {
return _syscall(_SYSCALL_MOUNT, handle, (int)path, len, 0);
}
-int _syscall_read(handle_t handle, void __user *buf, int len, int offset) {
- return _syscall(_SYSCALL_READ, handle, (int)buf, len, offset);
+int _syscall_read(handle_t handle, void __user *buf, size_t len, int offset) {
+ return _syscall(_SYSCALL_READ, handle, (int)buf, (int)len, offset);
}
-int _syscall_write(handle_t handle, const void __user *buf, int len, int offset) {
- return _syscall(_SYSCALL_WRITE, handle, (int)buf, len, offset);
+int _syscall_write(handle_t handle, const void __user *buf, size_t len, int offset) {
+ return _syscall(_SYSCALL_WRITE, handle, (int)buf, (int)len, offset);
}
int _syscall_close(handle_t handle) {
diff --git a/src/kernel/proc.h b/src/kernel/proc.h
index dc7525d..d754522 100644
--- a/src/kernel/proc.h
+++ b/src/kernel/proc.h
@@ -34,7 +34,7 @@ struct process {
} waits4fs; // PS_WAITS4FS
struct {
char __user *buf;
- int max_len;
+ size_t max_len;
struct fs_wait_response __user *res;
} awaited_req; // PS_WAITS4REQUEST
struct {
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c
index 85db57a..dfd7dd4 100644
--- a/src/kernel/syscalls.c
+++ b/src/kernel/syscalls.c
@@ -125,7 +125,7 @@ fail:
return -1;
}
-int _syscall_read(handle_t handle_num, void __user *buf, int len, int offset) {
+int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset) {
struct handle *handle = &process_current->handles[handle_num];
if (handle_num < 0 || handle_num >= HANDLE_MAX) return -1;
if (handle->type != HANDLE_FILE) return -1;
@@ -142,7 +142,7 @@ int _syscall_read(handle_t handle_num, void __user *buf, int len, int offset) {
});
}
-int _syscall_write(handle_t handle_num, const void __user *buf, int len, int offset) {
+int _syscall_write(handle_t handle_num, const void __user *buf, size_t len, int offset) {
struct handle *handle = &process_current->handles[handle_num];
if (handle_num < 0 || handle_num >= HANDLE_MAX) return -1;
if (handle->type != HANDLE_FILE) return -1;
@@ -228,8 +228,7 @@ int _syscall_fs_respond(char __user *buf, int ret) {
if (req->output.len > 0 && ret > 0) {
// if this vfsop outputs data and ret is positive, it's the length of the buffer
// TODO document
- if (ret > req->output.len)
- ret = req->output.len; // i'm not handling this in a special way - the fs server can prevent this on its own
+ ret = min(ret, capped_cast32(req->output.len));
if (!virt_cpy(req->caller->pages, req->output.buf,
process_current->pages, buf, ret)) {
// how should this error even be handled? TODO
diff --git a/src/kernel/util.h b/src/kernel/util.h
index 9b8cb3d..0e57d67 100644
--- a/src/kernel/util.h
+++ b/src/kernel/util.h
@@ -1,5 +1,6 @@
#pragma once
#include <stddef.h>
+#include <stdint.h>
#define __NUM2STR(x) #x
#define NUM2STR(x) __NUM2STR(x)
@@ -13,3 +14,8 @@
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
+
+/* casts an uint32_t to int32_t, capping it at INT32_MAX instead of overflowing */
+static inline int32_t capped_cast32(uint32_t u) {
+ return (int32_t)min(u, (uint32_t)INT32_MAX);
+}
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index 37b8c3a..151a066 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -26,11 +26,11 @@ struct vfs_request {
char __user *buf;
char *buf_kern;
};
- int len;
+ size_t len;
} input;
struct {
char __user *buf;
- int len;
+ size_t len;
} output;
int id; // handle.file.id
diff --git a/src/kernel/vfs/root.c b/src/kernel/vfs/root.c
index 2529b02..14f9a01 100644
--- a/src/kernel/vfs/root.c
+++ b/src/kernel/vfs/root.c
@@ -21,36 +21,28 @@ enum {
};
static bool exacteq(struct vfs_request *req, const char *str) {
- int len = strlen(str);
+ size_t len = strlen(str);
assert(req->input.kern);
return req->input.len == len && !memcmp(req->input.buf_kern, str, len);
}
/* truncates the length */
-static void req_preprocess(struct vfs_request *req, int max_len) {
- // max_len is signed because req->*.len are signed too
- // potential place for VULNs to occur - arbitrary kernel reads etc
+static void req_preprocess(struct vfs_request *req, size_t max_len) {
if (req->offset < 0) {
// TODO negative offsets
req->offset = 0;
}
- if (req->offset >= max_len) {
+ if (req->offset >= capped_cast32(max_len)) {
req->input.len = 0;
req->output.len = 0;
req->offset = max_len;
return;
}
- if (req->input.len < 0) req->input.len = 0;
- if (req->output.len < 0) req->output.len = 0;
-
req->input.len = min(req->input.len, max_len - req->offset);
req->output.len = min(req->output.len, max_len - req->offset);
- assert(req->input.len >= 0);
- assert(req->output.len >= 0);
-
assert(req->input.len + req->offset <= max_len);
assert(req->input.len + req->offset <= max_len);
}
@@ -84,7 +76,6 @@ static int handle(struct vfs_request *req, bool *ready) {
"com1\0"
"ps2\0"
"ata/";
- if (req->output.len < 0) return 0; // is this needed? TODO make that a size_t or something
int len = min((size_t) req->output.len, sizeof(src));
virt_cpy_to(req->caller->pages, req->output.buf, src, len);
return len;
@@ -106,7 +97,7 @@ static int handle(struct vfs_request *req, bool *ready) {
req->caller->waits4irq.ready = serial_ready;
return -1;
}
- uint8_t buf[16];
+ char buf[16];
size_t len = serial_read(buf, min(req->output.len, sizeof buf));
virt_cpy_to(req->caller->pages, req->output.buf, buf, len);
return len;
@@ -146,7 +137,7 @@ static int handle(struct vfs_request *req, bool *ready) {
if (req->offset < 0) return 0;
char buf[512];
uint32_t sector = req->offset / 512;
- int len = min(req->output.len, 512 - (req->offset & 511));
+ size_t len = min(req->output.len, 512 - ((size_t)req->offset & 511));
ata_read(req->id - HANDLE_ATA, sector, buf);
virt_cpy_to(req->caller->pages, req->output.buf, buf, len);
return len;
diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h
index 3e21b6c..9b250ab 100644
--- a/src/shared/syscalls.h
+++ b/src/shared/syscalls.h
@@ -43,16 +43,16 @@ int _syscall_fork(void);
handle_t _syscall_open(const char __user *path, int len);
int _syscall_mount(handle_t, const char __user *path, int len);
-int _syscall_read(handle_t, void __user *buf, int len, int offset);
-int _syscall_write(handle_t, const void __user *buf, int len, int offset);
+int _syscall_read(handle_t, void __user *buf, size_t len, int offset);
+int _syscall_write(handle_t, const void __user *buf, size_t len, int offset);
int _syscall_close(handle_t);
handle_t _syscall_fs_fork2(void);
struct fs_wait_response {
enum vfs_operation op;
- int len; // how much was put in *buf
- int capacity; // how much output can be accepted by the caller
+ size_t len; // how much was put in *buf
+ size_t capacity; // how much output can be accepted by the caller
int id; // file id (returned by the open handler, passed to other calls)
int offset;
};