Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

futex: Convert to get/put_user_inline()

Replace the open coded implementation with the new get/put_user_inline()
helpers. This might be replaced by a regular get/put_user(), but that needs
a proper performance evaluation.

No functional change intended.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://patch.msgid.link/20251027083745.736737934@linutronix.de

authored by

Thomas Gleixner and committed by
Ingo Molnar
e4e28fd6 b2cfc0cd

+5 -57
+2 -2
kernel/futex/core.c
··· 581 581 if (flags & FLAGS_NUMA) { 582 582 u32 __user *naddr = (void *)uaddr + size / 2; 583 583 584 - if (futex_get_value(&node, naddr)) 584 + if (get_user_inline(node, naddr)) 585 585 return -EFAULT; 586 586 587 587 if ((node != FUTEX_NO_NODE) && ··· 601 601 node = numa_node_id(); 602 602 node_updated = true; 603 603 } 604 - if (node_updated && futex_put_value(node, naddr)) 604 + if (node_updated && put_user_inline(node, naddr)) 605 605 return -EFAULT; 606 606 } 607 607
+3 -55
kernel/futex/futex.h
··· 281 281 return ret; 282 282 } 283 283 284 - /* 285 - * This does a plain atomic user space read, and the user pointer has 286 - * already been verified earlier by get_futex_key() to be both aligned 287 - * and actually in user space, just like futex_atomic_cmpxchg_inatomic(). 288 - * 289 - * We still want to avoid any speculation, and while __get_user() is 290 - * the traditional model for this, it's actually slower than doing 291 - * this manually these days. 292 - * 293 - * We could just have a per-architecture special function for it, 294 - * the same way we do futex_atomic_cmpxchg_inatomic(), but rather 295 - * than force everybody to do that, write it out long-hand using 296 - * the low-level user-access infrastructure. 297 - * 298 - * This looks a bit overkill, but generally just results in a couple 299 - * of instructions. 300 - */ 301 - static __always_inline int futex_get_value(u32 *dest, u32 __user *from) 302 - { 303 - u32 val; 304 - 305 - if (can_do_masked_user_access()) 306 - from = masked_user_access_begin(from); 307 - else if (!user_read_access_begin(from, sizeof(*from))) 308 - return -EFAULT; 309 - unsafe_get_user(val, from, Efault); 310 - user_read_access_end(); 311 - *dest = val; 312 - return 0; 313 - Efault: 314 - user_read_access_end(); 315 - return -EFAULT; 316 - } 317 - 318 - static __always_inline int futex_put_value(u32 val, u32 __user *to) 319 - { 320 - if (can_do_masked_user_access()) 321 - to = masked_user_access_begin(to); 322 - else if (!user_write_access_begin(to, sizeof(*to))) 323 - return -EFAULT; 324 - unsafe_put_user(val, to, Efault); 325 - user_write_access_end(); 326 - return 0; 327 - Efault: 328 - user_write_access_end(); 329 - return -EFAULT; 330 - } 331 - 284 + /* Read from user memory with pagefaults disabled */ 332 285 static inline int futex_get_value_locked(u32 *dest, u32 __user *from) 333 286 { 334 - int ret; 335 - 336 - pagefault_disable(); 337 - ret = futex_get_value(dest, from); 338 - pagefault_enable(); 339 - 340 - return ret; 287 + guard(pagefault)(); 288 + return get_user_inline(*dest, from); 341 289 } 342 290 343 291 extern void __futex_unqueue(struct futex_q *q);