Commit 28be6234fc968a42e835da1e39f7f5da74823b8c
1 parent
1455bf48
user access fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3623 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
57 additions
and
55 deletions
linux-user/signal.c
| @@ -667,7 +667,7 @@ struct rt_sigframe | @@ -667,7 +667,7 @@ struct rt_sigframe | ||
| 667 | /* XXX: save x87 state */ | 667 | /* XXX: save x87 state */ |
| 668 | static int | 668 | static int |
| 669 | setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, | 669 | setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
| 670 | - CPUX86State *env, unsigned long mask) | 670 | + CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr) |
| 671 | { | 671 | { |
| 672 | int err = 0; | 672 | int err = 0; |
| 673 | uint16_t magic; | 673 | uint16_t magic; |
| @@ -693,11 +693,11 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, | @@ -693,11 +693,11 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, | ||
| 693 | err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); | 693 | err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); |
| 694 | err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); | 694 | err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); |
| 695 | 695 | ||
| 696 | - cpu_x86_fsave(env, (void *)fpstate, 1); | 696 | + cpu_x86_fsave(env, fpstate_addr, 1); |
| 697 | fpstate->status = fpstate->sw; | 697 | fpstate->status = fpstate->sw; |
| 698 | magic = 0xffff; | 698 | magic = 0xffff; |
| 699 | err |= __put_user(magic, &fpstate->magic); | 699 | err |= __put_user(magic, &fpstate->magic); |
| 700 | - err |= __put_user(fpstate, &sc->fpstate); | 700 | + err |= __put_user(fpstate_addr, &sc->fpstate); |
| 701 | 701 | ||
| 702 | /* non-iBCS2 extensions.. */ | 702 | /* non-iBCS2 extensions.. */ |
| 703 | err |= __put_user(mask, &sc->oldmask); | 703 | err |= __put_user(mask, &sc->oldmask); |
| @@ -754,7 +754,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -754,7 +754,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 754 | if (err) | 754 | if (err) |
| 755 | goto give_sigsegv; | 755 | goto give_sigsegv; |
| 756 | 756 | ||
| 757 | - setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0]); | 757 | + setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], |
| 758 | + frame_addr + offsetof(struct sigframe, fpstate)); | ||
| 758 | if (err) | 759 | if (err) |
| 759 | goto give_sigsegv; | 760 | goto give_sigsegv; |
| 760 | 761 | ||
| @@ -769,7 +770,9 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -769,7 +770,9 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 769 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 770 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 770 | } else { | 771 | } else { |
| 771 | uint16_t val16; | 772 | uint16_t val16; |
| 772 | - err |= __put_user(frame->retcode, &frame->pretcode); | 773 | + abi_ulong retcode_addr; |
| 774 | + retcode_addr = frame_addr + offsetof(struct sigframe, retcode); | ||
| 775 | + err |= __put_user(retcode_addr, &frame->pretcode); | ||
| 773 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ | 776 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ |
| 774 | val16 = 0xb858; | 777 | val16 = 0xb858; |
| 775 | err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); | 778 | err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); |
| @@ -782,8 +785,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -782,8 +785,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
| 782 | goto give_sigsegv; | 785 | goto give_sigsegv; |
| 783 | 786 | ||
| 784 | /* Set up registers for signal handler */ | 787 | /* Set up registers for signal handler */ |
| 785 | - env->regs[R_ESP] = h2g(frame); | ||
| 786 | - env->eip = (unsigned long) ka->sa._sa_handler; | 788 | + env->regs[R_ESP] = frame_addr; |
| 789 | + env->eip = ka->sa._sa_handler; | ||
| 787 | 790 | ||
| 788 | cpu_x86_load_seg(env, R_DS, __USER_DS); | 791 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 789 | cpu_x86_load_seg(env, R_ES, __USER_DS); | 792 | cpu_x86_load_seg(env, R_ES, __USER_DS); |
| @@ -807,7 +810,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -807,7 +810,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 807 | target_siginfo_t *info, | 810 | target_siginfo_t *info, |
| 808 | target_sigset_t *set, CPUX86State *env) | 811 | target_sigset_t *set, CPUX86State *env) |
| 809 | { | 812 | { |
| 810 | - abi_ulong frame_addr; | 813 | + abi_ulong frame_addr, addr; |
| 811 | struct rt_sigframe *frame; | 814 | struct rt_sigframe *frame; |
| 812 | int i, err = 0; | 815 | int i, err = 0; |
| 813 | 816 | ||
| @@ -822,8 +825,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -822,8 +825,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 822 | ? current->exec_domain->signal_invmap[sig] | 825 | ? current->exec_domain->signal_invmap[sig] |
| 823 | : */sig), | 826 | : */sig), |
| 824 | &frame->sig); | 827 | &frame->sig); |
| 825 | - err |= __put_user((abi_ulong)&frame->info, &frame->pinfo); | ||
| 826 | - err |= __put_user((abi_ulong)&frame->uc, &frame->puc); | 828 | + addr = frame_addr + offsetof(struct rt_sigframe, info); |
| 829 | + err |= __put_user(addr, &frame->pinfo); | ||
| 830 | + addr = frame_addr + offsetof(struct rt_sigframe, uc); | ||
| 831 | + err |= __put_user(addr, &frame->puc); | ||
| 827 | err |= copy_siginfo_to_user(&frame->info, info); | 832 | err |= copy_siginfo_to_user(&frame->info, info); |
| 828 | if (err) | 833 | if (err) |
| 829 | goto give_sigsegv; | 834 | goto give_sigsegv; |
| @@ -838,7 +843,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -838,7 +843,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 838 | err |= __put_user(target_sigaltstack_used.ss_size, | 843 | err |= __put_user(target_sigaltstack_used.ss_size, |
| 839 | &frame->uc.tuc_stack.ss_size); | 844 | &frame->uc.tuc_stack.ss_size); |
| 840 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, | 845 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, |
| 841 | - env, set->sig[0]); | 846 | + env, set->sig[0], |
| 847 | + frame_addr + offsetof(struct rt_sigframe, fpstate)); | ||
| 842 | for(i = 0; i < TARGET_NSIG_WORDS; i++) { | 848 | for(i = 0; i < TARGET_NSIG_WORDS; i++) { |
| 843 | if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) | 849 | if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) |
| 844 | goto give_sigsegv; | 850 | goto give_sigsegv; |
| @@ -850,8 +856,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -850,8 +856,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 850 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 856 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 851 | } else { | 857 | } else { |
| 852 | uint16_t val16; | 858 | uint16_t val16; |
| 853 | - | ||
| 854 | - err |= __put_user(frame->retcode, &frame->pretcode); | 859 | + addr = frame_addr + offsetof(struct rt_sigframe, retcode); |
| 860 | + err |= __put_user(addr, &frame->pretcode); | ||
| 855 | /* This is movl $,%eax ; int $0x80 */ | 861 | /* This is movl $,%eax ; int $0x80 */ |
| 856 | err |= __put_user(0xb8, (char *)(frame->retcode+0)); | 862 | err |= __put_user(0xb8, (char *)(frame->retcode+0)); |
| 857 | err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); | 863 | err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); |
| @@ -863,8 +869,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | @@ -863,8 +869,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | ||
| 863 | goto give_sigsegv; | 869 | goto give_sigsegv; |
| 864 | 870 | ||
| 865 | /* Set up registers for signal handler */ | 871 | /* Set up registers for signal handler */ |
| 866 | - env->regs[R_ESP] = (unsigned long) frame; | ||
| 867 | - env->eip = (unsigned long) ka->sa._sa_handler; | 872 | + env->regs[R_ESP] = frame_addr; |
| 873 | + env->eip = ka->sa._sa_handler; | ||
| 868 | 874 | ||
| 869 | cpu_x86_load_seg(env, R_DS, __USER_DS); | 875 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 870 | cpu_x86_load_seg(env, R_ES, __USER_DS); | 876 | cpu_x86_load_seg(env, R_ES, __USER_DS); |
| @@ -887,49 +893,42 @@ static int | @@ -887,49 +893,42 @@ static int | ||
| 887 | restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) | 893 | restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) |
| 888 | { | 894 | { |
| 889 | unsigned int err = 0; | 895 | unsigned int err = 0; |
| 890 | - | ||
| 891 | - cpu_x86_load_seg(env, R_GS, lduw(&sc->gs)); | ||
| 892 | - cpu_x86_load_seg(env, R_FS, lduw(&sc->fs)); | ||
| 893 | - cpu_x86_load_seg(env, R_ES, lduw(&sc->es)); | ||
| 894 | - cpu_x86_load_seg(env, R_DS, lduw(&sc->ds)); | ||
| 895 | - | ||
| 896 | - env->regs[R_EDI] = ldl(&sc->edi); | ||
| 897 | - env->regs[R_ESI] = ldl(&sc->esi); | ||
| 898 | - env->regs[R_EBP] = ldl(&sc->ebp); | ||
| 899 | - env->regs[R_ESP] = ldl(&sc->esp); | ||
| 900 | - env->regs[R_EBX] = ldl(&sc->ebx); | ||
| 901 | - env->regs[R_EDX] = ldl(&sc->edx); | ||
| 902 | - env->regs[R_ECX] = ldl(&sc->ecx); | ||
| 903 | - env->eip = ldl(&sc->eip); | 896 | + abi_ulong fpstate_addr; |
| 897 | + unsigned int tmpflags; | ||
| 898 | + | ||
| 899 | + cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); | ||
| 900 | + cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); | ||
| 901 | + cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); | ||
| 902 | + cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); | ||
| 903 | + | ||
| 904 | + env->regs[R_EDI] = tswapl(sc->edi); | ||
| 905 | + env->regs[R_ESI] = tswapl(sc->esi); | ||
| 906 | + env->regs[R_EBP] = tswapl(sc->ebp); | ||
| 907 | + env->regs[R_ESP] = tswapl(sc->esp); | ||
| 908 | + env->regs[R_EBX] = tswapl(sc->ebx); | ||
| 909 | + env->regs[R_EDX] = tswapl(sc->edx); | ||
| 910 | + env->regs[R_ECX] = tswapl(sc->ecx); | ||
| 911 | + env->eip = tswapl(sc->eip); | ||
| 904 | 912 | ||
| 905 | cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); | 913 | cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); |
| 906 | cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3); | 914 | cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3); |
| 907 | 915 | ||
| 908 | - { | ||
| 909 | - unsigned int tmpflags; | ||
| 910 | - tmpflags = ldl(&sc->eflags); | ||
| 911 | - env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); | ||
| 912 | - // regs->orig_eax = -1; /* disable syscall checks */ | ||
| 913 | - } | 916 | + tmpflags = tswapl(sc->eflags); |
| 917 | + env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); | ||
| 918 | + // regs->orig_eax = -1; /* disable syscall checks */ | ||
| 914 | 919 | ||
| 915 | - { | ||
| 916 | - struct _fpstate * buf; | ||
| 917 | - buf = (void *)ldl(&sc->fpstate); | ||
| 918 | - if (buf) { | ||
| 919 | -#if 0 | ||
| 920 | - if (verify_area(VERIFY_READ, buf, sizeof(*buf))) | ||
| 921 | - goto badframe; | ||
| 922 | -#endif | ||
| 923 | - cpu_x86_frstor(env, (void *)buf, 1); | ||
| 924 | - } | 920 | + fpstate_addr = tswapl(sc->fpstate); |
| 921 | + if (fpstate_addr != 0) { | ||
| 922 | + if (!access_ok(VERIFY_READ, fpstate_addr, | ||
| 923 | + sizeof(struct target_fpstate))) | ||
| 924 | + goto badframe; | ||
| 925 | + cpu_x86_frstor(env, fpstate_addr, 1); | ||
| 925 | } | 926 | } |
| 926 | 927 | ||
| 927 | - *peax = ldl(&sc->eax); | 928 | + *peax = tswapl(sc->eax); |
| 928 | return err; | 929 | return err; |
| 929 | -#if 0 | ||
| 930 | badframe: | 930 | badframe: |
| 931 | return 1; | 931 | return 1; |
| 932 | -#endif | ||
| 933 | } | 932 | } |
| 934 | 933 | ||
| 935 | long do_sigreturn(CPUX86State *env) | 934 | long do_sigreturn(CPUX86State *env) |
| @@ -970,27 +969,30 @@ badframe: | @@ -970,27 +969,30 @@ badframe: | ||
| 970 | 969 | ||
| 971 | long do_rt_sigreturn(CPUX86State *env) | 970 | long do_rt_sigreturn(CPUX86State *env) |
| 972 | { | 971 | { |
| 973 | - struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4); | 972 | + abi_ulong frame_addr; |
| 973 | + struct rt_sigframe *frame; | ||
| 974 | sigset_t set; | 974 | sigset_t set; |
| 975 | int eax; | 975 | int eax; |
| 976 | 976 | ||
| 977 | -#if 0 | ||
| 978 | - if (verify_area(VERIFY_READ, frame, sizeof(*frame))) | ||
| 979 | - goto badframe; | ||
| 980 | -#endif | 977 | + frame_addr = env->regs[R_ESP] - 4; |
| 978 | + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) | ||
| 979 | + goto badframe; | ||
| 981 | target_to_host_sigset(&set, &frame->uc.tuc_sigmask); | 980 | target_to_host_sigset(&set, &frame->uc.tuc_sigmask); |
| 982 | sigprocmask(SIG_SETMASK, &set, NULL); | 981 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 983 | 982 | ||
| 984 | if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) | 983 | if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) |
| 985 | goto badframe; | 984 | goto badframe; |
| 986 | 985 | ||
| 987 | - if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) | 986 | + if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, |
| 987 | + get_sp_from_cpustate(env)) == -EFAULT) | ||
| 988 | goto badframe; | 988 | goto badframe; |
| 989 | 989 | ||
| 990 | + unlock_user_struct(frame, frame_addr, 0); | ||
| 990 | return eax; | 991 | return eax; |
| 991 | 992 | ||
| 992 | badframe: | 993 | badframe: |
| 993 | - force_sig(TARGET_SIGSEGV); | 994 | + unlock_user_struct(frame, frame_addr, 0); |
| 995 | + force_sig(TARGET_SIGSEGV); | ||
| 994 | return 0; | 996 | return 0; |
| 995 | } | 997 | } |
| 996 | 998 |