From e4ebea27b2f339706da76a3e79cb63ea9ed97c38 Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Sat, 11 May 2024 20:41:00 +0200
Subject: kernel: fix null dereference when delegating an nonexistent handle

---
 src/cmd/tests/kernel/fs.c | 23 +++++++++++++++++++++++
 src/kernel/vfs/request.c  |  7 ++++---
 2 files changed, 27 insertions(+), 3 deletions(-)

(limited to 'src')

diff --git a/src/cmd/tests/kernel/fs.c b/src/cmd/tests/kernel/fs.c
index 449ed43..6d4f4f4 100644
--- a/src/cmd/tests/kernel/fs.c
+++ b/src/cmd/tests/kernel/fs.c
@@ -77,9 +77,32 @@ static void test_no_fs(void) {
 	test(_sys_fs_wait(buf, 256, &res) == -EPIPE);
 }
 
+/* Tries to delegate a nonexistent handle */
+static void test_bad_delegate(void) {
+	hid_t h = -1;
+	int ret = _sys_fork(FORK_NEWFS, &h);
+	test(0 <= ret);
+	if (ret == 0) {
+		struct ufs_request res;
+		for (;;) {
+			h = _sys_fs_wait(NULL, 0, &res);
+			_sys_close(0);
+			_sys_fs_respond(h, NULL, 0, FSR_DELEGATE);
+		}
+	} else {
+		test(0 <= h);
+		test(_sys_mount(h, "/", 1) == 0);
+		for (int i = 0; i < 4; i++) {
+			int ret = _sys_open("/", 1, 0);
+			test(ret < 0);
+		}
+	}
+}
+
 void r_k_fs(void) {
 	run_test(test_unfinished_req);
 	run_test(test_orphaned_fs);
 	run_test(test_fs_cleanup);
 	run_test(test_no_fs);
+	run_test(test_bad_delegate);
 }
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index 0c763b3..e3f0316 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -60,9 +60,10 @@ void vfsreq_finish(VfsReq *req, char __user *stored, long ret,
 			/* delegating - moving a handle to the caller */
 			assert(handler);
 			h = hs_take(handler->hs, ret);
-			// TODO!!! no null check
-			h->readable = h->readable && OPEN_READABLE(req->flags);
-			h->writeable = h->writeable && OPEN_WRITEABLE(req->flags);
+			if (h) {
+				h->readable = h->readable && OPEN_READABLE(req->flags);
+				h->writeable = h->writeable && OPEN_WRITEABLE(req->flags);
+			}
 		}
 
 		if (h) {
-- 
cgit v1.2.3