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 | 667 | /* XXX: save x87 state */ |
| 668 | 668 | static int |
| 669 | 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 | 672 | int err = 0; |
| 673 | 673 | uint16_t magic; |
| ... | ... | @@ -693,11 +693,11 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
| 693 | 693 | err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); |
| 694 | 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 | 697 | fpstate->status = fpstate->sw; |
| 698 | 698 | magic = 0xffff; |
| 699 | 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 | 702 | /* non-iBCS2 extensions.. */ |
| 703 | 703 | err |= __put_user(mask, &sc->oldmask); |
| ... | ... | @@ -754,7 +754,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 754 | 754 | if (err) |
| 755 | 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 | 759 | if (err) |
| 759 | 760 | goto give_sigsegv; |
| 760 | 761 | |
| ... | ... | @@ -769,7 +770,9 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 769 | 770 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 770 | 771 | } else { |
| 771 | 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 | 776 | /* This is popl %eax ; movl $,%eax ; int $0x80 */ |
| 774 | 777 | val16 = 0xb858; |
| 775 | 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 | 785 | goto give_sigsegv; |
| 783 | 786 | |
| 784 | 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 | 791 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 789 | 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 | 810 | target_siginfo_t *info, |
| 808 | 811 | target_sigset_t *set, CPUX86State *env) |
| 809 | 812 | { |
| 810 | - abi_ulong frame_addr; | |
| 813 | + abi_ulong frame_addr, addr; | |
| 811 | 814 | struct rt_sigframe *frame; |
| 812 | 815 | int i, err = 0; |
| 813 | 816 | |
| ... | ... | @@ -822,8 +825,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 822 | 825 | ? current->exec_domain->signal_invmap[sig] |
| 823 | 826 | : */sig), |
| 824 | 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 | 832 | err |= copy_siginfo_to_user(&frame->info, info); |
| 828 | 833 | if (err) |
| 829 | 834 | goto give_sigsegv; |
| ... | ... | @@ -838,7 +843,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 838 | 843 | err |= __put_user(target_sigaltstack_used.ss_size, |
| 839 | 844 | &frame->uc.tuc_stack.ss_size); |
| 840 | 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 | 848 | for(i = 0; i < TARGET_NSIG_WORDS; i++) { |
| 843 | 849 | if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) |
| 844 | 850 | goto give_sigsegv; |
| ... | ... | @@ -850,8 +856,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 850 | 856 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 851 | 857 | } else { |
| 852 | 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 | 861 | /* This is movl $,%eax ; int $0x80 */ |
| 856 | 862 | err |= __put_user(0xb8, (char *)(frame->retcode+0)); |
| 857 | 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 | 869 | goto give_sigsegv; |
| 864 | 870 | |
| 865 | 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 | 875 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 870 | 876 | cpu_x86_load_seg(env, R_ES, __USER_DS); |
| ... | ... | @@ -887,49 +893,42 @@ static int |
| 887 | 893 | restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) |
| 888 | 894 | { |
| 889 | 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 | 913 | cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); |
| 906 | 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 | 929 | return err; |
| 929 | -#if 0 | |
| 930 | 930 | badframe: |
| 931 | 931 | return 1; |
| 932 | -#endif | |
| 933 | 932 | } |
| 934 | 933 | |
| 935 | 934 | long do_sigreturn(CPUX86State *env) |
| ... | ... | @@ -970,27 +969,30 @@ badframe: |
| 970 | 969 | |
| 971 | 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 | 974 | sigset_t set; |
| 975 | 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 | 980 | target_to_host_sigset(&set, &frame->uc.tuc_sigmask); |
| 982 | 981 | sigprocmask(SIG_SETMASK, &set, NULL); |
| 983 | 982 | |
| 984 | 983 | if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) |
| 985 | 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 | 988 | goto badframe; |
| 989 | 989 | |
| 990 | + unlock_user_struct(frame, frame_addr, 0); | |
| 990 | 991 | return eax; |
| 991 | 992 | |
| 992 | 993 | badframe: |
| 993 | - force_sig(TARGET_SIGSEGV); | |
| 994 | + unlock_user_struct(frame, frame_addr, 0); | |
| 995 | + force_sig(TARGET_SIGSEGV); | |
| 994 | 996 | return 0; |
| 995 | 997 | } |
| 996 | 998 | ... | ... |