From: Alexander Viro Date: Wed, 2 Feb 2005 05:21:26 +0000 (-0800) Subject: [PATCH] amd64 compat annotations X-Git-Tag: v2.6.11-rc3~16 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=ae774bbf38545b29bf59a590abe15b94377f025c;p=history.git [PATCH] amd64 compat annotations * new helper - ptr_to_compat(); inverse to compat_ptr(), with proper typechecking. A lot of open-coded equivalents replaced with using that one. * a couple of severely misguiding places got back to sanity - we had basically put_user((long)p, &foo->compat_uptr_t_field); That will, of course, cast (long)p further - to u32, but that fact is carefully obfuscated... Sanitized by replacing (long)p in such places with ptr_to_compat(p); fortunately, there hadn't been many of those... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c index 4a4f27741fb2..85534e58cbbf 100644 --- a/arch/x86_64/ia32/ia32_signal.c +++ b/arch/x86_64/ia32/ia32_signal.c @@ -35,8 +35,6 @@ #include #include -#define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ - #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -62,7 +60,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) if (from->si_code < 0) { err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); - err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr); + err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); } else { /* First 32bits of unions are always present: * si_pid === si_band === si_tid === si_addr(LS half) */ @@ -83,7 +81,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) break; case __SI_TIMER >> 16: err |= __put_user(from->si_overrun, &to->si_overrun); - err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr); + err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr); break; case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ case __SI_MESGQ >> 16: @@ -160,7 +158,7 @@ sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || - __put_user((u32)(u64)uoss.ss_sp, &uoss_ptr->ss_sp) || + __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || __put_user(uoss.ss_size, &uoss_ptr->ss_size)) ret = -EFAULT; @@ -391,7 +389,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __ else { clear_used_math(); stts(); - err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate); + err |= __put_user(ptr_to_compat(tmp ? fpstate : NULL), &sc->fpstate); } /* non-iBCS2 extensions.. */ @@ -467,7 +465,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, void __user *restorer = VSYSCALL32_SIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; - err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); + err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); } /* These are actually not used anymore, but left because some gdb versions depend on them as a marker. */ @@ -540,8 +538,8 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, : sig), &frame->sig); } - err |= __put_user((u32)(u64)&frame->info, &frame->pinfo); - err |= __put_user((u32)(u64)&frame->uc, &frame->puc); + err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); + err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); err |= copy_siginfo_to_user32(&frame->info, info); if (err) goto give_sigsegv; @@ -564,7 +562,7 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, void __user *restorer = VSYSCALL32_RTSIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; - err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); + err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); } /* This is movl $,%eax ; int $0x80 */ diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index d2cd083b03b3..b98b6d2462f6 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -365,7 +365,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) } case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message,(unsigned int __user *)(u64)data); + ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data)); break; default: diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c index 84c74c0f2bc6..a8cb4f6bd25b 100644 --- a/arch/x86_64/ia32/sys_ia32.c +++ b/arch/x86_64/ia32/sys_ia32.c @@ -73,10 +73,7 @@ #include #include -#define A(__x) ((unsigned long)(__x)) #define AA(__x) ((unsigned long)(__x)) -#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf) { @@ -305,8 +302,8 @@ sys32_rt_sigaction(int sig, struct sigaction32 __user *act, set32.sig[0] = old_ka.sa.sa_mask.sig[0]; } if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || + __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t))) return -EFAULT; @@ -342,8 +339,8 @@ sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigacti if (!ret && oact) { if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || + __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) || __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; @@ -670,9 +667,9 @@ sys32_sysctl(struct sysctl_ia32 __user *args32) { struct sysctl_ia32 a32; mm_segment_t old_fs = get_fs (); - void *oldvalp, *newvalp; + void __user *oldvalp, *newvalp; size_t oldlen; - int *namep; + int __user *namep; long ret; extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, void *newval, size_t newlen); @@ -688,9 +685,9 @@ sys32_sysctl(struct sysctl_ia32 __user *args32) * addresses, we KNOW that access_ok() will always succeed, so this is an * expensive NOP, but so what... */ - namep = (int *) A(a32.name); - oldvalp = (void *) A(a32.oldval); - newvalp = (void *) A(a32.newval); + namep = compat_ptr(a32.name); + oldvalp = compat_ptr(a32.oldval); + newvalp = compat_ptr(a32.newval); if ((oldvalp && get_user(oldlen, (int __user *)compat_ptr(a32.oldlenp))) || !access_ok(VERIFY_WRITE, namep, 0) diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h index 165a0b1d49f5..d0f453c5adfc 100644 --- a/include/asm-x86_64/compat.h +++ b/include/asm-x86_64/compat.h @@ -191,6 +191,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr) return (void __user *)(unsigned long)uptr; } +static inline compat_uptr_t ptr_to_compat(void __user *uptr) +{ + return (u32)(unsigned long)uptr; +} + static __inline__ void __user *compat_alloc_user_space(long len) { struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs);