From: "Zou, Nanhai" Signed-off-by: Zou Nan hai Signed-off-by: Andrew Morton --- 25-akpm/arch/ia64/ia32/ia32_entry.S | 2 25-akpm/arch/ia64/ia32/ia32_signal.c | 39 +---------- 25-akpm/arch/ia64/ia32/ia32priv.h | 8 -- 25-akpm/arch/ia64/ia32/sys_ia32.c | 2 25-akpm/arch/mips/kernel/scall64-n32.S | 2 25-akpm/arch/mips/kernel/scall64-o32.S | 2 25-akpm/arch/mips/kernel/signal32.c | 105 ++---------------------------- 25-akpm/arch/ppc64/kernel/misc.S | 2 25-akpm/arch/ppc64/kernel/signal32.c | 34 --------- 25-akpm/arch/s390/kernel/compat_linux.c | 86 ------------------------ 25-akpm/arch/s390/kernel/compat_linux.h | 7 -- 25-akpm/arch/s390/kernel/compat_signal.c | 10 +- 25-akpm/arch/s390/kernel/compat_wrapper.S | 6 - 25-akpm/arch/s390/kernel/ptrace.c | 4 - 25-akpm/arch/s390/kernel/syscalls.S | 2 25-akpm/arch/sparc64/kernel/signal32.c | 14 ++-- 25-akpm/arch/sparc64/kernel/sys_sparc32.c | 89 ------------------------- 25-akpm/arch/sparc64/kernel/systbls.S | 2 25-akpm/arch/x86_64/ia32/ia32_signal.c | 12 +-- 25-akpm/arch/x86_64/ia32/ia32entry.S | 2 25-akpm/arch/x86_64/ia32/sys_ia32.c | 47 +------------ 25-akpm/include/asm-mips/compat.h | 3 25-akpm/include/asm-sparc64/siginfo.h | 5 - 25-akpm/include/asm-x86_64/ia32.h | 8 -- 25-akpm/include/linux/compat.h | 4 - 25-akpm/kernel/compat.c | 86 ++++++++++++++++++++++++ 26 files changed, 153 insertions(+), 430 deletions(-) diff -puN arch/ia64/ia32/ia32_entry.S~compat-sigtimedwait arch/ia64/ia32/ia32_entry.S --- 25/arch/ia64/ia32/ia32_entry.S~compat-sigtimedwait 2004-12-14 01:15:38.289531528 -0800 +++ 25-akpm/arch/ia64/ia32/ia32_entry.S 2004-12-14 01:15:38.328525600 -0800 @@ -387,7 +387,7 @@ ia32_syscall_table: data8 sys32_rt_sigaction data8 sys32_rt_sigprocmask /* 175 */ data8 sys_rt_sigpending - data8 sys32_rt_sigtimedwait + data8 compat_rt_sigtimedwait data8 sys32_rt_sigqueueinfo data8 sys32_rt_sigsuspend data8 sys32_pread /* 180 */ diff -puN arch/ia64/ia32/ia32priv.h~compat-sigtimedwait arch/ia64/ia32/ia32priv.h --- 25/arch/ia64/ia32/ia32priv.h~compat-sigtimedwait 2004-12-14 01:15:38.291531224 -0800 +++ 25-akpm/arch/ia64/ia32/ia32priv.h 2004-12-14 01:15:38.330525296 -0800 @@ -232,7 +232,7 @@ typedef union sigval32 { #define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) -typedef struct siginfo32 { +typedef struct compat_siginfo { int si_signo; int si_errno; int si_code; @@ -282,7 +282,7 @@ typedef struct siginfo32 { int _fd; } _sigpoll; } _sifields; -} siginfo_t32; +} compat_siginfo_t; typedef struct sigevent32 { sigval_t32 sigev_value; @@ -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_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 /* _ASM_IA64_IA32_PRIV_H */ diff -puN arch/ia64/ia32/ia32_signal.c~compat-sigtimedwait arch/ia64/ia32/ia32_signal.c --- 25/arch/ia64/ia32/ia32_signal.c~compat-sigtimedwait 2004-12-14 01:15:38.292531072 -0800 +++ 25-akpm/arch/ia64/ia32/ia32_signal.c 2004-12-14 01:15:38.329525448 -0800 @@ -59,19 +59,19 @@ struct rt_sigframe_ia32 int sig; int pinfo; int puc; - siginfo_t32 info; + compat_siginfo_t info; struct ucontext_ia32 uc; struct _fpstate_ia32 fpstate; char retcode[8]; }; 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; int err; - if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32))) + if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t))) return -EFAULT; err = __get_user(to->si_signo, &from->si_signo); @@ -110,12 +110,12 @@ copy_siginfo_from_user32 (siginfo_t *to, } 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; int err; - if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32))) + if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please be sure @@ -589,34 +589,7 @@ sys32_rt_sigprocmask (int how, compat_si } asmlinkage long -sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __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) +sys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo) { mm_segment_t old_fs = get_fs(); siginfo_t info; diff -puN arch/ia64/ia32/sys_ia32.c~compat-sigtimedwait arch/ia64/ia32/sys_ia32.c --- 25/arch/ia64/ia32/sys_ia32.c~compat-sigtimedwait 2004-12-14 01:15:38.294530768 -0800 +++ 25-akpm/arch/ia64/ia32/sys_ia32.c 2004-12-14 01:15:38.331525144 -0800 @@ -2641,7 +2641,7 @@ long sys32_fadvise64_64(int fd, __u32 of } 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) { siginfo_t info; diff -puN arch/mips/kernel/scall64-n32.S~compat-sigtimedwait arch/mips/kernel/scall64-n32.S --- 25/arch/mips/kernel/scall64-n32.S~compat-sigtimedwait 2004-12-14 01:15:38.295530616 -0800 +++ 25-akpm/arch/mips/kernel/scall64-n32.S 2004-12-14 01:15:38.332524992 -0800 @@ -243,7 +243,7 @@ EXPORT(sysn32_call_table) PTR sys_capget PTR sys_capset PTR sys32_rt_sigpending /* 6125 */ - PTR sys32_rt_sigtimedwait + PTR compat_rt_sigtimedwait PTR sys32_rt_sigqueueinfo PTR sys32_rt_sigsuspend PTR sys32_sigaltstack diff -puN arch/mips/kernel/scall64-o32.S~compat-sigtimedwait arch/mips/kernel/scall64-o32.S --- 25/arch/mips/kernel/scall64-o32.S~compat-sigtimedwait 2004-12-14 01:15:38.296530464 -0800 +++ 25-akpm/arch/mips/kernel/scall64-o32.S 2004-12-14 01:15:38.333524840 -0800 @@ -420,7 +420,7 @@ sys_call_table: PTR sys32_rt_sigaction PTR sys32_rt_sigprocmask /* 4195 */ PTR sys32_rt_sigpending - PTR sys32_rt_sigtimedwait + PTR compat_rt_sigtimedwait PTR sys32_rt_sigqueueinfo PTR sys32_rt_sigsuspend PTR sys32_pread /* 4200 */ diff -puN arch/mips/kernel/signal32.c~compat-sigtimedwait arch/mips/kernel/signal32.c --- 25/arch/mips/kernel/signal32.c~compat-sigtimedwait 2004-12-14 01:15:38.298530160 -0800 +++ 25-akpm/arch/mips/kernel/signal32.c 2004-12-14 01:15:38.334524688 -0800 @@ -37,7 +37,7 @@ typedef union sigval32 { s32 sival_ptr; } sigval_t32; -typedef struct siginfo32 { +typedef struct compat_siginfo{ int si_signo; int si_code; int si_errno; @@ -93,7 +93,7 @@ typedef struct siginfo32 { } _rt; } _sifields; -} siginfo_t32; +} compat_siginfo_t; /* * Including would give use the 64-bit syscall numbers ... @@ -389,15 +389,15 @@ struct sigframe { struct rt_sigframe32 { u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_code[2]; /* signal trampoline */ - struct siginfo32 rs_info; + struct compat_siginfo_t rs_info; 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; - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) + if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please be sure @@ -677,7 +677,7 @@ static inline void setup_rt_frame(struct err |= __put_user(0x0000000c , frame->rs_code + 1); 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); /* Create the ucontext. */ @@ -890,98 +890,7 @@ asmlinkage int sys32_rt_sigpending(compa return ret; } -asmlinkage int sys32_rt_sigtimedwait(compat_sigset_t *uthese, - 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(¤t->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(¤t->blocked, ¤t->blocked, &these); - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - sig = dequeue_signal(current, &these, &info); - current->blocked = oldblocked; - recalc_sigpending(); - } - spin_unlock_irq(¤t->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) +asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t *uinfo) { siginfo_t info; int ret; diff -puN arch/ppc64/kernel/misc.S~compat-sigtimedwait arch/ppc64/kernel/misc.S --- 25/arch/ppc64/kernel/misc.S~compat-sigtimedwait 2004-12-14 01:15:38.299530008 -0800 +++ 25-akpm/arch/ppc64/kernel/misc.S 2004-12-14 01:15:38.335524536 -0800 @@ -870,7 +870,7 @@ _GLOBAL(sys_call_table32) .llong .sys32_rt_sigaction .llong .sys32_rt_sigprocmask .llong .sys32_rt_sigpending /* 175 */ - .llong .sys32_rt_sigtimedwait + .llong .compat_rt_sigtimedwait .llong .sys32_rt_sigqueueinfo .llong .ppc32_rt_sigsuspend .llong .sys32_pread64 diff -puN arch/ppc64/kernel/signal32.c~compat-sigtimedwait arch/ppc64/kernel/signal32.c --- 25/arch/ppc64/kernel/signal32.c~compat-sigtimedwait 2004-12-14 01:15:38.301529704 -0800 +++ 25-akpm/arch/ppc64/kernel/signal32.c 2004-12-14 01:15:38.337524232 -0800 @@ -71,7 +71,7 @@ struct sigregs32 { * */ struct rt_sigframe32 { - struct compat_siginfo info; + compat_siginfo_t info; struct ucontext32 uc; /* * Programs using the rs6000/xcoff abi can save up to 19 gp @@ -342,7 +342,6 @@ long sys32_sigaction(int sig, struct old * sigpending sys32_rt_sigpending * sigprocmask sys32_rt_sigprocmask * sigreturn sys32_rt_sigreturn - * sigtimedwait sys32_rt_sigtimedwait * sigqueueinfo sys32_rt_sigqueueinfo * sigsuspend sys32_rt_sigsuspend * @@ -446,7 +445,7 @@ long sys32_rt_sigpending(compat_sigset_t } -static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s) +long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s) { long err; @@ -501,35 +500,6 @@ static long copy_siginfo_to_user32(compa 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 * corresponding cast to a signed int to insure that the proper conversion diff -puN arch/s390/kernel/compat_linux.c~compat-sigtimedwait arch/s390/kernel/compat_linux.c --- 25/arch/s390/kernel/compat_linux.c~compat-sigtimedwait 2004-12-14 01:15:38.302529552 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.c 2004-12-14 01:15:38.338524080 -0800 @@ -634,92 +634,8 @@ asmlinkage long sys32_rt_sigpending(comp 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(¤t->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(¤t->blocked, ¤t->blocked, &these); - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - sig = dequeue_signal(current, &these, &info); - current->blocked = current->real_blocked; - siginitset(¤t->real_blocked, 0); - recalc_sigpending(); - } - spin_unlock_irq(¤t->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 -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; int ret; diff -puN arch/s390/kernel/compat_linux.h~compat-sigtimedwait arch/s390/kernel/compat_linux.h --- 25/arch/s390/kernel/compat_linux.h~compat-sigtimedwait 2004-12-14 01:15:38.303529400 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.h 2004-12-14 01:15:38.338524080 -0800 @@ -34,7 +34,7 @@ typedef union sigval32 { __u32 sival_ptr; } sigval_t32; -typedef struct siginfo32 { +typedef struct compat_siginfo { int si_signo; int si_errno; int si_code; @@ -82,7 +82,7 @@ typedef struct siginfo32 { int _fd; } _sigpoll; } _sifields; -} siginfo_t32; +} compat_siginfo_t; /* * How these fields are to be accessed. @@ -214,7 +214,4 @@ struct sigevent32 { } _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 */ diff -puN arch/s390/kernel/compat_signal.c~compat-sigtimedwait arch/s390/kernel/compat_signal.c --- 25/arch/s390/kernel/compat_signal.c~compat-sigtimedwait 2004-12-14 01:15:38.305529096 -0800 +++ 25-akpm/arch/s390/kernel/compat_signal.c 2004-12-14 01:15:38.339523928 -0800 @@ -48,17 +48,17 @@ typedef struct { __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; __u8 retcode[S390_SYSCALL_SIZE]; - struct siginfo32 info; + compat_siginfo_t info; struct ucontext32 uc; } rt_sigframe32; 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; - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) + if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please be sure @@ -106,12 +106,12 @@ int copy_siginfo_to_user32(siginfo_t32 _ 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; u32 tmp; - if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) + if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t))) return -EFAULT; err = __get_user(to->si_signo, &from->si_signo); diff -puN arch/s390/kernel/compat_wrapper.S~compat-sigtimedwait arch/s390/kernel/compat_wrapper.S --- 25/arch/s390/kernel/compat_wrapper.S~compat-sigtimedwait 2004-12-14 01:15:38.306528944 -0800 +++ 25-akpm/arch/s390/kernel/compat_wrapper.S 2004-12-14 01:15:38.340523776 -0800 @@ -840,13 +840,13 @@ sys32_rt_sigpending_wrapper: llgfr %r3,%r3 # size_t jg sys32_rt_sigpending # branch to system call - .globl sys32_rt_sigtimedwait_wrapper -sys32_rt_sigtimedwait_wrapper: + .globl compat_rt_sigtimedwait_wrapper +compat_rt_sigtimedwait_wrapper: llgtr %r2,%r2 # const sigset_emu31_t * llgtr %r3,%r3 # siginfo_emu31_t * llgtr %r4,%r4 # const struct compat_timespec * 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 sys32_rt_sigqueueinfo_wrapper: diff -puN arch/s390/kernel/ptrace.c~compat-sigtimedwait arch/s390/kernel/ptrace.c --- 25/arch/s390/kernel/ptrace.c~compat-sigtimedwait 2004-12-14 01:15:38.308528640 -0800 +++ 25-akpm/arch/s390/kernel/ptrace.c 2004-12-14 01:15:38.341523624 -0800 @@ -559,13 +559,13 @@ do_ptrace_emu31(struct task_struct *chil case PTRACE_GETSIGINFO: if (child->last_siginfo == NULL) return -EINVAL; - return copy_siginfo_to_user32((siginfo_t32 __user *) data, + return copy_siginfo_to_user32((compat_siginfo_t __user *) data, child->last_siginfo); case PTRACE_SETSIGINFO: if (child->last_siginfo == NULL) return -EINVAL; return copy_siginfo_from_user32(child->last_siginfo, - (siginfo_t32 __user *) data); + (compat_siginfo_t __user *) data); } return ptrace_request(child, request, addr, data); } diff -puN arch/s390/kernel/syscalls.S~compat-sigtimedwait arch/s390/kernel/syscalls.S --- 25/arch/s390/kernel/syscalls.S~compat-sigtimedwait 2004-12-14 01:15:38.309528488 -0800 +++ 25-akpm/arch/s390/kernel/syscalls.S 2004-12-14 01:15:38.342523472 -0800 @@ -185,7 +185,7 @@ SYSCALL(sys_rt_sigreturn_glue,sys_rt_sig 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_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_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue) SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper) /* 180 */ diff -puN arch/sparc64/kernel/signal32.c~compat-sigtimedwait arch/sparc64/kernel/signal32.c --- 25/arch/sparc64/kernel/signal32.c~compat-sigtimedwait 2004-12-14 01:15:38.310528336 -0800 +++ 25-akpm/arch/sparc64/kernel/signal32.c 2004-12-14 01:15:38.343523320 -0800 @@ -86,7 +86,7 @@ struct new_signal_frame32 { __siginfo_fpu_t fpu_state; }; -struct siginfo32 { +typedef struct compat_siginfo{ int si_signo; int si_errno; int si_code; @@ -136,11 +136,11 @@ struct siginfo32 { int _fd; } _sigpoll; } _sifields; -}; +}compat_siginfo_t; struct rt_signal_frame32 { struct sparc_stackf32 ss; - struct siginfo32 info; + compat_siginfo_t info; struct pt_regs32 regs; compat_sigset_t mask; /* __siginfo_fpu32_t * */ u32 fpu_save; @@ -157,11 +157,11 @@ struct rt_signal_frame32 { #define NF_ALIGNEDSZ (((sizeof(struct new_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; - if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32))) + if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please be sure @@ -210,9 +210,9 @@ int copy_siginfo_to_user32(struct siginf /* CAUTION: This is just a very minimalist implementation for the * sake of compat_sys_rt_sigqueueinfo() */ -int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from) +int copy_siginfo_to_kernel32(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; if (copy_from_user(to, from, 3*sizeof(int)) || diff -puN arch/sparc64/kernel/sys_sparc32.c~compat-sigtimedwait arch/sparc64/kernel/sys_sparc32.c --- 25/arch/sparc64/kernel/sys_sparc32.c~compat-sigtimedwait 2004-12-14 01:15:38.312528032 -0800 +++ 25-akpm/arch/sparc64/kernel/sys_sparc32.c 2004-12-14 01:15:38.345523016 -0800 @@ -1044,93 +1044,8 @@ asmlinkage long sys32_rt_sigpending(comp 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(¤t->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(¤t->blocked, ¤t->blocked, &these); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - timeout = schedule_timeout(timeout); - - spin_lock_irq(¤t->sighand->siglock); - sig = dequeue_signal(current, &these, &info); - current->blocked = current->real_blocked; - siginitset(¤t->real_blocked, 0); - recalc_sigpending(); - } - } - spin_unlock_irq(¤t->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, - struct siginfo32 __user *uinfo) + compat_siginfo_t __user *uinfo) { siginfo_t info; int ret; @@ -1739,7 +1654,7 @@ sys32_timer_create(u32 clock, struct sig } asmlinkage long compat_sys_waitid(u32 which, u32 pid, - struct siginfo32 __user *uinfo, u32 options, + compat_siginfo_t __user *uinfo, u32 options, struct compat_rusage __user *uru) { siginfo_t info; diff -puN arch/sparc64/kernel/systbls.S~compat-sigtimedwait arch/sparc64/kernel/systbls.S --- 25/arch/sparc64/kernel/systbls.S~compat-sigtimedwait 2004-12-14 01:15:38.314527728 -0800 +++ 25-akpm/arch/sparc64/kernel/systbls.S 2004-12-14 01:15:38.345523016 -0800 @@ -41,7 +41,7 @@ sys_call_table32: /*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 /*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 .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 diff -puN arch/x86_64/ia32/ia32entry.S~compat-sigtimedwait arch/x86_64/ia32/ia32entry.S --- 25/arch/x86_64/ia32/ia32entry.S~compat-sigtimedwait 2004-12-14 01:15:38.315527576 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32entry.S 2004-12-14 01:15:38.347522712 -0800 @@ -479,7 +479,7 @@ ia32_sys_call_table: .quad sys32_rt_sigaction .quad sys32_rt_sigprocmask /* 175 */ .quad sys32_rt_sigpending - .quad sys32_rt_sigtimedwait + .quad compat_rt_sigtimedwait .quad sys32_rt_sigqueueinfo .quad stub32_rt_sigsuspend .quad sys32_pread /* 180 */ diff -puN arch/x86_64/ia32/ia32_signal.c~compat-sigtimedwait arch/x86_64/ia32/ia32_signal.c --- 25/arch/x86_64/ia32/ia32_signal.c~compat-sigtimedwait 2004-12-14 01:15:38.316527424 -0800 +++ 25-akpm/arch/x86_64/ia32/ia32_signal.c 2004-12-14 01:15:38.346522864 -0800 @@ -44,10 +44,10 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); 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; - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) + if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please make sure that @@ -95,11 +95,11 @@ int ia32_copy_siginfo_to_user(siginfo_t3 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; u32 ptr32; - if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32))) + if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t))) return -EFAULT; err = __get_user(to->si_signo, &from->si_signo); @@ -188,7 +188,7 @@ struct rt_sigframe int sig; u32 pinfo; u32 puc; - struct siginfo32 info; + compat_siginfo_t info; struct ucontext_ia32 uc; struct _fpstate_ia32 fpstate; char retcode[8]; @@ -536,7 +536,7 @@ void ia32_setup_rt_frame(int sig, struct } err |= __put_user((u32)(u64)&frame->info, &frame->pinfo); 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) goto give_sigsegv; diff -puN arch/x86_64/ia32/sys_ia32.c~compat-sigtimedwait arch/x86_64/ia32/sys_ia32.c --- 25/arch/x86_64/ia32/sys_ia32.c~compat-sigtimedwait 2004-12-14 01:15:38.318527120 -0800 +++ 25-akpm/arch/x86_64/ia32/sys_ia32.c 2004-12-14 01:15:38.348522560 -0800 @@ -628,53 +628,14 @@ sys32_rt_sigpending(compat_sigset_t __us 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 -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; int ret; mm_segment_t old_fs = get_fs(); - if (ia32_copy_siginfo_from_user(&info, uinfo)) + if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); @@ -1000,7 +961,7 @@ asmlinkage long sys32_clone(unsigned int } 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) { siginfo_t info; @@ -1022,7 +983,7 @@ asmlinkage long sys32_waitid(int which, BUG_ON(info.si_code & __SI_MASK); info.si_code |= __SI_CHLD; - return ia32_copy_siginfo_to_user(uinfo, &info); + return copy_siginfo_to_user32(uinfo, &info); } /* diff -puN include/asm-mips/compat.h~compat-sigtimedwait include/asm-mips/compat.h --- 25/include/asm-mips/compat.h~compat-sigtimedwait 2004-12-14 01:15:38.319526968 -0800 +++ 25-akpm/include/asm-mips/compat.h 2004-12-14 01:15:38.348522560 -0800 @@ -137,5 +137,8 @@ static inline void *compat_alloc_user_sp return (void *) (regs->regs[29] - len); } +#if defined (__MIPSEL__) +#define __COMPAT_ENDIAN_SWAP__ 1 +#endif #endif /* _ASM_COMPAT_H */ diff -puN include/asm-sparc64/siginfo.h~compat-sigtimedwait include/asm-sparc64/siginfo.h --- 25/include/asm-sparc64/siginfo.h~compat-sigtimedwait 2004-12-14 01:15:38.320526816 -0800 +++ 25-akpm/include/asm-sparc64/siginfo.h 2004-12-14 01:15:38.349522408 -0800 @@ -24,7 +24,7 @@ typedef union sigval32 { u32 sival_ptr; } sigval_t32; -struct siginfo32; +struct compat_siginfo; #endif /* CONFIG_COMPAT */ @@ -56,9 +56,6 @@ typedef struct sigevent32 { } _sigev_un; } 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 /* __KERNEL__ */ diff -puN include/asm-x86_64/ia32.h~compat-sigtimedwait include/asm-x86_64/ia32.h --- 25/include/asm-x86_64/ia32.h~compat-sigtimedwait 2004-12-14 01:15:38.322526512 -0800 +++ 25-akpm/include/asm-x86_64/ia32.h 2004-12-14 01:15:38.349522408 -0800 @@ -78,7 +78,7 @@ struct stat64 { unsigned long long st_ino; } __attribute__((packed)); -typedef struct siginfo32 { +typedef struct compat_siginfo{ int si_signo; int si_errno; int si_code; @@ -128,7 +128,7 @@ typedef struct siginfo32 { int _fd; } _sigpoll; } _sifields; -} siginfo_t32; +} compat_siginfo_t; struct sigframe32 { @@ -145,7 +145,7 @@ struct rt_sigframe32 int sig; u32 pinfo; u32 puc; - struct siginfo32 info; + compat_siginfo_t info; struct ucontext_ia32 uc; struct _fpstate_ia32 fpstate; }; @@ -165,8 +165,6 @@ struct siginfo_t; 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 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 /* !CONFIG_IA32_SUPPORT */ diff -puN include/linux/compat.h~compat-sigtimedwait include/linux/compat.h --- 25/include/linux/compat.h~compat-sigtimedwait 2004-12-14 01:15:38.323526360 -0800 +++ 25-akpm/include/linux/compat.h 2004-12-14 01:15:38.349522408 -0800 @@ -143,6 +143,8 @@ long compat_get_bitmap(unsigned long *ma unsigned long bitmap_size); long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, 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 /* _LINUX_COMPAT_H */ diff -puN kernel/compat.c~compat-sigtimedwait kernel/compat.c --- 25/kernel/compat.c~compat-sigtimedwait 2004-12-14 01:15:38.324526208 -0800 +++ 25-akpm/kernel/compat.c 2004-12-14 01:15:38.350522256 -0800 @@ -682,6 +682,92 @@ long compat_put_bitmap(compat_ulong_t __ 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(¤t->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(¤t->blocked, ¤t->blocked, &s); + + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + timeout = schedule_timeout(timeout); + + spin_lock_irq(¤t->sighand->siglock); + sig = dequeue_signal(current, &s, &info); + current->blocked = current->real_blocked; + siginitset(¤t->real_blocked, 0); + recalc_sigpending(); + } + } + spin_unlock_irq(¤t->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 /* compat_time_t is a 32 bit "long" and needs to get converted. */ _