public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Adhemerval Zanella <azanella@sourceware.org>
To: glibc-cvs@sourceware.org
Subject: [glibc/azanella/master-posix_clock] Linux: Adjust gedents64 buffer size to int range [BZ #24740]
Date: Tue, 02 Jul 2019 17:25:00 -0000	[thread overview]
Message-ID: <20190702172507.2010.qmail@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a620bd7935c4b2dc94e472e62bd9a5c9434ea7b7

commit a620bd7935c4b2dc94e472e62bd9a5c9434ea7b7
Author: Florian Weimer <fweimer@redhat.com>
Date:   Thu Jun 27 15:08:40 2019 +0200

    Linux: Adjust gedents64 buffer size to int range [BZ #24740]
    
    The kernel interface uses type unsigned int, but there is an
    internal conversion to int, so INT_MAX is the correct limit.
    Part of the buffer will always be unused, but this is not a
    problem.  Such huge buffers do not occur in practice anyway.
    
    Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

Diff:
---
 ChangeLog                                        | 12 +++++++
 sysdeps/unix/sysv/linux/getdents64.c             |  5 +++
 sysdeps/unix/sysv/linux/mips/mips64/getdents64.c |  6 ++++
 sysdeps/unix/sysv/linux/tst-getdents64.c         | 44 ++++++++++++++++++++++++
 4 files changed, 67 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c10f372..306c942 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2019-06-27  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #24740]
+	* sysdeps/unix/sysv/linux/getdents64.c (__getdents64): Adjust
+	buffer size if necessary.
+	* sysdeps/unix/sysv/linux/mips/mips64/getdents64.c (__getdents64):
+	Likewise.
+	* sysdeps/unix/sysv/linux/tst-getdents64.c (large_buffer_check):
+	New function.
+	(large_buffer_checks): Likewise.
+	(do_test): Call large_buffer_checks.
+
 2019-06-26  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* sysdeps/i386/dl-lookupcfg.h: Moved to ...
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
index a6dd221..5e3ef99 100644
--- a/sysdeps/unix/sysv/linux/getdents64.c
+++ b/sysdeps/unix/sysv/linux/getdents64.c
@@ -19,11 +19,16 @@
 #include <string.h>
 #include <dirent.h>
 #include <errno.h>
+#include <limits.h>
 
 /* The kernel struct linux_dirent64 matches the 'struct dirent64' type.  */
 ssize_t
 __getdents64 (int fd, void *buf, size_t nbytes)
 {
+  /* The system call takes an unsigned int argument, and some length
+     checks in the kernel use an int type.  */
+  if (nbytes > INT_MAX)
+    nbytes = INT_MAX;
   return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
 }
 libc_hidden_def (__getdents64)
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
index 1e22fa4..8bf3abb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
+++ b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
@@ -23,12 +23,18 @@
 #include <sys/param.h>
 #include <unistd.h>
 #include <scratch_buffer.h>
+#include <limits.h>
 
 ssize_t
 __getdents64 (int fd, void *buf0, size_t nbytes)
 {
   char *buf = buf0;
 
+  /* The system call takes an unsigned int argument, and some length
+     checks in the kernel use an int type.  */
+  if (nbytes > INT_MAX)
+    nbytes = INT_MAX;
+
 #ifdef __NR_getdents64
   ssize_t ret = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
   if (ret != -1)
diff --git a/sysdeps/unix/sysv/linux/tst-getdents64.c b/sysdeps/unix/sysv/linux/tst-getdents64.c
index c1f7721..24e77e0 100644
--- a/sysdeps/unix/sysv/linux/tst-getdents64.c
+++ b/sysdeps/unix/sysv/linux/tst-getdents64.c
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -28,6 +29,47 @@
 #include <support/xunistd.h>
 #include <unistd.h>
 
+/* Called by large_buffer_checks below.  */
+static void
+large_buffer_check (int fd, char *large_buffer, size_t large_buffer_size)
+{
+  xlseek (fd, 0, SEEK_SET);
+  ssize_t ret = getdents64 (fd, large_buffer, large_buffer_size);
+  if (ret < 0)
+    FAIL_EXIT1 ("getdents64 for buffer of %zu bytes failed: %m",
+                large_buffer_size);
+  if (ret < offsetof (struct dirent64, d_name))
+    FAIL_EXIT1 ("getdents64 for buffer of %zu returned small value %zd",
+                large_buffer_size, ret);
+}
+
+/* Bug 24740: Make sure that the system call argument is adjusted
+   properly for the int type.  A large value should stay a large
+   value, and not wrap around to something small, causing the system
+   call to fail with EINVAL.  */
+static void
+large_buffer_checks (int fd)
+{
+  size_t large_buffer_size;
+  if (!__builtin_add_overflow (UINT_MAX, 2, &large_buffer_size))
+    {
+      char *large_buffer = malloc (large_buffer_size);
+      if (large_buffer == NULL)
+        printf ("warning: could not allocate %zu bytes of memory,"
+                " subtests skipped\n", large_buffer_size);
+      else
+        {
+          large_buffer_check (fd, large_buffer, INT_MAX);
+          large_buffer_check (fd, large_buffer, (size_t) INT_MAX + 1);
+          large_buffer_check (fd, large_buffer, (size_t) INT_MAX + 2);
+          large_buffer_check (fd, large_buffer, UINT_MAX);
+          large_buffer_check (fd, large_buffer, (size_t) UINT_MAX + 1);
+          large_buffer_check (fd, large_buffer, (size_t) UINT_MAX + 2);
+        }
+      free (large_buffer);
+    }
+}
+
 static int
 do_test (void)
 {
@@ -105,6 +147,8 @@ do_test (void)
       rewinddir (reference);
     }
 
+  large_buffer_checks (fd);
+
   xclose (fd);
   closedir (reference);
   return 0;


                 reply	other threads:[~2019-07-02 17:25 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190702172507.2010.qmail@sourceware.org \
    --to=azanella@sourceware.org \
    --cc=glibc-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).