Date: Tue, 21 Aug 2007 00:30:28 GMT From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 125471 for review Message-ID: <200708210030.l7L0USiP014939@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=125471 Change 125471 by peter@peter_cheese on 2007/08/21 00:29:48 Hopefully solve the stack smashing problem with async syscalls. Change putSyscallArgsIntoGuestState() into a NOP for FreeBSD. On linux, this is harmless because it just writes into the VEX register state, and the syscalls are defined to trash all registers anyway. For FreeBSD, args are on the stack. We'd have to memcpy the new args over the stack frame belonging to the syscall's caller, which the compiler may expect to use later to restore registers (which is entirely reasonable). Pass &sci->args as an additional parameters to do_syscall_for_client() rather than putSyscallArgsIntoGuestState(). Affected files ... .. //depot/projects/valgrind/coregrind/m_syswrap/syscall-x86-freebsd.S#2 edit .. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-main.c#3 edit Differences ... ==== //depot/projects/valgrind/coregrind/m_syswrap/syscall-x86-freebsd.S#2 (text+ko) ==== @@ -67,7 +67,23 @@ void* guest_state, // 4 const vki_sigset_t *sysmask, // 8 const vki_sigset_t *postmask, // 12 - Int nsigwords) // 16 + Int nsigwords, // 16 + SyscallArgs *args) // 20 + +See priv_types_n_macros.h for SyscallArgs layout: + UWord sysno; // 0 + UWord arg1; // 4 + UWord arg2; // 8 + UWord arg3; // 12 + UWord arg4; // 16 + UWord arg5; // 20 + UWord arg6; // 24 +#ifdef VGO_freebsd + UWord arg7; // 28 + UWord arg8; // 32 + Word indir_sysno; // 36 (-1 if indirect syscall() or __syscall()) + UWord nargs; // 40 +#endif */ @@ -101,8 +117,7 @@ jb 7f /* sigprocmask failed */ /* We have already collapsed the stupid FreeBSD/i386 indirect syscalls */ - movl 4+FSZ(%esp), %eax /* eax == ThreadState * */ - movl OFFSET_x86_ESP(%eax), %ebx + movl 20+FSZ(%esp), %ebx movl 0+FSZ(%esp), %eax /* use syscallno argument rather than thread EAX */ /* copy 8 args */ movl 4(%ebx), %ecx ==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-main.c#3 (text+ko) ==== @@ -227,18 +227,20 @@ void* guest_state, const vki_sigset_t *syscall_mask, const vki_sigset_t *restore_mask, - Int nsigwords ); + Int nsigwords, SyscallArgs *args ); static void do_syscall_for_client ( Int syscallno, ThreadState* tst, - const vki_sigset_t* syscall_mask ) + const vki_sigset_t* syscall_mask, + SyscallArgs * args ) { vki_sigset_t saved; UWord err = ML_(do_syscall_for_client_WRK)( syscallno, &tst->arch.vex, - syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord) + syscall_mask, &saved, _VKI_NSIG_WORDS * sizeof(UWord), + args ); vg_assert2( err == 0, @@ -411,8 +413,7 @@ gst->guest_EDI = canonical->arg5; gst->guest_EBP = canonical->arg6; -// AAA: missing 7th arg for freebsd/amd64 -#elif defined(VGP_amd64_linux) || defined(VGP_amd64_freebsd) +#elif defined(VGP_amd64_linux) VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla; gst->guest_RAX = canonical->sysno; gst->guest_RDI = canonical->arg1; @@ -442,11 +443,9 @@ gst->guest_GPR7 = canonical->arg5; gst->guest_GPR8 = canonical->arg6; -#elif defined(VGP_x86_freebsd) - VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla; - UWord *argv = (void *)(UWord)gst->guest_ESP; - gst->guest_EAX = canonical->sysno; - memcpy(&argv[1], &canonical->arg1, canonical->nargs * sizeof(UWord)); +#elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) + /* Nothing. Uses args passed out of band. */ +#endif #else # error "putSyscallArgsIntoGuestState: unknown arch" @@ -905,6 +904,10 @@ /* Gack. More impedance matching. Copy the possibly modified syscall args back into the guest state. */ vg_assert(eq_SyscallArgs(&sci->args, &sci->orig_args)); + /* This is a NOP on FreeBSD - syscall args came from + the user's private stack. We can't change it because + the compiler sometimes expects to restore registers + after the call returns. */ putSyscallArgsIntoGuestState( &sci->args, &tst->arch.vex ); /* Drop the lock */ @@ -912,7 +915,7 @@ /* Do the call, which operates directly on the guest state, not on our abstracted copies of the args/result. */ - do_syscall_for_client(sysno, tst, &mask); + do_syscall_for_client(sysno, tst, &mask, &sci->args); /* do_syscall_for_client may not return if the syscall was interrupted by a signal. In that case, flow of control is
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200708210030.l7L0USiP014939>