Skip site navigation (1)Skip section navigation (2)
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>