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
+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;