Hello!

I was checking the libnetfs library code and found a place where the mmap
function's return value wasn't checked for MAP_FAILED, so I decided to check
all the other places in GNU/Hurd that also call this function. Here are all
the places I could find and their fixes.

Thanks,

--
Mikhail Karpov
From 08f2a968961d993b68ecd2857545e1c5bcd4f4d5 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Thu, 11 Jun 2026 19:15:13 +0700
Subject: [PATCH] Added checks for mmap return value in several places

---
 boot/boot.c                    | 39 ++++++++++++++++++++---
 boot/userland-boot.c           |  3 ++
 console/pager.c                | 12 ++++++--
 exec/exec.c                    | 15 +++++++++
 fatfs/dir.c                    |  7 ++++-
 fatfs/main.c                   |  2 ++
 isofs/lookup.c                 |  7 ++++-
 isofs/pager.c                  |  8 +++--
 libmachdev/trivfs_server.c     |  3 ++
 libnetfs/file-get-translator.c | 56 +++++++++++++++++++++++++++++++---
 libnetfs/io-read.c             |  9 +++++-
 lwip/pfinet-ops.c              | 10 ++++--
 lwip/socket-ops.c              | 10 ++++--
 nfs/ops.c                      | 12 +++++++-
 pfinet/socket-ops.c            | 11 +++++--
 pflocal/pf.c                   |  9 +++++-
 term/ptyio.c                   | 12 +++++++-
 term/users.c                   | 11 ++++++-
 trans/magic.c                  |  7 +++--
 19 files changed, 214 insertions(+), 29 deletions(-)

diff --git a/boot/boot.c b/boot/boot.c
index 70a82f06..b957a199 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -898,9 +898,23 @@ read_reply (void)
   pthread_spin_unlock (&queuelock);
 
   if (qr->type == DEV_READ)
-    buf = mmap (0, qr->amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      buf = mmap (0, qr->amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      if (buf == MAP_FAILED)
+	{
+	  pthread_spin_unlock (&readlock);
+	  return;
+        }
+    }
   else
-    buf = alloca (qr->amount);
+    {
+      buf = alloca (qr->amount);
+      if (!buf)
+	{
+	  pthread_spin_unlock (&readlock);
+	  return;
+	}
+    }
   amtread = read (0, buf, qr->amount);
 
   pthread_spin_unlock (&readlock);
@@ -1138,7 +1152,14 @@ ds_device_read (device_t device,
       ioctl (0, FIONREAD, &avail);
       if (avail)
 	{
-	  *data = mmap (0, bytes_wanted, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+	  void *new_data = mmap (0, bytes_wanted, PROT_READ|PROT_WRITE,
+				 MAP_ANON, 0, 0);
+	  if (new_data == MAP_FAILED)
+	    {
+	      unlock_readlock ();
+	      return errno;
+	    }
+	  *data = new_data;
 	  *datalen = read (0, *data, bytes_wanted);
 	  unlock_readlock ();
 	  return (*datalen == -1 ? D_IO_ERROR : D_SUCCESS);
@@ -1484,7 +1505,17 @@ S_io_read (mach_port_t object,
     {
       data_t orig_data = *data;
       if (amount > *datalen)
-	*data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+	{
+	  void *new_data = mmap (0, amount, PROT_READ|PROT_WRITE,
+				 MAP_ANON, 0, 0);
+	  if (new_data == MAP_FAILED)
+	    {
+	      unlock_readlock();
+	      return errno;
+	    }
+
+	  *data = new_data;
+        }
       *datalen = read (0, *data, amount);
       if (*datalen == -1 && *data != orig_data)
 	munmap (*data, amount);
diff --git a/boot/userland-boot.c b/boot/userland-boot.c
index 4bbfbbb6..1739eb91 100644
--- a/boot/userland-boot.c
+++ b/boot/userland-boot.c
@@ -212,6 +212,7 @@ load_image (task_t t,
 
 	    buf = (vm_address_t) mmap (0, bufsz,
 				       PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+	    assert_backtrace (buf != MAP_FAILED);
 
 	    lseek (fd, ph->p_offset, SEEK_SET);
 	    err = read (fd, (void *)(buf + offs), ph->p_filesz);
@@ -247,6 +248,7 @@ load_image (task_t t,
       amount = headercruft + hdr.a.a_text + hdr.a.a_data;
       rndamount = round_page (amount);
       buf = mmap (0, rndamount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      assert_backtrace (buf != MAP_FAILED);
       lseek (fd, sizeof hdr.a - headercruft, SEEK_SET);
       err = read (fd, buf, amount);
       assert_backtrace (err == amount);
@@ -315,6 +317,7 @@ boot_script_exec_cmd (void *hook,
   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);
+  assert_backtrace (args != MAP_FAILED);
   str_start = ((vm_address_t) arg_pos
 	       + (argc + 2) * sizeof (char *) + sizeof (intptr_t));
   p = args + ((vm_address_t) arg_pos & (vm_page_size - 1));
diff --git a/console/pager.c b/console/pager.c
index a18d4d13..83c981e9 100644
--- a/console/pager.c
+++ b/console/pager.c
@@ -68,10 +68,16 @@ pager_read_page (struct user_pager_info *upi, vm_offset_t page,
     {
       *buf = upi->memobj_pages[page / vm_page_size];
       upi->memobj_pages[page / vm_page_size] = (vm_address_t) NULL;
+
+      return 0;
     }
-  else
-    *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
-				MAP_ANON, 0, 0);
+
+  void *new_buf = mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
+                        MAP_ANON, 0, 0);
+  if (new_buf == MAP_FAILED)
+    return errno;
+
+  *buf = (vm_address_t) new_buf;
   return 0;
 }
 
diff --git a/exec/exec.c b/exec/exec.c
index 4d7bada6..c0fa86f6 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -1003,6 +1003,11 @@ do_exec (file_t file,
 	    new_envplen = sizeof (ld_origin_s) - 1 + pathlen + envplen;
 	    new_envp = mmap (0, new_envplen,
 			     PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+	    if (new_envp == MAP_FAILED)
+	      {
+		e.error = errno;
+		goto stdout;
+	      }
 
 	    memcpy (new_envp, ld_origin_s + 1, sizeof (ld_origin_s) - 2);
 	    memcpy (new_envp + sizeof (ld_origin_s) - 2, abspath, pathlen);
@@ -1044,6 +1049,11 @@ do_exec (file_t file,
 	    /* Allocate a new vector that is big enough.  */
 	    boot->intarray = mmap (0, INIT_INT_MAX * sizeof (int),
 				   PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+	    if (boot->intarray == MAP_FAILED)
+	      {
+		e.error = errno;
+		goto stdout;
+	      }
 	    memcpy (boot->intarray, intarray, nints * sizeof (int));
 	    intarray_dealloc = !intarray_copy;
 	  }
@@ -1069,6 +1079,11 @@ do_exec (file_t file,
     boot->nports = nports < INIT_PORT_MAX ? INIT_PORT_MAX : nports;
     boot->portarray = mmap (0, boot->nports * sizeof (mach_port_t),
 			    PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    if (boot->portarray == MAP_FAILED)
+      {
+	e.error = errno;
+	goto stdout;
+      }
     /* Start by copying the array as passed.  */
     for (i = 0; i < nports; ++i)
       boot->portarray[i] = portarray[i];
diff --git a/fatfs/dir.c b/fatfs/dir.c
index dbe243c6..03515528 100644
--- a/fatfs/dir.c
+++ b/fatfs/dir.c
@@ -854,7 +854,12 @@ diskfs_get_directs (struct node *dp,
   allocsize = bufsiz ? round_page (bufsiz) : vm_page_size * 4;
   if (allocsize > *datacnt)
     {
-      *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      void *new_data = mmap (0, allocsize, PROT_READ|PROT_WRITE,
+                             MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        return errno;
+
+      *data = new_data;
       ouralloc = 1;
     }
 
diff --git a/fatfs/main.c b/fatfs/main.c
index da6aa949..448e7e30 100644
--- a/fatfs/main.c
+++ b/fatfs/main.c
@@ -235,6 +235,8 @@ main (int argc, char **argv)
 
   zerocluster = (vm_address_t) mmap (0, bytes_per_cluster, PROT_READ|PROT_WRITE,
 				     MAP_ANON, 0, 0);
+  if (zerocluster == MAP_FAILED)
+    return errno;
 
   fetch_root ();
 
diff --git a/isofs/lookup.c b/isofs/lookup.c
index d9322fac..51eabcfb 100644
--- a/isofs/lookup.c
+++ b/isofs/lookup.c
@@ -244,7 +244,12 @@ diskfs_get_directs (struct node *dp,
   allocsize = bufsiz ? round_page (bufsiz) : vm_page_size * 4;
   if (allocsize > *datacnt)
     {
-      *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      void *new_data = mmap (0, allocsize, PROT_READ|PROT_WRITE,
+                             MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        return errno;
+
+      *data = new_data;
       ouralloc = 1;
     }
 
diff --git a/isofs/pager.c b/isofs/pager.c
index 7838bdfc..b42a5905 100644
--- a/isofs/pager.c
+++ b/isofs/pager.c
@@ -54,8 +54,12 @@ pager_read_page (struct user_pager_info *upi,
   
       if (page >= np->dn_stat.st_size)
 	{
-	  *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
-				      MAP_ANON, 0, 0);
+	  void *new_buf = mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
+				MAP_ANON, 0, 0);
+	  if (new_buf == MAP_FAILED)
+	    return errno;
+
+	  *buf = (vm_address_t) new_buf;
 	  return 0;
 	}
 
diff --git a/libmachdev/trivfs_server.c b/libmachdev/trivfs_server.c
index 2c905a63..92672490 100644
--- a/libmachdev/trivfs_server.c
+++ b/libmachdev/trivfs_server.c
@@ -294,6 +294,9 @@ trivfs_S_fsys_init (struct trivfs_control *fsys,
 
   portarray = mmap (0, INIT_PORT_MAX * sizeof *portarray,
                     PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+  if (portarray == MAP_FAILED)
+    return errno;
+
   for (i = 0; i < INIT_PORT_MAX; ++i)
     portarray[i] = MACH_PORT_NULL;
   portarray[INIT_PORT_PROC] = procserver;
diff --git a/libnetfs/file-get-translator.c b/libnetfs/file-get-translator.c
index 63c74c0b..61c1156e 100644
--- a/libnetfs/file-get-translator.c
+++ b/libnetfs/file-get-translator.c
@@ -55,7 +55,16 @@ netfs_S_file_get_translator (struct protid *user,
       if (!err)
 	{
 	  if (len > *translen)
-	    *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+            {
+              void *buf = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+              if (buf == MAP_FAILED)
+                {
+                  pthread_mutex_unlock (&np->lock);
+                  return errno;
+                }
+
+              *trans = buf;
+            }
 	  memcpy (*trans, string, len);
 	  *translen = len;
 	  free (string);
@@ -66,7 +75,16 @@ netfs_S_file_get_translator (struct protid *user,
       unsigned int len = sizeof _HURD_SYMLINK + np->nn_stat.st_size + 1;
 
       if (len  > *translen)
-	*trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+        {
+          void *buf = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+          if (buf == MAP_FAILED)
+            {
+              pthread_mutex_unlock (&np->lock);
+              return errno;
+            }
+
+          *trans = buf;
+        }
       memcpy (*trans, _HURD_SYMLINK, sizeof _HURD_SYMLINK);
 
       err = netfs_attempt_readlink (user->user, np,
@@ -98,7 +116,17 @@ netfs_S_file_get_translator (struct protid *user,
 	  buflen++;			/* terminating nul */
 
 	  if (buflen > *translen)
-	    *trans = mmap (0, buflen, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+            {
+              void *buf = mmap (0, buflen, PROT_READ|PROT_WRITE,
+                                MAP_ANON, 0, 0);
+              if (buf == MAP_FAILED)
+                {
+                  pthread_mutex_unlock (&np->lock);
+                  return errno;
+                }
+
+              *trans = buf;
+            }
 	  memcpy (*trans, buf, buflen);
 	  free (buf);
 	  *translen = buflen;
@@ -111,7 +139,16 @@ netfs_S_file_get_translator (struct protid *user,
 
       len = sizeof _HURD_FIFO;
       if (len > *translen)
-	*trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+        {
+          void *buf = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+          if (buf == MAP_FAILED)
+            {
+              pthread_mutex_unlock (&np->lock);
+              return errno;
+            }
+
+          *trans = buf;
+        }
       memcpy (*trans, _HURD_FIFO, sizeof _HURD_FIFO);
       *translen = len;
       err = 0;
@@ -122,7 +159,16 @@ netfs_S_file_get_translator (struct protid *user,
 
       len = sizeof _HURD_IFSOCK;
       if (len > *translen)
-        *trans = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+        {
+          void *buf = mmap (0, len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+          if (buf == MAP_FAILED)
+            {
+              pthread_mutex_unlock (&np->lock);
+              return errno;
+            }
+
+          *trans = buf;
+        }
       memcpy (*trans, _HURD_IFSOCK, sizeof _HURD_IFSOCK);
       *translen = len;
       err = 0;
diff --git a/libnetfs/io-read.c b/libnetfs/io-read.c
index 96b003b3..16abee56 100644
--- a/libnetfs/io-read.c
+++ b/libnetfs/io-read.c
@@ -50,8 +50,15 @@ netfs_S_io_read (struct protid *user,
 
   if (amount > data_size)
     {
+      void *new_data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+	{
+	  pthread_mutex_unlock (&node->lock);
+	  return errno;
+	}
+
       alloced = 1;
-      *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      *data = new_data;
     }
   data_size = amount;
 
diff --git a/lwip/pfinet-ops.c b/lwip/pfinet-ops.c
index 93373e51..633b9ab5 100644
--- a/lwip/pfinet-ops.c
+++ b/lwip/pfinet-ops.c
@@ -102,8 +102,14 @@ lwip_S_pfinet_siocgifconf (io_t port,
     {
       /* Possibly allocate a new buffer */
       if (*len < amount)
-	ifc.ifc_buf = (char *) mmap (0, amount, PROT_READ | PROT_WRITE,
-				     MAP_ANON, 0, 0);
+	{
+	  void *buf = mmap (0, amount, PROT_READ | PROT_WRITE,
+			    MAP_ANON, 0, 0);
+	  if (buf == MAP_FAILED)
+	    return ENOMEM;
+
+	  ifc.ifc_buf = buf;
+	}
       else
 	ifc.ifc_buf = *ifr;
 
diff --git a/lwip/socket-ops.c b/lwip/socket-ops.c
index 0d8eaee6..339aa7bc 100644
--- a/lwip/socket-ops.c
+++ b/lwip/socket-ops.c
@@ -287,8 +287,14 @@ lwip_S_socket_whatis_address (struct sock_addr * addr,
 
   *type = addr->address.sa.sa_family;
   if (*datalen < addr->address.sa.sa_len)
-    *data = mmap (0, addr->address.sa.sa_len,
-		  PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *buf = mmap (0, addr->address.sa.sa_len, PROT_READ | PROT_WRITE,
+                        MAP_ANON, 0, 0);
+      if (buf == MAP_FAILED)
+        return ENOMEM;
+
+      *data = buf;
+    }
   *datalen = addr->address.sa.sa_len;
   memcpy (*data, &addr->address.sa, addr->address.sa.sa_len);
 
diff --git a/nfs/ops.c b/nfs/ops.c
index 95e8b11c..affdd931 100644
--- a/nfs/ops.c
+++ b/nfs/ops.c
@@ -2022,7 +2022,17 @@ netfs_get_dirents (struct iouser *cred, struct node *np,
   else
     allocsize = round_page (bufsiz);
   if (allocsize > *datacnt)
-    *data = mmap (0, allocsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *new_data = mmap (0, allocsize, PROT_READ|PROT_WRITE,
+                             MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        {
+          free (buf);
+          return errno;
+        }
+
+      *data = new_data;
+    }
 
   /* Skip ahead to the correct entry. */
   bp = buf;
diff --git a/pfinet/socket-ops.c b/pfinet/socket-ops.c
index ce10682b..935c9ed6 100644
--- a/pfinet/socket-ops.c
+++ b/pfinet/socket-ops.c
@@ -345,8 +345,15 @@ S_socket_whatis_address (struct sock_addr *addr,
 
   *type = addr->address.sa_family;
   if (*datalen < addr->address.sa_len)
-    *data = mmap (0, addr->address.sa_len,
-		  PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *new_data = mmap (0, addr->address.sa_len, PROT_READ|PROT_WRITE,
+                             MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        return ENOMEM;
+
+      *data = new_data;
+    }
+
   *datalen = addr->address.sa_len;
   memcpy (*data, &addr->address, addr->address.sa_len);
 
diff --git a/pflocal/pf.c b/pflocal/pf.c
index 457ebfbd..d69cedc8 100644
--- a/pflocal/pf.c
+++ b/pflocal/pf.c
@@ -141,7 +141,14 @@ S_socket_whatis_address (struct addr *addr,
 
   *sockaddr_type = AF_LOCAL;
   if (*sockaddr_len < addr_len)
-    *sockaddr = mmap (0, addr_len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *buf = mmap (0, addr_len, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      if (buf == MAP_FAILED)
+        return errno;
+
+      *sockaddr = buf;
+    }
+
   ((struct sockaddr *) *sockaddr)->sa_len = addr_len;
   ((struct sockaddr *) *sockaddr)->sa_family = *sockaddr_type;
   ((struct sockaddr *) *sockaddr)->sa_data[0] = 0;
diff --git a/term/ptyio.c b/term/ptyio.c
index 73a99e24..2f3931eb 100644
--- a/term/ptyio.c
+++ b/term/ptyio.c
@@ -353,7 +353,17 @@ pty_io_read (struct trivfs_protid *cred,
   if (size > amount)
     size = amount;
   if (size > *datalen)
-    *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *new_data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        {
+          pthread_mutex_unlock (&global_lock);
+          return errno;
+        }
+
+      *data = new_data;
+    }
+
   *datalen = size;
 
   if (control_byte)
diff --git a/term/users.c b/term/users.c
index bb5a9e09..629534ff 100644
--- a/term/users.c
+++ b/term/users.c
@@ -721,7 +721,16 @@ trivfs_S_io_read (struct trivfs_protid *cred,
   max = (amount < avail) ? amount : avail;
 
   if (max > *datalen)
-    *data = mmap (0, max, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+    {
+      void *new_data = mmap (0, max, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+      if (new_data == MAP_FAILED)
+        {
+          pthread_mutex_unlock (&global_lock);
+          return errno;
+        }
+
+      *data = new_data;
+    }
 
   cancel = 0;
   cp = *data;
diff --git a/trans/magic.c b/trans/magic.c
index 7c809fbc..73fdaea3 100644
--- a/trans/magic.c
+++ b/trans/magic.c
@@ -424,9 +424,12 @@ parse_opt (int opt, char *arg, struct argp_state *state)
 			     & ~(__alignof (struct dirent) - 1));
 	      return (struct dirent *) ((char *) d + d->d_reclen);
 	    }
-	  struct dirent *d;
-	  m->dirbuf = mmap (0, getpagesize (), PROT_READ|PROT_WRITE,
+	  void *buf = mmap (0, getpagesize (), PROT_READ|PROT_WRITE,
 			    MAP_ANON, 0, 0);
+	  if (buf == MAP_FAILED)
+	    return errno;
+	  m->dirbuf = buf;
+	  struct dirent *d;
 	  d = add (m->dirbuf, ".");
 	  d = add (d, "..");
 	  m->dirbufsize = (char *) d - (char *) m->dirbuf;
-- 
2.43.0

Reply via email to