On Thu, Jan 25, 2024 at 12:47 AM Valentin Obst <kernel@xxxxxxxxxxxxxxx> wrote: > > > +/* > > nit: this would be the first comment in the kernel crate to use this > style, not sure if there is a rule about that though. Maybe still > preferable to keep it consistent. > > > + * These methods skip the `check_object_size` check that `copy_[to|from]_user` > > + * normally performs. > > nit: They skip the (stronger, and also present without usercopy > hardening) `check_copy_size` wrapping that one. The only difference between check_object_size and check_copy_size is the extra check with __builtin_object_size, but that doesn't work across the C/Rust boundary, and Rust doesn't have a direct equivalent. > > In C, these checks are skipped whenever the length is a > > + * compile-time constant, since when that is the case, the kernel pointer > > + * usually points at a local variable that is being initialized > > Question: I thought that this exemption is about dynamic size > calculations being more susceptible to bugs than hard-coded ones. Does > someone recall the original rationale for that? > > > and the kernel > > + * pointer is trivially non-dangling. > > As far as I know the hardened usercopy checks are not meant to catch > UAFs but rather about OOB accesses (and some info leaks). For example, > if the object is on the heap they check if the copy size exceeds the > allocation size, or, if the object is on the stack, they verify the copy > size does not leave the stack frame. Right, I can reword to say OOB instead of UAF. > > + * > > + * These helpers serve the same purpose in Rust. Whenever the length is known at > > + * compile-time, we call this helper to skip the check. > > + */ > > +unsigned long rust_helper_copy_from_user_unsafe_skip_check_object_size(void *to, const void __user *from, unsigned long n) > > +{ > > + unsigned long res; > > + > > + might_fault(); > > + instrument_copy_from_user_before(to, from, n); > > + if (should_fail_usercopy()) > > + return n; > > + res = raw_copy_from_user(to, from, n); > > + instrument_copy_from_user_after(to, from, n, res); > > + return res; > > +} > > +EXPORT_SYMBOL_GPL(rust_helper_copy_from_user_unsafe_skip_check_object_size); > > + > > +unsigned long rust_helper_copy_to_user_unsafe_skip_check_object_size(void __user *to, const void *from, unsigned long n) > > +{ > > + might_fault(); > > + if (should_fail_usercopy()) > > + return n; > > + instrument_copy_to_user(to, from, n); > > + return raw_copy_to_user(to, from, n); > > +} > > +EXPORT_SYMBOL_GPL(rust_helper_copy_to_user_unsafe_skip_check_object_size); > > Could those be wrapping `_copy_[to|from]_user` instead? Yeah maybe, see the other thread with Arnd Bergmann. Alice