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

Re: [microblaze-uclinux] BUG: fstat64() clobbers stack; uclibc and kernel don't agree on "struct kernel_stat64".



Hi again,

Graeme Smecher wrote:
I've just tracked down a header mismatch that causes stack corruption on Petalinux releases v0.20-rc3 and v0.30-rc1. The fstat64() syscall relies on coherent headers between the kernel and userspace, but they appear to be out-of-sync.

The original message was a bit terse. Here's a bit of clarification, in case it helps:

  * This bug affects newlib as well as uClibc.
  * It affects fstat() as well as fstat64(), since one maps to the other.
  * A quick glance suggests it affects both 2.4.x and 2.6.x kernels.

Since newlib binaries are incorporated into the microblaze-uclinux toolset, the quickest workaround (pending a new release, I guess) is to remove the __unused8 field from the kernel headers and swap the order of "st_blocks" and "__unused4". Then, rebuilding the kernel should take care of the rest.

This bug popped up for me when cross-compiling Python 2.5.1 for Microblaze. Without a patch, Python starts up with some rather obscure "bad magic" and "lost sys.stderr" messages; with the kernel headers patched, it appears to start up fine.

Under the hood, the mismatch in structure defs causes libc (newlib / uClibc) to reserve 4 bytes too few for the "struct kernel_stat64" structure. Then the kernel writes out the full-size structure, and whatever occupied the last (unexpected) 4 bytes on the stack was overwritten with zeros. In my case, this was convincing Python that stdin/stdout/stderr were directories.

best,
Graeme


 We have:

-----------

$ diff -ub linux-2.4.x/include/asm-microblaze/stat.h uClibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h --- linux-2.4.x/include/asm-microblaze/stat.h 2006-01-30 00:57:53.000000000 -0500 +++ uClibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h 2006-01-29 22:37:04.000000000 -0500
@@ -1,7 +1,10 @@
-#ifndef __MICROBLAZE_STAT_H__
-#define __MICROBLAZE_STAT_H__
+/* Stat structure for linux/microblaze*/

-struct stat {
+#ifndef _BITS_STAT_STRUCT_H
+#define _BITS_STAT_STRUCT_H
+
+struct kernel_stat
+{
    __kernel_dev_t    st_dev;
    __kernel_ino_t    st_ino;
    __kernel_mode_t    st_mode;
@@ -22,7 +25,8 @@
    unsigned long    __unused5;
};

-struct stat64 {
+struct kernel_stat64
+{
    __kernel_dev_t    st_dev;
    unsigned long    __unused0;
    unsigned long    __unused1;
@@ -42,8 +46,8 @@
    __kernel_loff_t    st_size;
    unsigned long    st_blksize;

-    unsigned long    st_blocks; /* No. of 512-byte blocks allocated */
    unsigned long    __unused4; /* future possible st_blocks high bits */
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */

    unsigned long    st_atime;
    unsigned long    __unused5;
@@ -53,8 +57,6 @@

    unsigned long    st_ctime;
    unsigned long    __unused7; /* high 32 bits of ctime someday */
-
-    unsigned long    __unused8;
};

-#endif /* __MICROBLAZE_STAT_H__ */
+#endif    /*  _BITS_STAT_STRUCT_H */

-----------

Two problems:
  * the kernel_stat->st_blocks entry is in the wrong spot, and
* __unused8 is present in the kernel, but not in userspace. The result is a clobbered int32_t on the stack.

Please let me know if I can do anything to help resolve this.

regards,
Graeme Smecher
___________________________
microblaze-uclinux mailing list
microblaze-uclinux@xxxxxxxxxxxxxx
Project Home Page : http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux
Mailing List Archive : http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/


___________________________
microblaze-uclinux mailing list
microblaze-uclinux@xxxxxxxxxxxxxx
Project Home Page : http://www.itee.uq.edu.au/~jwilliams/mblaze-uclinux
Mailing List Archive : http://www.itee.uq.edu.au/~listarch/microblaze-uclinux/