On Sun, 9 Feb 2025 at 11:00, David Laight <david.laight.linux@xxxxxxxxx> wrote: > > They still do 'stuff' and end up containing a slow memory synchronising > instruction (to avoid speculative accesses controlled by the application). > > But there are better ways to handle bad user pointers. Not always. If you use __get_user() and friends, you basically *have* to use access_ok(), or you have to be playing games (like some tracing code does, which actually wants to use it as a "I want a kernel pointer _or_ a user pointer{". Now, admittedly probably nobody should be using __get_user() and friends any more. Almost all the reasons for using it are entirely historical and just not true any more. But also, comparing against TASK_SIZE_MAX isn't actually the same as access_ok() historically. We've moved in that direction, yes, but we very much used to have a distinction between "this is the fixed maximum", and "this is the actual run-time size". We've moved towards just using TASK_SIZE_MAX mainly because the run-time size check was annoyingly expensive is some pretty critical code. But historically the TASK_SIZE_MAX thing is the "this is fast but not exact, use it only for special code that knows what it is doing", and "access_ok()" was "this is proper" > So, mostly access_ok() isn't needed outside the architecture code > that handles userspace accesses. Oh, there is still a fair amount of code that really does need it. Admittedly most of it should either be converted to just using regular get/put_user(), or into the modern "user_access_begin()" model, but we do have a number of __get/put_user() users that still very much need that access_ok(). And anything that follows page tables had better check that it's proper. But in that case, I do believe checking for TASK_SIZE_MAX tends to be equivalent. Linus