I have successfully rebuilt glibc 2.3 with this dpatch.  I verified that
readdir01 passes on a mounted IRIX NFS directory.  I can now see all
9000 linux-kernel messages in my maildir again.  :)

glibc23-getdents-fix.dpatch:
---------------------------
#! /bin/sh -e

# All lines beginning with `# DP:' are a description of the patch.
# DP: Fix the overflow detection in the getdents code

if [ $# -ne 2 ]; then
    echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
    exit 1
fi
case "$1" in
    -patch) patch -d "$2" -f --no-backup-if-mismatch -p1 < $0;;
    -unpatch) patch -d "$2" -f --no-backup-if-mismatch -R -p1 < $0;;
    *)
        echo >&2 "`basename $0`: script expects -patch|-unpatch as argument"
        exit 1
esac
exit 0

# append the patch here and adjust the -p? flag in the patch calls.
--- glibc-2.3.1/sysdeps/unix/sysv/linux/getdents.c~     2003-02-10 10:19:12.000000000 
-0600
+++ glibc-2.3.1/sysdeps/unix/sysv/linux/getdents.c      2003-02-10 10:20:09.000000000 
+-0600
@@ -47,6 +47,7 @@
 #endif
 
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define test_overflow(VAR, SIZE) ((((VAR) < 0 ? -(VAR):(VAR)) >> 8*(SIZE)) != 0)
 
 extern int __syscall_getdents (int fd, char *__unbounded buf, unsigned int nbytes);
 extern int __syscall_getdents64 (int fd, char *__unbounded buf, unsigned int nbytes);
@@ -97,7 +98,6 @@
 internal_function
 __GETDENTS (int fd, char *buf, size_t nbytes)
 {
-  off64_t last_offset = -1;
   ssize_t retval;
 
 #ifdef __NR_getdents64
@@ -129,6 +129,7 @@
       if (retval != -1 || (errno != EINVAL && errno != ENOSYS))
 # endif
        {
+         int64_t last_offset = 0;
          const size_t size_diff = (offsetof (struct kernel_dirent64, d_name)
                                    - offsetof (DIRENT_TYPE, d_name));
 
@@ -176,7 +177,7 @@
              if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino)
                   && outp->u.d_ino != d_ino)
                  || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off)
-                     && outp->u.d_off != d_off))
+                     && test_overflow(d_off, sizeof(outp->u.d_off))))
                {
                  /* Overflow.  If there was at least one entry
                     before this one, return them without error,
@@ -210,6 +211,7 @@
   {
     size_t red_nbytes;
     struct kernel_dirent *skdp, *kdp;
+    __kernel_off_t last_offset = 0;
     const size_t size_diff = (offsetof (DIRENT_TYPE, d_name)
                              - offsetof (struct kernel_dirent, d_name));
 
-- 
Nate Straz                                              [EMAIL PROTECTED]
sgi, inc                                           http://www.sgi.com/
Linux Test Project                                  http://ltp.sf.net/


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to