Commit 9918041c authored by Stephen Rothwell's avatar Stephen Rothwell Committed by Linus Torvalds

[PATCH] consolidate the last of the compat sigevent structs

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: default avatarStephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ba6965f2
...@@ -277,19 +277,6 @@ typedef struct compat_siginfo { ...@@ -277,19 +277,6 @@ typedef struct compat_siginfo {
} _sifields; } _sifields;
} compat_siginfo_t; } 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 { struct old_linux32_dirent {
u32 d_ino; u32 d_ino;
u32 d_offset; u32 d_offset;
......
...@@ -2592,7 +2592,7 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info) ...@@ -2592,7 +2592,7 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
} }
asmlinkage long 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; struct sigevent se;
mm_segment_t oldfs; mm_segment_t oldfs;
...@@ -2602,12 +2602,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *ti ...@@ -2602,12 +2602,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *ti
if (se32 == NULL) if (se32 == NULL)
return sys_timer_create(clock, NULL, timer_id); return sys_timer_create(clock, NULL, timer_id);
memset(&se, 0, sizeof(struct sigevent)); if (get_compat_sigevent(&se, se32))
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)))
return -EFAULT; return -EFAULT;
if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
......
...@@ -1290,14 +1290,7 @@ long ppc32_timer_create(clockid_t clock, ...@@ -1290,14 +1290,7 @@ long ppc32_timer_create(clockid_t clock,
if (ev32 == NULL) if (ev32 == NULL)
return sys_timer_create(clock, NULL, timer_id); return sys_timer_create(clock, NULL, timer_id);
memset(&event, 0, sizeof(event)); if (get_compat_sigevent(&event, ev32))
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))
return -EFAULT; return -EFAULT;
if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t))) if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
......
...@@ -1019,7 +1019,7 @@ extern asmlinkage long ...@@ -1019,7 +1019,7 @@ extern asmlinkage long
sys_timer_create(clockid_t, struct sigevent *, timer_t *); sys_timer_create(clockid_t, struct sigevent *, timer_t *);
asmlinkage long 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) timer_t *timer_id)
{ {
struct sigevent se; struct sigevent se;
...@@ -1030,16 +1030,7 @@ sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32, ...@@ -1030,16 +1030,7 @@ sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32,
if (se32 == NULL) if (se32 == NULL)
return sys_timer_create(which_clock, NULL, timer_id); return sys_timer_create(which_clock, NULL, timer_id);
/* XXX: converting se32 to se is filthy because of the if (get_compat_sigevent(&se, se32))
* 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)))
return -EFAULT; return -EFAULT;
old_fs = get_fs(); old_fs = get_fs();
......
...@@ -194,21 +194,4 @@ struct ucontext32 { ...@@ -194,21 +194,4 @@ struct ucontext32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */ 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 */ #endif /* _ASM_S390X_S390_H */
...@@ -1087,7 +1087,7 @@ sys_timer_create(clockid_t which_clock, ...@@ -1087,7 +1087,7 @@ sys_timer_create(clockid_t which_clock,
timer_t __user *created_timer_id); timer_t __user *created_timer_id);
long 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) timer_t __user *timer_id)
{ {
struct sigevent se; struct sigevent se;
...@@ -1098,12 +1098,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, ...@@ -1098,12 +1098,7 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
if (se32 == NULL) if (se32 == NULL)
return sys_timer_create(clock, NULL, timer_id); return sys_timer_create(clock, NULL, timer_id);
memset(&se, 0, sizeof(struct sigevent)); if (get_compat_sigevent(&se, se32))
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)))
return -EFAULT; return -EFAULT;
if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t))) if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
......
...@@ -993,31 +993,19 @@ asmlinkage long sys32_open(const char __user * filename, int flags, int mode) ...@@ -993,31 +993,19 @@ asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
return fd; return fd;
} }
struct sigevent32 {
u32 sigev_value;
u32 sigev_signo;
u32 sigev_notify;
u32 payload[(64 / 4) - 3];
};
extern asmlinkage long extern asmlinkage long
sys_timer_create(clockid_t which_clock, sys_timer_create(clockid_t which_clock,
struct sigevent __user *timer_event_spec, struct sigevent __user *timer_event_spec,
timer_t __user * created_timer_id); timer_t __user * created_timer_id);
long 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; struct sigevent __user *p = NULL;
if (se32) { if (se32) {
struct sigevent se; struct sigevent se;
p = compat_alloc_user_space(sizeof(struct sigevent)); p = compat_alloc_user_space(sizeof(struct sigevent));
memset(&se, 0, sizeof(struct sigevent)); if (get_compat_sigevent(&se, se32) ||
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)) ||
copy_to_user(p, &se, sizeof(se))) copy_to_user(p, &se, sizeof(se)))
return -EFAULT; return -EFAULT;
} }
......
...@@ -32,26 +32,4 @@ struct compat_siginfo; ...@@ -32,26 +32,4 @@ struct compat_siginfo;
#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */ #define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
#define NSIGEMT 1 #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 #endif
...@@ -155,5 +155,8 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, ...@@ -155,5 +155,8 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
unsigned long bitmap_size); unsigned long bitmap_size);
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from); 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 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 /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */ #endif /* _LINUX_COMPAT_H */
...@@ -102,20 +102,6 @@ asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes, ...@@ -102,20 +102,6 @@ asmlinkage ssize_t compat_sys_mq_timedreceive(mqd_t mqdes,
u_msg_prio, u_ts); 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, asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
const struct compat_sigevent __user *u_notification) const struct compat_sigevent __user *u_notification)
{ {
......
...@@ -630,6 +630,27 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, ...@@ -630,6 +630,27 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
return err; 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 */ /* timer_create is architecture specific because it needs sigevent conversion */
long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask, long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment