mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: usercopy functions
This commit is contained in:
@@ -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
@@ -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;
|
||||
|
||||
@@ -51,6 +51,7 @@ typedef struct thread_t {
|
||||
int wakeupreason;
|
||||
bool shouldexit;
|
||||
void *kernelarg;
|
||||
context_t *usercopyctx;
|
||||
struct {
|
||||
spinlock_t lock;
|
||||
stack_t stack;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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,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, ©, sizeof(blockdesc_t));
|
||||
break;
|
||||
default:
|
||||
ret = ENOTTY;
|
||||
|
||||
+3
-4
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -6,5 +6,6 @@ syscallret_t syscall_gettid(context_t *) {
|
||||
.errno = 0,
|
||||
.ret = _cpu()->thread->tid
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user