> On Nov 14, 2018, at 4:09 AM, David Laight <David.Laight@xxxxxxxxxx> wrote: > > From: William Kucharski >> Sent: 14 November 2018 10:35 >> >>> On Nov 13, 2018, at 5:51 PM, Isaac J. Manjarres <isaacm@xxxxxxxxxxxxxx> wrote: >>> >>> diff --git a/mm/usercopy.c b/mm/usercopy.c >>> index 852eb4e..0293645 100644 >>> --- a/mm/usercopy.c >>> +++ b/mm/usercopy.c >>> @@ -151,7 +151,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n, >>> bool to_user) >>> { >>> /* Reject if object wraps past end of memory. */ >>> - if (ptr + n < ptr) >>> + if (ptr + (n - 1) < ptr) >>> usercopy_abort("wrapped address", NULL, to_user, 0, ptr + n); >> >> I'm being paranoid, but is it possible this routine could ever be passed "n" set to zero? >> >> If so, it will erroneously abort indicating a wrapped address as (n - 1) wraps to ULONG_MAX. >> >> Easily fixed via: >> >> if ((n != 0) && (ptr + (n - 1) < ptr)) > > Ugg... you don't want a double test. > > I'd guess that a length of zero is likely, but a usercopy that includes > the highest address is going to be invalid because it is a kernel address > (on most archs, and probably illegal on others). > What you really want to do is add 'ptr + len' and check the carry flag. The extra test is only a few extra instructions, but I understand the concern. (Though I don't know how you'd access the carry flag from C in a machine-independent way. Also, for the calculation to be correct you still need to check 'ptr + (len - 1)' for the wrap.) You could also theoretically call gcc's __builtin_uadd_overflow() if you want to get carried away. As I mentioned, I was just being paranoid, but the passed zero length issue stood out to me. William Kucharski