[PATCH] nptl: Fix SYSCALL_CANCEL for return values larger than INT_MAX (BZ 33245)

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Aug 5 16:43:55 GMT 2025



On 02/08/25 16:07, Sam James wrote:
> Sam James <sam@gentoo.org> writes:
> 
>> Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
>>
>>> The SYSCALL_CANCEL calls __syscall_cancel, which in turn
>>> calls __internal_syscall_cancel with an 'int' return instead of the
>>> expected 'long int'.  This causes issues with syscalls that return
>>> values larger than INT_MAX, such as copy_file_range [1].
>>>
>>> Checked on x86_64-linux-gnu.
>>>
>>> [1] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=79139
>>
>> The patch is OK:
>>
>> Reviewed-by: Sam James <sam@gentoo.org>
>>
>>> ---
>>>  nptl/cancellation.c | 4 ++--
>>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> but I have a question about some other instances, though I didn't look
>> afresh yet today, just from last night.
>>
>> Do we need something like the attached? I think the readlink one doesn't
>> actually matter because of path sizes.
> 
> OK, looked more closely..
> 
>>
>> diff --git a/sysdeps/unix/sysv/linux/dl-origin.c b/sysdeps/unix/sysv/linux/dl-origin.c
>> index 3c52ba51a6..b7fec7cc3f 100644
>> --- a/sysdeps/unix/sysv/linux/dl-origin.c
>> +++ b/sysdeps/unix/sysv/linux/dl-origin.c
>> @@ -32,7 +32,7 @@ _dl_get_origin (void)
>>  {
>>    char linkval[PATH_MAX];
>>    char *result;
>> -  int len;
>> +  long len;
>>  
>>    len = INTERNAL_SYSCALL_CALL (readlinkat, AT_FDCWD, "/proc/self/exe",
>>  			       linkval, sizeof (linkval));
>> @@ -84,7 +84,7 @@ _dl_canonicalize (int fd)
>>    struct fd_to_filename fdfilename;
>>    char canonical[PATH_MAX];
>>    char *path = __fd_to_filename (fd, &fdfilename);
>> -  int size = INTERNAL_SYSCALL_CALL (readlinkat, AT_FDCWD, path,
>> +  long size = INTERNAL_SYSCALL_CALL (readlinkat, AT_FDCWD, path,
>>                                      canonical, PATH_MAX - 1);
> 
> Again, doesn't really matter in practice AFAICT.
> 
>>  
>>    /* Check if the path was truncated.  */
>> diff --git a/sysdeps/unix/sysv/linux/lseek.c b/sysdeps/unix/sysv/linux/lseek.c
>> index ff83735d09..9a1383f782 100644
>> --- a/sysdeps/unix/sysv/linux/lseek.c
>> +++ b/sysdeps/unix/sysv/linux/lseek.c
>> @@ -47,7 +47,7 @@ __lseek (int fd, off_t offset, int whence)
>>  
>>  # ifdef __NR__llseek
>>    loff_t res;
>> -  int rc = INLINE_SYSCALL_CALL (_llseek, fd,
>> +  long int rc = INLINE_SYSCALL_CALL (_llseek, fd,
>>  				(long) (((uint64_t) (offset)) >> 32),
>>  				(long) offset, &res, whence);
>>    return rc ?: lseek_overflow (res);
> 
> *llseek* uses a parameter for its return value, so it should be fine. If
> the arch lacks llseek, the other path is fine.
> 
>> diff --git a/sysdeps/unix/sysv/linux/lseek64.c b/sysdeps/unix/sysv/linux/lseek64.c
>> index 49f4136844..b5624388cc 100644
>> --- a/sysdeps/unix/sysv/linux/lseek64.c
>> +++ b/sysdeps/unix/sysv/linux/lseek64.c
>> @@ -32,7 +32,7 @@ __lseek64 (int fd, off64_t offset, int whence)
>>  
>>  #ifdef __NR__llseek
>>    loff_t res;
>> -  int rc = INLINE_SYSCALL_CALL (_llseek, fd,
>> +  long int rc = INLINE_SYSCALL_CALL (_llseek, fd,
>>  				(long) (((uint64_t) (offset)) >> 32),
>>  				(long) offset, &res, whence);
> 
> Ditto llseek/lseek above.

The rc is just used to signal an error, where the kABI will set -errno in
this case (which is handled by INLINE_SYSCALL_CALL). On success the
'res' will be returned, which is 'long long'.

> 
>>    return rc ?: res;
>> diff --git a/sysdeps/unix/sysv/linux/sendfile.c b/sysdeps/unix/sysv/linux/sendfile.c
>> index 990a26a3ea..1f04ce5aab 100644
>> --- a/sysdeps/unix/sysv/linux/sendfile.c
>> +++ b/sysdeps/unix/sysv/linux/sendfile.c
>> @@ -32,7 +32,7 @@ sendfile (int out_fd, int in_fd, off_t *offset, size_t count)
>>    return INLINE_SYSCALL_CALL (sendfile, out_fd, in_fd, offset, count);
>>  # else
>>    __off64_t off64;
>> -  int rc;
>> +  ssize_t rc;
>>  
>>    if (offset != NULL)
>>      {
>>
> 
> This one looks wrong but all arches have __NR_sendfile, so limited impact.

$ python3 sysdeps/unix/sysv/linux/glibcsyscalls.py query-syscall sendfile
sendfile:
  defined: aarch64 alpha arm hppa i386 loongarch m68k microblaze mips/mips32 mips/mips64/n32 mips/mips64/n64 powerpc/powerpc32 powerpc/powerpc64 riscv/rv64 s390/s390-32 s390/s390-64 sh sparc/sparc32 sparc/sparc64 x86_64/64 x86_64/x32
  undefined: arc csky or1k riscv/rv32

The arc, ork1, and riscv/v32 has __OFF_T_MATCHES_OFF64_T, but even on or1k
it should not be a problem because off_t will be the size of int.

> 
>>
>> (Completely untested, it's just from the audit I did earlier.)
>>
>>> [...]
>>
>> sam
> 
> sam

So I think for INLINE_SYSCALL_CALL we are currently fine, although I agree
that 'long int' is the correct type for the return value.


More information about the Libc-alpha mailing list