Description of problem: When compiling a program that uses preadv() with -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 set, the last off_t parameter is supposed to be 64-bit in size, however, an incorrect prototype causes it to remain 32-bit. This results in data being read/written to/from the wrong place This short demo illustrating the problem $ cat > p.c <<EOF #include <unistd.h> #include <stdio.h> #include <sys/uio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> int main (int argc, char **argv) { int fd; unsigned long long off = 0xffffffffeeffull; char data[11] = "0123456789"; char got[11]; struct iovec gotv[] = { { got, 11 }, }; fd = open("demo.img", O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR); ftruncate(fd, off); lseek(fd, off, SEEK_SET); write(fd, data, 11); memset(got, 0, 11); preadv(fd, gotv, 1, off); memset(got, 0, 11); lseek(fd, off, SEEK_SET); read(fd, got, 11); return 0; } EOF Compiling this program using $ gcc -g -O0 -Wall $(getconf LFS_CFLAGS) $(getconf LFS_LIBS) $(getconf LFS_LDFLAGS) -o p p.c And then strace'ing the program open("demo.img", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0600) = 3 ftruncate64(3, 281474976706303) = -1 EFBIG (File too large) _llseek(3, 281474976706303, 0xbfee6220, SEEK_SET) = -1 EINVAL (Invalid argument) write(3, "0123456789\0"..., 11) = 11 pread64(3, 0xbfee61d0, 11, 13830099914970885887) = -1 EINVAL (Invalid argument) _llseek(3, 281474976706303, 0xbfee6220, SEEK_SET) = -1 EINVAL (Invalid argument) read(3, ""..., 11) = 0 exit_group(0) = ? If everything were operating correctly, the larst arg to pread64 should have been the same as that used in ftruncate64/__llseek Version-Release number of selected component (if applicable): glibc-headers-2.10.1-5.i586 How reproducible: Always Steps to Reproduce: 1. Build above test program on an i386 host, using -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 2. Run it under strace 3. Actual results: Offsets to preadv/pwritev system calls are incorrect Expected results: Additional info:
It would appear to me that in /usr/include/sys/uio.h, that these prototypes extern ssize_t __REDIRECT (preadv, (int __fd, __const struct iovec *__iovec, int __count, __off_t __offset), preadv64) __wur; extern ssize_t __REDIRECT (pwritev, (int __fd, __const struct iovec *__iovec, int __count, __off_t __offset), pwritev64) __wur; should be using '__off64_t' instead ?
bug #526549 is the 32 bit qemu data corruptor that uncovered this; we've worked around the issue by disabling preadv/pwritev use for F-12 GA
Yes, the suggested change in #c1 looks correct to me. While off_t is 64-bit, __off_t is not for 32-bit arches, even when -D_FILE_OFFSET_BITS=64.
http://sources.redhat.com/ml/libc-hacker/2009-11/msg00001.html
Built as 2.11-2.
<adamw> notting: where are we on 533063 (the glibc bug), did we tag the fixed glibc and rebuilds of affected packages? <notting> adamw: yeah, a couple of hours ago. <adamw> notting: should we close the bug then? <notting> adamw: sure! -- Fedora Bugzappers volunteer triage team https://fedoraproject.org/wiki/BugZappers
glibc-2.10.2-1 has been submitted as an update for Fedora 11. http://admin.fedoraproject.org/updates/glibc-2.10.2-1
glibc-2.10.2-1 has been pushed to the Fedora 11 stable repository. If problems still persist, please make note of it in this bug report.