x32: fix decoding of flags argument of preadv2 and pwritev2 syscalls

x32 is the only linux architecture where preadv2 and pwritev2 syscalls
take 5 arguments instead of 6.

* io.c (PREADV2_PWRITEV2_FLAGS_ARG_NO): New macro.
(SYS_FUNC(preadv2), SYS_FUNC(pwritev2)): Use it.
* linux/x32/syscallent.h (preadv2, pwritev2): Change nargs to 5.
* NEWS: Mention this fix.
* tests/preadv2-pwritev2.c (main): Fix invocation of preadv2
and pwritev2 syscalls on x32.
This commit is contained in:
Дмитрий Левин 2017-02-25 15:55:31 +00:00
parent 7519e54937
commit f7b9a6ac63
4 changed files with 60 additions and 23 deletions

3
NEWS
View File

@ -4,6 +4,9 @@ Noteworthy changes in release ?.?? (????-??-??)
* Improvements
* Enhanced decoding of sched_setattr syscall.
* Bug fixes
* Fixed decoding of flags argument of preadv2 and pwritev2 syscalls on x32.
Noteworthy changes in release 4.16 (2017-02-14)
===============================================

27
io.c
View File

@ -224,11 +224,6 @@ SYS_FUNC(preadv)
return do_preadv(tcp, -1);
}
SYS_FUNC(preadv2)
{
return do_preadv(tcp, 5);
}
static int
do_pwritev(struct tcb *tcp, const int flags_arg)
{
@ -253,9 +248,29 @@ SYS_FUNC(pwritev)
return do_pwritev(tcp, -1);
}
/*
* x32 is the only architecture where preadv2 takes 5 arguments
* instead of 6, see preadv64v2 in kernel sources.
* Likewise, x32 is the only architecture where pwritev2 takes 5 arguments
* instead of 6, see pwritev64v2 in kernel sources.
*/
#if defined X86_64
# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 2 ? 4 : 5)
#elif defined X32
# define PREADV2_PWRITEV2_FLAGS_ARG_NO (current_personality == 0 ? 4 : 5)
#else
# define PREADV2_PWRITEV2_FLAGS_ARG_NO 5
#endif
SYS_FUNC(preadv2)
{
return do_preadv(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
}
SYS_FUNC(pwritev2)
{
return do_pwritev(tcp, 5);
return do_pwritev(tcp, PREADV2_PWRITEV2_FLAGS_ARG_NO);
}
#include "xlat/splice_flags.h"

View File

@ -369,5 +369,5 @@
[543] = { 2, CST|TM, SEN(io_setup), "io_setup" },
[544] = { 3, CST, SEN(io_submit), "io_submit" },
[545] = { 5, CST|TD|TF|TP|SE|SI, SEN(execveat), "execveat" },
[546] = { 6, TD, SEN(preadv2), "preadv2" },
[547] = { 6, TD, SEN(pwritev2), "pwritev2" },
[546] = { 5, TD, SEN(preadv2), "preadv2" },
[547] = { 5, TD, SEN(pwritev2), "pwritev2" },

View File

@ -181,26 +181,45 @@ int
main(void)
{
const kernel_ulong_t vlen = (kernel_ulong_t) 0xfac1fed2dad3bef4ULL;
const unsigned long long pos = 0xfac5fed6dad7bef8;
const unsigned long long pos = 0x7ac5fed6dad7bef8;
const kernel_ulong_t pos_l = (kernel_ulong_t) pos;
const kernel_ulong_t pos_h =
(sizeof(kernel_ulong_t) == sizeof(long long)) ?
(kernel_ulong_t) 0xbadc0deddeadbeefULL : 0xfac5fed6UL;
int test_dumpio = 1;
long rc;
int test_dumpio;
tprintf("%s", "");
syscall(__NR_preadv2, -1, NULL, vlen, pos_l, pos_h, 1);
if (ENOSYS == errno)
test_dumpio = 0;
tprintf("preadv2(-1, NULL, %lu, %lld, RWF_HIPRI) = -1 %s (%m)\n",
(unsigned long) vlen, pos, errno2name());
#if defined __x86_64__ && defined __ILP32__
/*
* x32 is the only architecture where preadv2 takes 5 arguments,
* see preadv64v2 in kernel sources.
*/
rc = syscall(__NR_preadv2, -1, NULL, vlen, pos_l, 1);
#else
const kernel_ulong_t pos_h =
(sizeof(pos_l) == sizeof(pos)) ?
(kernel_ulong_t) 0xbadc0deddeadbeefULL :
(kernel_ulong_t) (pos >> 32);
rc = syscall(__NR_preadv2, -1, NULL, vlen, pos_l, pos_h, 1);
#endif
if (rc != -1 || (ENOSYS != errno && EBADF != errno))
perror_msg_and_fail("preadv2");
test_dumpio = EBADF == errno;
tprintf("preadv2(-1, NULL, %lu, %lld, RWF_HIPRI) = %s\n",
(unsigned long) vlen, pos, sprintrc(rc));
syscall(__NR_pwritev2, -1, NULL, vlen, pos_l, pos_h, 1);
if (ENOSYS == errno)
test_dumpio = 0;
tprintf("pwritev2(-1, NULL, %lu, %lld, RWF_HIPRI) = -1 %s (%m)\n",
(unsigned long) vlen, pos, errno2name());
#if defined __x86_64__ && defined __ILP32__
/*
* x32 is the only architecture where pwritev2 takes 5 arguments,
* see pwritev64v2 in kernel sources.
*/
rc = syscall(__NR_pwritev2, -1, NULL, vlen, pos_l, 1);
#else
rc = syscall(__NR_pwritev2, -1, NULL, vlen, pos_l, pos_h, 1);
#endif
if (rc != -1 || (ENOSYS != errno && EBADF != errno))
perror_msg_and_fail("pwritev2");
tprintf("pwritev2(-1, NULL, %lu, %lld, RWF_HIPRI) = %s\n",
(unsigned long) vlen, pos, sprintrc(rc));
if (test_dumpio)
dumpio();