Bob,

Am Samstag 13 September 2008 10:25:48 schrieb Bob Amstadt:
> I ported the ISP1362 driver from the Blackfin processor to the Coldfire
> processor.  Specifically I'm using the MCF5282.  Everything works perfectly
> on smaller flash drives (128MB and 256MB).  In fact, a 2GB flash drive that
> is formatted to only 512MB also works perfectly.
>
> A 2GB flash drive formatted for 2GB will cause uClinux to crash usually on
> a simple operation such as an ls of the root directory.  The device does
> mount successfully, but an ls will cause a crash.  The crash is
> unfortunately not consistent.  A variety of different types of failures
> occur.

This is a known bug. 

For directory parsing, there is a huge area allocated on the stack, and at 2 
GBytes, the busybox application crashes because of stack overflow.

The quick fix is to allocate more stack for busybox.

The right fix is to patch uClibc.
Patch from <[EMAIL PROTECTED]> (see attachment)

best regards

Wolfgang
-- 
Wahre Worte sind nicht schön. Schöne Worte sind nicht wahr.

(Laotse)

diff U3b /users/anta/uClinux/uClinux/uClibc/libc/sysdeps/linux/common/getdents.c.org /users/anta/uClinux/uClinux/uClibc/libc/sysdeps/linux/common/getdents.c
--- /users/anta/uClinux/uClinux/uClibc/libc/sysdeps/linux/common/getdents.c.org	Thu May 22 10:17:14 2008
+++ /users/anta/uClinux/uClinux/uClibc/libc/sysdeps/linux/common/getdents.c	Thu Jun 26 17:35:18 2008
@@ -52,29 +52,39 @@
     struct dirent *dp;
     off_t last_offset = -1;
     ssize_t retval;
-    size_t red_nbytes;
+	size_t skip_bytes;
     struct kernel_dirent *skdp, *kdp;
     const size_t size_diff = (offsetof (struct dirent, d_name)
 	    - offsetof (struct kernel_dirent, d_name));
+	const size_t alignment = __alignof__ (struct dirent);
+
+	skip_bytes = (nbytes / (offsetof (struct dirent, d_name) + 14)) *
+				((size_diff + alignment -1) & ~ alignment);
+	skip_bytes  = MAX(skip_bytes, alignment);
 
-    red_nbytes = MIN (nbytes - ((nbytes / 
-		    (offsetof (struct dirent, d_name) + 14)) * size_diff), 
-	    nbytes - size_diff);
+	if(skip_bytes >= nbytes)
+	{
+		/* The buffer the user passed in is too small to hold even
+		   one entry.  */
+		__set_errno (EINVAL);
+		return -1;
+	}
 
     dp = (struct dirent *) buf;
-    skdp = kdp = alloca (red_nbytes);
+    skdp = kdp = (struct kernel_dirent*)(buf + skip_bytes);
 
-    retval = __syscall_getdents(fd, (unsigned char *)kdp, red_nbytes);
+    retval = __syscall_getdents(fd, (unsigned char *)kdp, nbytes - skip_bytes);
     if (retval == -1)
 	return -1;
 
     while ((char *) kdp < (char *) skdp + retval) {
-	const size_t alignment = __alignof__ (struct dirent);
 	/* Since kdp->d_reclen is already aligned for the kernel structure
 	   this may compute a value that is bigger than necessary.  */
-	size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
+		size_t reclen = kdp->d_reclen;
+		ino_t tmp_ino = kdp->d_ino;
+		size_t new_reclen = ((reclen + size_diff + alignment - 1)
 		& ~(alignment - 1));
-	if ((char *) dp + new_reclen > buf + nbytes) {
+		if ((char *)dp + size_diff > (char *)kdp) {
 	    /* Our heuristic failed.  We read too many entries.  Reset
 	       the stream.  */
 	    assert (last_offset != -1);
@@ -90,14 +100,16 @@
 	}
 
 	last_offset = kdp->d_off;
-	dp->d_ino = kdp->d_ino;
-	dp->d_off = kdp->d_off;
+
+		memcpy (dp->d_name, kdp->d_name,
+			reclen - offsetof (struct kernel_dirent, d_name));
+
+		dp->d_ino = tmp_ino;
+		dp->d_off = last_offset;
 	dp->d_reclen = new_reclen;
 	dp->d_type = DT_UNKNOWN;
-	memcpy (dp->d_name, kdp->d_name,
-		kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
 	dp = (struct dirent *) ((char *) dp + new_reclen);
-	kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
+		kdp = (struct kernel_dirent *) (((char *) kdp) + reclen);
     }
     return (char *) dp - buf;
 }
_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to