There are two functions for handling robust lists during the task
exit: exit_robust_list() and compat_exit_robust_list(). The first one
handles either 64bit or 32bit lists, depending if it's a 64bit or 32bit
kernel. The compat_exit_robust_list() only exists in 64bit kernels that
supports 32bit syscalls, and handles 32bit lists.
For the new syscall set_robust_list2(), 64bit kernels need to be able to
handle 32bit lists despite having or not support for 32bit syscalls, so
make compat_exit_robust_list() exist regardless of compat_ config.
Also, use explicitly sizing, otherwise in a 32bit kernel both
exit_robust_list() and compat_exit_robust_list() would be the exactly
same function, with none of them dealing with 64bit robust lists.
Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
include/linux/compat.h | 12 +-----------
include/linux/futex.h | 10 ++++++++++
include/linux/sched.h | 2 +-
kernel/futex/core.c | 48 ++++++++++++++++++++++++++++++++----------------
kernel/futex/syscalls.c | 4 ++--
5 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 56cebaff0c910fda853a0e2b3d6d0517e55f8b38..968a9135ff486cf9c8be2a18b80cd4c46e890236 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -385,16 +385,6 @@ struct compat_ifconf {
compat_caddr_t ifcbuf;
};
-struct compat_robust_list {
- compat_uptr_t next;
-};
-
-struct compat_robust_list_head {
- struct compat_robust_list list;
- compat_long_t futex_offset;
- compat_uptr_t list_op_pending;
-};
-
#ifdef CONFIG_COMPAT_OLD_SIGACTION
struct compat_old_sigaction {
compat_uptr_t sa_handler;
@@ -672,7 +662,7 @@ asmlinkage long compat_sys_waitid(int, compat_pid_t,
struct compat_siginfo __user *, int,
struct compat_rusage __user *);
asmlinkage long
-compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+compat_sys_set_robust_list(struct robust_list_head32 __user *head,
compat_size_t len);
asmlinkage long
compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
diff --git a/include/linux/futex.h b/include/linux/futex.h
index b37193653e6b5d7d562ac08f93d4ee41eb8e72a2..c5b6976909c7d51360e1831e017f4d1544c258fa 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -55,6 +55,16 @@ union futex_key {
#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } }
+struct robust_list32 {
+ u32 next;
+};
+
+struct robust_list_head32 {
+ struct robust_list32 list;
+ s32 futex_offset;
+ u32 list_op_pending;
+};
+
#ifdef CONFIG_FUTEX
enum {
FUTEX_STATE_OK,
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4f78a64beb52c425e46c66427b2f608ba30b3d99..b0f64029d53e8b2ab56f24f77054aa7645a185c5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1333,7 +1333,7 @@ struct task_struct {
#ifdef CONFIG_FUTEX
struct robust_list_head __user *robust_list;
#ifdef CONFIG_COMPAT
- struct compat_robust_list_head __user *compat_robust_list;
+ struct robust_list_head32 __user *compat_robust_list;
#endif
struct list_head pi_state_list;
struct futex_pi_state *pi_state_cache;
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 90d53fb0ee9e1563c355ef0499df441367e1a46c..f0ac4b897ddbb667fa85daf5853cb47c749d512d 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1144,15 +1144,16 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
return 0;
}
+#ifdef CONFIG_64BIT
/*
* Walk curr->robust_list (very carefully, it's a userspace list!)
* and mark any locks found there dead, and notify any waiters.
*
* We silently return on any sign of list-walking problem.
*/
-static void exit_robust_list(struct task_struct *curr)
+static void exit_robust_list64(struct task_struct *curr,
+ struct robust_list_head __user *head)
{
- struct robust_list_head __user *head = curr->robust_list;
struct robust_list __user *entry, *next_entry, *pending;
unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
unsigned int next_pi;
@@ -1211,8 +1212,15 @@ static void exit_robust_list(struct task_struct *curr)
curr, pip, HANDLE_DEATH_PENDING);
}
}
+#else
+static void exit_robust_list64(struct task_struct *curr,
+ struct robust_list_head __user *head)
+{
+ pr_warn("32bit kernel should not allow ROBUST_LIST_64BIT");
+}
+#endif
-#ifdef CONFIG_COMPAT
+#if defined(CONFIG_COMPAT) || !defined(CONFIG_64BIT)
static void __user *futex_uaddr(struct robust_list __user *entry,
compat_long_t futex_offset)
{
@@ -1226,13 +1234,13 @@ static void __user *futex_uaddr(struct robust_list __user *entry,
* Fetch a robust-list pointer. Bit 0 signals PI futexes:
*/
static inline int
-compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
- compat_uptr_t __user *head, unsigned int *pi)
+fetch_robust_entry32(u32 *uentry, struct robust_list __user **entry,
+ u32 __user *head, unsigned int *pi)
{
if (get_user(*uentry, head))
return -EFAULT;
- *entry = compat_ptr((*uentry) & ~1);
+ *entry = (void __user *)(unsigned long)((*uentry) & ~1);
*pi = (unsigned int)(*uentry) & 1;
return 0;
@@ -1244,21 +1252,21 @@ compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **ent
*
* We silently return on any sign of list-walking problem.
*/
-static void compat_exit_robust_list(struct task_struct *curr)
+static void exit_robust_list32(struct task_struct *curr,
+ struct robust_list_head32 __user *head)
{
- struct compat_robust_list_head __user *head = curr->compat_robust_list;
struct robust_list __user *entry, *next_entry, *pending;
unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
unsigned int next_pi;
- compat_uptr_t uentry, next_uentry, upending;
- compat_long_t futex_offset;
+ u32 uentry, next_uentry, upending;
+ s32 futex_offset;
int rc;
/*
* Fetch the list head (which was registered earlier, via
* sys_set_robust_list()):
*/
- if (compat_fetch_robust_entry(&uentry, &entry, &head->list.next, &pi))
+ if (fetch_robust_entry32((u32 *)&uentry, &entry, (u32 *)&head->list.next, &pi))
return;
/*
* Fetch the relative futex offset:
@@ -1269,7 +1277,7 @@ static void compat_exit_robust_list(struct task_struct *curr)
* Fetch any possibly pending lock-add first, and handle it
* if it exists:
*/
- if (compat_fetch_robust_entry(&upending, &pending,
+ if (fetch_robust_entry32(&upending, &pending,
&head->list_op_pending, &pip))
return;
@@ -1279,8 +1287,8 @@ static void compat_exit_robust_list(struct task_struct *curr)
* Fetch the next entry in the list before calling
* handle_futex_death:
*/
- rc = compat_fetch_robust_entry(&next_uentry, &next_entry,
- (compat_uptr_t __user *)&entry->next, &next_pi);
+ rc = fetch_robust_entry32(&next_uentry, &next_entry,
+ (u32 __user *)&entry->next, &next_pi);
/*
* A pending lock might already be on the list, so
* dont process it twice:
@@ -1406,14 +1414,22 @@ static inline void exit_pi_state_list(struct task_struct *curr) { }
static void futex_cleanup(struct task_struct *tsk)
{
+#ifdef CONFIG_64BIT
if (unlikely(tsk->robust_list)) {
- exit_robust_list(tsk);
+ exit_robust_list64(tsk, tsk->robust_list);
tsk->robust_list = NULL;
}
+#else
+ if (unlikely(tsk->robust_list)) {
+ exit_robust_list32(tsk,
+ (struct robust_list_head32 __user *) tsk->robust_list);
+ tsk->robust_list = NULL;
+ }
+#endif
#ifdef CONFIG_COMPAT
if (unlikely(tsk->compat_robust_list)) {
- compat_exit_robust_list(tsk);
+ exit_robust_list32(tsk, tsk->compat_robust_list);
tsk->compat_robust_list = NULL;
}
#endif
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 4b6da9116aa6c33db9796e3055ce0c90b02d7b91..dba193dfd216cc929c8f4d979aa2bcd99237e2d8 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -440,7 +440,7 @@ SYSCALL_DEFINE4(futex_requeue,
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE2(set_robust_list,
- struct compat_robust_list_head __user *, head,
+ struct robust_list_head32 __user *, head,
compat_size_t, len)
{
if (unlikely(len != sizeof(*head)))
@@ -455,7 +455,7 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
compat_uptr_t __user *, head_ptr,
compat_size_t __user *, len_ptr)
{
- struct compat_robust_list_head __user *head;
+ struct robust_list_head32 __user *head;
unsigned long ret;
struct task_struct *p;
--
2.49.0
Hi André, kernel test robot noticed the following build warnings: [auto build test WARNING on a24cc6ce1933eade12aa2b9859de0fcd2dac2c06] url: https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/selftests-futex-Add-ASSERT_-macros/20250627-011636 base: a24cc6ce1933eade12aa2b9859de0fcd2dac2c06 patch link: https://lore.kernel.org/r/20250626-tonyk-robust_futex-v5-3-179194dbde8f%40igalia.com patch subject: [PATCH v5 3/7] futex: Use explicit sizes for compat_exit_robust_list config: arm-randconfig-003-20250627 (https://download.01.org/0day-ci/archive/20250628/202506282104.ThReVuLD-lkp@intel.com/config) compiler: clang version 21.0.0git (https://github.com/llvm/llvm-project e04c938cc08a90ae60440ce22d072ebc69d67ee8) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250628/202506282104.ThReVuLD-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202506282104.ThReVuLD-lkp@intel.com/ All warnings (new ones prefixed by >>): In file included from net/sched/sch_qfq.c:13: In file included from include/linux/netdevice.h:44: In file included from include/uapi/linux/neighbour.h:6: In file included from include/linux/netlink.h:9: In file included from include/net/scm.h:13: In file included from include/net/compat.h:8: >> include/linux/compat.h:665:35: warning: declaration of 'struct robust_list_head32' will not be visible outside of this function [-Wvisibility] 665 | compat_sys_set_robust_list(struct robust_list_head32 __user *head, | ^ 1 warning generated. -- In file included from net/sched/sch_multiq.c:15: In file included from include/net/netlink.h:6: In file included from include/linux/netlink.h:9: In file included from include/net/scm.h:13: In file included from include/net/compat.h:8: >> include/linux/compat.h:665:35: warning: declaration of 'struct robust_list_head32' will not be visible outside of this function [-Wvisibility] 665 | compat_sys_set_robust_list(struct robust_list_head32 __user *head, | ^ net/sched/sch_multiq.c:36:6: warning: variable 'err' set but not used [-Wunused-but-set-variable] 36 | int err; | ^ 2 warnings generated. vim +665 include/linux/compat.h 621 622 #ifdef __ARCH_WANT_COMPAT_SYS_PWRITEV64 623 asmlinkage long compat_sys_pwritev64(unsigned long fd, 624 const struct iovec __user *vec, 625 unsigned long vlen, loff_t pos); 626 #endif 627 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, 628 compat_off_t __user *offset, compat_size_t count); 629 asmlinkage long compat_sys_sendfile64(int out_fd, int in_fd, 630 compat_loff_t __user *offset, compat_size_t count); 631 asmlinkage long compat_sys_pselect6_time32(int n, compat_ulong_t __user *inp, 632 compat_ulong_t __user *outp, 633 compat_ulong_t __user *exp, 634 struct old_timespec32 __user *tsp, 635 void __user *sig); 636 asmlinkage long compat_sys_pselect6_time64(int n, compat_ulong_t __user *inp, 637 compat_ulong_t __user *outp, 638 compat_ulong_t __user *exp, 639 struct __kernel_timespec __user *tsp, 640 void __user *sig); 641 asmlinkage long compat_sys_ppoll_time32(struct pollfd __user *ufds, 642 unsigned int nfds, 643 struct old_timespec32 __user *tsp, 644 const compat_sigset_t __user *sigmask, 645 compat_size_t sigsetsize); 646 asmlinkage long compat_sys_ppoll_time64(struct pollfd __user *ufds, 647 unsigned int nfds, 648 struct __kernel_timespec __user *tsp, 649 const compat_sigset_t __user *sigmask, 650 compat_size_t sigsetsize); 651 asmlinkage long compat_sys_signalfd4(int ufd, 652 const compat_sigset_t __user *sigmask, 653 compat_size_t sigsetsize, int flags); 654 asmlinkage long compat_sys_newfstatat(unsigned int dfd, 655 const char __user *filename, 656 struct compat_stat __user *statbuf, 657 int flag); 658 asmlinkage long compat_sys_newfstat(unsigned int fd, 659 struct compat_stat __user *statbuf); 660 /* No generic prototype for sync_file_range and sync_file_range2 */ 661 asmlinkage long compat_sys_waitid(int, compat_pid_t, 662 struct compat_siginfo __user *, int, 663 struct compat_rusage __user *); 664 asmlinkage long > 665 compat_sys_set_robust_list(struct robust_list_head32 __user *head, 666 compat_size_t len); 667 asmlinkage long 668 compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, 669 compat_size_t __user *len_ptr); 670 asmlinkage long compat_sys_getitimer(int which, 671 struct old_itimerval32 __user *it); 672 asmlinkage long compat_sys_setitimer(int which, 673 struct old_itimerval32 __user *in, 674 struct old_itimerval32 __user *out); 675 asmlinkage long compat_sys_kexec_load(compat_ulong_t entry, 676 compat_ulong_t nr_segments, 677 struct compat_kexec_segment __user *, 678 compat_ulong_t flags); 679 asmlinkage long compat_sys_timer_create(clockid_t which_clock, 680 struct compat_sigevent __user *timer_event_spec, 681 timer_t __user *created_timer_id); 682 asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, 683 compat_long_t addr, compat_long_t data); 684 asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, 685 unsigned int len, 686 compat_ulong_t __user *user_mask_ptr); 687 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, 688 unsigned int len, 689 compat_ulong_t __user *user_mask_ptr); 690 asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, 691 compat_stack_t __user *uoss_ptr); 692 asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, 693 compat_size_t sigsetsize); 694 #ifndef CONFIG_ODD_RT_SIGACTION 695 asmlinkage long compat_sys_rt_sigaction(int, 696 const struct compat_sigaction __user *, 697 struct compat_sigaction __user *, 698 compat_size_t); 699 #endif 700 asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, 701 compat_sigset_t __user *oset, 702 compat_size_t sigsetsize); 703 asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, 704 compat_size_t sigsetsize); 705 asmlinkage long compat_sys_rt_sigtimedwait_time32(compat_sigset_t __user *uthese, 706 struct compat_siginfo __user *uinfo, 707 struct old_timespec32 __user *uts, compat_size_t sigsetsize); 708 asmlinkage long compat_sys_rt_sigtimedwait_time64(compat_sigset_t __user *uthese, 709 struct compat_siginfo __user *uinfo, 710 struct __kernel_timespec __user *uts, compat_size_t sigsetsize); 711 asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, 712 struct compat_siginfo __user *uinfo); 713 /* No generic prototype for rt_sigreturn */ 714 asmlinkage long compat_sys_times(struct compat_tms __user *tbuf); 715 asmlinkage long compat_sys_getrlimit(unsigned int resource, 716 struct compat_rlimit __user *rlim); 717 asmlinkage long compat_sys_setrlimit(unsigned int resource, 718 struct compat_rlimit __user *rlim); 719 asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru); 720 asmlinkage long compat_sys_gettimeofday(struct old_timeval32 __user *tv, 721 struct timezone __user *tz); 722 asmlinkage long compat_sys_settimeofday(struct old_timeval32 __user *tv, 723 struct timezone __user *tz); 724 asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); 725 asmlinkage long compat_sys_mq_open(const char __user *u_name, 726 int oflag, compat_mode_t mode, 727 struct compat_mq_attr __user *u_attr); 728 asmlinkage long compat_sys_mq_notify(mqd_t mqdes, 729 const struct compat_sigevent __user *u_notification); 730 asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes, 731 const struct compat_mq_attr __user *u_mqstat, 732 struct compat_mq_attr __user *u_omqstat); 733 asmlinkage long compat_sys_msgctl(int first, int second, void __user *uptr); 734 asmlinkage long compat_sys_msgrcv(int msqid, compat_uptr_t msgp, 735 compat_ssize_t msgsz, compat_long_t msgtyp, int msgflg); 736 asmlinkage long compat_sys_msgsnd(int msqid, compat_uptr_t msgp, 737 compat_ssize_t msgsz, int msgflg); 738 asmlinkage long compat_sys_semctl(int semid, int semnum, int cmd, int arg); 739 asmlinkage long compat_sys_shmctl(int first, int second, void __user *uptr); 740 asmlinkage long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg); 741 asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, compat_size_t len, 742 unsigned flags, struct sockaddr __user *addr, 743 int __user *addrlen); 744 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, 745 unsigned flags); 746 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, 747 unsigned int flags); 748 /* No generic prototype for readahead */ 749 asmlinkage long compat_sys_keyctl(u32 option, 750 u32 arg2, u32 arg3, u32 arg4, u32 arg5); 751 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, 752 const compat_uptr_t __user *envp); 753 /* No generic prototype for fadvise64_64 */ 754 /* CONFIG_MMU only */ 755 asmlinkage long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, 756 compat_pid_t pid, int sig, 757 struct compat_siginfo __user *uinfo); 758 asmlinkage long compat_sys_recvmmsg_time64(int fd, struct compat_mmsghdr __user *mmsg, 759 unsigned vlen, unsigned int flags, 760 struct __kernel_timespec __user *timeout); 761 asmlinkage long compat_sys_recvmmsg_time32(int fd, struct compat_mmsghdr __user *mmsg, 762 unsigned vlen, unsigned int flags, 763 struct old_timespec32 __user *timeout); 764 asmlinkage long compat_sys_wait4(compat_pid_t pid, 765 compat_uint_t __user *stat_addr, int options, 766 struct compat_rusage __user *ru); 767 asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32, 768 int, const char __user *); 769 asmlinkage long compat_sys_open_by_handle_at(int mountdirfd, 770 struct file_handle __user *handle, 771 int flags); 772 asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, 773 unsigned vlen, unsigned int flags); 774 asmlinkage long compat_sys_execveat(int dfd, const char __user *filename, 775 const compat_uptr_t __user *argv, 776 const compat_uptr_t __user *envp, int flags); 777 asmlinkage ssize_t compat_sys_preadv2(compat_ulong_t fd, 778 const struct iovec __user *vec, 779 compat_ulong_t vlen, u32 pos_low, u32 pos_high, rwf_t flags); 780 asmlinkage ssize_t compat_sys_pwritev2(compat_ulong_t fd, 781 const struct iovec __user *vec, 782 compat_ulong_t vlen, u32 pos_low, u32 pos_high, rwf_t flags); 783 #ifdef __ARCH_WANT_COMPAT_SYS_PREADV64V2 784 asmlinkage long compat_sys_preadv64v2(unsigned long fd, 785 const struct iovec __user *vec, 786 unsigned long vlen, loff_t pos, rwf_t flags); 787 #endif 788 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
On Thu, Jun 26 2025 at 14:11, André Almeida wrote: $subject lacks a () function notation .... > There are two functions for handling robust lists during the task during a tasks exit > exit: exit_robust_list() and compat_exit_robust_list(). The first one > handles either 64bit or 32bit lists, depending if it's a 64bit or 32bit > kernel. The compat_exit_robust_list() only exists in 64bit kernels that s/The// > supports 32bit syscalls, and handles 32bit lists. 32-bit 64-bit all over the place > For the new syscall set_robust_list2(), 64bit kernels need to be able to > handle 32bit lists despite having or not support for 32bit syscalls, so > make compat_exit_robust_list() exist regardless of compat_ config. What new syscall and what are the requirements here? You really want to add some rationale and background here. > Also, use explicitly sizing, otherwise in a 32bit kernel both > exit_robust_list() and compat_exit_robust_list() would be the exactly > same function, with none of them dealing with 64bit robust lists. Explicit sizing of what? The changelog should give information which allows me to verify the implementation and not some blurb which makes me to oracle the meaning of the changelog out of the actual implementation. What is the actual gist of this patch? The subject says: Use explicit sizes for compat_exit_robust_list Now you say 'Also,' which means aside of the above actual statement to make compat_exit_robust_list() unconditional this is now a side effect or what? The subject line is misleading because the real purpose of this patch is to make compat_exit_robust_list() unconditionally available independent of bitness. Now the obvious question is why this patch isn't split into two pieces: 1) The patch matching the above subject line and does the struct/argument rename 2) A subsequent patch which makes the function unconditionally available That's not done because obfuscating changes makes everyones life easier, right? > +++ b/include/linux/compat.h > @@ -385,16 +385,6 @@ struct compat_ifconf { > compat_caddr_t ifcbuf; > }; > > -struct compat_robust_list { > - compat_uptr_t next; > -}; > - > -struct compat_robust_list_head { > - struct compat_robust_list list; > - compat_long_t futex_offset; > - compat_uptr_t list_op_pending; > -}; > - > #ifdef CONFIG_COMPAT_OLD_SIGACTION > struct compat_old_sigaction { > compat_uptr_t sa_handler; > @@ -672,7 +662,7 @@ asmlinkage long compat_sys_waitid(int, compat_pid_t, > struct compat_siginfo __user *, int, > struct compat_rusage __user *); > asmlinkage long > -compat_sys_set_robust_list(struct compat_robust_list_head __user *head, > +compat_sys_set_robust_list(struct robust_list_head32 __user *head, > compat_size_t len); How does this even survive a full kernel build without a forward declaration of struct robust_list_head32? Not everything which includes compat.h includes futex.h first. There is a reason why the structs were define here. Sure you can move them, but not without a forward declaration. Thanks, tglx
© 2016 - 2025 Red Hat, Inc.