On Thu, 8 Mar 2018 15:37:57 -0800 Mike Kravetz mike.kravetz@oracle.com wrote:
Here are a couple options for computing the mask. I changed the name you suggested to make it more obvious that the mask is being used to check for loff_t overflow.
If we want to explicitly comptue the mask as in code above. #define PGOFF_LOFFT_MAX \ (((1UL << (PAGE_SHIFT + 1)) - 1) << (BITS_PER_LONG - (PAGE_SHIFT + 1)))
Or, we use PAGE_MASK #define PGOFF_LOFFT_MAX (PAGE_MASK << (BITS_PER_LONG - (2 * PAGE_SHIFT) - 1))
Sounds good.
In either case, we need a big comment explaining the mask and how we have that extra bit +/- 1 because the offset will be converted to a signed value.
Yup.
Also, we later to
len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); /* check for overflow */ if (len < vma_len) return -EINVAL;
which is ungainly: even if we passed the PGOFF_T_MAX test, there can still be an overflow which we still must check for. Is that avoidable? Probably not...
Yes, it is required. That check takes into account the length argument which is added to page offset. So, yes you can pass the first check and fail this one.
Well I was sort of wondering if both checks could be done in a single operation, but I guess not.