aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2012-05-18 07:12:47 -0700
committerH.J. Lu <hjl.tools@gmail.com>2012-05-18 07:12:47 -0700
commit7cd195df6204a8575b3b1d303affb9aa5756a828 (patch)
tree938298a964fefc7d13990d277fa9a68d2be5450d
parent94b07d20dd07d8426dbde1e83bafcd15eeead281 (diff)
downloadglibc-7cd195df6204a8575b3b1d303affb9aa5756a828.tar
glibc-7cd195df6204a8575b3b1d303affb9aa5756a828.tar.gz
glibc-7cd195df6204a8575b3b1d303affb9aa5756a828.tar.bz2
glibc-7cd195df6204a8575b3b1d303affb9aa5756a828.zip
Check d_ino/d_off before using getdents syscall
-rw-r--r--ChangeLog4
-rw-r--r--sysdeps/unix/sysv/linux/getdents.c15
2 files changed, 16 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index f59b01a637..15a012f764 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2012-05-18 H.J. Lu <hongjiu.lu@intel.com>
+ * sysdeps/unix/sysv/linux/getdents.c (__GETDENTS): Use
+ getdents system call only if kernel and user dirents have the
+ same d_ino and d_off.
+
* stdio-common/_itoa.c: Check _ITOA_NEEDED instead of
LLONG_MAX != LONG_MAX.
(_itoa_word): Use _ITOA_WORD_TYPE on value.
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index eb9cfefbcc..ac4979efb2 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1993, 1995-2004, 2006, 2007, 2010
- Free Software Foundation, Inc.
+/* Copyright (C) 19932-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
@@ -99,7 +98,17 @@ __GETDENTS (int fd, char *buf, size_t nbytes)
ssize_t retval;
#ifdef __ASSUME_GETDENTS32_D_TYPE
- if (sizeof (DIRENT_TYPE) == sizeof (struct dirent))
+ /* The d_ino and d_off fields in kernel_dirent and dirent must have
+ the same sizes and alignments. */
+ if (sizeof (DIRENT_TYPE) == sizeof (struct dirent)
+ && (sizeof (((struct kernel_dirent *) 0)->d_ino)
+ == sizeof (((struct dirent *) 0)->d_ino))
+ && (sizeof (((struct kernel_dirent *) 0)->d_off)
+ == sizeof (((struct dirent *) 0)->d_off))
+ && (offsetof (struct kernel_dirent, d_off)
+ == offsetof (struct dirent, d_off))
+ && (offsetof (struct kernel_dirent, d_reclen)
+ == offsetof (struct dirent, d_reclen)))
{
retval = INLINE_SYSCALL (getdents, 3, fd, CHECK_N(buf, nbytes), nbytes);