Skip to content

Commit 1c27f1f

Browse files
committed
iov_iter: fix build issue due to possible type mis-match
Commit 6c77676 ("iov_iter: Fix iter_xarray_get_pages{,_alloc}()") introduced a problem on some 32-bit architectures (at least arm, xtensa, csky,sparc and mips), that have a 'size_t' that is 'unsigned int'. The reason is that we now do min(nr * PAGE_SIZE - offset, maxsize); where 'nr' and 'offset' and both 'unsigned int', and PAGE_SIZE is 'unsigned long'. As a result, the normal C type rules means that the first argument to 'min()' ends up being 'unsigned long'. In contrast, 'maxsize' is of type 'size_t'. Now, 'size_t' and 'unsigned long' are always the same physical type in the kernel, so you'd think this doesn't matter, and from an actual arithmetic standpoint it doesn't. But on 32-bit architectures 'size_t' is commonly 'unsigned int', even if it could also be 'unsigned long'. In that situation, both are unsigned 32-bit types, but they are not the *same* type. And as a result 'min()' will complain about the distinct types (ignore the "pointer types" part of the error message: that's an artifact of the way we have made 'min()' check types for being the same): lib/iov_iter.c: In function 'iter_xarray_get_pages': include/linux/minmax.h:20:35: error: comparison of distinct pointer types lacks a cast [-Werror] 20 | (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) | ^~ lib/iov_iter.c:1464:16: note: in expansion of macro 'min' 1464 | return min(nr * PAGE_SIZE - offset, maxsize); | ^~~ This was not visible on 64-bit architectures (where we always define 'size_t' to be 'unsigned long'). Force these cases to use 'min_t(size_t, x, y)' to make the type explicit and avoid the issue. [ Nit-picky note: technically 'size_t' doesn't have to match 'unsigned long' arithmetically. We've certainly historically seen environments with 16-bit address spaces and 32-bit 'unsigned long'. Similarly, even in 64-bit modern environments, 'size_t' could be its own type distinct from 'unsigned long', even if it were arithmetically identical. So the above type commentary is only really descriptive of the kernel environment, not some kind of universal truth for the kinds of wild and crazy situations that are allowed by the C standard ] Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Link: https://lore.kernel.org/all/YqRyL2sIqQNDfky2@debian/ Cc: Jeff Layton <jlayton@kernel.org> Cc: David Howells <dhowells@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 0885eac commit 1c27f1f

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

lib/iov_iter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,7 @@ static ssize_t iter_xarray_get_pages(struct iov_iter *i,
14611461
if (nr == 0)
14621462
return 0;
14631463

1464-
return min(nr * PAGE_SIZE - offset, maxsize);
1464+
return min_t(size_t, nr * PAGE_SIZE - offset, maxsize);
14651465
}
14661466

14671467
/* must be done on non-empty ITER_IOVEC one */
@@ -1625,7 +1625,7 @@ static ssize_t iter_xarray_get_pages_alloc(struct iov_iter *i,
16251625
if (nr == 0)
16261626
return 0;
16271627

1628-
return min(nr * PAGE_SIZE - offset, maxsize);
1628+
return min_t(size_t, nr * PAGE_SIZE - offset, maxsize);
16291629
}
16301630

16311631
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i,

0 commit comments

Comments
 (0)