]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
hurd: Protect against servers returning bogus read/write lengths
authorSergey Bugaev <bugaevc@gmail.com>
Wed, 4 Dec 2024 11:29:15 +0000 (14:29 +0300)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Thu, 5 Dec 2024 07:49:35 +0000 (08:49 +0100)
There already was a branch checking for this case in _hurd_fd_read ()
when the data is returned out-of-line. Do the same for inline data, as
well as for _hurd_fd_write (). It's also not possible for the length to
be negative, since it's stored in an unsigned integer.

Not verifying the returned length can confuse the callers who assume
the returned length is always reasonable. This manifested as libzstd
test suite failing on writes to /dev/zero, even though the write () call
appeared to succeed. In fact, the zero store backing /dev/zero was
returning a larger written length than the size actually submitted to
it, which is a separate bug to be fixed on the Hurd side. With this
patch, EGRATUITOUS is now propagated to the caller.

Reported-by: Diego Nieto Cid <dnietoc@gmail.com>
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
Message-ID: <20241204112915.540032-1-bugaevc@gmail.com>

hurd/fd-read.c
hurd/fd-write.c

index 7ce5d5bde142e3c906fc428687435fae4b12ab28..e492c3288b97ffa4d022c002d3e2f609ac3110b7 100644 (file)
@@ -38,13 +38,15 @@ _hurd_fd_read (struct hurd_fd *fd, void *buf, size_t *nbytes, loff_t offset)
   if (err = HURD_FD_PORT_USE_CANCEL (fd, _hurd_ctty_input (port, ctty, readfd)))
     return err;
 
+  if (__glibc_unlikely (nread > *nbytes))      /* Sanity check for bogus server.  */
+    {
+      if (data != buf)
+       __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
+      return EGRATUITOUS;
+    }
+
   if (data != buf)
     {
-      if (nread > *nbytes)     /* Sanity check for bogus server.  */
-       {
-         __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
-         return EGRATUITOUS;
-       }
       memcpy (buf, data, nread);
       __vm_deallocate (__mach_task_self (), (vm_address_t) data, nread);
     }
index 797880756b4b740569daab8ce71110eed0fe095f..2f070c5c5a86df4862d6f5bfdce7d66645aa92a5 100644 (file)
@@ -34,9 +34,13 @@ _hurd_fd_write (struct hurd_fd *fd,
     }
 
   err = HURD_FD_PORT_USE_CANCEL (fd, _hurd_ctty_output (port, ctty, writefd));
+  if (err)
+    return err;
 
-  if (! err)
-    *nbytes = wrote;
+  if (__glibc_unlikely (wrote > *nbytes))      /* Sanity check for bogus server.  */
+    return EGRATUITOUS;
 
-  return err;
+  *nbytes = wrote;
+
+  return 0;
 }