This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/23951] pread64(fd, buf, (size_t)-1, offset) do not works as expected, using 32bit glibc-2.27 under 64bit-linux-4.4


https://sourceware.org/bugzilla/show_bug.cgi?id=23951

Adhemerval Zanella <adhemerval.zanella at linaro dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |adhemerval.zanella at linaro dot o
                   |                            |rg
         Resolution|---                         |INVALID

--- Comment #5 from Adhemerval Zanella <adhemerval.zanella at linaro dot org> ---
(In reply to wangfangpeng from comment #4)
> (In reply to Andreas Schwab from comment #2)
> > I don't think there is a bug here, as in both cases we pass the arguments
> > unchanged to the kernel, and return what the kernel reports:
> > 
> > pread64(0, "", 4294967295, 0)           = 0
> > 
> > pread64(0, 0x7ffdd658d2d0, 18446744073709551615, 0) = -1 EFAULT (Bad address)
> 
> You mean this is a kernel bug,not a glibc bug?

You are relying on implementation detail when checking for EFAULT. POSIX [1]
does not define EFAULT as a possible error, even on 'may fail'.

pread64, when used on compat mode, does not fail with EFAULT because the check
on vfs_read that check if the user address access is 'ok' won't report an
invalid address:

fs/read_write.c

 440 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t
*pos)
 441 {
 442         ssize_t ret;
 443 
 444         if (!(file->f_mode & FMODE_READ))
 445                 return -EBADF;
 446         if (!(file->f_mode & FMODE_CAN_READ))
 447                 return -EINVAL;
 448         if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
 449                 return -EFAULT;

arch/x86/include/asm/uaccess.h

 36 #define user_addr_max() (current_thread_info()->addr_limit.seg)

 89 #define access_ok(type, addr, size) \
 90         likely(!__range_not_ok(addr, size, user_addr_max()))

 44 static inline bool __chk_range_not_ok(unsigned long addr, unsigned long
size, unsigned long limit)
 45 {
 46         /*
 47          * If we have used "sizeof()" for the size,
 48          * we know it won't overflow the limit (but
 49          * it might overflow the 'addr', so it's
 50          * important to subtract the size from the
 51          * limit, not add it to the address).
 52          */
 53         if (__builtin_constant_p(size))
 54                 return unlikely(addr > limit - size);
 55 
 56         /* Arbitrary sizes? Be careful about overflow */
 57         addr += size;
 58         if (unlikely(addr < size))
 59                 return true;
 60         return unlikely(addr > limit);
 61 }
 62 
 63 #define __range_not_ok(addr, size, limit)                               \
 64 ({                                                                      \
 65         __chk_user_ptr(addr);                                           \
 66         __chk_range_not_ok((unsigned long __force)(addr), size, limit); \
 67 })

Assuming user_addr_max use the definition of USER_DS, it will check against
TASK_SIZE_MAX (usually (1UL << 47) - PAGE_SIZE for x86_64 kernels), any 32-bit
ADDR plus any 32-bit size won't trigger the invalid range. I think current
Linux does not handle TASK_SIZE_MAX differently depending on if the process is
32 or 64 in 64-bit kernels. 

In any case, this has not to do with glibc since from standard it should not
emulate this behavior. As Andreas Schwab has put on comment #2, it is up to
kernel to provide identical semantic for pread regardless it is running on 32
or 64-bit kernel. 

As a side note, I see the same issue on glibc-2.20. It will use essentially
__NR_pread64 as for newer glibc.

[1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]