Commit 4b36077f authored by Zou Nanhai's avatar Zou Nanhai Committed by Linus Torvalds

[PATCH] compat: sigtimedwait

- Merge sys32_rt_sigtimedwait function in X86_64, IA64, PPC64, MIPS,
  SPARC64, S390 32 bit layer into 1 compat_rt_sigtimedwait function.  It will
  also fix a bug of copy wrong information to 32 bit userspace siginfo
  structure on X86_64, IA64 and SPARC64 when calling sigtimedwait on 32 bit
  layer.

- Change all name the of siginfo_t32 structure in X86_64, IA64, MIPS,
  SPARC64 and S390 to the name compat_siginfo_t as used in PPC64.

- Patch introduced a macro __COMPAT_ENDIAN_SWAP__ in
  include/asm-mips/compat.h when MIPS kernel is compiled in little-endian
  mode.  This macro is used to do byte swapping in function
  sigset_from_compat.

- This patch is only tested on X86_64 and IA_64.
Signed-off-by: default avatarZou Nan hai <Nanhai.zou@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent effe830d
...@@ -387,7 +387,7 @@ ia32_syscall_table: ...@@ -387,7 +387,7 @@ ia32_syscall_table:
data8 sys32_rt_sigaction data8 sys32_rt_sigaction
data8 sys32_rt_sigprocmask /* 175 */ data8 sys32_rt_sigprocmask /* 175 */
data8 sys_rt_sigpending data8 sys_rt_sigpending
data8 sys32_rt_sigtimedwait data8 compat_rt_sigtimedwait
data8 sys32_rt_sigqueueinfo data8 sys32_rt_sigqueueinfo
data8 sys32_rt_sigsuspend data8 sys32_rt_sigsuspend
data8 sys32_pread /* 180 */ data8 sys32_pread /* 180 */
......
...@@ -59,19 +59,19 @@ struct rt_sigframe_ia32 ...@@ -59,19 +59,19 @@ struct rt_sigframe_ia32
int sig; int sig;
int pinfo; int pinfo;
int puc; int puc;
siginfo_t32 info; compat_siginfo_t info;
struct ucontext_ia32 uc; struct ucontext_ia32 uc;
struct _fpstate_ia32 fpstate; struct _fpstate_ia32 fpstate;
char retcode[8]; char retcode[8];
}; };
int int
copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from) copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
{ {
unsigned long tmp; unsigned long tmp;
int err; int err;
if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32))) if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
err = __get_user(to->si_signo, &from->si_signo); err = __get_user(to->si_signo, &from->si_signo);
...@@ -110,12 +110,12 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from) ...@@ -110,12 +110,12 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from)
} }
int int
copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from) copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
{ {
unsigned int addr; unsigned int addr;
int err; int err;
if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32))) if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
/* If you change siginfo_t structure, please be sure /* If you change siginfo_t structure, please be sure
...@@ -589,34 +589,7 @@ sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __us ...@@ -589,34 +589,7 @@ sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __us
} }
asmlinkage long asmlinkage long
sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo, sys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo)
struct compat_timespec __user *uts, unsigned int sigsetsize)
{
mm_segment_t old_fs = get_fs();
struct timespec t;
siginfo_t info;
sigset_t s;
int ret;
if (copy_from_user(&s.sig, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
if (uts && get_compat_timespec(&t, uts))
return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
uinfo ? (siginfo_t __user *) &info : NULL,
uts ? (struct timespec __user *) &t : NULL,
sigsetsize);
set_fs(old_fs);
if (ret >= 0 && uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
return -EFAULT;
}
return ret;
}
asmlinkage long
sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo)
{ {
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
siginfo_t info; siginfo_t info;
......
...@@ -232,7 +232,7 @@ typedef union sigval32 { ...@@ -232,7 +232,7 @@ typedef union sigval32 {
#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
typedef struct siginfo32 { typedef struct compat_siginfo {
int si_signo; int si_signo;
int si_errno; int si_errno;
int si_code; int si_code;
...@@ -282,7 +282,7 @@ typedef struct siginfo32 { ...@@ -282,7 +282,7 @@ typedef struct siginfo32 {
int _fd; int _fd;
} _sigpoll; } _sigpoll;
} _sifields; } _sifields;
} siginfo_t32; } compat_siginfo_t;
typedef struct sigevent32 { typedef struct sigevent32 {
sigval_t32 sigev_value; sigval_t32 sigev_value;
...@@ -559,10 +559,6 @@ struct user_regs_struct32 { ...@@ -559,10 +559,6 @@ struct user_regs_struct32 {
extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *); extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *); extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
/* Prototypes for use in sys_ia32.c */
int copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from);
int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from);
#endif /* !CONFIG_IA32_SUPPORT */ #endif /* !CONFIG_IA32_SUPPORT */
#endif /* _ASM_IA64_IA32_PRIV_H */ #endif /* _ASM_IA64_IA32_PRIV_H */
...@@ -2641,7 +2641,7 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, ...@@ -2641,7 +2641,7 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
} }
asmlinkage long sys32_waitid(int which, compat_pid_t pid, asmlinkage long sys32_waitid(int which, compat_pid_t pid,
siginfo_t32 __user *uinfo, int options, compat_siginfo_t __user *uinfo, int options,
struct compat_rusage __user *uru) struct compat_rusage __user *uru)
{ {
siginfo_t info; siginfo_t info;
......
...@@ -243,7 +243,7 @@ EXPORT(sysn32_call_table) ...@@ -243,7 +243,7 @@ EXPORT(sysn32_call_table)
PTR sys_capget PTR sys_capget
PTR sys_capset PTR sys_capset
PTR sys32_rt_sigpending /* 6125 */ PTR sys32_rt_sigpending /* 6125 */
PTR sys32_rt_sigtimedwait PTR compat_rt_sigtimedwait
PTR sys32_rt_sigqueueinfo PTR sys32_rt_sigqueueinfo
PTR sys32_rt_sigsuspend PTR sys32_rt_sigsuspend
PTR sys32_sigaltstack PTR sys32_sigaltstack
......
...@@ -420,7 +420,7 @@ sys_call_table: ...@@ -420,7 +420,7 @@ sys_call_table:
PTR sys32_rt_sigaction PTR sys32_rt_sigaction
PTR sys32_rt_sigprocmask /* 4195 */ PTR sys32_rt_sigprocmask /* 4195 */
PTR sys32_rt_sigpending PTR sys32_rt_sigpending
PTR sys32_rt_sigtimedwait PTR compat_rt_sigtimedwait
PTR sys32_rt_sigqueueinfo PTR sys32_rt_sigqueueinfo
PTR sys32_rt_sigsuspend PTR sys32_rt_sigsuspend
PTR sys32_pread /* 4200 */ PTR sys32_pread /* 4200 */
......
...@@ -37,7 +37,7 @@ typedef union sigval32 { ...@@ -37,7 +37,7 @@ typedef union sigval32 {
s32 sival_ptr; s32 sival_ptr;
} sigval_t32; } sigval_t32;
typedef struct siginfo32 { typedef struct compat_siginfo{
int si_signo; int si_signo;
int si_code; int si_code;
int si_errno; int si_errno;
...@@ -93,7 +93,7 @@ typedef struct siginfo32 { ...@@ -93,7 +93,7 @@ typedef struct siginfo32 {
} _rt; } _rt;
} _sifields; } _sifields;
} siginfo_t32; } compat_siginfo_t;
/* /*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ... * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
...@@ -389,15 +389,15 @@ struct sigframe { ...@@ -389,15 +389,15 @@ struct sigframe {
struct rt_sigframe32 { struct rt_sigframe32 {
u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2]; /* signal trampoline */ u32 rs_code[2]; /* signal trampoline */
struct siginfo32 rs_info; struct compat_siginfo_t rs_info;
struct ucontext32 rs_uc; struct ucontext32 rs_uc;
}; };
static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from) int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
{ {
int err; int err;
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
/* If you change siginfo_t structure, please be sure /* If you change siginfo_t structure, please be sure
...@@ -677,7 +677,7 @@ static inline void setup_rt_frame(struct k_sigaction * ka, ...@@ -677,7 +677,7 @@ static inline void setup_rt_frame(struct k_sigaction * ka,
err |= __put_user(0x0000000c , frame->rs_code + 1); err |= __put_user(0x0000000c , frame->rs_code + 1);
flush_cache_sigtramp((unsigned long) frame->rs_code); flush_cache_sigtramp((unsigned long) frame->rs_code);
/* Convert (siginfo_t -> siginfo_t32) and copy to user. */ /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
err |= copy_siginfo_to_user32(&frame->rs_info, info); err |= copy_siginfo_to_user32(&frame->rs_info, info);
/* Create the ucontext. */ /* Create the ucontext. */
...@@ -890,98 +890,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, ...@@ -890,98 +890,7 @@ asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset,
return ret; return ret;
} }
asmlinkage int sys32_rt_sigtimedwait(compat_sigset_t *uthese, asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo)
siginfo_t32 *uinfo, struct compat_timespec *uts,
compat_time_t sigsetsize)
{
int ret, sig;
sigset_t these;
compat_sigset_t these32;
struct timespec ts;
siginfo_t info;
long timeout = 0;
/*
* As the result of a brainfarting competition a few years ago the
* size of sigset_t for the 32-bit kernel was choosen to be 128 bits
* but nothing so far is actually using that many, 64 are enough. So
* for now we just drop the high bits.
*/
if (copy_from_user (&these32, uthese, sizeof(compat_old_sigset_t)))
return -EFAULT;
switch (_NSIG_WORDS) {
#ifdef __MIPSEB__
case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
#endif
#ifdef __MIPSEL__
case 4: these.sig[3] = these32.sig[7] | (((long)these32.sig[6]) << 32);
case 3: these.sig[2] = these32.sig[5] | (((long)these32.sig[4]) << 32);
case 2: these.sig[1] = these32.sig[3] | (((long)these32.sig[2]) << 32);
case 1: these.sig[0] = these32.sig[1] | (((long)these32.sig[0]) << 32);
#endif
}
/*
* Invert the set of allowed signals to get those we
* want to block.
*/
sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
signotset(&these);
if (uts) {
if (get_user (ts.tv_sec, &uts->tv_sec) ||
get_user (ts.tv_nsec, &uts->tv_nsec))
return -EINVAL;
if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
|| ts.tv_sec < 0)
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
if (!sig) {
/* None ready -- temporarily unblock those we're interested
in so that we'll be awakened when they arrive. */
sigset_t oldblocked = current->blocked;
sigandsets(&current->blocked, &current->blocked, &these);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
timeout = MAX_SCHEDULE_TIMEOUT;
if (uts)
timeout = (timespec_to_jiffies(&ts)
+ (ts.tv_sec || ts.tv_nsec));
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
current->blocked = oldblocked;
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock);
if (sig) {
ret = sig;
if (uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
ret = -EFAULT;
}
} else {
ret = -EAGAIN;
if (timeout)
ret = -EINTR;
}
return ret;
}
asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
{ {
siginfo_t info; siginfo_t info;
int ret; int ret;
......
...@@ -863,7 +863,7 @@ _GLOBAL(sys_call_table32) ...@@ -863,7 +863,7 @@ _GLOBAL(sys_call_table32)
.llong .sys32_rt_sigaction .llong .sys32_rt_sigaction
.llong .sys32_rt_sigprocmask .llong .sys32_rt_sigprocmask
.llong .sys32_rt_sigpending /* 175 */ .llong .sys32_rt_sigpending /* 175 */
.llong .sys32_rt_sigtimedwait .llong .compat_rt_sigtimedwait
.llong .sys32_rt_sigqueueinfo .llong .sys32_rt_sigqueueinfo
.llong .ppc32_rt_sigsuspend .llong .ppc32_rt_sigsuspend
.llong .sys32_pread64 .llong .sys32_pread64
......
...@@ -72,7 +72,7 @@ struct sigregs32 { ...@@ -72,7 +72,7 @@ struct sigregs32 {
* *
*/ */
struct rt_sigframe32 { struct rt_sigframe32 {
struct compat_siginfo info; compat_siginfo_t info;
struct ucontext32 uc; struct ucontext32 uc;
/* /*
* Programs using the rs6000/xcoff abi can save up to 19 gp * Programs using the rs6000/xcoff abi can save up to 19 gp
...@@ -341,7 +341,6 @@ long sys32_sigaction(int sig, struct old_sigaction32 __user *act, ...@@ -341,7 +341,6 @@ long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
* sigpending sys32_rt_sigpending * sigpending sys32_rt_sigpending
* sigprocmask sys32_rt_sigprocmask * sigprocmask sys32_rt_sigprocmask
* sigreturn sys32_rt_sigreturn * sigreturn sys32_rt_sigreturn
* sigtimedwait sys32_rt_sigtimedwait
* sigqueueinfo sys32_rt_sigqueueinfo * sigqueueinfo sys32_rt_sigqueueinfo
* sigsuspend sys32_rt_sigsuspend * sigsuspend sys32_rt_sigsuspend
* *
...@@ -445,9 +444,9 @@ long sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) ...@@ -445,9 +444,9 @@ long sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
} }
static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s) int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
{ {
long err; int err;
if (!access_ok (VERIFY_WRITE, d, sizeof(*d))) if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
return -EFAULT; return -EFAULT;
...@@ -500,35 +499,6 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s) ...@@ -500,35 +499,6 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
return err; return err;
} }
long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, compat_siginfo_t __user *uinfo,
struct compat_timespec __user *uts, compat_size_t sigsetsize)
{
sigset_t s;
compat_sigset_t s32;
struct timespec t;
int ret;
mm_segment_t old_fs = get_fs();
siginfo_t info;
if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
sigset_from_compat(&s, &s32);
if (uts && get_compat_timespec(&t, uts))
return -EFAULT;
set_fs(KERNEL_DS);
/* The __user pointer casts are valid because of the set_fs() */
ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
uinfo ? (siginfo_t __user *) &info : NULL,
uts ? (struct timespec __user *) &t : NULL,
sigsetsize);
set_fs(old_fs);
if (ret >= 0 && uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
return -EFAULT;
}
return ret;
}
/* /*
* Note: it is necessary to treat pid and sig as unsigned ints, with the * Note: it is necessary to treat pid and sig as unsigned ints, with the
* corresponding cast to a signed int to insure that the proper conversion * corresponding cast to a signed int to insure that the proper conversion
......
...@@ -634,92 +634,8 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, ...@@ -634,92 +634,8 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
return ret; return ret;
} }
extern int
copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
asmlinkage long
sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo,
struct compat_timespec *uts, size_t sigsetsize)
{
int ret, sig;
sigset_t these;
compat_sigset_t these32;
struct timespec ts;
siginfo_t info;
long timeout = 0;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
switch (_NSIG_WORDS) {
case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
}
/*
* Invert the set of allowed signals to get those we
* want to block.
*/
sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
signotset(&these);
if (uts) {
if (get_compat_timespec(&ts, uts))
return -EINVAL;
if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
|| ts.tv_sec < 0)
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
if (!sig) {
/* None ready -- temporarily unblock those we're interested
in so that we'll be awakened when they arrive. */
current->real_blocked = current->blocked;
sigandsets(&current->blocked, &current->blocked, &these);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
timeout = MAX_SCHEDULE_TIMEOUT;
if (uts)
timeout = (timespec_to_jiffies(&ts)
+ (ts.tv_sec || ts.tv_nsec));
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
current->blocked = current->real_blocked;
siginitset(&current->real_blocked, 0);
recalc_sigpending();
}
spin_unlock_irq(&current->sighand->siglock);
if (sig) {
ret = sig;
if (uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
ret = -EFAULT;
}
} else {
ret = -EAGAIN;
if (timeout)
ret = -EINTR;
}
return ret;
}
asmlinkage long asmlinkage long
sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo) sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
{ {
siginfo_t info; siginfo_t info;
int ret; int ret;
......
...@@ -34,7 +34,7 @@ typedef union sigval32 { ...@@ -34,7 +34,7 @@ typedef union sigval32 {
__u32 sival_ptr; __u32 sival_ptr;
} sigval_t32; } sigval_t32;
typedef struct siginfo32 { typedef struct compat_siginfo {
int si_signo; int si_signo;
int si_errno; int si_errno;
int si_code; int si_code;
...@@ -82,7 +82,7 @@ typedef struct siginfo32 { ...@@ -82,7 +82,7 @@ typedef struct siginfo32 {
int _fd; int _fd;
} _sigpoll; } _sigpoll;
} _sifields; } _sifields;
} siginfo_t32; } compat_siginfo_t;
/* /*
* How these fields are to be accessed. * How these fields are to be accessed.
...@@ -214,7 +214,4 @@ struct sigevent32 { ...@@ -214,7 +214,4 @@ struct sigevent32 {
} _sigev_un; } _sigev_un;
}; };
extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
extern int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from);
#endif /* _ASM_S390X_S390_H */ #endif /* _ASM_S390X_S390_H */
...@@ -48,17 +48,17 @@ typedef struct ...@@ -48,17 +48,17 @@ typedef struct
{ {
__u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
__u8 retcode[S390_SYSCALL_SIZE]; __u8 retcode[S390_SYSCALL_SIZE];
struct siginfo32 info; compat_siginfo_t info;
struct ucontext32 uc; struct ucontext32 uc;
} rt_sigframe32; } rt_sigframe32;
asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset)); asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{ {
int err; int err;
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
/* If you change siginfo_t structure, please be sure /* If you change siginfo_t structure, please be sure
...@@ -106,12 +106,12 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from) ...@@ -106,12 +106,12 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
return err; return err;
} }
int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from) int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{ {
int err; int err;
u32 tmp; u32 tmp;
if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
err = __get_user(to->si_signo, &from->si_signo); err = __get_user(to->si_signo, &from->si_signo);
......
...@@ -840,13 +840,13 @@ sys32_rt_sigpending_wrapper: ...@@ -840,13 +840,13 @@ sys32_rt_sigpending_wrapper:
llgfr %r3,%r3 # size_t llgfr %r3,%r3 # size_t
jg sys32_rt_sigpending # branch to system call jg sys32_rt_sigpending # branch to system call
.globl sys32_rt_sigtimedwait_wrapper .globl compat_rt_sigtimedwait_wrapper
sys32_rt_sigtimedwait_wrapper: compat_rt_sigtimedwait_wrapper:
llgtr %r2,%r2 # const sigset_emu31_t * llgtr %r2,%r2 # const sigset_emu31_t *
llgtr %r3,%r3 # siginfo_emu31_t * llgtr %r3,%r3 # siginfo_emu31_t *
llgtr %r4,%r4 # const struct compat_timespec * llgtr %r4,%r4 # const struct compat_timespec *
llgfr %r5,%r5 # size_t llgfr %r5,%r5 # size_t
jg sys32_rt_sigtimedwait # branch to system call jg compat_rt_sigtimedwait # branch to system call
.globl sys32_rt_sigqueueinfo_wrapper .globl sys32_rt_sigqueueinfo_wrapper
sys32_rt_sigqueueinfo_wrapper: sys32_rt_sigqueueinfo_wrapper:
......
...@@ -559,13 +559,13 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) ...@@ -559,13 +559,13 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
case PTRACE_GETSIGINFO: case PTRACE_GETSIGINFO:
if (child->last_siginfo == NULL) if (child->last_siginfo == NULL)
return -EINVAL; return -EINVAL;
return copy_siginfo_to_user32((siginfo_t32 __user *) data, return copy_siginfo_to_user32((compat_siginfo_t __user *) data,
child->last_siginfo); child->last_siginfo);
case PTRACE_SETSIGINFO: case PTRACE_SETSIGINFO:
if (child->last_siginfo == NULL) if (child->last_siginfo == NULL)
return -EINVAL; return -EINVAL;
return copy_siginfo_from_user32(child->last_siginfo, return copy_siginfo_from_user32(child->last_siginfo,
(siginfo_t32 __user *) data); (compat_siginfo_t __user *) data);
} }
return ptrace_request(child, request, addr, data); return ptrace_request(child, request, addr, data);
} }
......
...@@ -185,7 +185,7 @@ SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue) ...@@ -185,7 +185,7 @@ SYSCALL(sys_rt_sigreturn_glue,sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue)
SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper) SYSCALL(sys_rt_sigaction,sys_rt_sigaction,sys32_rt_sigaction_wrapper)
SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */ SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */
SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper) SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper) SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_rt_sigtimedwait_wrapper)
SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper) SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue) SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper) /* 180 */ SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper) /* 180 */
......
...@@ -86,7 +86,7 @@ struct new_signal_frame32 { ...@@ -86,7 +86,7 @@ struct new_signal_frame32 {
__siginfo_fpu_t fpu_state; __siginfo_fpu_t fpu_state;
}; };
struct siginfo32 { typedef struct compat_siginfo{
int si_signo; int si_signo;
int si_errno; int si_errno;
int si_code; int si_code;
...@@ -136,11 +136,11 @@ struct siginfo32 { ...@@ -136,11 +136,11 @@ struct siginfo32 {
int _fd; int _fd;
} _sigpoll; } _sigpoll;
} _sifields; } _sifields;
}; }compat_siginfo_t;
struct rt_signal_frame32 { struct rt_signal_frame32 {
struct sparc_stackf32 ss; struct sparc_stackf32 ss;
struct siginfo32 info; compat_siginfo_t info;
struct pt_regs32 regs; struct pt_regs32 regs;
compat_sigset_t mask; compat_sigset_t mask;
/* __siginfo_fpu32_t * */ u32 fpu_save; /* __siginfo_fpu32_t * */ u32 fpu_save;
...@@ -157,11 +157,11 @@ struct rt_signal_frame32 { ...@@ -157,11 +157,11 @@ struct rt_signal_frame32 {
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7))) #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from) int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{ {
int err; int err;
if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32))) if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
/* If you change siginfo_t structure, please be sure /* If you change siginfo_t structure, please be sure
...@@ -210,9 +210,9 @@ int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from) ...@@ -210,9 +210,9 @@ int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
/* CAUTION: This is just a very minimalist implementation for the /* CAUTION: This is just a very minimalist implementation for the
* sake of compat_sys_rt_sigqueueinfo() * sake of compat_sys_rt_sigqueueinfo()
*/ */
int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from) int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{ {
if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32))) if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
if (copy_from_user(to, from, 3*sizeof(int)) || if (copy_from_user(to, from, 3*sizeof(int)) ||
......
...@@ -1044,99 +1044,14 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, ...@@ -1044,99 +1044,14 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
return ret; return ret;
} }
asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
struct siginfo32 __user *uinfo,
struct compat_timespec __user *uts,
compat_size_t sigsetsize)
{
int ret, sig;
sigset_t these;
compat_sigset_t these32;
struct timespec ts;
siginfo_t info;
long timeout = 0;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user (&these32, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
switch (_NSIG_WORDS) {
case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
}
/*
* Invert the set of allowed signals to get those we
* want to block.
*/
sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
signotset(&these);
if (uts) {
if (get_compat_timespec(&ts, uts))
return -EINVAL;
if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
|| ts.tv_sec < 0)
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
if (!sig) {
timeout = MAX_SCHEDULE_TIMEOUT;
if (uts)
timeout = (timespec_to_jiffies(&ts)
+ (ts.tv_sec || ts.tv_nsec));
if (timeout) {
/* None ready -- temporarily unblock those we're
* interested while we are sleeping in so that we'll
* be awakened when they arrive. */
current->real_blocked = current->blocked;
sigandsets(&current->blocked, &current->blocked, &these);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
current->blocked = current->real_blocked;
siginitset(&current->real_blocked, 0);
recalc_sigpending();
}
}
spin_unlock_irq(&current->sighand->siglock);
if (sig) {
ret = sig;
if (uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
ret = -EFAULT;
}
} else {
ret = -EAGAIN;
if (timeout)
ret = -EINTR;
}
return ret;
}
asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig, asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
struct siginfo32 __user *uinfo) struct compat_siginfo __user *uinfo)
{ {
siginfo_t info; siginfo_t info;
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
if (copy_siginfo_to_kernel32(&info, uinfo)) if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT; return -EFAULT;
set_fs (KERNEL_DS); set_fs (KERNEL_DS);
...@@ -1739,8 +1654,8 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, ...@@ -1739,8 +1654,8 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
} }
asmlinkage long compat_sys_waitid(u32 which, u32 pid, asmlinkage long compat_sys_waitid(u32 which, u32 pid,
struct siginfo32 __user *uinfo, u32 options, struct compat_siginfo __user *uinfo,
struct compat_rusage __user *uru) u32 options, struct compat_rusage __user *uru)
{ {
siginfo_t info; siginfo_t info;
struct rusage ru; struct rusage ru;
......
...@@ -41,7 +41,7 @@ sys_call_table32: ...@@ -41,7 +41,7 @@ sys_call_table32:
/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
.word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid .word compat_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
.word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
......
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
void signal_fault(struct pt_regs *regs, void __user *frame, char *where); void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from) int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{ {
int err; int err;
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
/* If you change siginfo_t structure, please make sure that /* If you change siginfo_t structure, please make sure that
...@@ -95,11 +95,11 @@ int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from) ...@@ -95,11 +95,11 @@ int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from)
return err; return err;
} }
int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from) int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{ {
int err; int err;
u32 ptr32; u32 ptr32;
if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
return -EFAULT; return -EFAULT;
err = __get_user(to->si_signo, &from->si_signo); err = __get_user(to->si_signo, &from->si_signo);
...@@ -188,7 +188,7 @@ struct rt_sigframe ...@@ -188,7 +188,7 @@ struct rt_sigframe
int sig; int sig;
u32 pinfo; u32 pinfo;
u32 puc; u32 puc;
struct siginfo32 info; compat_siginfo_t info;
struct ucontext_ia32 uc; struct ucontext_ia32 uc;
struct _fpstate_ia32 fpstate; struct _fpstate_ia32 fpstate;
char retcode[8]; char retcode[8];
...@@ -536,7 +536,7 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -536,7 +536,7 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
err |= __put_user((u32)(u64)&frame->info, &frame->pinfo); err |= __put_user((u32)(u64)&frame->info, &frame->pinfo);
err |= __put_user((u32)(u64)&frame->uc, &frame->puc); err |= __put_user((u32)(u64)&frame->uc, &frame->puc);
err |= ia32_copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user32(&frame->info, info);
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
......
...@@ -479,7 +479,7 @@ ia32_sys_call_table: ...@@ -479,7 +479,7 @@ ia32_sys_call_table:
.quad sys32_rt_sigaction .quad sys32_rt_sigaction
.quad sys32_rt_sigprocmask /* 175 */ .quad sys32_rt_sigprocmask /* 175 */
.quad sys32_rt_sigpending .quad sys32_rt_sigpending
.quad sys32_rt_sigtimedwait .quad compat_rt_sigtimedwait
.quad sys32_rt_sigqueueinfo .quad sys32_rt_sigqueueinfo
.quad stub32_rt_sigsuspend .quad stub32_rt_sigsuspend
.quad sys32_pread /* 180 */ .quad sys32_pread /* 180 */
......
...@@ -628,53 +628,14 @@ sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) ...@@ -628,53 +628,14 @@ sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
return ret; return ret;
} }
asmlinkage long
sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
struct compat_timespec __user *uts, compat_size_t sigsetsize)
{
sigset_t s;
compat_sigset_t s32;
struct timespec t;
int ret;
mm_segment_t old_fs = get_fs();
siginfo_t info;
if (copy_from_user (&s32, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
switch (_NSIG_WORDS) {
case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
}
if (uts && get_compat_timespec(&t, uts))
return -EFAULT;
if (uinfo) {
/* stop data leak to user space in case of structure fill mismatch
* between sys_rt_sigtimedwait & ia32_copy_siginfo_to_user.
*/
memset(&info, 0, sizeof(info));
}
set_fs (KERNEL_DS);
ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
sigsetsize);
set_fs (old_fs);
if (ret >= 0 && uinfo) {
if (ia32_copy_siginfo_to_user(uinfo, &info))
return -EFAULT;
}
return ret;
}
asmlinkage long asmlinkage long
sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo) sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
{ {
siginfo_t info; siginfo_t info;
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
if (ia32_copy_siginfo_from_user(&info, uinfo)) if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT; return -EFAULT;
set_fs (KERNEL_DS); set_fs (KERNEL_DS);
ret = sys_rt_sigqueueinfo(pid, sig, &info); ret = sys_rt_sigqueueinfo(pid, sig, &info);
...@@ -1000,7 +961,7 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, ...@@ -1000,7 +961,7 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
} }
asmlinkage long sys32_waitid(int which, compat_pid_t pid, asmlinkage long sys32_waitid(int which, compat_pid_t pid,
siginfo_t32 __user *uinfo, int options, compat_siginfo_t __user *uinfo, int options,
struct compat_rusage __user *uru) struct compat_rusage __user *uru)
{ {
siginfo_t info; siginfo_t info;
...@@ -1022,7 +983,7 @@ asmlinkage long sys32_waitid(int which, compat_pid_t pid, ...@@ -1022,7 +983,7 @@ asmlinkage long sys32_waitid(int which, compat_pid_t pid,
BUG_ON(info.si_code & __SI_MASK); BUG_ON(info.si_code & __SI_MASK);
info.si_code |= __SI_CHLD; info.si_code |= __SI_CHLD;
return ia32_copy_siginfo_to_user(uinfo, &info); return copy_siginfo_to_user32(uinfo, &info);
} }
/* /*
......
...@@ -137,5 +137,8 @@ static inline void *compat_alloc_user_space(long len) ...@@ -137,5 +137,8 @@ static inline void *compat_alloc_user_space(long len)
return (void *) (regs->regs[29] - len); return (void *) (regs->regs[29] - len);
} }
#if defined (__MIPSEL__)
#define __COMPAT_ENDIAN_SWAP__ 1
#endif
#endif /* _ASM_COMPAT_H */ #endif /* _ASM_COMPAT_H */
...@@ -24,7 +24,7 @@ typedef union sigval32 { ...@@ -24,7 +24,7 @@ typedef union sigval32 {
u32 sival_ptr; u32 sival_ptr;
} sigval_t32; } sigval_t32;
struct siginfo32; struct compat_siginfo;
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
...@@ -56,9 +56,6 @@ typedef struct sigevent32 { ...@@ -56,9 +56,6 @@ typedef struct sigevent32 {
} _sigev_un; } _sigev_un;
} sigevent_t32; } sigevent_t32;
extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -78,7 +78,7 @@ struct stat64 { ...@@ -78,7 +78,7 @@ struct stat64 {
unsigned long long st_ino; unsigned long long st_ino;
} __attribute__((packed)); } __attribute__((packed));
typedef struct siginfo32 { typedef struct compat_siginfo{
int si_signo; int si_signo;
int si_errno; int si_errno;
int si_code; int si_code;
...@@ -128,7 +128,7 @@ typedef struct siginfo32 { ...@@ -128,7 +128,7 @@ typedef struct siginfo32 {
int _fd; int _fd;
} _sigpoll; } _sigpoll;
} _sifields; } _sifields;
} siginfo_t32; } compat_siginfo_t;
struct sigframe32 struct sigframe32
{ {
...@@ -145,7 +145,7 @@ struct rt_sigframe32 ...@@ -145,7 +145,7 @@ struct rt_sigframe32
int sig; int sig;
u32 pinfo; u32 pinfo;
u32 puc; u32 puc;
struct siginfo32 info; compat_siginfo_t info;
struct ucontext_ia32 uc; struct ucontext_ia32 uc;
struct _fpstate_ia32 fpstate; struct _fpstate_ia32 fpstate;
}; };
...@@ -165,8 +165,6 @@ struct siginfo_t; ...@@ -165,8 +165,6 @@ struct siginfo_t;
int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info); int do_get_thread_area(struct thread_struct *t, struct user_desc __user *info);
int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info); int do_set_thread_area(struct thread_struct *t, struct user_desc __user *info);
int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs); int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from);
int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from);
#endif #endif
#endif /* !CONFIG_IA32_SUPPORT */ #endif /* !CONFIG_IA32_SUPPORT */
......
...@@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask, ...@@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
unsigned long bitmap_size); unsigned long bitmap_size);
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
unsigned long bitmap_size); unsigned long bitmap_size);
struct compat_siginfo;
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);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */ #endif /* _LINUX_COMPAT_H */
...@@ -682,6 +682,92 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, ...@@ -682,6 +682,92 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
return 0; return 0;
} }
void
sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
{
switch (_NSIG_WORDS) {
#if defined (__COMPAT_ENDIAN_SWAP__)
case 4: set->sig[3] = compat->sig[7] | (((long)compat->sig[6]) << 32 );
case 3: set->sig[2] = compat->sig[5] | (((long)compat->sig[4]) << 32 );
case 2: set->sig[1] = compat->sig[3] | (((long)compat->sig[2]) << 32 );
case 1: set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 );
#else
case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
#endif
}
}
asmlinkage long
compat_rt_sigtimedwait (compat_sigset_t __user *uthese,
struct compat_siginfo __user *uinfo,
struct compat_timespec __user *uts, compat_size_t sigsetsize)
{
compat_sigset_t s32;
sigset_t s;
int sig;
struct timespec t;
siginfo_t info;
long ret, timeout = 0;
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
return -EFAULT;
sigset_from_compat(&s, &s32);
sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP));
signotset(&s);
if (uts) {
if (get_compat_timespec (&t, uts))
return -EFAULT;
if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0
|| t.tv_sec < 0)
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &s, &info);
if (!sig) {
timeout = MAX_SCHEDULE_TIMEOUT;
if (uts)
timeout = timespec_to_jiffies(&t)
+(t.tv_sec || t.tv_nsec);
if (timeout) {
current->real_blocked = current->blocked;
sigandsets(&current->blocked, &current->blocked, &s);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &s, &info);
current->blocked = current->real_blocked;
siginitset(&current->real_blocked, 0);
recalc_sigpending();
}
}
spin_unlock_irq(&current->sighand->siglock);
if (sig) {
ret = sig;
if (uinfo) {
if (copy_siginfo_to_user32(uinfo, &info))
ret = -EFAULT;
}
}else {
ret = timeout?-EINTR:-EAGAIN;
}
return ret;
}
#ifdef __ARCH_WANT_COMPAT_SYS_TIME #ifdef __ARCH_WANT_COMPAT_SYS_TIME
/* compat_time_t is a 32 bit "long" and needs to get converted. */ /* compat_time_t is a 32 bit "long" and needs to get converted. */
......
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