On Tue, Jan 28, 2025, at 10:39, Jérémy Lal wrote:
> Le mar. 28 janv. 2025 à 10:21, Arnd Bergmann <a...@arndb.de> a écrit :
>> On Tue, Jan 28, 2025, at 09:38, Jérémy Lal wrote:
>> > Le mar. 28 janv. 2025 à 09:29, Arnd Bergmann <a...@arndb.de> a écrit :
>> 
>> Can you debug into this file on i386 to see which symbol
>> it picks up in the end, and whether off_t is defined
>> as a 32-bit or 64-bit type?
>
> After patch, preadv64.
> In both cases,
> (gdb) whatis off
> type = off_t
> (gdb) whatis off_t
> type = __off64_t
> 
>> It's possible that for some reason the testcase fails
>> to report a bug on i386 despite the code being wrong
>> either before or after your patch.

Ok, good, so most likely your new version just works and
it was broken on all 32-bit targets including i386 before
your patch. That leaves the question why the testcase
didn't catch that bug on i386.

What I think is going on here is that i386 calling
conventions for 64-bit function arguments happen to
make it work correctly, as they are passed on the stack
as five 32-bit words in preadv64()

<fd> <iov> <iovcnt> <off_low> <off_high>

and preadv() takes exactly the same four arguments
but ignores the last one.

On ARM EABI, the arguments are passed in six registers
instead, with the 64-bit argument in an aligned pair
of registers

<fd> <iov> <iovcnt> <_PAD_> <off_low> <off_high>

which in turn means that calling preadv() by accident
with the preadv64 arguments puts uninitialized stack
data into the 32-bit offset argument slow. The same thing
happens on mips, powerpc, xtensa, arc, nios2, openrisc
sh and riscv. On top of this, big-endian architectures
also typically flip the low and high word for the
64-bit argument, so you pass the wrong word on m68k,
parisc, s390, sparc and openrisc despite those not
inserting the padding argument.

To catch these bugs better, I think a testcase could
be added that passes and argument that has valid
32-bit offset, but garbage in the high bits, e.g.
0xffffffff00000008. On correctly working targets this
should return errno=ENXIO, while on broken i386
systems it would succeed reading from file offset 8.

     Arnd

Reply via email to