This patch adds a new robust_list() syscall. The current syscall can't be expanded to cover the following use case, so a new one is needed. This new syscall allows users to set multiple robust lists per process and to have either 32bit or 64bit pointers in the list. * Use case FEX-Emu[1] is an application that runs x86 and x86-64 binaries on an AArch64 Linux host. One of the tasks of FEX-Emu is to translate syscalls from one platform to another. Existing set_robust_list() can't be easily translated because of two limitations: 1) x86 apps can have 32bit pointers robust lists. For a x86-64 kernel this is not a problem, because of the compat entry point. But there's no such compat entry point for AArch64, so the kernel would do the pointer arithmetic wrongly. Is also unviable to userspace to keep track every addition/removal to the robust list and keep a 64bit version of it somewhere else to feed the kernel. Thus, the new interface has an option of telling the kernel if the list is filled with 32bit or 64bit pointers. 2) Apps can set just one robust list (in theory, x86-64 can set two if they also use the compat entry point). That means that when a x86 app asks FEX-Emu to call set_robust_list(), FEX have two options: to overwrite their own robust list pointer and make the app robust, or to ignore the app robust list and keep the emulator robust. The new interface allows for multiple robust lists per application, solving this. * Interface This is the proposed interface: long set_robust_list2(void *head, int index, unsigned int flags) `head` is the head of the userspace struct robust_list_head, just as old set_robust_list(). It needs to be a void pointer since it can point to a normal robust_list_head or a compat_robust_list_head. `flags` can be used for defining the list type: enum robust_list_type { ROBUST_LIST_32BIT, ROBUST_LIST_64BIT, }; `index` is the index in the internal robust_list's linked list (the naming starts to get confusing, I reckon). If `index == -1`, that means that user wants to set a new robust_list, and the kernel will append it in the end of the list, assign a new index and return this index to the user. If `index >= 0`, that means that user wants to re-set `*head` of an already existing list (similarly to what happens when you call set_robust_list() twice with different `*head`). If `index` is out of range, or it points to a non-existing robust_list, or if the internal list is full, an error is returned. * Implementation The implementation re-uses most of the existing robust list interface as possible. The new task_struct member `struct list_head robust_list2` is just a linked list where new lists are appended as the user requests more lists, and by futex_cleanup(), the kernel walks through the internal list feeding exit_robust_list() with the robust_list's. This implementation supports up to 10 lists (defined at ROBUST_LISTS_PER_TASK), but it was an arbitrary number for this RFC. For the described use case above, 4 should be enough, I'm not sure which should be the limit. It doesn't support list removal (should it support?). It doesn't have a proper get_robust_list2() yet as well, but I can add it in a next revision. We could also have a generic robust_list() syscall that can be used to set/get and be controlled by flags. The new interface has a `unsigned int flags` argument, making it extensible for future use cases as well. * Testing I will provide a selftest similar to the one I proposed for the current interface here: https://lore.kernel.org/lkml/20241010011142.905297-1-andrealmeid@xxxxxxxxxx/ Also, FEX-Emu added support for this interface to validate it: https://github.com/FEX-Emu/FEX/pull/3966 Feedback is very welcomed! Thanks, André [1] https://github.com/FEX-Emu/FEX Changelog: - Added a patch to properly deal with exit_robust_list() in 64bit vs 32bit - Wired-up syscall for all archs - Added more of the cover letter to the commit message v1: https://lore.kernel.org/lkml/20241024145735.162090-1-andrealmeid@xxxxxxxxxx/ André Almeida (3): futex: Use explicit sizes for compat_exit_robust_list futex: Create set_robust_list2 futex: Wire up set_robust_list2 syscall arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + arch/mips/kernel/syscalls/syscall_o32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/linux/compat.h | 12 +- include/linux/futex.h | 12 ++ include/linux/sched.h | 3 +- include/uapi/asm-generic/unistd.h | 5 +- include/uapi/linux/futex.h | 24 ++++ init/init_task.c | 3 + kernel/futex/core.c | 116 +++++++++++++++++--- kernel/futex/futex.h | 3 + kernel/futex/syscalls.c | 40 ++++++- kernel/sys_ni.c | 1 + scripts/syscall.tbl | 1 + 26 files changed, 203 insertions(+), 32 deletions(-) -- 2.47.0