From 446acde84c7f244792bf412996678254ee296356 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 18 Aug 2024 19:51:22 +0200 Subject: kernel/req: support combined kernel and user inputs prep work for setxattr --- src/kernel/vfs/request.c | 53 +++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 4e8a162..9c5b327 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -144,36 +144,51 @@ vfsback_useraccept(VfsReq *req) handler = backend->user.handler; assert(handler->state == PS_WAITS4REQUEST); + res.capacity = req->outlen; + res.id = req->id; + res.id2 = req->id2; + res.offset = req->offset; + res.flags = req->flags; + res.op = req->type; + // the pcpy calls aren't present in all kernel backends // it's a way to tell apart kernel and user backends apart // TODO check validity of memory regions somewhere else - assert(!(req->kin && req->uin)); - if (req->kin) { + if (req->kin || req->uin) { void __user *buf = handler->awaited_req.buf; - if (req->kinlen+1 <= handler->awaited_req.max_len) { + size_t space = handler->awaited_req.max_len; + len = 0; + if (req->kin) { + /* the +1 is for the NUL terminator, the length passed to userland + * doesn't include it. */ + if (space < req->kinlen+1) { + /* no space to fit the string, fail instead of truncating */ + // XXX this is an easy way to tell user fses apart from kernel fses + vfsreq_finish_short(req, -ENOENT); + return; + } len = req->kinlen; pcpy_to(handler, buf, req->kin, len+1); /* +1 for NUL */ - } else { - // XXX this is an easy way to tell user fses apart from kernel fses - vfsreq_finish_short(req, -ENOENT); - return; + buf += len+1; + space -= len+1; + } + if (req->uin) { + if (req->kin) { + /* save the address of the "second buffer" in id2, + * which should be free */ + assert(res.id2 == NULL); + res.id2 = buf; + } + + len = min(req->uinlen, space); + len = pcpy_bi(handler, buf, req->caller, req->uin, len); } - } else if (req->uin) { - void __user *buf = handler->awaited_req.buf; - len = min(req->uinlen, handler->awaited_req.max_len); - len = pcpy_bi(handler, buf, req->caller, req->uin, len); } else { + /* this is stupid but a bunch of old code depends on it */ len = req->outlen; } - - res.len = len; - res.capacity = req->outlen; - res.id = req->id; - res.id2 = req->id2; - res.offset = req->offset; - res.flags = req->flags; - res.op = req->type; + res.len = len; if (pcpy_to(handler, handler->awaited_req.res, &res, sizeof res) < sizeof(res)) { -- cgit v1.2.3