[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#180065: I'm running with this patch successfuly



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                                              nstraz@sgi.com
sgi, inc                                           http://www.sgi.com/
Linux Test Project                                  http://ltp.sf.net/



Reply to: