Thread (10 messages) 10 messages, 4 authors, 2021-09-23

Re: [LTP] ia32 signed long treated as x64 unsigned int by __ia32_sys*

From: Richard Palethorpe <hidden>
Date: 2021-09-23 10:01:19
Also in: linux-api, linux-fsdevel, lkml

Hello Arnd,

Arnd Bergmann [off-list ref] writes:
On Wed, Sep 22, 2021 at 10:46 AM Richard Palethorpe [off-list ref] wrote:
quoted
Richard Palethorpe [off-list ref] writes:
quoted
quoted
Then the output is:

[   11.252268] io_pgetevents(f7f19000, 4294967295, 1, ...)
[   11.252401] comparing 4294967295 <= 1
io_pgetevents02.c:114: TPASS: invalid min_nr: io_pgetevents() failed as expected: EINVAL (22)
[   11.252610] io_pgetevents(f7f19000, 1, 4294967295, ...)
[   11.252748] comparing 1 <= 4294967295
io_pgetevents02.c:103: TFAIL: invalid max_nr: io_pgetevents() passed unexpectedly
and below is the macro expansion for the automatically generated 32bit to
64bit io_pgetevents. I believe it is casting u32 to s64, which appears
to mean there is no sign extension. I don't know if this is the expected
behaviour?
Thank you for digging through this, I meant to already reply once more yesterday
but didn't get around to that.
Thanks, no problem. I suppose this will effect other systemcalls as
well. Which if nothing else is a pain for testing.
quoted
    __typeof(__builtin_choose_expr(
        (__builtin_types_compatible_p(typeof((long)0), typeof(0LL)) ||
         __builtin_types_compatible_p(typeof((long)0), typeof(0ULL))),
        0LL, 0L)) min_nr,
    __typeof(__builtin_choose_expr(
        (__builtin_types_compatible_p(typeof((long)0), typeof(0LL)) ||
         __builtin_types_compatible_p(typeof((long)0), typeof(0ULL))),
        0LL, 0L)) nr,
The part that I remembered is in arch/s390/include/asm/syscall_wrapper.h,
which uses this version instead:

#define __SC_COMPAT_CAST(t, a)                                          \
({                                                                      \
        long __ReS = a;                                                 \
                                                                        \
        BUILD_BUG_ON((sizeof(t) > 4) && !__TYPE_IS_L(t) &&              \
                     !__TYPE_IS_UL(t) && !__TYPE_IS_PTR(t) &&           \
                     !__TYPE_IS_LL(t));                                 \
        if (__TYPE_IS_L(t))                                             \
                __ReS = (s32)a;                                         \
        if (__TYPE_IS_UL(t))                                            \
                __ReS = (u32)a;                                         \
        if (__TYPE_IS_PTR(t))                                           \
                __ReS = a & 0x7fffffff;                                 \
        if (__TYPE_IS_LL(t))                                            \
                return -ENOSYS;                                         \
        (t)__ReS;                                                       \
})

This also takes care of s390-specific pointer conversion, which is the
reason for needing an architecture-specific wrapper, but I suppose the
handling of signed arguments as done in s390 should also be done
everywhere else.

I also noticed that only x86 and s390 even have separate entry
points for normal syscalls when called in compat mode, while
the others all just zero the upper halves of the registers in the
low-level entry code and then call the native entry point.

        Arnd
It looks to me like aarch64 also has something similar? At any rate, I
can try to fix it for x86 and investigate what else might be effected.

-- 
Thank you,
Richard.

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help