Similar to the previous checks, I looked for places where the value returned
by the vm_* functions was not checked.
I am not entirely certain that I am handling the error correctly in
libdiskfs/io-map-cntl.c simply unlocking the mutex and exiting the function
in the second case might not be sufficient.
Also, in the previous patch, pager_read_page simply returned err, even
though
only EIO, EDQUOT, and ENOSPC are permitted return values. I think it would
be worth adding a comment noting this to prevent similar errors in the
future.
Thanks,
--
Mikhail Karpov
From 3ad1e3674c27f3bc0d422af8d023fe02c809689d Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Thu, 3 Sep 2026 11:26:56 +0700
Subject: [PATCH 2/2] Added checks for vm_* return value in several place
---
boot/userland-boot.c | 47 ++++++++++++++++++++++++++++-------------
defpager/defpager.c | 8 +++++--
fatfs/dir.c | 11 ++++++----
fatfs/inode.c | 3 +++
isofs/lookup.c | 16 ++++++++++----
libdiskfs/io-map-cntl.c | 24 ++++++++++++++++-----
tmpfs/node.c | 6 +++---
trans/streamio.c | 6 +++++-
8 files changed, 87 insertions(+), 34 deletions(-)
diff --git a/boot/userland-boot.c b/boot/userland-boot.c
index 1739eb9..48cafd4 100644
--- a/boot/userland-boot.c
+++ b/boot/userland-boot.c
@@ -223,13 +223,19 @@ load_image (task_t t,
ph->p_vaddr &= ~(ph->p_align - 1);
ph->p_memsz -= ph->p_vaddr;
- vm_allocate (t, (vm_address_t*)&ph->p_vaddr, ph->p_memsz, 0);
- vm_write (t, ph->p_vaddr, buf, bufsz);
+ err = vm_allocate (t, (vm_address_t*)&ph->p_vaddr,
+ ph->p_memsz, 0);
+ assert_backtrace (err == KERN_SUCCESS);
+
+ err = vm_write (t, ph->p_vaddr, buf, bufsz);
+ assert_backtrace (err == KERN_SUCCESS);
+
munmap ((caddr_t) buf, bufsz);
- vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
- ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
- ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
- ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
+ err = vm_protect (t, ph->p_vaddr, ph->p_memsz, 0,
+ ((ph->p_flags & PF_R) ? VM_PROT_READ : 0) |
+ ((ph->p_flags & PF_W) ? VM_PROT_WRITE : 0) |
+ ((ph->p_flags & PF_X) ? VM_PROT_EXECUTE : 0));
+ assert_backtrace (err == KERN_SUCCESS);
}
return hdr.e.e_entry;
}
@@ -252,17 +258,25 @@ load_image (task_t t,
lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
err = read (fd, buf, amount);
assert_backtrace (err == amount);
- vm_allocate (t, &base, rndamount, 0);
- vm_write (t, base, (vm_address_t) buf, rndamount);
+ err = vm_allocate (t, &base, rndamount, 0);
+ assert_backtrace (err == KERN_SUCCESS);
+
+ err = vm_write (t, base, (vm_address_t) buf, rndamount);
+ assert_backtrace (err == KERN_SUCCESS);
+
if (magic != OMAGIC)
- vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
- 0, VM_PROT_READ | VM_PROT_EXECUTE);
+ {
+ err = vm_protect (t, base, trunc_page (headercruft + hdr.a.a_text),
+ 0, VM_PROT_READ | VM_PROT_EXECUTE);
+ assert_backtrace (err == KERN_SUCCESS);
+ }
munmap ((caddr_t) buf, rndamount);
bssstart = base + hdr.a.a_text + hdr.a.a_data + headercruft;
bsspagestart = round_page (bssstart);
- vm_allocate (t, &bsspagestart,
- hdr.a.a_bss - (bsspagestart - bssstart), 0);
+ err = vm_allocate (t, &bsspagestart,
+ hdr.a.a_bss - (bsspagestart - bssstart), 0);
+ assert_backtrace (err == KERN_SUCCESS);
return hdr.a.a_entry;
}
@@ -313,7 +327,8 @@ boot_script_exec_cmd (void *hook,
arg_len += 5 * sizeof (intptr_t);
stack_end = VM_MAX_ADDRESS;
stack_start = VM_MAX_ADDRESS - 16 * 1024 * 1024;
- vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
+ err = vm_allocate (task, &stack_start, stack_end - stack_start, FALSE);
+ assert_backtrace (err == KERN_SUCCESS);
arg_pos = (void *) ((stack_end - arg_len) & ~(sizeof (intptr_t) - 1));
args = mmap (0, stack_end - trunc_page ((vm_offset_t) arg_pos),
PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
@@ -334,8 +349,10 @@ boot_script_exec_cmd (void *hook,
p = (void *) p + sizeof (char *);
memcpy (p, strings, stringlen);
memset (args, 0, (vm_offset_t)arg_pos & (vm_page_size - 1));
- vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
- stack_end - trunc_page ((vm_offset_t) arg_pos));
+ err = vm_write (task, trunc_page ((vm_offset_t) arg_pos), (vm_address_t) args,
+ stack_end - trunc_page ((vm_offset_t) arg_pos));
+ assert_backtrace (err == KERN_SUCCESS);
+
munmap ((caddr_t) args,
stack_end - trunc_page ((vm_offset_t) arg_pos));
diff --git a/defpager/defpager.c b/defpager/defpager.c
index 02589a2..e34aec9 100644
--- a/defpager/defpager.c
+++ b/defpager/defpager.c
@@ -56,6 +56,10 @@ expand_map (struct user_pager_info *p, vm_offset_t addr)
return 0;
}
+/* The user must define this function. For pager PAGER, read one
+ page from offset PAGE. Set *BUF to be the address of the page,
+ and set *WRITE_LOCK if the page must be provided read-only.
+ The only permissible error returns are EIO, EDQUOT, and ENOSPC. */
error_t
pager_read_page (struct user_pager_info *pager,
vm_offset_t page,
@@ -70,13 +74,13 @@ pager_read_page (struct user_pager_info *pager,
error_t err = expand_map (pager, page);
if (err)
- return err;
+ return EIO;
if (!pager->map[pfn])
{
err = vm_allocate (mach_task_self (), buf, vm_page_size, 1);
if (err)
- return err;
+ return EIO;
}
else
{
diff --git a/fatfs/dir.c b/fatfs/dir.c
index 0351552..1b7bfe0 100644
--- a/fatfs/dir.c
+++ b/fatfs/dir.c
@@ -955,10 +955,13 @@ diskfs_get_directs (struct node *dp,
{
vm_address_t newdata;
- vm_allocate (mach_task_self (), &newdata,
- (ouralloc
- ? (allocsize *= 2)
- : (allocsize = vm_page_size * 2)), 1);
+ err = vm_allocate (mach_task_self (), &newdata,
+ (ouralloc
+ ? (allocsize *= 2)
+ : (allocsize = vm_page_size * 2)), 1);
+ if (err)
+ return err;
+
memcpy ((void *) newdata, (void *) *data, datap - *data);
if (ouralloc)
diff --git a/fatfs/inode.c b/fatfs/inode.c
index cefcba4..7134714 100644
--- a/fatfs/inode.c
+++ b/fatfs/inode.c
@@ -190,6 +190,9 @@ diskfs_user_read_node (struct node *np, struct lookup_context *ctx)
err = vm_map (mach_task_self (),
&buf, buflen, 0, 1, memobj, 0, 0, prot, prot, 0);
mach_port_deallocate (mach_task_self (), memobj);
+ if (err)
+ return err;
+
our_buf = 1;
}
diff --git a/isofs/lookup.c b/isofs/lookup.c
index 51eabcf..f12c62d 100644
--- a/isofs/lookup.c
+++ b/isofs/lookup.c
@@ -345,10 +345,18 @@ diskfs_get_directs (struct node *dp,
{
vm_address_t newdata;
- vm_allocate (mach_task_self (), &newdata,
- (ouralloc
- ? (allocsize *= 2)
- : (allocsize = vm_page_size * 2)), 1);
+ err = vm_allocate (mach_task_self (), &newdata,
+ (ouralloc
+ ? (allocsize *= 2)
+ : (allocsize = vm_page_size * 2)), 1);
+ if (err)
+ {
+ if (ouralloc)
+ munmap (*data, allocsize);
+
+ return err;
+ }
+
memcpy ((void *) newdata, (void *) *data, datap - *data);
if (ouralloc)
diff --git a/libdiskfs/io-map-cntl.c b/libdiskfs/io-map-cntl.c
index 6432fa0..981681f 100644
--- a/libdiskfs/io-map-cntl.c
+++ b/libdiskfs/io-map-cntl.c
@@ -32,11 +32,25 @@ diskfs_S_io_map_cntl (struct protid *cred,
pthread_mutex_lock (&cred->po->np->lock);
if (!cred->mapped)
{
- default_pager_object_create (diskfs_default_pager, &cred->shared_object,
- __vm_page_size);
- vm_map (mach_task_self (), (vm_address_t *)&cred->mapped, vm_page_size,
- 0, 1, cred->shared_object, 0, 0,
- VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, 0);
+ error_t err = default_pager_object_create (diskfs_default_pager,
+ &cred->shared_object,
+ __vm_page_size);
+ if (err)
+ {
+ pthread_mutex_unlock (&cred->po->np->lock);
+ return err;
+ }
+
+ err = vm_map (mach_task_self (), (vm_address_t *)&cred->mapped,
+ vm_page_size, 0, 1, cred->shared_object, 0, 0,
+ VM_PROT_READ|VM_PROT_WRITE,
+ VM_PROT_READ|VM_PROT_WRITE, 0);
+ if (err)
+ {
+ pthread_mutex_unlock (&cred->po->np->lock);
+ return err;
+ }
+
cred->mapped->shared_page_magic = SHARED_PAGE_MAGIC;
cred->mapped->conch_status = USER_HAS_NOT_CONCH;
pthread_spin_init (&cred->mapped->lock, PTHREAD_PROCESS_PRIVATE);
diff --git a/tmpfs/node.c b/tmpfs/node.c
index 7689561..ff6c28e 100644
--- a/tmpfs/node.c
+++ b/tmpfs/node.c
@@ -557,9 +557,9 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
/* XXX we need to keep a reference to the object, or GNU Mach
will terminate it when we release the map. */
np->dn->u.reg.memref = 0;
- vm_map (mach_task_self (), &np->dn->u.reg.memref, 4096, 0, 1,
- np->dn->u.reg.memobj, 0, 0, VM_PROT_NONE, VM_PROT_NONE,
- VM_INHERIT_NONE);
+ err = vm_map (mach_task_self (), &np->dn->u.reg.memref, 4096, 0, 1,
+ np->dn->u.reg.memobj, 0, 0, VM_PROT_NONE, VM_PROT_NONE,
+ VM_INHERIT_NONE);
assert_perror_backtrace (err);
}
diff --git a/trans/streamio.c b/trans/streamio.c
index f7cd442..694da06 100644
--- a/trans/streamio.c
+++ b/trans/streamio.c
@@ -1046,7 +1046,11 @@ dev_read (size_t amount, void **buf, size_t *len, int nowait)
avail = buffer_size (input_buffer);
max = (amount < avail) ? amount : avail;
if (max > *len)
- vm_allocate (mach_task_self (), (vm_address_t *)buf, max, 1);
+ {
+ err = vm_allocate (mach_task_self (), (vm_address_t *)buf, max, 1);
+ if (err)
+ return err;
+ }
*len = buffer_read (input_buffer, *buf, max);
assert_backtrace (*len == max);
--
2.43.0