[PATCH] IPC_INFO: Cast shmmax and shmall fields to uintptr_t [BZ #26736]
Adhemerval Zanella
adhemerval.zanella@linaro.org
Thu Oct 15 17:44:40 GMT 2020
On 15/10/2020 14:40, H.J. Lu wrote:
> On Thu, Oct 15, 2020 at 10:24 AM Adhemerval Zanella via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
>>
>>
>>
>> On 15/10/2020 12:17, H.J. Lu via Libc-alpha wrote:
>>> On x32, the shmctl (IPC_INFO) syscall returns the x86-64 values for
>>> shmmax and shmall. Since x32 is limited to 32-bit address space,
>>> shmmax and shmall should be casted to uintptr_t and shmmax should be
>>> clamped to INT_MAX only if the size of shmmax is the size of int.
>>> ---
>>> sysdeps/unix/sysv/linux/shmctl.c | 20 ++++++++++++++++----
>>> sysdeps/unix/sysv/linux/tst-sysvshm-linux.c | 3 ++-
>>> 2 files changed, 18 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c
>>> index 833f013e69..8d34c0e7bf 100644
>>> --- a/sysdeps/unix/sysv/linux/shmctl.c
>>> +++ b/sysdeps/unix/sysv/linux/shmctl.c
>>> @@ -138,11 +138,11 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
>>>
>>> switch (cmd)
>>> {
>>> - case IPC_STAT:
>>> - case SHM_STAT:
>>> - case SHM_STAT_ANY:
>>> + case IPC_STAT:
>>> + case SHM_STAT:
>>> + case SHM_STAT_ANY:
>>> #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T
>>> - arg->shm_perm.mode >>= 16;
>>> + arg->shm_perm.mode >>= 16;
>>> #else
>>> /* Old Linux kernel versions might not clear the mode padding. */
>>> if (sizeof ((struct shmid_ds){0}.shm_perm.mode)
>>> @@ -153,6 +153,18 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf)
>>> #if __IPC_TIME64
>>> kshmid64_to_shmid64 (arg, buf);
>>> #endif
>>> + break;
>>> +
>>> + case IPC_INFO:
>>> + if (sizeof (((struct shminfo *) 0)->shmmax) > sizeof (uintptr_t))
>>> + {
>>> + /* Since the address space is limited by the size of uintptr_t,
>>> + cast shmmax and shmall to uintptr_t. */
>>> + struct shminfo *shminfo_p = (struct shminfo *) arg;
>>> + shminfo_p->shmmax = (uintptr_t) shminfo_p->shmmax;
>>> + shminfo_p->shmall = (uintptr_t) shminfo_p->shmall;
>>> + }
>>> + break;
>>> }
>>>
>>> return ret;
>>> diff --git a/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c b/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>>> index 7128ae2e14..abeeb37a78 100644
>>> --- a/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>>> +++ b/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>>> @@ -128,7 +128,8 @@ do_test (void)
>>> #if LONG_MAX == INT_MAX
>>> /* Kernel explicit clamp the value for shmmax on compat symbol (32-bit
>>> binaries running on 64-bit kernels). */
>>> - if (v > INT_MAX)
>>> + if (sizeof (((struct shminfo *) 0)->shmmax) == sizeof (int)
>>> + && v > INT_MAX)
>>> v = INT_MAX;
>>> #endif
>>> tipcinfo.shmmax = v;
>>>
>>
>> This is semantic change of shmctl for x32, which I really do not oppose
>> but I think we should rely on kernel to clamp the value correctly for x32
>> (the shmctl is already rather complex to handle y2038 safeness).
>>
>> What about changing the testcase to use the expected types for shminfo
>> fields (__syscall_ulong_t instead of unsigned long int) and check for
>> the expected provided kernel value:
>>
>> ---
>>
>> diff --git a/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c b/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>> index 7128ae2e14..cb32bd522e 100644
>> --- a/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>> +++ b/sysdeps/unix/sysv/linux/tst-sysvshm-linux.c
>> @@ -54,9 +54,9 @@ do_prepare (int argc, char *argv[])
>>
>> struct test_shminfo
>> {
>> - unsigned long int shmall;
>> - unsigned long int shmmax;
>> - unsigned long int shmmni;
>> + __syscall_ulong_t shmall;
>> + __syscall_ulong_t shmmax;
>> + __syscall_ulong_t shmmni;
>> };
>>
>> /* It tries to obtain some system-wide SysV shared memory information from
>> @@ -128,7 +128,8 @@ do_test (void)
>> #if LONG_MAX == INT_MAX
>> /* Kernel explicit clamp the value for shmmax on compat symbol (32-bit
>> binaries running on 64-bit kernels). */
>> - if (v > INT_MAX)
>> + if (sizeof (__syscall_ulong_t) == sizeof (unsigned long int)
>> + && v > INT_MAX)
>> v = INT_MAX;
>> #endif
>> tipcinfo.shmmax = v;
>
> This works. Can you check it in?
I will do it.
More information about the Libc-alpha
mailing list