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 | ... | ... |