Incorrect preadv/pwritev argument parsing on ARM EABI

Dmitry V. Levin ldv at altlinux.org
Thu Apr 17 00:30:09 UTC 2014


On Wed, Apr 16, 2014 at 02:28:40AM -0700, Dima Kogan wrote:
> Dima Kogan <lists at dima.secretsauce.net> writes:
> > Dima Kogan <lists at dima.secretsauce.net> writes:
> >
> >> Does anybody know what's going on? I can imagine anything from the
> >> kernel being inconsistent with itself to glibc producing an incorrect
> >> kernel interface.
> >
> > So I just checked to see what data the kernel returns in response to the
> > pread() and preadv() calls in the example. The kernel sees the correct
> > addresses in both of those calls, so libc is doing the right thing, and
> > this is an strace bug/kernel weirdness.
> 
> I'll just keep replying to myself :)
> 
> I looked into this, and I know what's happening, and a patch is
> attached.

Thanks for reporting and analysis, I've pushed a test case for this bug at
http://sourceforge.net/p/strace/code/ci/cc3d59199d80588a53ee353da5d69726bd093c51/

> preadv/pwritev have a 64-bit 'offset' argument in userspace. The system call,
> however, has two separate 32-bit arguments. This is different from syscalls like
> pread where the syscall has a 64-bit argument.
> 
> In the latter case, alignment requirements apply. In the former (preadv) case,
> however, NO alignment requirements apply, since as far as the kernel is
> concerned, there are no 64 bit arguments.
> 
> To be absolutely clear, here are the syscall definitions of preadv and pread
> (I'm looking at fs/read_write.c in Linux 3.14):
> 
> SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
> 			size_t, count, loff_t, pos)
> SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
> 		unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
> 
> Note that pread64 has a single loff_t pos while preadv has a split pos.
> 
> This patch removes the alignment requirements from preadv and pwritev, so the
> pos argument is reported correctly

Unfortunately, your patch breaks all 64-bit architectures because offset
is passed as a single argument.  You can see what's really going on using
strace -raw option:

x86_64$ strace -edesc -eraw=all -o'|grep ^p' ./uio
pread(0x3, 0x7fff662ee170, 0x4, 0xdefaceddeadbeef) = 0x4
preadv(0x3, 0x7fff662ee160, 0x1, 0xdefaceddeadbeef) = 0x4
pwrite(0x3, 0x7fff662ee170, 0x4, 0xdefaceddeadbeef) = 0x4
pwritev(0x3, 0x7fff662ee160, 0x1, 0xdefaceddeadbeef) = 0x4

x86$ strace -edesc -eraw=all -o'|grep ^p' ./uio
pread64(0x3, 0xbf92e708, 0x4, 0xdeadbeef, 0xdefaced) = 0x4
preadv(0x3, 0xbf92e700, 0x1, 0xdeadbeef, 0xdefaced) = 0x4
pwrite64(0x3, 0xbf92e708, 0x4, 0xdeadbeef, 0xdefaced) = 0x4
pwritev(0x3, 0xbf92e700, 0x1, 0xdeadbeef, 0xdefaced) = 0x4

arm$ strace -edesc -eraw=all -o'|grep ^p' ./uio
pread(0x3, 0xbeb86650, 0x4, 0, 0xdeadbeef, 0xdefaced) = 0x4
preadv(0x3, 0xbeb86648, 0x1, 0xdeadbeef, 0xdefaced) = 0x4
pwrite(0x3, 0xbeb86650, 0x4, 0, 0xdeadbeef, 0xdefaced) = 0x4
pwritev(0x3, 0xbeb86648, 0x1, 0xdeadbeef, 0xdefaced) = 0x4


-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20140417/f9882310/attachment.bin>


More information about the Strace-devel mailing list