Bug 533063

Summary: preadv()/pwritev() prototypes are broken on i386 with -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
Product: [Fedora] Fedora Reporter: Daniel BerrangĂ© <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   
Whiteboard:
Fixed In Version: 2.10.2-1 Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-11-05 18:40:27 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 473303, 498969, 545006    

Description Daniel Berrangé 2009-11-04 20:55:41 UTC
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:

Comment 1 Daniel Berrangé 2009-11-04 20:57:22 UTC
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 21:01:36 UTC
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 21:34:28 UTC
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 14:51:11 UTC
Built as 2.11-2.

Comment 6 Adam Williamson 2009-11-05 18:40:27 UTC
<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

Comment 7 Fedora Update System 2009-11-20 12:48:30 UTC
glibc-2.10.2-1 has been submitted as an update for Fedora 11.
http://admin.fedoraproject.org/updates/glibc-2.10.2-1

Comment 8 Fedora Update System 2009-12-16 01:07:31 UTC
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.