diff --git a/kernel-src/sys/syscalls/setsockopt.c b/kernel-src/sys/syscalls/setsockopt.c index d52f63ed..8e4c2de3 100644 --- a/kernel-src/sys/syscalls/setsockopt.c +++ b/kernel-src/sys/syscalls/setsockopt.c @@ -2,6 +2,7 @@ #include #include #include +#include #include syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, void *val, size_t len) { @@ -9,28 +10,8 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi .ret = -1 }; - if (level != SOL_SOCKET) { - ret.errno = ENOPROTOOPT; - return ret; - } - - void *buffer = NULL; - if (val) { - buffer = alloc(len); - if (buffer == NULL) { - ret.errno = ENOMEM; - return ret; - } - ret.errno = usercopy_fromuser(buffer, val, len); - if (ret.errno) { - free(buffer); - return ret; - } - } - file_t *file = fd_get(fd); if (file == NULL) { - free(buffer); ret.errno = EBADF; return ret; } @@ -42,36 +23,44 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); - MUTEX_ACQUIRE(&socket->mutex); - switch (optname) { - case SO_BINDTODEVICE: { - if (val) { - socket->netdev = netdev_getdev(buffer); - ret.errno = socket->netdev ? 0 : ENODEV; - } else { - socket->netdev = NULL; + if (level == SOL_SOCKET) { + // handle some generic cases here + switch (optname) { + case SO_BINDTODEVICE: { + if (val) { + size_t size; + ret.errno = usercopy_strlen(val, &size); + if (ret.errno) + break; + + if (size > 32) { + ret.errno = EINVAL; + break; + } + + char name[size + 1]; + ret.errno = usercopy_fromuser(name, val, size); + if (ret.errno) + break; + name[size] = '\0'; + + socket->netdev = netdev_getdev(name); + ret.errno = socket->netdev ? 0 : ENODEV; + } else { + socket->netdev = NULL; + } + break; } - break; - } - case SO_BROADCAST: { - if (val == NULL) { - ret.errno = EFAULT; - } else { - socket->broadcast = *((int *)buffer); - ret.errno = 0; + case SO_BROADCAST: { + ret.errno = usercopy_fromuser(&socket->broadcast, val, sizeof(int)); + break; } - break; + default: + ret.errno = socket->ops->setopt ? socket->ops->setopt(socket, level, optname, val, len, ¤t_thread()->proc->cred) : ENOPROTOOPT; } - case SO_KEEPALIVE: { - if (val == NULL) - ret.errno = EFAULT; - else - ret.errno = socket->ops->setopt ? socket->ops->setopt(socket, optname, buffer, len, ¤t_thread()->proc->cred) : ENOPROTOOPT; - break; - } - default: - ret.errno = ENOPROTOOPT; + } else { + ret.errno = socket->ops->setopt ? socket->ops->setopt(socket, level, optname, val, len, ¤t_thread()->proc->cred) : ENOPROTOOPT; } MUTEX_RELEASE(&socket->mutex); @@ -81,8 +70,5 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi fd_release(file); - if (val) - free(buffer); - return ret; }