kernel: usercopy functions

This commit is contained in:
Matheus
2024-06-09 19:31:26 -03:00
parent 429f56aced
commit 50b4b45d00
53 changed files with 712 additions and 260 deletions
+18 -6
View File
@@ -263,6 +263,7 @@ static volatile struct limine_kernel_address_request kaddrreq = {
#define ERROR_FETCH 16
static void pfisr(isr_t *self, context_t *ctx) {
thread_t *thread = _cpu()->thread;
interrupt_set(true);
int vmmerror = 0;
if (ctx->error & ERROR_PRESENT)
@@ -275,18 +276,29 @@ static void pfisr(isr_t *self, context_t *ctx) {
vmmerror |= VMM_ACTION_EXEC;
if (vmm_pagefault((void *)ctx->cr2, ctx->cs != 8, vmmerror) == false) {
if (ARCH_CONTEXT_ISUSER(ctx))
signal_signalthread(_cpu()->thread, SIGSEGV, true);
else
if (thread->usercopyctx) {
memcpy(ctx, thread->usercopyctx, sizeof(context_t));
thread->usercopyctx = NULL;
CTX_RET(ctx) = EFAULT;
} else if (ARCH_CONTEXT_ISUSER(ctx)) {
signal_signalthread(thread, SIGSEGV, true);
} else {
_panic("Page Fault", ctx);
}
}
}
static void gpfisr(isr_t *self, context_t *ctx) {
if (ARCH_CONTEXT_ISUSER(ctx))
signal_signalthread(_cpu()->thread, SIGSEGV, true);
else
thread_t *thread = _cpu()->thread;
if (thread->usercopyctx) {
memcpy(ctx, thread->usercopyctx, sizeof(context_t));
thread->usercopyctx = NULL;
CTX_RET(ctx) = EFAULT;
} else if (ARCH_CONTEXT_ISUSER(ctx)) {
signal_signalthread(thread, SIGSEGV, true);
} else {
_panic("General Protection Fault", ctx);
}
}
void arch_mmu_init() {
+38 -30
View File
@@ -70,13 +70,16 @@ int sockfs_setattr(vnode_t *node, vattr_t *attr, int which, cred_t *cred) {
// arg can be in userspace
int sockfs_ioctl(vnode_t *node, unsigned long request, void *arg, int *result) {
switch (request) {
case SIOCSIFADDR:
{
ifreq_t *ifreq = arg;
netdev_t *netdev = netdev_getdev(ifreq->name);
case SIOCSIFADDR: {
ifreq_t ifreq;
int e = USERCOPY_POSSIBLY_FROM_USER(&ifreq, arg, sizeof(ifreq_t));
if (e)
return e;
netdev_t *netdev = netdev_getdev(ifreq.name);
if(netdev) {
sockaddr_t sockaddr;
int e = sock_convertaddress(&sockaddr, &ifreq->addr);
e = sock_convertaddress(&sockaddr, &ifreq.addr);
if (e)
return e;
netdev->ip = sockaddr.ipv4addr.addr;
@@ -85,50 +88,57 @@ int sockfs_ioctl(vnode_t *node, unsigned long request, void *arg, int *result) {
}
break;
}
case SIOCGIFHWADDR:
{
case SIOCGIFHWADDR: {
ifreq_t *ifreq = arg;
netdev_t *netdev = netdev_getdev(ifreq->name);
ifreq_t kifreq;
int e = USERCOPY_POSSIBLY_FROM_USER(&kifreq, arg, sizeof(ifreq_t));
if (e)
return e;
netdev_t *netdev = netdev_getdev(kifreq.name);
if (netdev) {
memcpy(ifreq->addr.addr, netdev->mac.address, sizeof(mac_t));
return 0;
return USERCOPY_POSSIBLY_TO_USER(ifreq->addr.addr, netdev->mac.address, sizeof(mac_t));
} else {
return ENODEV;
}
break;
}
case SIOCADDRT:
{
case SIOCADDRT: {
abirtentry_t abirtentry;
memcpy(&abirtentry, arg, sizeof(abirtentry_t));
abisockaddr_t abiaddr;
abisockaddr_t abigateway;
abisockaddr_t abimask;
memcpy(&abiaddr, (void *)&abirtentry.rt_dst, sizeof(abisockaddr_t));
memcpy(&abigateway, (void *)&abirtentry.rt_gateway, sizeof(abisockaddr_t));
memcpy(&abimask, (void *)&abirtentry.rt_genmask, sizeof(abisockaddr_t));
int e = USERCOPY_POSSIBLY_FROM_USER(&abirtentry, arg, sizeof(abirtentry_t));
if (e)
return e;
sockaddr_t addr;
sockaddr_t gateway;
sockaddr_t mask;
int e = sock_convertaddress(&addr, &abiaddr);
e = sock_convertaddress(&addr, &abirtentry.rt_dst);
if (e)
return e;
e = sock_convertaddress(&gateway, &abigateway);
e = sock_convertaddress(&gateway, &abirtentry.rt_gateway);
if (e)
return e;
e = sock_convertaddress(&mask, &abimask);
e = sock_convertaddress(&mask, &abirtentry.rt_genmask);
if (e)
return e;
char *dev = alloc(strlen(abirtentry.rt_dev) + 1);
size_t devlen;
e = USERCOPY_POSSIBLY_STRLEN_FROM_USER(abirtentry.rt_dev, &devlen);
if (e)
return e;
char *dev = alloc(devlen + 1);
if (dev == NULL)
return ENOMEM;
strcpy(dev, abirtentry.rt_dev);
e = USERCOPY_POSSIBLY_FROM_USER(dev, abirtentry.rt_dev, devlen);
if (e) {
free(dev);
return e;
}
netdev_t *netdev = netdev_getdev(dev);
if (netdev == NULL) {
@@ -141,15 +151,13 @@ int sockfs_ioctl(vnode_t *node, unsigned long request, void *arg, int *result) {
free(dev);
return e;
}
case FIONREAD:
{
case FIONREAD: {
socket_t *socket = SOCKFS_SOCKET_FROM_NODE(node);
int *count = arg;
if (socket->ops->datacount == NULL)
return ENOTTY;
*count = socket->ops->datacount(socket);
return 0;
int count = socket->ops->datacount(socket);
return USERCOPY_POSSIBLY_TO_USER(arg, &count, sizeof(int));
}
default:
return ENOTTY;
+1
View File
@@ -51,6 +51,7 @@ typedef struct thread_t {
int wakeupreason;
bool shouldexit;
void *kernelarg;
context_t *usercopyctx;
struct {
spinlock_t lock;
stack_t stack;
+14 -3
View File
@@ -5,6 +5,7 @@
#include <kernel/vfs.h>
#include <mutex.h>
#include <kernel/poll.h>
#include <kernel/usercopy.h>
#define SOCKET_STATE_UNBOUND 0
#define SOCKET_STATE_BOUND 1
@@ -93,11 +94,16 @@ static inline int sock_addrtoabiaddr(int socktype, sockaddr_t *sockaddr, abisock
}
static inline int sock_copymsghdr(msghdr_t *khdr, msghdr_t *uhdr) {
memcpy(khdr, uhdr, sizeof(msghdr_t));
if (usercopy_fromuser(khdr, uhdr, sizeof(msghdr_t)))
return EFAULT;
iovec_t *iovectmp = alloc(sizeof(iovec_t) * khdr->iovcount);
if (iovectmp == NULL)
return ENOMEM;
memcpy(iovectmp, khdr->iov, sizeof(iovec_t) * khdr->iovcount);
if (usercopy_fromuser(iovectmp, khdr->iov, sizeof(iovec_t) * khdr->iovcount))
return EFAULT;
khdr->iov = iovectmp;
if (khdr->addr) {
@@ -106,7 +112,12 @@ static inline int sock_copymsghdr(msghdr_t *khdr, msghdr_t *uhdr) {
free(iovectmp);
return ENOMEM;
}
memcpy(addrtmp, khdr->addr, khdr->addrlen);
if (usercopy_fromuser(addrtmp, khdr->addr, khdr->addrlen)) {
free(iovectmp);
return EFAULT;
}
khdr->addr = addrtmp;
}
+1
View File
@@ -6,6 +6,7 @@
#include <kernel/vfs.h>
#include <kernel/file.h>
#include <kernel/scheduler.h>
#include <kernel/usercopy.h>
typedef struct {
uint64_t ret;
+29
View File
@@ -0,0 +1,29 @@
#ifndef _USERCOPY_H
#define _USERCOPY_H
#include <stddef.h>
#include <stdint.h>
#include <string.h>
//IS_USER_ADDRESS(a) is provided by arch/mmu.h
#include <arch/mmu.h>
static inline int _usercopy_memcpy_wrapper(void *dst, void *src, size_t size) {
memcpy(dst, src, size);
return 0;
}
static inline int _usercopy_strlen_wrapper(void *str, size_t *size) {
*size = strlen(str);
return 0;
}
#define USERCOPY_POSSIBLY_FROM_USER(kernel, user, size) (IS_USER_ADDRESS(user) ? usercopy_fromuser(kernel, user, size) : _usercopy_memcpy_wrapper(kernel, user, size))
#define USERCOPY_POSSIBLY_TO_USER(user, kernel, size) (IS_USER_ADDRESS(user) ? usercopy_touser(user, kernel, size) : _usercopy_memcpy_wrapper(user, kernel, size))
#define USERCOPY_POSSIBLY_STRLEN_FROM_USER(user, sizep) (IS_USER_ADDRESS(user) ? usercopy_strlen(user, sizep) : _usercopy_strlen_wrapper(user, sizep))
int usercopy_touser(void *user, void *kernel, size_t size);
int usercopy_fromuser(void *kernel, void *user, size_t size);
int usercopy_fromuseratomic32(uint32_t *user32, uint32_t *value);
int usercopy_strlen(const char *, size_t *size);
#endif
+1 -1
View File
@@ -77,7 +77,7 @@ typedef struct {
}
void arch_context_switch(context_t *context);
void arch_context_saveandcall(void (*fn)(context_t *context, void *argument), void *stack, void *argument);
int arch_context_saveandcall(void (*fn)(context_t *context, void *argument), void *stack, void *argument);
#include <string.h>
+2
View File
@@ -10,6 +10,8 @@
#define USERSPACE_START (void *)0x0000000000001000
#define USERSPACE_END (void *)0x0000800000000000
#define IS_USER_ADDRESS(a) ((void *)a < USERSPACE_END)
#define PAGE_SIZE 4096
#define ARCH_MMU_FLAGS_READ (uint64_t)1
#define ARCH_MMU_FLAGS_WRITE (uint64_t)2
+6 -4
View File
@@ -6,6 +6,7 @@
#include <kernel/devfs.h>
#include <string.h>
#include <kernel/vmm.h>
#include <kernel/usercopy.h>
#define DISK_READ(desc, buf, lba, size) (desc)->read(desc->private, buf, lba, size)
#define DISK_WRITE(desc, buf, lba, size) (desc)->write(desc->private, buf, lba, size)
@@ -140,10 +141,11 @@ static int ioctl(int minor, unsigned long request, void *arg, int *result) {
switch (request) {
case BLOCK_IOCTL_GETDESC:
*(blockdesc_t *)arg = *desc;
((blockdesc_t *)arg)->write = NULL;
((blockdesc_t *)arg)->read = NULL;
((blockdesc_t *)arg)->private = NULL;
blockdesc_t copy = *desc;
copy.write = NULL;
copy.read = NULL;
copy.private = NULL;
ret = USERCOPY_POSSIBLY_TO_USER(arg, &copy, sizeof(blockdesc_t));
break;
default:
ret = ENOTTY;
+3 -4
View File
@@ -6,6 +6,7 @@
#include <kernel/devfs.h>
#include <arch/cpu.h>
#include <kernel/pmm.h>
#include <kernel/usercopy.h>
typedef struct bitfield_t {
uint32_t offset;
@@ -177,11 +178,9 @@ static int ioctl(int minor, unsigned long request, void *arg, int *result){
case FBIOPUT_VSCREENINFO:
break;
case FBIOGET_FSCREENINFO:
*(fixinfo_t *)arg = fixinfos[minor];
break;
return USERCOPY_POSSIBLY_TO_USER(arg, &fixinfos[minor], sizeof(fixinfo_t));
case FBIOGET_VSCREENINFO:
*(varinfo_t *)arg = varinfos[minor];
break;
return USERCOPY_POSSIBLY_TO_USER(arg, &varinfos[minor], sizeof(varinfo_t));
default:
return ENOTTY;
}
+3 -4
View File
@@ -3,6 +3,7 @@
#include <spinlock.h>
#include <logging.h>
#include <kernel/alloc.h>
#include <kernel/usercopy.h>
#define PTY_BUFFER 4096
#define PTY_MAX 1024
@@ -198,12 +199,10 @@ static int ioctl(int minor, unsigned long request, void *_arg, int *result) {
switch (request) {
case TIOCGPTN: {
int *arg = _arg;
*arg = pty->minor;
break;
return USERCOPY_POSSIBLY_TO_USER(_arg, &pty->minor, sizeof(int));
}
default:
return tty_ioctl(pty->tty, request, _arg, result);
return tty_ioctl(pty->tty, request, _arg, result);
}
return 0;
+31 -25
View File
@@ -3,6 +3,7 @@
#include <logging.h>
#include <kernel/alloc.h>
#include <kernel/jobctl.h>
#include <kernel/usercopy.h>
#define TTY_MAX_COUNT 4096
#define CONTROLLING_TTY_MINOR TTY_MAX_COUNT
@@ -300,14 +301,13 @@ static int poll(int minor, polldata_t *data, int events) {
int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result) {
switch (req) {
case TIOCGWINSZ: {
winsize_t *w = arg;
*w = tty->winsize;
break;
}
case TIOCGWINSZ:
return USERCOPY_POSSIBLY_TO_USER(arg, &tty->winsize, sizeof(winsize_t));
case TIOCSWINSZ: {
winsize_t *w = arg;
tty->winsize = *w;
int e = USERCOPY_POSSIBLY_FROM_USER(&tty->winsize, arg, sizeof(winsize_t));
if (e)
return e;
proc_t *foreground = getforeground(tty);
if (foreground) {
jobctl_signal(foreground, SIGWINCH);
@@ -315,18 +315,22 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result) {
}
break;
}
case TCGETS: {
*(termios_t *)arg = tty->termios;
break;
}
case TCSETS: {
tty->termios = *(termios_t *)arg;
break;
}
case TCGETS:
return USERCOPY_POSSIBLY_TO_USER(arg, &tty->termios, sizeof(termios_t));
case TCSETS:
return USERCOPY_POSSIBLY_FROM_USER(&tty->termios, arg, sizeof(termios_t));
case TIOCSCTTY: {
int *steal = arg;
if (steal && *steal == 1)
printf("tty: stealing not supported\n");
if (arg) {
int steal;
int e = USERCOPY_POSSIBLY_FROM_USER(&steal, arg, sizeof(int));
if (e)
return e;
if (steal == 1) {
printf("tty: stealing not supported\n");
return EINVAL;
}
}
// set as controlling tty
jobctl_setctty(_cpu()->thread->proc, tty);
break;
@@ -336,14 +340,17 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result) {
if (foreground == NULL)
return ENOTTY;
int *pgrp = arg;
*pgrp = foreground->pid;
int pgrp = foreground->pid;
PROC_RELEASE(foreground);
break;
return USERCOPY_POSSIBLY_TO_USER(arg, &pgrp, sizeof(int));
}
case TIOCSPGRP: {
int *pgrpptr = arg;
int pgrp = *pgrpptr;
int pgrp;
int e = USERCOPY_POSSIBLY_FROM_USER(&pgrp, arg, sizeof(int));
if (e)
return e;
proc_t *proc = sched_getprocfrompid(pgrp);
if (proc == NULL)
return ESRCH;
@@ -354,8 +361,7 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result) {
}
case TTY_IOCTL_NAME: {
size_t len = min(strlen(tty->name) + 1, TTY_NAME_MAX);
memcpy(arg, tty->name, len);
break;
return USERCOPY_POSSIBLY_TO_USER(arg, tty->name, len);
}
default:
return ENOTTY;
+111
View File
@@ -0,0 +1,111 @@
#include <kernel/usercopy.h>
#include <arch/context.h>
#include <arch/cpu.h>
typedef struct {
void *dst;
void *src;
size_t size;
} memcpydesc_t;
typedef struct {
const char *str;
size_t *size;
} strlendesc_t;
typedef struct {
uint32_t *value;
uint32_t *address;
} atomic32desc_t;
static void memcpyinternal(context_t *ctx, void *arg) {
memcpydesc_t *desc = arg;
// this sets up the thread so that in the next invalid page fault, it will jump to
// this context with CTX_RET set to EFAULT
_cpu()->thread->usercopyctx = ctx;
memcpy(desc->dst, desc->src, desc->size);
// no errors!
CTX_RET(ctx) = 0;
_cpu()->thread->usercopyctx = NULL;
}
static void strleninternal(context_t *ctx, void *arg) {
strlendesc_t *desc = arg;
// this sets up the thread so that in the next invalid page fault, it will jump to
// this context with CTX_RET set to EFAULT
_cpu()->thread->usercopyctx = ctx;
*desc->size = strlen(desc->str);
// no errors!
CTX_RET(ctx) = 0;
_cpu()->thread->usercopyctx = NULL;
}
static void atomic32internal(context_t *ctx, void *arg) {
atomic32desc_t *desc = arg;
// this sets up the thread so that in the next invalid page fault, it will jump to
// this context with CTX_RET set to EFAULT
_cpu()->thread->usercopyctx = ctx;
__atomic_load(desc->address, desc->value, __ATOMIC_SEQ_CST);
// no errors!
CTX_RET(ctx) = 0;
_cpu()->thread->usercopyctx = NULL;
}
int usercopy_touser(void *user, void *kernel, size_t size) {
memcpydesc_t desc = {
.dst = user,
.src = kernel,
.size = size
};
if (IS_USER_ADDRESS(user) == false)
return EFAULT;
return arch_context_saveandcall(memcpyinternal, NULL, &desc);
}
int usercopy_fromuser(void *kernel, void *user, size_t size) {
memcpydesc_t desc = {
.dst = kernel,
.src = user,
.size = size
};
if (IS_USER_ADDRESS(user) == false)
return EFAULT;
return arch_context_saveandcall(memcpyinternal, NULL, &desc);
}
int usercopy_strlen(const char *str, size_t *size) {
strlendesc_t desc = {
.str = str,
.size = size
};
if (IS_USER_ADDRESS(str) == false)
return EFAULT;
return arch_context_saveandcall(strleninternal, NULL, &desc);
}
int usercopy_fromuseratomic32(uint32_t *user32, uint32_t *value) {
atomic32desc_t desc = {
.value = value,
.address = user32
};
if (IS_USER_ADDRESS(user32) == false)
return EFAULT;
return arch_context_saveandcall(atomic32internal, NULL, &desc);
}
+1
View File
@@ -3,6 +3,7 @@
#include <kernel/sock.h>
#include <errno.h>
// TODO handle abisockaddr
syscallret_t syscall_accept(context_t *, int oldfd, abisockaddr_t *abisockaddr, int *addrlen, int acceptflags) {
syscallret_t ret = {
.ret = -1
+3 -1
View File
@@ -35,7 +35,9 @@ syscallret_t syscall_bind(context_t *, int fd, void *uaddr, size_t addrlen) {
goto cleanup;
}
memcpy(addr, uaddr, addrlen);
ret.errno = usercopy_fromuser(addr, uaddr, addrlen);
if (ret.errno)
goto cleanup;
sockaddr_t sockaddr;
ret.errno = sock_convertaddress(&sockaddr, addr);
+14 -6
View File
@@ -4,19 +4,27 @@
#include <kernel/alloc.h>
#include <errno.h>
syscallret_t syscall_chdir(context_t *, const char *upath) {
syscallret_t syscall_chdir(context_t *, char *upath) {
syscallret_t ret = {
.ret = -1
};
if (upath > (char *)USERSPACE_END) {
ret.errno = EFAULT;
size_t pathlen = 0;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
// TODO safe string ops
char *path = alloc(strlen(upath) + 1);
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *ref = path[0] == '/' ? sched_getroot() : sched_getcwd();
vnode_t *new = NULL;
+12 -3
View File
@@ -16,18 +16,27 @@ static int dochmod(vnode_t *node, mode_t mode) {
return VOP_SETATTR(node, &attr, V_ATTR_MODE, cred);
}
syscallret_t syscall_fchmodat(context_t *, int dirfd, const char *upath, mode_t mode, int flags) {
syscallret_t syscall_fchmodat(context_t *, int dirfd, char *upath, mode_t mode, int flags) {
syscallret_t ret = {
.ret = -1
};
char *path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
file_t *file = NULL;
vnode_t *dirnode = NULL;
+14 -6
View File
@@ -4,19 +4,27 @@
#include <kernel/alloc.h>
#include <errno.h>
syscallret_t syscall_chroot(context_t *, const char *upath) {
syscallret_t syscall_chroot(context_t *, char *upath) {
syscallret_t ret = {
.ret = -1
};
if (upath > (char *)USERSPACE_END) {
ret.errno = EFAULT;
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
// TODO safe string ops
char *path = alloc(strlen(upath) + 1);
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *ref = path[0] == '/' ? sched_getroot() : sched_getcwd();
vnode_t *new = NULL;
+11 -13
View File
@@ -7,30 +7,28 @@
#define CLOCK_REALTIME 0
#define CLOCK_BOOTTIME 7
syscallret_t syscall_clockget(context_t *, int clockid, timespec_t *tp){
syscallret_t syscall_clockget(context_t *, int clockid, timespec_t *tp) {
syscallret_t ret = {
.ret = -1
};
if ((void *)tp > USERSPACE_END) {
ret.errno = EFAULT;
return ret;
}
switch (clockid) {
case CLOCK_REALTIME:
// TODO safe memcpy
*tp = timekeeper_time();
case CLOCK_REALTIME: {
timespec_t ts = timekeeper_time();
usercopy_touser(tp, &ts, sizeof(timespec_t));
ret.errno = 0;
break;
case CLOCK_BOOTTIME:
// TODO safe memcpy
*tp = timekeeper_timefromboot();
}
case CLOCK_BOOTTIME: {
timespec_t ts = timekeeper_timefromboot();
usercopy_touser(tp, &ts, sizeof(timespec_t));
ret.errno = 0;
break;
default:
}
default: {
ret.errno = EINVAL;
break;
}
}
ret.ret = ret.errno ? -1 : 0;
+3 -1
View File
@@ -36,7 +36,9 @@ syscallret_t syscall_connect(context_t *, int fd, abisockaddr_t *uaddr, size_t a
goto cleanup;
}
memcpy(addr, uaddr, addrlen);
ret.errno = usercopy_fromuser(addr, uaddr, addrlen);
if (ret.errno)
goto cleanup;
sockaddr_t sockaddr;
ret.errno = sock_convertaddress(&sockaddr, addr);
+78 -9
View File
@@ -29,13 +29,27 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
return ret;
}
// TODO user str ops
char *path = alloc(strlen(upath) + 1);
if (depth == 0 && (IS_USER_ADDRESS(upath) == false || IS_USER_ADDRESS(uargv) == false || IS_USER_ADDRESS(uenvp) == false)) {
ret.errno = EFAULT;
return ret;
}
size_t pathlen;
ret.errno = USERCOPY_POSSIBLY_STRLEN_FROM_USER(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
strcpy(path, upath);
ret.errno = USERCOPY_POSSIBLY_FROM_USER(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
size_t argsize = 0;
size_t envsize = 0;
@@ -49,8 +63,25 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
void *stack = NULL;
char shebang[SHEBANG_SIZE];
while (uargv[argsize++]);
while (uenvp[envsize++]);
for (;;) {
char *arg;
ret.errno = USERCOPY_POSSIBLY_FROM_USER(&arg, &uargv[argsize], sizeof(arg));
++argsize;
if (ret.errno)
goto error;
if (arg == NULL)
break;
}
for (;;) {
char *env;
ret.errno = USERCOPY_POSSIBLY_FROM_USER(&env, &uenvp[envsize], sizeof(env));
++envsize;
if (ret.errno)
goto error;
if (env == NULL)
break;
}
size_t argoffset = (sbold ? 1 : 0) + (sbarg ? 1 : 0);
argsize += argoffset;
@@ -84,22 +115,60 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char
argv[0] = tmp;
}
// copy arguments
for (int i = argoffset; i < argsize - 1; ++i) {
argv[i] = alloc(strlen(uargv[i - argoffset]) + 1);
void *uarg;
ret.errno = USERCOPY_POSSIBLY_FROM_USER(&uarg, &uargv[i - argoffset], sizeof(uarg));
if (ret.errno)
goto error;
if (IS_USER_ADDRESS(uarg) == false && depth == 0) {
ret.errno = EFAULT;
goto error;
}
size_t len;
ret.errno = USERCOPY_POSSIBLY_STRLEN_FROM_USER(uarg, &len);
if (ret.errno)
goto error;
argv[i] = alloc(len + 1);
if (argv[i] == NULL) {
ret.errno = ENOMEM;
goto error;
}
strcpy(argv[i], uargv[i - argoffset]);
ret.errno = USERCOPY_POSSIBLY_FROM_USER(argv[i], uarg, len);
if (ret.errno)
goto error;
}
// copy env
for (int i = 0; i < envsize - 1; ++i) {
envp[i] = alloc(strlen(uenvp[i]) + 1);
void *uenv;
ret.errno = USERCOPY_POSSIBLY_FROM_USER(&uenv, &uenvp[i], sizeof(uenv));
if (ret.errno)
goto error;
if (IS_USER_ADDRESS(uenv) == false && depth == 0) {
ret.errno = EFAULT;
goto error;
}
size_t len;
ret.errno = USERCOPY_POSSIBLY_STRLEN_FROM_USER(uenv, &len);
if (ret.errno)
goto error;
envp[i] = alloc(len + 1);
if (envp[i] == NULL) {
ret.errno = ENOMEM;
goto error;
}
strcpy(envp[i], uenvp[i]);
ret.errno = USERCOPY_POSSIBLY_FROM_USER(envp[i], uenv, len);
if (ret.errno)
goto error;
}
refnode = *path == '/' ? sched_getroot() : sched_getcwd();
+12 -4
View File
@@ -5,19 +5,27 @@
#include <arch/cpu.h>
#include <string.h>
syscallret_t syscall_faccessat(context_t *, int dirfd, const char *upath, int mode, int flags) {
syscallret_t syscall_faccessat(context_t *, int dirfd, char *upath, int mode, int flags) {
syscallret_t ret = {
.ret = -1
};
char *path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *dirnode = NULL;
file_t *file = NULL;
+9 -3
View File
@@ -2,7 +2,7 @@
#include <kernel/alloc.h>
#include <kernel/vfs.h>
syscallret_t syscall_fchownat(context_t *, int fd, const char *upath, uid_t owner, gid_t group, int flags) {
syscallret_t syscall_fchownat(context_t *, int fd, char *upath, uid_t owner, gid_t group, int flags) {
syscallret_t ret = {
.ret = -1
};
@@ -11,7 +11,10 @@ syscallret_t syscall_fchownat(context_t *, int fd, const char *upath, uid_t owne
vnode_t *dirnode = NULL;
file_t *file = NULL;
char *path = NULL;
size_t pathlen = strlen(upath);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
if (pathlen == 0 && (flags & AT_EMPTY_PATH)) {
// chown is done on the file pointed to by fd
@@ -32,7 +35,10 @@ syscallret_t syscall_fchownat(context_t *, int fd, const char *upath, uid_t owne
goto cleanup;
}
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno)
goto cleanup;
ret.errno = dirfd_enter(path, fd, &file, &dirnode);
if (ret.errno)
goto cleanup;
+5 -2
View File
@@ -74,12 +74,14 @@ syscallret_t syscall_futex(context_t *, uint32_t *futexp, int op, uint32_t value
MUTEX_ACQUIRE(&futexmutex, false);
bool doleave = true;
uint32_t word;
__atomic_load(futexp, &word, __ATOMIC_RELAXED);
ret.errno = usercopy_fromuseratomic32(futexp, &word);
if (ret.errno)
goto cleanup;
uint32_t *physical = vmm_getphysical(futexp);
futex_t *futex = getfutex(physical);
bool doleave = true;
switch (op) {
case FUTEX_WAKE:
@@ -161,6 +163,7 @@ syscallret_t syscall_futex(context_t *, uint32_t *futexp, int op, uint32_t value
ret.errno = ENOSYS;
}
cleanup:
if (doleave)
poll_leave(&desc);
+5 -8
View File
@@ -9,11 +9,6 @@ syscallret_t syscall_getdents(context_t *, int dirfd, void *ubuffer, size_t read
.ret = -1
};
if (ubuffer > USERSPACE_END) {
ret.errno = EFAULT;
return ret;
}
size_t count = readmax / sizeof(dent_t);
if (count == 0) {
@@ -46,11 +41,13 @@ syscallret_t syscall_getdents(context_t *, int dirfd, void *ubuffer, size_t read
goto cleanup;
fd->offset = offset + ret.ret;
ret.ret *= sizeof(dent_t);
// TODO safe memcpy
memcpy(ubuffer, buffer, ret.ret);
ret.errno = usercopy_touser(ubuffer, buffer, ret.ret);
if (ret.errno) {
ret.ret = -1;
goto cleanup;
}
cleanup:
free(buffer);
+7 -1
View File
@@ -6,6 +6,9 @@ syscallret_t syscall_getpeername(context_t *, int fd, void *uaddr, int *addrlen)
.ret = -1
};
ret.errno = ENOSYS;
return ret;
file_t *file = fd_get(fd);
if (file == NULL) {
ret.errno = EBADF;
@@ -30,7 +33,10 @@ syscallret_t syscall_getpeername(context_t *, int fd, void *uaddr, int *addrlen)
if (ret.errno)
goto cleanup;
memcpy(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t)));
ret.errno = usercopy_touser(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t)));
if (ret.errno)
goto cleanup;
*addrlen = sizeof(abisockaddr_t);
ret.ret = 0;
+4 -1
View File
@@ -30,7 +30,10 @@ syscallret_t syscall_getsockname(context_t *, int fd, void *uaddr, int *addrlen)
if (ret.errno)
goto cleanup;
memcpy(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t)));
ret.errno = usercopy_touser(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t)));
if (ret.errno)
goto cleanup;
*addrlen = sizeof(abisockaddr_t);
ret.ret = 0;
+1
View File
@@ -6,5 +6,6 @@ syscallret_t syscall_gettid(context_t *) {
.errno = 0,
.ret = _cpu()->thread->tid
};
return ret;
}
+8 -6
View File
@@ -31,29 +31,31 @@ syscallret_t syscall_hostname(context_t *, char *unew, size_t newsize, char *uol
char new[HOST_NAME_MAX];
char old[HOST_NAME_MAX + 1];
if (unew)
memcpy(new, unew, newsize);
if (unew) {
ret.errno = usercopy_fromuser(new, unew, newsize);
if (ret.errno)
return ret;
}
interrupt_set(false);
spinlock_acquire(&lock);
size_t copysize = min(oldsize - 1, bufferlen);
if (uold) {
size_t copysize = min(oldsize - 1, bufferlen);
memcpy(old, buffer, copysize);
old[copysize] = '\0';
}
if (unew) {
bufferlen = newsize;
strcpy(buffer, new);
memcpy(buffer, new, newsize);
}
spinlock_release(&lock);
interrupt_set(true);
if (uold)
strcpy(uold, old);
ret.errno = usercopy_touser(uold, old, copysize + 1);
ret.errno = 0;
ret.ret = 0;
+5
View File
@@ -7,6 +7,11 @@ syscallret_t syscall_ioctl(context_t *, int fd, unsigned long request, void *arg
.ret = -1
};
if (IS_USER_ADDRESS(arg) == false) {
ret.errno = EFAULT;
return ret;
}
file_t *file = fd_get(fd);
if (file == NULL) {
ret.errno = EBADF;
+17 -6
View File
@@ -2,27 +2,38 @@
#include <kernel/alloc.h>
syscallret_t syscall_linkat(context_t *, int olddirfd, const char *uoldpath, int newdirfd, const char *unewpath, int flags, int type) {
syscallret_t syscall_linkat(context_t *, int olddirfd, char *uoldpath, int newdirfd, char *unewpath, int flags, int type) {
syscallret_t ret = {
.ret = -1
};
char *oldpath = alloc(strlen(uoldpath) + 1);
size_t oldpathlen;
size_t newpathlen;
if (usercopy_strlen(uoldpath, &oldpathlen) || usercopy_strlen(unewpath, &newpathlen)) {
ret.errno = EFAULT;
return ret;
}
char *oldpath = alloc(oldpathlen + 1);
if (oldpath == NULL) {
ret.errno = ENOMEM;
return ret;
}
char *newpath = alloc(strlen(unewpath) + 1);
char *newpath = alloc(newpathlen + 1);
if (newpath == NULL) {
free(oldpath);
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(oldpath, uoldpath);
strcpy(newpath, unewpath);
if (usercopy_fromuser(oldpath, uoldpath, oldpathlen) || usercopy_fromuser(newpath, unewpath, newpathlen)) {
ret.errno = EFAULT;
free(newpath);
free(oldpath);
return ret;
}
vnode_t *olddirnode = NULL;
file_t *oldfile = NULL;
+12 -4
View File
@@ -5,19 +5,27 @@
#include <kernel/abi.h>
#include <arch/cpu.h>
syscallret_t syscall_mkdirat(context_t *, int dirfd, const char *upath, mode_t mode) {
syscallret_t syscall_mkdirat(context_t *, int dirfd, char *upath, mode_t mode) {
syscallret_t ret = {
.ret = -1
};
char *path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *dirnode = NULL;
file_t *file = NULL;
+41 -13
View File
@@ -4,24 +4,36 @@
#include <kernel/vfs.h>
#include <logging.h>
syscallret_t syscall_mount(context_t *context, const char *ubacking, const char *umountpoint, const char *ufs, unsigned long flags, void *data) {
static void freeptrs(void *a, void *b, void *c) {
if (a)
free(a);
if (b)
free (b);
if (c)
free (c);
}
syscallret_t syscall_mount(context_t *context, char *ubacking, char *umountpoint, char *ufs, unsigned long flags, void *data) {
syscallret_t ret = {
.ret = -1
};
__assert(flags == 0);
if ((void *)ubacking > USERSPACE_END || (void *)umountpoint > USERSPACE_END || (void *)ufs > USERSPACE_END) {
size_t mountpointlen, fslen;
if (usercopy_strlen(umountpoint, &mountpointlen) || usercopy_strlen(ufs, &fslen)) {
ret.errno = EFAULT;
return ret;
}
ret.errno = ENOMEM;
char *mountpoint = alloc(strlen(umountpoint) + 1);
if (mountpoint == NULL) {
char *mountpoint = alloc(mountpointlen + 1);
if (mountpoint == NULL)
return ret;
}
char *fs = alloc(strlen(ufs) + 1);
char *fs = alloc(fslen + 1);
if (fs == NULL) {
free(mountpoint);
return ret;
@@ -29,16 +41,32 @@ syscallret_t syscall_mount(context_t *context, const char *ubacking, const char
char *backing = NULL;
if (ubacking) {
backing = alloc(strlen(ubacking) + 1);
if (backing == NULL) {
free(mountpoint);
free(fs);
size_t backinglen;
ret.errno = usercopy_strlen(ubacking, &backinglen);
if (ret.errno) {
freeptrs(mountpoint, fs, NULL);
return ret;
}
backing = alloc(backinglen + 1);
if (backing == NULL) {
freeptrs(mountpoint, fs, NULL);
return ret;
}
ret.errno = usercopy_fromuser(backing, ubacking, backinglen);
if (ret.errno) {
freeptrs(backing, mountpoint, fs);
return ret;
}
strcpy(backing, ubacking);
}
strcpy(fs, ufs);
strcpy(mountpoint, umountpoint);
if (usercopy_fromuser(fs, ufs, fslen) || usercopy_fromuser(mountpoint, umountpoint, mountpointlen)) {
ret.errno = EFAULT;
freeptrs(fs, mountpoint, backing);
return ret;
}
vnode_t *backingrefnode = NULL;
if (ubacking)
+12 -3
View File
@@ -5,7 +5,7 @@
#include <errno.h>
#include <logging.h>
syscallret_t syscall_openat(context_t *context, int dirfd, const char *path, int flags, mode_t mode) {
syscallret_t syscall_openat(context_t *context, int dirfd, char *path, int flags, mode_t mode) {
syscallret_t ret = {
.ret = -1,
.errno = -1
@@ -17,16 +17,25 @@ syscallret_t syscall_openat(context_t *context, int dirfd, const char *path, int
vnode_t *dirnode = NULL;
file_t *dirfile = NULL;
size_t pathsize = strlen(path); // TODO u_strlen
size_t pathsize;
ret.errno = usercopy_strlen(path, &pathsize);
char *pathbuf = alloc(pathsize + 1);
if (pathbuf == NULL) {
ret.errno = ENOMEM;
return ret;
}
strcpy(pathbuf, path); // TODO u_strcpy
ret.errno = usercopy_fromuser(pathbuf, path, pathsize);
if (ret.errno) {
free(pathbuf);
return ret;
}
ret.errno = dirfd_enter(pathbuf, dirfd, &dirfile, &dirnode);
if (ret.errno) {
free(pathbuf);
return ret;
}
retry_open:
file_t *newfile = NULL;
+7 -8
View File
@@ -16,11 +16,6 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms
.ret = -1
};
if ((void *)fds > USERSPACE_END) {
ret.errno = EFAULT;
return ret;
}
size_t fdsbuffsize = nfds * sizeof(pollfd_t);
pollfd_t *fdsbuff = alloc(fdsbuffsize);
if (fdsbuff == NULL) {
@@ -28,7 +23,11 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms
return ret;
}
memcpy(fdsbuff, fds, fdsbuffsize);
ret.errno = usercopy_fromuser(fdsbuff, fds, fdsbuffsize);
if (ret.errno) {
free(fdsbuff);
return ret;
}
// we need to keep holding the files so another thread doesn't close them and break everything
file_t **filebuff = alloc(sizeof(file_t *) * nfds);
@@ -80,7 +79,7 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms
}
}
memcpy(fds, fdsbuff, fdsbuffsize);
ret.errno = usercopy_touser(fds, fdsbuff, fdsbuffsize);
poll_leave(&desc);
poll_destroydesc(&desc);
@@ -91,7 +90,7 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms
fd_release(filebuff[i]);
}
ret.ret = eventcount;
ret.ret = ret.errno ? -1 : eventcount;
cleanup:
if (filebuff)
+2 -6
View File
@@ -36,12 +36,8 @@ syscallret_t syscall_read(context_t *context, int fd, void *buffer, size_t size)
goto cleanup;
file->offset = offset + bytesread;
ret.ret = bytesread;
ret.errno = 0;
// TODO safe memcpy
memcpy(buffer, kernelbuff, bytesread);
ret.errno = usercopy_touser(buffer, kernelbuff, bytesread);
ret.ret = ret.errno ? -1 : bytesread;
cleanup:
if (file)
fd_release(file);
+14 -6
View File
@@ -4,18 +4,27 @@
#include <kernel/alloc.h>
#include <arch/cpu.h>
syscallret_t syscall_readlinkat(context_t *, int dirfd, const char *upath, char *ubuffer, size_t ubuffersize) {
syscallret_t syscall_readlinkat(context_t *, int dirfd, char *upath, char *ubuffer, size_t ubuffersize) {
syscallret_t ret = {
.ret = -1
};
char *path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
file_t *file = NULL;
vnode_t *dirnode = NULL;
@@ -36,9 +45,8 @@ syscallret_t syscall_readlinkat(context_t *, int dirfd, const char *upath, char
size_t bufferlen = strlen(buffer);
size_t copylen = bufferlen > ubuffersize ? ubuffersize : bufferlen;
memcpy(ubuffer, buffer, copylen);
ret.ret = copylen;
ret.errno = usercopy_touser(ubuffer, buffer, copylen);
ret.ret = ret.errno ? -1 : copylen;
cleanup:
+8 -3
View File
@@ -48,14 +48,19 @@ syscallret_t syscall_recvmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
uintmax_t iovoffset = 0;
for (int i = 0; i < msghdr.iovcount; ++i) {
memcpy(msghdr.iov[i].addr, (void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].len);
ret.errno = usercopy_touser(msghdr.iov[i].addr, (void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].len);
if (ret.errno)
goto cleanup;
iovoffset += msghdr.iov[i].len;
}
if (umsghdr->addr) {
ret.errno = sock_addrtoabiaddr(socket->type, &sockaddr, umsghdr->addr);
if (msghdr.addr) {
abisockaddr_t abisockaddr;
ret.errno = sock_addrtoabiaddr(socket->type, &sockaddr, &abisockaddr);
if (ret.errno)
goto cleanup;
ret.errno = usercopy_touser(msghdr.addr, &abisockaddr, min(sizeof(abisockaddr), msghdr.addrlen));
}
cleanup:
+17 -8
View File
@@ -3,31 +3,40 @@
#include <string.h>
#include <logging.h>
syscallret_t syscall_renameat(context_t *context, int olddirfd, const char *uoldpath, int newdirfd, const char *unewpath, unsigned int flags) {
syscallret_t syscall_renameat(context_t *context, int olddirfd, char *uoldpath, int newdirfd, char *unewpath, unsigned int flags) {
syscallret_t ret = {
.ret = -1
};
__assert(flags == 0);
size_t oldpathlen;
size_t newpathlen;
if (usercopy_strlen(uoldpath, &oldpathlen) || usercopy_strlen(unewpath, &newpathlen)) {
ret.errno = EFAULT;
return ret;
}
char *oldcomponent = NULL;
char *newcomponent = NULL;
char *oldpath = alloc(strlen(uoldpath) + 1);
char *oldpath = alloc(oldpathlen + 1);
if (oldpath == NULL) {
ret.errno = ENOMEM;
return ret;
}
char *newpath = alloc(strlen(unewpath) + 1);
char *newpath = alloc(newpathlen + 1);
if (newpath == NULL) {
free(oldpath);
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(oldpath, uoldpath);
strcpy(newpath, unewpath);
if (usercopy_fromuser(oldpath, uoldpath, oldpathlen) || usercopy_fromuser(newpath, unewpath, newpathlen)) {
ret.errno = EFAULT;
return ret;
}
vnode_t *olddirnode = NULL;
file_t *oldfile = NULL;
@@ -45,8 +54,8 @@ syscallret_t syscall_renameat(context_t *context, int olddirfd, const char *uold
if (ret.errno)
goto cleanup;
oldcomponent = alloc(strlen(oldpath));
newcomponent = alloc(strlen(newpath));
oldcomponent = alloc(strlen(oldpath) + 1);
newcomponent = alloc(strlen(newpath) + 1);
if (oldcomponent == NULL && newcomponent == NULL)
goto cleanup;
+6 -2
View File
@@ -5,8 +5,9 @@
#include <kernel/net.h>
#include <kernel/alloc.h>
// TODO nosignal
syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags) {
__assert(flags == 0);
//__assert(flags == 0);
syscallret_t ret;
msghdr_t msghdr;
@@ -25,7 +26,10 @@ syscallret_t syscall_sendmsg(context_t *, int fd, msghdr_t *umsghdr, int flags)
uintmax_t iovoffset = 0;
for (int i = 0; i < msghdr.iovcount; ++i) {
memcpy((void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].addr, msghdr.iov[i].len);
ret.errno = usercopy_fromuser((void *)((uintptr_t)buffer + iovoffset), msghdr.iov[i].addr, msghdr.iov[i].len);
if (ret.errno)
goto cleanup;
iovoffset += msghdr.iov[i].len;
}
+18 -8
View File
@@ -45,11 +45,14 @@ syscallret_t syscall_getitimer(context_t *context, int which, itimerval_t *value
MUTEX_RELEASE(&_cpu()->thread->proc->timer.mutex);
value->interval.s = oldrepeat / 1000000;
value->interval.us = oldrepeat % 1000000;
value->value.s = oldremaining / 1000000;
value->value.us = oldremaining % 1000000;
ret.errno = 0;
itimerval_t tmp;
tmp.interval.s = oldrepeat / 1000000;
tmp.interval.us = oldrepeat % 1000000;
tmp.value.s = oldremaining / 1000000;
tmp.value.us = oldremaining % 1000000;
ret.errno = usercopy_touser(value, &tmp, sizeof(tmp));
ret.ret = ret.errno ? -1 : 0;
return ret;
}
@@ -67,8 +70,11 @@ syscallret_t syscall_setitimer(context_t *context, int which, itimerval_t *unew,
}
itimerval_t val = {0};
if (unew)
val = *unew;
if (unew) {
ret.errno = usercopy_fromuser(&val, unew, sizeof(val));
if (ret.errno)
return ret;
}
MUTEX_ACQUIRE(&_cpu()->thread->proc->timer.mutex, false);
uintmax_t oldremaining, oldrepeat;
@@ -84,13 +90,17 @@ syscallret_t syscall_setitimer(context_t *context, int which, itimerval_t *unew,
MUTEX_RELEASE(&_cpu()->thread->proc->timer.mutex);
ret.errno = 0;
if (uold) {
itimerval_t tmp;
uold->interval.s = oldrepeat / 1000000;
uold->interval.us = oldrepeat % 1000000;
uold->value.s = oldremaining / 1000000;
uold->value.us = oldremaining % 1000000;
ret.errno = usercopy_touser(uold, &tmp, sizeof(tmp));
}
ret.errno = 0;
ret.ret = ret.errno ? -1 : 0;
return ret;
}
+6 -2
View File
@@ -21,7 +21,11 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
ret.errno = ENOMEM;
return ret;
}
memcpy(buffer, val, len);
ret.errno = usercopy_fromuser(buffer, val, len);
if (ret.errno) {
free(buffer);
return ret;
}
}
file_t *file = fd_get(fd);
@@ -43,7 +47,7 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi
switch (optname) {
case SO_BINDTODEVICE: {
if (val) {
socket->netdev = netdev_getdev(val);
socket->netdev = netdev_getdev(buffer);
ret.errno = socket->netdev ? 0 : ENODEV;
} else {
socket->netdev = NULL;
+12 -4
View File
@@ -14,14 +14,22 @@ syscallret_t syscall_sigaction(context_t *, int sig, sigaction_t *new, sigaction
sigaction_t newtmp, oldtmp;
if (new) {
newtmp = *new;
__assert(newtmp.flags & SA_RESTORER);
ret.errno = usercopy_fromuser(&newtmp, new, sizeof(sigaction_t));
if (ret.errno)
return ret;
if ((newtmp.flags & SA_RESTORER) == 0) {
ret.errno = EINVAL;
return ret;
}
}
signal_action(_cpu()->thread->proc, sig, new ? &newtmp : NULL, old ? &oldtmp : NULL);
if (old)
*old = oldtmp;
if (old && usercopy_touser(old, &oldtmp, sizeof(sigaction_t))) {
ret.errno = EFAULT;
return ret;
}
ret.errno = 0;
ret.ret = 0;
+8 -4
View File
@@ -7,13 +7,17 @@ syscallret_t syscall_sigaltstack(context_t *, stack_t *new, stack_t *old) {
};
stack_t newtmp, oldtmp;
if (new)
newtmp = *new;
if (new && usercopy_fromuser(&newtmp, new, sizeof(stack_t))) {
ret.errno = EFAULT;
return ret;
}
signal_altstack(_cpu()->thread, new ? &newtmp : NULL, old ? &oldtmp : NULL);
if (old)
*old = oldtmp;
if (old && usercopy_touser(old, &oldtmp, sizeof(stack_t))) {
ret.errno = EFAULT;
return ret;
}
ret.errno = 0;
ret.ret = 0;
+7 -3
View File
@@ -18,13 +18,17 @@ syscallret_t syscall_sigprocmask(context_t *, int how, sigset_t *set, sigset_t *
return ret;
}
new = *set;
ret.errno = usercopy_fromuser(&new, set, sizeof(sigset_t));
if (ret.errno)
return ret;
}
signal_changemask(_cpu()->thread, how, set ? &new : NULL, oldset ? &old : NULL);
if (oldset)
*oldset = old;
if (oldset && usercopy_touser(oldset, &old, sizeof(sigset_t))) {
ret.errno = EFAULT;
return ret;
}
ret.ret = 0;
ret.errno = 0;
+5 -2
View File
@@ -5,9 +5,12 @@
// this expects CTX_SP to be pointing to the signal frame
__attribute__((noreturn)) void syscall_sigreturn(context_t *context) {
// TODO check if the information is valid
sigframe_t sigframe;
memcpy(&sigframe, (void *)CTX_SP(context), sizeof(sigframe_t));
int error = usercopy_fromuser(&sigframe, (void *)CTX_SP(context), sizeof(sigframe_t));
if (error || ARCH_CONTEXT_ISUSER(&sigframe.context) == false) {
printf("syscall_sigreturn: bad return stack or bad return information\n");
sched_terminateprogram(SIGSEGV);
}
interrupt_set(false);
signal_altstack(_cpu()->thread, &sigframe.oldstack, NULL);
+9 -7
View File
@@ -14,12 +14,10 @@ syscallret_t syscall_nanosleep(context_t *, timespec_t *utime, timespec_t *remai
.ret = -1
};
if ((void *)utime > USERSPACE_END || (void *)remaining > USERSPACE_END) {
ret.errno = EFAULT;
timespec_t time;
ret.errno = usercopy_fromuser(&time, utime, sizeof(timespec_t));
if (ret.errno)
return ret;
}
timespec_t time = *utime;
if (time.ns > 999999999 || time.ns < 0) {
ret.errno = EINVAL;
@@ -34,8 +32,12 @@ syscallret_t syscall_nanosleep(context_t *, timespec_t *utime, timespec_t *remai
ret.errno = sched_yield();
if (ret.errno)
timer_remove(_cpu()->timer, &sleepentry);
if (ret.errno) {
uintmax_t remainingus = timer_remove(_cpu()->timer, &sleepentry);
time.ns = (remainingus % 1000000) * 1000;
time.s = (remainingus / 1000000);
ret.errno = usercopy_touser(remaining, &time, sizeof(timespec_t)) ? EFAULT : EINTR;
}
sched_targetcpu(NULL);
+16 -8
View File
@@ -44,9 +44,8 @@ syscallret_t syscall_fstat(context_t *ctx, int fd, stat_t *ustat) {
if (ret.errno)
goto cleanup;
// TODO safe memcpy
*ustat = buf;
ret.ret = 0;
ret.errno = usercopy_touser(ustat, &buf, sizeof(stat_t));
ret.ret = ret.errno ? -1 : 0;
cleanup:
fd_release(file);
@@ -58,12 +57,22 @@ syscallret_t syscall_fstatat(context_t *ctx, int dirfd, char *upath, stat_t *ust
.ret = -1
};
char *path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *dirnode = NULL;
file_t *file = NULL;
@@ -81,9 +90,8 @@ syscallret_t syscall_fstatat(context_t *ctx, int dirfd, char *upath, stat_t *ust
if (ret.errno)
goto cleanup;
// TODO safe memcpy
*ustat = buf;
ret.ret = 0;
ret.errno = usercopy_touser(ustat, &buf, sizeof(stat_t));
ret.ret = ret.errno ? -1 : 0;
cleanup:
if (node)
+10 -6
View File
@@ -11,6 +11,8 @@ typedef struct {
} utsname_t;
void hostname_get(char *buf);
static char *sysname = "Astral";
static char *release = "Astral";
syscallret_t syscall_uname(context_t *, utsname_t *utsname) {
syscallret_t ret = {0};
@@ -18,12 +20,14 @@ syscallret_t syscall_uname(context_t *, utsname_t *utsname) {
char hostname[HOST_NAME_MAX + 1];
hostname_get(hostname);
strcpy(utsname->sysname, "Astral");
strcpy(utsname->nodename, hostname);
strcpy(utsname->release, "Astral");
strcpy(utsname->version, BUILD_DATE);
strcpy(utsname->machine, BUILD_TARGET);
strcpy(utsname->domainname, hostname);
if (
usercopy_touser(utsname->sysname, sysname, strlen(sysname) + 1) ||
usercopy_touser(utsname->nodename, hostname, strlen(hostname) + 1) ||
usercopy_touser(utsname->release, release, strlen(release) + 1) ||
usercopy_touser(utsname->version, BUILD_DATE, strlen(BUILD_DATE) + 1) ||
usercopy_touser(utsname->machine, BUILD_TARGET, strlen(BUILD_TARGET) + 1) ||
usercopy_touser(utsname->domainname, hostname, strlen(hostname) + 1))
ret.errno = EFAULT;
return ret;
}
+13 -6
View File
@@ -5,25 +5,32 @@
#include <arch/cpu.h>
#include <string.h>
syscallret_t syscall_unlinkat(context_t *, int dirfd, const char *upath, int flags) {
syscallret_t syscall_unlinkat(context_t *, int dirfd, char *upath, int flags) {
syscallret_t ret = {
.ret = -1
};
size_t pathlen = strlen(upath) + 1;
char *path = alloc(pathlen);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
return ret;
char *path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
return ret;
}
// TODO safe strcopy
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno) {
free(path);
return ret;
}
vnode_t *dirnode = NULL;
file_t *file = NULL;
char *component = alloc(pathlen);
char *component = alloc(pathlen + 1);
if (component == NULL) {
ret.errno = ENOMEM;
goto cleanup;
+16 -4
View File
@@ -4,14 +4,18 @@
syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[2], int flags) {
syscallret_t ret = {
.ret = -1
.ret = -1,
.errno = 0
};
timespec_t ts[2];
if (uts == NULL)
ts[0] = ts[1] = timekeeper_time();
else
memcpy(ts, uts, sizeof(timespec_t) * 2);
ret.errno = usercopy_fromuser(ts, uts, sizeof(timespec_t) * 2);
if (ret.errno)
return ret;
vnode_t *node = NULL;
vnode_t *dirnode = NULL;
@@ -31,13 +35,21 @@ syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[
fd_release(file);
} else {
// operation is done on the file pointed to by the path relative to fd
path = alloc(strlen(upath) + 1);
size_t pathlen;
ret.errno = usercopy_strlen(upath, &pathlen);
if (ret.errno)
goto cleanup;
path = alloc(pathlen + 1);
if (path == NULL) {
ret.errno = ENOMEM;
goto cleanup;
}
strcpy(path, upath);
ret.errno = usercopy_fromuser(path, upath, pathlen);
if (ret.errno)
goto cleanup;
ret.errno = dirfd_enter(path, fd, &file, &dirnode);
if (ret.errno)
goto cleanup;
+3 -4
View File
@@ -14,7 +14,6 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
.ret = -1
};
// TODO address check
__assert((options & ~KNOWN_FLAGS) == 0);
// TODO implement these
__assert(pid == -1 || pid > 0);
@@ -94,10 +93,11 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
proc->child = iterator->sibling;
}
// TODO memory safe operation
if (status) {
int statustmp = iterator->status;
*status = statustmp;
ret.errno = usercopy_touser(status, &statustmp, sizeof(statustmp));
} else {
ret.errno = 0;
}
MUTEX_RELEASE(&proc->mutex);
@@ -125,7 +125,6 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
}
ret.ret = iterator->pid;
ret.errno = 0;
__assert(iterator);
// process will no longer be referenced by the child list
+3 -2
View File
@@ -27,8 +27,9 @@ syscallret_t syscall_write(context_t *context, int fd, void *buffer, size_t size
goto cleanup;
}
// TODO safe memcpy
memcpy(kernelbuff, buffer, size);
ret.errno = usercopy_fromuser(kernelbuff, buffer, size);
if (ret.errno)
goto cleanup;
size_t byteswritten;
uintmax_t offset = file->offset;