diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index cdd13880..78179f48 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -69,6 +69,10 @@ extern syscall_fsync extern syscall_fchdir extern syscall_getitimer extern syscall_setitimer +extern syscall_socketpair +extern syscall_getsockname +extern syscall_getpeername +extern syscall_chroot syscalltab: dq syscall_print dq syscall_mmap @@ -140,7 +144,11 @@ dq syscall_fsync dq syscall_fchdir dq syscall_setitimer dq syscall_getitimer -syscallcount equ 70 +dq syscall_socketpair +dq syscall_getsockname +dq syscall_getpeername +dq syscall_chroot +syscallcount equ 74 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index fb57a755..70b551f0 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -5,7 +5,7 @@ #ifdef SYSCALL_LOGGING -#define SYSCALL_COUNT 68 +#define SYSCALL_COUNT 74 #define LOGSTR(x) arch_e9_puts(x) static char *name[] = { @@ -78,7 +78,11 @@ static char *name[] = { "fsync", "fchdir", "getitimer", - "setitimer" + "setitimer", + "socketpair", + "getsockname", + "getpeername", + "chroot" }; static char *args[] = { @@ -152,6 +156,10 @@ static char *args[] = { "fd %d", // fchdir "which %d new %p old %p\n", // setitimer "which %d value %p\n", // getitimer + "domain %d type %d protocol %d", // socketpair + "fd %d addr %p addrlen %p", // getsockname + "fd %d addr %p addrlen %p", // getpeername + "path %s" // chroot }; #endif diff --git a/kernel-src/sys/syscalls/chroot.c b/kernel-src/sys/syscalls/chroot.c new file mode 100644 index 00000000..5cec4834 --- /dev/null +++ b/kernel-src/sys/syscalls/chroot.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +syscallret_t syscall_chroot(context_t *, const char *upath) { + syscallret_t ret = { + .ret = -1 + }; + + if (upath > (char *)USERSPACE_END) { + ret.errno = EFAULT; + return ret; + } + + // TODO safe string ops + char *path = alloc(strlen(upath) + 1); + strcpy(path, upath); + + vnode_t *ref = path[0] == '/' ? sched_getroot() : sched_getcwd(); + vnode_t *new = NULL; + + ret.errno = vfs_lookup(&new, ref, path, NULL, 0); + if (ret.errno) + goto cleanup; + + if (new->type != V_TYPE_DIR) { + ret.errno = ENOTDIR; + goto cleanup; + } + + sched_setroot(new); + ret.ret = 0; + + cleanup: + if (new) + VOP_RELEASE(new); + + free(path); + VOP_RELEASE(ref); + + return ret; +} diff --git a/kernel-src/sys/syscalls/getpeername.c b/kernel-src/sys/syscalls/getpeername.c new file mode 100644 index 00000000..cce07161 --- /dev/null +++ b/kernel-src/sys/syscalls/getpeername.c @@ -0,0 +1,42 @@ +#include +#include + +syscallret_t syscall_getpeername(context_t *, int fd, void *uaddr, int *addrlen) { + syscallret_t ret = { + .ret = -1 + }; + + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + goto cleanup; + } + + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + + sockaddr_t sockaddr; + socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); + + ret.errno = socket->ops->getpeername(socket, &sockaddr); + if (ret.errno) + goto cleanup; + + abisockaddr_t abisockaddr; + + ret.errno = sock_addrtoabiaddr(socket->type, &sockaddr, &abisockaddr); + if (ret.errno) + goto cleanup; + + memcpy(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t))); + *addrlen = sizeof(abisockaddr_t); + ret.ret = 0; + + cleanup: + if (file) + fd_release(file); + + return ret; +} diff --git a/kernel-src/sys/syscalls/getsockname.c b/kernel-src/sys/syscalls/getsockname.c new file mode 100644 index 00000000..6701c2c0 --- /dev/null +++ b/kernel-src/sys/syscalls/getsockname.c @@ -0,0 +1,42 @@ +#include +#include + +syscallret_t syscall_getsockname(context_t *, int fd, void *uaddr, int *addrlen) { + syscallret_t ret = { + .ret = -1 + }; + + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + goto cleanup; + } + + if (file->vnode->type != V_TYPE_SOCKET) { + ret.errno = ENOTSOCK; + goto cleanup; + } + + sockaddr_t sockaddr; + socket_t *socket = SOCKFS_SOCKET_FROM_NODE(file->vnode); + + ret.errno = socket->ops->getname(socket, &sockaddr); + if (ret.errno) + goto cleanup; + + abisockaddr_t abisockaddr; + + ret.errno = sock_addrtoabiaddr(socket->type, &sockaddr, &abisockaddr); + if (ret.errno) + goto cleanup; + + memcpy(uaddr, &abisockaddr, min(*addrlen, sizeof(abisockaddr_t))); + *addrlen = sizeof(abisockaddr_t); + ret.ret = 0; + + cleanup: + if (file) + fd_release(file); + + return ret; +} diff --git a/kernel-src/sys/syscalls/socketpair.c b/kernel-src/sys/syscalls/socketpair.c new file mode 100644 index 00000000..13bccd6e --- /dev/null +++ b/kernel-src/sys/syscalls/socketpair.c @@ -0,0 +1,82 @@ +#include +#include + +syscallret_t syscall_socketpair(context_t *, int domain, int type, int protocol) { + syscallret_t ret = { + .ret = -1 + }; + + // TODO flags could be OR in with type + // we will only support pairs of local sockets + if (domain != AF_LOCAL || type != SOCK_STREAM) { + ret.errno = EOPNOTSUPP; + return ret; + } + + vnode_t *node1 = NULL; + vnode_t *node2 = NULL; + int fd1, fd2; + file_t *file1 = NULL; + file_t *file2 = NULL; + socket_t *sock1 = NULL; + socket_t *sock2 = NULL; + + // create pair + ret.errno = localsock_pair(&sock1, &sock2); + if (ret.errno) + return ret; + + // create vnodes + ret.errno = sockfs_newsocket(&node1, sock1); + if (ret.errno) + goto error; + + ret.errno = sockfs_newsocket(&node2, sock2); + if (ret.errno) + goto error; + + // create fds + ret.errno = fd_new(0, &file1, &fd1); + if (ret.errno) + goto error; + + file1->vnode = node1; + file1->flags = FILE_WRITE | FILE_READ; + file1->offset = 0; + file1->mode = 0777; + + ret.errno = fd_new(0, &file2, &fd2); + if (ret.errno) + goto error; + + file2->vnode = node2; + file2->flags = FILE_WRITE | FILE_READ; + file2->offset = 0; + file2->mode = 0777; + + ret.errno = 0; + ret.ret = (uint64_t)fd1 | ((uint64_t)fd2 << 32); + + return ret; + error: + + if (file1) { + fd_release(file1); + fd_close(fd1); + } else if (node1) { + VOP_RELEASE(node1); + } else { + sock1->ops->destroy(sock1); + } + + if (file2) { + fd_release(file2); + fd_close(fd2); + } if (node2) { + VOP_RELEASE(node2); + } else { + sock1->ops->destroy(sock2); + } + + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index e0944814..3dfd6bd0 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -13,14 +13,15 @@ index eb7be7b..eb83b56 100644 #define IPPROTO_HOPOPTS 0 #define IPPROTO_ICMP 1 diff --git mlibc-clean/meson.build mlibc-workdir/meson.build -index 6db3421..aa22660 100644 +index 6db3421..40887ba 100644 --- mlibc-clean/meson.build +++ mlibc-workdir/meson.build -@@ -256,6 +256,12 @@ elif host_machine.system() == 'dripos' +@@ -256,6 +256,13 @@ elif host_machine.system() == 'dripos' rtld_include_dirs += include_directories('sysdeps/dripos/include') libc_include_dirs += include_directories('sysdeps/dripos/include') subdir('sysdeps/dripos') +elif host_machine.system() == 'astral' ++ disable_crypt_option = true + rtld_include_dirs += include_directories('sysdeps/astral/include') + libc_include_dirs += include_directories('sysdeps/astral/include') + internal_conf.set10('MLIBC_MAP_DSO_SEGMENTS', true) @@ -58,6 +59,20 @@ index 8defd0e..d6cb65b 100644 case ENOTTY: s = "Inappropriate ioctl for device (ENOTTY)"; break; case EOVERFLOW: s = "Value too large for defined datatype (EOVERFLOW)"; break; #if EOPNOTSUPP != ENOTSUP +diff --git mlibc-clean/options/crypt/generic/crypt-stubs.cpp mlibc-workdir/options/crypt/generic/crypt-stubs.cpp +index 65e0d23..95b060c 100644 +--- mlibc-clean/options/crypt/generic/crypt-stubs.cpp ++++ mlibc-workdir/options/crypt/generic/crypt-stubs.cpp +@@ -1,7 +1,8 @@ + #include + #include ++#include + +-char *crypt(const char *, const char *) { ++char *crypt(const char *passwd, const char *) { + __ensure(!"Not implemented"); + __builtin_unreachable(); + } diff --git mlibc-clean/options/glibc/generic/execinfo.cpp mlibc-workdir/options/glibc/generic/execinfo.cpp index 3474615..e034881 100644 --- mlibc-clean/options/glibc/generic/execinfo.cpp @@ -192,10 +207,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..31b763b +index 0000000..c025a3b --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,730 @@ +@@ -0,0 +1,789 @@ +#include +#include +#include @@ -209,6 +224,11 @@ index 0000000..31b763b +#include +#include + ++static int gid; ++static int egid; ++static int uid; ++static int euid; ++ +#ifndef MLIBC_BUILDING_RTLD +// (s)brk is emulated in the libc rather than being +// an actual system call. @@ -251,39 +271,93 @@ index 0000000..31b763b +namespace mlibc { + int sys_setuid(uid_t id) { + // TODO UNSTUB ++ uid = id; + return 0; + } + + int sys_setgid(gid_t id) { + // TODO UNSTUB ++ gid = id; + return 0; + } + + uid_t sys_getuid() { + // TODO UNSTUB -+ return 0; ++ return uid; + } + + gid_t sys_getgid() { + // TODO UNSTUB -+ return 0; ++ return gid; + } + + uid_t sys_geteuid() { + // TODO UNSTUB -+ return 0; ++ return euid; + } + + gid_t sys_getegid() { + // TODO UNSTUB ++ return egid; ++ } ++ ++ int sys_setgroups(size_t size, const gid_t *list) { ++ // TODO unstub ++ return 0; ++ } ++ ++ int sys_setresuid(uid_t _ruid, uid_t _euid, uid_t _suid) { ++ // TODO unstub ++ uid = _ruid; ++ euid = _euid; ++ return 0; ++ } ++ ++ int sys_setresgid(gid_t _rgid, gid_t _egid, gid_t _sgid) { ++ // TODO unstub ++ gid = _rgid; ++ egid = _egid; + return 0; + } + + int sys_getsockopt(int fd, int layer, int number, + void *__restrict buffer, socklen_t *__restrict size) { ++ // TODO unstub + mlibc::infoLogger() << "getsockopt: " << fd << " " << layer << " " << number << frg::endlog; + return 0; + } ++ ++ int sys_chroot(const char *path) { ++ long ret; ++ return syscall(SYSCALL_CHROOT, &ret, (uint64_t)path); ++ } ++ ++ int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { ++ long ret; ++ int len = max_addr_length; ++ long error = syscall(SYSCALL_GETPEERNAME, &ret, fd, (uint64_t)addr_ptr, (uint64_t)&len); ++ *actual_length = len; ++ return error; ++ } ++ ++ int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, socklen_t *actual_length) { ++ long ret; ++ int len = max_addr_length; ++ long error = syscall(SYSCALL_GETSOCKNAME, &ret, fd, (uint64_t)addr_ptr, (uint64_t)&len); ++ *actual_length = len; ++ return error; ++ } ++ ++ int sys_socketpair(int domain, int type_and_flags, int proto, int *fds) { ++ long ret = 0; ++ long err = syscall(SYSCALL_SOCKETPAIR, &ret, domain, type_and_flags, proto); ++ if (err) ++ return err; ++ ++ fds[0] = ret & 0xffffffff; ++ fds[1] = (ret >> 32) & 0xffffffff; ++ return err; ++ } + + int sys_getitimer(int which, struct itimerval *curr_value) { + long ret; @@ -945,10 +1019,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..956a10b +index 0000000..d1d26ed --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,93 @@ +@@ -0,0 +1,97 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -1022,6 +1096,10 @@ index 0000000..956a10b +#define SYSCALL_FCHDIR 67 +#define SYSCALL_SETITIMER 68 +#define SYSCALL_GETITIMER 69 ++#define SYSCALL_SOCKETPAIR 70 ++#define SYSCALL_GETSOCKNAME 71 ++#define SYSCALL_GETPEERNAME 72 ++#define SYSCALL_CHROOT 73 + +#include +#include