From: Stephen Rothwell This patch pulls together the compat_sigevent structs. It also consolidates the copying of these structures into the kernel. The only part of the second union in sigevent that the kernel looks at currently is the _tid, so that is the only bit we copy. This patch depends on my previous two patches "add and use COMPAT_SIGEV_PAD_SIZE" and "Consolidate the last compat sigvals". Signed-off-by: Stephen Rothwell Signed-off-by: Andrew Morton --- 25-akpm/arch/ia64/ia32/ia32priv.h | 13 ------------- 25-akpm/arch/ia64/ia32/sys_ia32.c | 9 ++------- 25-akpm/arch/ppc64/kernel/sys_ppc32.c | 9 +-------- 25-akpm/arch/s390/kernel/compat_linux.c | 13 ++----------- 25-akpm/arch/s390/kernel/compat_linux.h | 17 ----------------- 25-akpm/arch/sparc64/kernel/sys_sparc32.c | 9 ++------- 25-akpm/arch/x86_64/ia32/sys_ia32.c | 16 ++-------------- 25-akpm/include/asm-sparc64/siginfo.h | 22 ---------------------- 25-akpm/include/linux/compat.h | 3 +++ 25-akpm/ipc/compat_mq.c | 14 -------------- 25-akpm/kernel/compat.c | 21 +++++++++++++++++++++ 11 files changed, 33 insertions(+), 113 deletions(-) diff -puN arch/ia64/ia32/ia32priv.h~consolidate-the-last-of-the-compat-sigevent-structs arch/ia64/ia32/ia32priv.h --- 25/arch/ia64/ia32/ia32priv.h~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/ia64/ia32/ia32priv.h 2005-03-07 22:56:42.000000000 -0800 @@ -277,19 +277,6 @@ typedef struct compat_siginfo { } _sifields; } compat_siginfo_t; -typedef struct sigevent32 { - compat_sigval_t sigev_value; - int sigev_signo; - int sigev_notify; - union { - int _pad[COMPAT_SIGEV_PAD_SIZE]; - struct { - u32 _function; - u32 _attribute; /* really pthread_attr_t */ - } _sigev_thread; - } _sigev_un; -} sigevent_t32; - struct old_linux32_dirent { u32 d_ino; u32 d_offset; diff -puN arch/ia64/ia32/sys_ia32.c~consolidate-the-last-of-the-compat-sigevent-structs arch/ia64/ia32/sys_ia32.c --- 25/arch/ia64/ia32/sys_ia32.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/ia64/ia32/sys_ia32.c 2005-03-07 22:56:42.000000000 -0800 @@ -2592,7 +2592,7 @@ sys32_get_thread_area (struct ia32_user_ } asmlinkage long -sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) +sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) { struct sigevent se; mm_segment_t oldfs; @@ -2602,12 +2602,7 @@ sys32_timer_create(u32 clock, struct sig if (se32 == NULL) return sys_timer_create(clock, NULL, timer_id); - memset(&se, 0, sizeof(struct sigevent)); - if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || - __get_user(se.sigev_signo, &se32->sigev_signo) || - __get_user(se.sigev_notify, &se32->sigev_notify) || - __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, - sizeof(se._sigev_un._pad))) + if (get_compat_sigevent(&se, se32)) return -EFAULT; if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) diff -puN arch/ppc64/kernel/sys_ppc32.c~consolidate-the-last-of-the-compat-sigevent-structs arch/ppc64/kernel/sys_ppc32.c --- 25/arch/ppc64/kernel/sys_ppc32.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/sys_ppc32.c 2005-03-07 22:56:42.000000000 -0800 @@ -1290,14 +1290,7 @@ long ppc32_timer_create(clockid_t clock, if (ev32 == NULL) return sys_timer_create(clock, NULL, timer_id); - memset(&event, 0, sizeof(event)); - if (!access_ok(VERIFY_READ, ev32, sizeof(struct compat_sigevent)) - || __get_user(event.sigev_value.sival_int, - &ev32->sigev_value.sival_int) - || __get_user(event.sigev_signo, &ev32->sigev_signo) - || __get_user(event.sigev_notify, &ev32->sigev_notify) - || __get_user(event.sigev_notify_thread_id, - &ev32->sigev_notify_thread_id)) + if (get_compat_sigevent(&event, ev32)) return -EFAULT; if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t))) diff -puN arch/s390/kernel/compat_linux.c~consolidate-the-last-of-the-compat-sigevent-structs arch/s390/kernel/compat_linux.c --- 25/arch/s390/kernel/compat_linux.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.c 2005-03-07 22:56:42.000000000 -0800 @@ -1019,7 +1019,7 @@ extern asmlinkage long sys_timer_create(clockid_t, struct sigevent *, timer_t *); asmlinkage long -sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32, +sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32, timer_t *timer_id) { struct sigevent se; @@ -1030,16 +1030,7 @@ sys32_timer_create(clockid_t which_clock if (se32 == NULL) return sys_timer_create(which_clock, NULL, timer_id); - /* XXX: converting se32 to se is filthy because of the - * two union members. For now it is ok, because the pointers - * are not touched in kernel. - */ - memset(&se, 0, sizeof(se)); - if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || - get_user(se.sigev_signo, &se32->sigev_signo) || - get_user(se.sigev_notify, &se32->sigev_notify) || - copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, - sizeof(se._sigev_un._pad))) + if (get_compat_sigevent(&se, se32)) return -EFAULT; old_fs = get_fs(); diff -puN arch/s390/kernel/compat_linux.h~consolidate-the-last-of-the-compat-sigevent-structs arch/s390/kernel/compat_linux.h --- 25/arch/s390/kernel/compat_linux.h~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.h 2005-03-07 22:56:42.000000000 -0800 @@ -194,21 +194,4 @@ struct ucontext32 { compat_sigset_t uc_sigmask; /* mask last for extensibility */ }; -struct sigevent32 { - union { - int sival_int; - u32 sival_ptr; - } sigev_value; - int sigev_signo; - int sigev_notify; - union { - int _pad[COMPAT_SIGEV_PAD_SIZE]; - int _tid; - struct { - u32 *_function; - u32 *_attribute; - } _sigev_thread; - } _sigev_un; -}; - #endif /* _ASM_S390X_S390_H */ diff -puN arch/sparc64/kernel/sys_sparc32.c~consolidate-the-last-of-the-compat-sigevent-structs arch/sparc64/kernel/sys_sparc32.c --- 25/arch/sparc64/kernel/sys_sparc32.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/sparc64/kernel/sys_sparc32.c 2005-03-07 22:56:42.000000000 -0800 @@ -1087,7 +1087,7 @@ sys_timer_create(clockid_t which_clock, timer_t __user *created_timer_id); long -sys32_timer_create(u32 clock, struct sigevent32 __user *se32, +sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) { struct sigevent se; @@ -1098,12 +1098,7 @@ sys32_timer_create(u32 clock, struct sig if (se32 == NULL) return sys_timer_create(clock, NULL, timer_id); - memset(&se, 0, sizeof(struct sigevent)); - if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || - __get_user(se.sigev_signo, &se32->sigev_signo) || - __get_user(se.sigev_notify, &se32->sigev_notify) || - __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, - sizeof(se._sigev_un._pad))) + if (get_compat_sigevent(&se, se32)) return -EFAULT; if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) diff -puN arch/x86_64/ia32/sys_ia32.c~consolidate-the-last-of-the-compat-sigevent-structs arch/x86_64/ia32/sys_ia32.c --- 25/arch/x86_64/ia32/sys_ia32.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/arch/x86_64/ia32/sys_ia32.c 2005-03-07 22:56:42.000000000 -0800 @@ -993,31 +993,19 @@ asmlinkage long sys32_open(const char __ return fd; } -struct sigevent32 { - u32 sigev_value; - u32 sigev_signo; - u32 sigev_notify; - u32 payload[(64 / 4) - 3]; -}; - extern asmlinkage long sys_timer_create(clockid_t which_clock, struct sigevent __user *timer_event_spec, timer_t __user * created_timer_id); long -sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) +sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id) { struct sigevent __user *p = NULL; if (se32) { struct sigevent se; p = compat_alloc_user_space(sizeof(struct sigevent)); - memset(&se, 0, sizeof(struct sigevent)); - if (get_user(se.sigev_value.sival_int, &se32->sigev_value) || - __get_user(se.sigev_signo, &se32->sigev_signo) || - __get_user(se.sigev_notify, &se32->sigev_notify) || - __copy_from_user(&se._sigev_un._pad, &se32->payload, - sizeof(se32->payload)) || + if (get_compat_sigevent(&se, se32) || copy_to_user(p, &se, sizeof(se))) return -EFAULT; } diff -puN include/asm-sparc64/siginfo.h~consolidate-the-last-of-the-compat-sigevent-structs include/asm-sparc64/siginfo.h --- 25/include/asm-sparc64/siginfo.h~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/include/asm-sparc64/siginfo.h 2005-03-07 22:56:42.000000000 -0800 @@ -32,26 +32,4 @@ struct compat_siginfo; #define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */ #define NSIGEMT 1 -#ifdef __KERNEL__ - -#ifdef CONFIG_COMPAT - -typedef struct sigevent32 { - compat_sigval_t sigev_value; - int sigev_signo; - int sigev_notify; - union { - int _pad[COMPAT_SIGEV_PAD_SIZE]; - - struct { - u32 _function; - u32 _attribute; /* really pthread_attr_t */ - } _sigev_thread; - } _sigev_un; -} sigevent_t32; - -#endif /* CONFIG_COMPAT */ - -#endif /* __KERNEL__ */ - #endif diff -puN include/linux/compat.h~consolidate-the-last-of-the-compat-sigevent-structs include/linux/compat.h --- 25/include/linux/compat.h~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/include/linux/compat.h 2005-03-07 22:56:42.000000000 -0800 @@ -155,5 +155,8 @@ long compat_put_bitmap(compat_ulong_t __ unsigned long bitmap_size); int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from); +int get_compat_sigevent(struct sigevent *event, + const struct compat_sigevent __user *u_event); + #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff -puN ipc/compat_mq.c~consolidate-the-last-of-the-compat-sigevent-structs ipc/compat_mq.c --- 25/ipc/compat_mq.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/ipc/compat_mq.c 2005-03-07 22:56:42.000000000 -0800 @@ -102,20 +102,6 @@ asmlinkage ssize_t compat_sys_mq_timedre u_msg_prio, u_ts); } -static int get_compat_sigevent(struct sigevent *event, - const struct compat_sigevent __user *u_event) -{ - if (verify_area(VERIFY_READ, u_event, sizeof(*u_event))) - return -EFAULT; - - return __get_user(event->sigev_value.sival_int, - &u_event->sigev_value.sival_int) - | __get_user(event->sigev_signo, &u_event->sigev_signo) - | __get_user(event->sigev_notify, &u_event->sigev_notify) - | __get_user(event->sigev_notify_thread_id, - &u_event->sigev_notify_thread_id); -} - asmlinkage long compat_sys_mq_notify(mqd_t mqdes, const struct compat_sigevent __user *u_notification) { diff -puN kernel/compat.c~consolidate-the-last-of-the-compat-sigevent-structs kernel/compat.c --- 25/kernel/compat.c~consolidate-the-last-of-the-compat-sigevent-structs 2005-03-07 22:56:42.000000000 -0800 +++ 25-akpm/kernel/compat.c 2005-03-07 22:56:42.000000000 -0800 @@ -630,6 +630,27 @@ long compat_sys_clock_nanosleep(clockid_ return err; } +/* + * We currently only need the following fields from the sigevent + * structure: sigev_value, sigev_signo, sig_notify and (sometimes + * sigev_notify_thread_id). The others are handled in user mode. + * We also assume that copying sigev_value.sival_int is sufficient + * to keep all the bits of sigev_value.sival_ptr intact. + */ +int get_compat_sigevent(struct sigevent *event, + const struct compat_sigevent __user *u_event) +{ + memset(&event, 0, sizeof(*event)); + return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) || + __get_user(event->sigev_value.sival_int, + &u_event->sigev_value.sival_int) || + __get_user(event->sigev_signo, &u_event->sigev_signo) || + __get_user(event->sigev_notify, &u_event->sigev_notify) || + __get_user(event->sigev_notify_thread_id, + &u_event->sigev_notify_thread_id)) + ? -EFAULT : 0; +} + /* timer_create is architecture specific because it needs sigevent conversion */ long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask, _