From 8b4a2d50de67b746bcc472bd46c55d83eff668fc Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 18 Aug 2024 23:06:26 +0200 Subject: kernel: basic _sys_setxattr implementation --- src/kernel/syscalls.c | 36 ++++++++++++++++++++++++++++++++++++ src/kernel/vfs/request.c | 9 +++++++++ src/kernel/vfs/request.h | 2 +- 3 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src/kernel') diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 436000c..50ff589 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -548,6 +548,41 @@ ssize_t _sys_getxattr(hid_t hid, const char __user *name, void __user *buf, size return 0; } +ssize_t _sys_setxattr(hid_t hid, const char __user *name, const void __user *buf, size_t len, int flags) { + Handle *h = hs_get(proc_cur->hs, hid); + if (!h) { + SYSCALL_RETURN(-EBADF); + } + if (h->type != HANDLE_FILE || flags != 0) { + SYSCALL_RETURN(-ENOSYS); + } + if (!h->writeable) { + SYSCALL_RETURN(-EACCES); + } + char tmpbuf[XATTRNAME_MAX]; + size_t namelen = pcpy_from_str(proc_cur, tmpbuf, name, XATTRNAME_MAX); + if (namelen == 0) { + SYSCALL_RETURN(-EFAULT); + } + assert(namelen <= XATTRNAME_MAX); + assert(tmpbuf[namelen-1] == '\0'); + + char *namebuf = kmalloc(namelen, TagXattrName); + memcpy(namebuf, tmpbuf, namelen); + + vfsreq_dispatchcopy((VfsReq) { + .type = VFSOP_SETXATTR, + .backend = h->backend, + .id = h->file_id, + .caller = proc_cur, + .kin = namebuf, + .kinlen = namelen-1, + .uin = buf, + .uinlen = len, + }); + return 0; +} + long _sys_execbuf(void __user *ubuf, size_t len) { if (len == 0) SYSCALL_RETURN(0); static_assert(EXECBUF_MAX_LEN <= KMALLOC_MAX); @@ -607,6 +642,7 @@ long _syscall(long num, long a, long b, long c, long d, long e) { break; case _SYS_DUPLEX: _sys_duplex(a, b, c); break; case _SYS_INTR_RETURN: _sys_intr_return((userptr_t)a, b); break; case _SYS_GETXATTR: _sys_getxattr(a, (userptr_t)b, (userptr_t)c, d, e); + break; case _SYS_SETXATTR: _sys_setxattr(a, (userptr_t)b, (userptr_t)c, d, e); break; case _SYS_EXECBUF: _sys_execbuf((userptr_t)a, b); break; case _SYS_DEBUG_KLOG: _sys_debug_klog((userptr_t)a, b); break; diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 9c5b327..194ee49 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -174,6 +174,12 @@ vfsback_useraccept(VfsReq *req) space -= len+1; } if (req->uin) { + if (space < req->uinlen && req->type == VFSOP_SETXATTR) { + /* don't truncate xattr values */ + // TODO test + vfsreq_finish_short(req, -ERANGE); + return; + } if (req->kin) { /* save the address of the "second buffer" in id2, * which should be free */ @@ -181,6 +187,9 @@ vfsback_useraccept(VfsReq *req) res.id2 = buf; } + /* intentionally overriding the prior len */ + assert(len == 0 || req->type == VFSOP_SETXATTR); + len = min(req->uinlen, space); len = pcpy_bi(handler, buf, req->caller, req->uin, len); } diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index 484fdd7..fa62b35 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -45,7 +45,7 @@ struct VfsReq { size_t kinlen; /* user inputs and outputs - just point to some buffer in the caller */ - char __user *uin; + const char __user *uin; size_t uinlen; char __user *out; size_t outlen; -- cgit v1.2.3