On Thu, Oct 22, 2020 at 01:59:32PM -0700, Eric Biggers wrote: > Also note the following program succeeds on Linux 5.9 on x86_64. On kernels > that have this bug, it should fail. (I couldn't get it to actually fail, so it > must depend on the compiler and/or the kernel config...) It doesn't. See https://www.spinics.net/lists/linux-scsi/msg147836.html for discussion of that mess. ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, unsigned long vlen, loff_t *pos, rwf_t flags) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; struct iov_iter iter; ssize_t ret; ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter); if (ret >= 0) { ret = do_iter_read(file, &iter, pos, flags); kfree(iov); } return ret; } and import_iovec() takes unsigned int as the third argument, so it *will* truncate to 32 bits, no matter what. Has done so since 0504c074b546 "switch {compat_,}do_readv_writev() to {compat_,}import_iovec()" back in March 2015. Yes, it was an incompatible userland ABI change, even though nothing that used glibc/uclibc/dietlibc would've noticed. Better yet, up until 2.1.90pre1 passing a 64bit value as the _first_ argument of readv(2) used to fail with -EBADF if it was too large; at that point it started to get quietly truncated to 32bit first. And again, no libc users would've noticed (neither would anything except deliberate regression test looking for that specific behaviour). Note that we also have process_madvise(2) with size_t for vlen (huh? It's a number of array elements, not an object size) and process_vm_{read,write}v(2), that have unsigned long for the same thing. And the last two *are* using the same unsigned long from glibc POV.