On 2019-09-25, Linus Torvalds <[email protected]> wrote: > On Wed, Sep 25, 2019 at 10:00 AM Aleksa Sarai <[email protected]> wrote: > > > > +int is_zeroed_user(const void __user *from, size_t size) > > I like how you've done this, but it's buggy and only works on 64-bit. > > All the "u64" and "8" cases need to be "unsigned long" and > "sizeof(unsigned long)". > > Part of that requirement is: > > > + unsafe_get_user(val, (u64 __user *) from, err_fault); > > This part works fine - although 64-bit accesses migth be much more > expensive and the win of unrolling might not be sufficient - but: > > > + if (align) { > > + /* @from is unaligned. */ > > + val &= ~aligned_byte_mask(align); > > + align = 0; > > + } > > This part fundamentally only works on 'unsigned long'.
Just to make sure I understand, the following diff would this solve the
problem? If so, I'll apply it, and re-send in a few hours.
--8<--------------------------------------------------------------------------
int is_zeroed_user(const void __user *from, size_t size)
{
- u64 val;
- uintptr_t align = (uintptr_t) from % 8;
+ unsigned long val;
+ uintptr_t align = (uintptr_t) from % sizeof(unsigned long);
if (unlikely(!size))
return true;
@@ -150,8 +150,8 @@ int is_zeroed_user(const void __user *from, size_t size)
if (!user_access_begin(from, size))
return -EFAULT;
- while (size >= 8) {
- unsafe_get_user(val, (u64 __user *) from, err_fault);
+ while (size >= sizeof(unsigned long)) {
+ unsafe_get_user(val, (unsigned long __user *) from, err_fault);
if (align) {
/* @from is unaligned. */
val &= ~aligned_byte_mask(align);
@@ -159,12 +159,12 @@ int is_zeroed_user(const void __user *from, size_t size)
}
if (val)
goto done;
- from += 8;
- size -= 8;
+ from += sizeof(unsigned long);
+ size -= sizeof(unsigned long);
}
if (size) {
/* (@from + @size) is unaligned. */
- unsafe_get_user(val, (u64 __user *) from, err_fault);
+ unsafe_get_user(val, (unsigned long __user *) from, err_fault);
val &= aligned_byte_mask(size);
}
--
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>
signature.asc
Description: PGP signature

