Bug 533063

Summary: preadv()/pwritev() prototypes are broken on i386 with -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
Product: [Fedora] Fedora Reporter: Daniel Berrange <berrange>
Component: glibcAssignee: Andreas Schwab <schwab>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: high    
Version: 11CC: agk, awilliam, chrisw, herbert.xu, jakub, jforbes, markmc, mbroz, notting, rjones, schwab, sct, tao, virt-maint
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Fixed In Version: 2.10.2-1 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-11-05 13:40:27 EST Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---
Bug Depends On:    
Bug Blocks: 473303, 498969, 545006    

Description Daniel Berrange 2009-11-04 15:55:41 EST
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;

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):

How reproducible:

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
Actual results:
Offsets to preadv/pwritev system calls are incorrect

Expected results:

Additional info:
Comment 1 Daniel Berrange 2009-11-04 15:57:22 EST
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 ?
Comment 2 Mark McLoughlin 2009-11-04 16:01:36 EST
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
Comment 3 Jakub Jelinek 2009-11-04 16:34:28 EST
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.
Comment 5 Bill Nottingham 2009-11-05 09:51:11 EST
Built as 2.11-2.
Comment 6 Adam Williamson 2009-11-05 13:40:27 EST
<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
Comment 7 Fedora Update System 2009-11-20 07:48:30 EST
glibc-2.10.2-1 has been submitted as an update for Fedora 11.
Comment 8 Fedora Update System 2009-12-15 20:07:31 EST
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.