PERFORCE change 125471 for review
Peter Wemm
peter at FreeBSD.org
Mon Aug 20 17:30:29 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=125471
Change 125471 by peter at 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
More information about the p4-projects
mailing list