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 |