}
static int pipe_node_create(struct pipe_state* ps, int is_read_end, fs_node_t** out_node) {
- if (!ps || !out_node) return -1;
+ if (!ps || !out_node) return -EINVAL;
struct pipe_node* pn = (struct pipe_node*)kmalloc(sizeof(*pn));
- if (!pn) return -1;
+ if (!pn) return -ENOMEM;
memset(pn, 0, sizeof(*pn));
pn->ps = ps;
}
static int fd_alloc_from(int start_fd, struct file* f) {
- if (!current_process || !f) return -1;
+ if (!current_process || !f) return -EINVAL;
if (start_fd < 0) start_fd = 0;
- if (start_fd >= PROCESS_MAX_FILES) return -1;
+ if (start_fd >= PROCESS_MAX_FILES) return -EINVAL;
for (int fd = start_fd; fd < PROCESS_MAX_FILES; fd++) {
if (current_process->files[fd] == NULL) {
return fd;
}
}
- return -1;
+ return -EMFILE;
}
static int fd_alloc(struct file* f) {
- if (!current_process || !f) return -1;
+ if (!current_process || !f) return -EINVAL;
for (int fd = 3; fd < PROCESS_MAX_FILES; fd++) {
if (current_process->files[fd] == NULL) {
return fd;
}
}
- return -1;
+ return -EMFILE;
}
static struct file* fd_get(int fd) {
#include "uaccess.h"
+#include "errno.h"
+
#include <stdint.h>
#if defined(__i386__)
return 1;
}
+static int x86_user_page_writable_user(uintptr_t vaddr) {
+ volatile uint32_t* pd = (volatile uint32_t*)0xFFFFF000U;
+ volatile uint32_t* pt_base = (volatile uint32_t*)0xFFC00000U;
+
+ uint32_t pde = pd[vaddr >> 22];
+ if (!(pde & 0x1)) return 0;
+ if (!(pde & 0x4)) return 0;
+
+ volatile uint32_t* pt = pt_base + ((vaddr >> 22) << 10);
+ uint32_t pte = pt[(vaddr >> 12) & 0x3FF];
+ if (!(pte & 0x1)) return 0;
+ if (!(pte & 0x4)) return 0;
+ if (!(pte & 0x2)) return 0;
+ return 1;
+}
+
static int x86_user_page_present_and_user(uintptr_t vaddr) {
volatile uint32_t* pd = (volatile uint32_t*)0xFFFFF000U;
volatile uint32_t* pt_base = (volatile uint32_t*)0xFFC00000U;
}
return 1;
}
+
+static int x86_user_range_writable_user(uintptr_t uaddr, size_t len) {
+ if (!x86_user_range_basic_ok(uaddr, len)) return 0;
+ if (len == 0) return 1;
+
+ uintptr_t start = uaddr & ~(uintptr_t)0xFFF;
+ uintptr_t end = (uaddr + len - 1) & ~(uintptr_t)0xFFF;
+ for (uintptr_t va = start;; va += 0x1000) {
+ if (!x86_user_page_writable_user(va)) return 0;
+ if (va == end) break;
+ }
+ return 1;
+}
#endif
int user_range_ok(const void* user_ptr, size_t len) {
int copy_from_user(void* dst, const void* src_user, size_t len) {
if (len == 0) return 0;
- if (!user_range_ok(src_user, len)) return -1;
+ if (!user_range_ok(src_user, len)) return -EFAULT;
uintptr_t up = (uintptr_t)src_user;
for (size_t i = 0; i < len; i++) {
int copy_to_user(void* dst_user, const void* src, size_t len) {
if (len == 0) return 0;
- if (!user_range_ok(dst_user, len)) return -1;
+
+#if defined(__i386__)
+ if (!x86_user_range_writable_user((uintptr_t)dst_user, len)) return -EFAULT;
+#else
+ if (!user_range_ok(dst_user, len)) return -EFAULT;
+#endif
uintptr_t up = (uintptr_t)dst_user;
for (size_t i = 0; i < len; i++) {