about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2012-10-16 10:33:50 +0200
committerFlorian Weimer <fweimer@redhat.com>2012-10-16 10:33:50 +0200
commit172a631a1fc8ec8fcef80af1f91438d092957c3e (patch)
tree8cbc1cd11a3e922cb60994ac47018db43e6a8e5f
parente9f372520618161d7d73e028ca23818e83b88bbc (diff)
downloadglibc-172a631a1fc8ec8fcef80af1f91438d092957c3e.tar.gz
glibc-172a631a1fc8ec8fcef80af1f91438d092957c3e.tar.xz
glibc-172a631a1fc8ec8fcef80af1f91438d092957c3e.zip
__alloc_dir: avoid integer overflow in malloc argument
-rw-r--r--ChangeLog6
-rw-r--r--sysdeps/posix/opendir.c15
2 files changed, 17 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 0c05941f6f..8e83c46e2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-10-16  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #14700]
+	* sysdeps/posix/opendir.c (MAX_DIR_BUFFER_SIZE): New constant.
+	(__alloc_dir): Limit buffer to MAX_DIR_BUFFER_SIZE.
+
 2012-10-16  Maxim Kuvyrkov  <maxim@codesourcery.com>
 
 	* NEWS: Mention BZ #14716.
diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index e093142f62..f1cc1aeb57 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1991-1996,98,2000-2003,2005,2007,2009,2011
-   Free Software Foundation, Inc.
+/* Copyright (C) 1991-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -33,6 +32,11 @@
 #include <not-cancel.h>
 #include <kernel-features.h>
 
+/* The st_blksize value of the directory is used as a hint for the
+   size of the buffer which receives struct dirent values from the
+   kernel.  st_blksize is limited to MAX_DIR_BUFFER_SIZE, in case the
+   file system provides a bogus value.  */
+#define MAX_DIR_BUFFER_SIZE 1048576U
 
 /* opendir() must not accidentally open something other than a directory.
    Some OS's have kernel support for that, some don't.  In the worst
@@ -192,8 +196,11 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
 				   ? sizeof (struct dirent64) : BUFSIZ);
   size_t allocation = default_allocation;
 #ifdef _STATBUF_ST_BLKSIZE
-  if (statp != NULL && default_allocation < statp->st_blksize)
-    allocation = statp->st_blksize;
+  /* Increase allocation if requested, but not if the value appears to
+     be bogus.  */
+  if (statp != NULL)
+    allocation = MIN (MAX ((size_t) statp->st_blksize, default_allocation),
+		      MAX_DIR_BUFFER_SIZE);
 #endif
 
   DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation);