svn commit: r362342 - head/sys/compat/linux

Konstantin Belousov kib at FreeBSD.org
Thu Jun 18 20:49:57 UTC 2020


Author: kib
Date: Thu Jun 18 20:49:56 2020
New Revision: 362342
URL: https://svnweb.freebsd.org/changeset/base/362342

Log:
  Fix execution of linux binary from multithreaded non-Linux process.
  
  If multithreaded non-Linux process execs Linux binary, then non-Linux
  threads different from the one that execing are cleared by
  single-threading at boundary, and then terminating them in
  post_execve(). Since at that time the process is already switched to
  linux ABI, linuxolator is involved in the thread clearing on boundary,
  but cannot find the emul data.
  
  Handle it by pre-creating emuldata for all threads in the execing process.
  
  Also remove a code in linux_proc_exec() handler that cleared emul data
  for other threads when execing from multithreaded Linux process. It is
  excessive.
  
  PR:	247020
  Reported by:	Martin FIlla <freebsd at sysctl.cz>
  Reported by:	Henrique L. Amorim, Independent Security Researcher
  Reported by:	Rodrigo Rubira Branco (BSDaemon), Amazon Web Services
  Reviewed by:	markj
  Tested by:	trasz
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D25293

Modified:
  head/sys/compat/linux/linux_emul.c

Modified: head/sys/compat/linux/linux_emul.c
==============================================================================
--- head/sys/compat/linux/linux_emul.c	Thu Jun 18 20:41:43 2020	(r362341)
+++ head/sys/compat/linux/linux_emul.c	Thu Jun 18 20:49:56 2020	(r362342)
@@ -291,22 +291,13 @@ linux_common_execve(struct thread *td, struct image_ar
 void
 linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
 {
-	struct thread *td = curthread;
+	struct thread *td;
 	struct thread *othertd;
 #if defined(__amd64__)
 	struct linux_pemuldata *pem;
 #endif
 
-	/*
-	 * In a case of execing from Linux binary properly detach
-	 * other threads from the user space.
-	 */
-	if (__predict_false(SV_PROC_ABI(p) == SV_ABI_LINUX)) {
-		FOREACH_THREAD_IN_PROC(p, othertd) {
-			if (td != othertd)
-				(p->p_sysent->sv_thread_detach)(othertd);
-		}
-	}
+	td = curthread;
 
 	/*
 	 * In a case of execing to Linux binary we create Linux
@@ -314,11 +305,32 @@ linux_proc_exec(void *arg __unused, struct proc *p, st
 	 */
 	if (__predict_false((imgp->sysent->sv_flags & SV_ABI_MASK) ==
 	    SV_ABI_LINUX)) {
-
-		if (SV_PROC_ABI(p) == SV_ABI_LINUX)
+		if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
+			/*
+			 * Process already was under Linuxolator
+			 * before exec.  Update emuldata to reflect
+			 * single-threaded cleaned state after exec.
+			 */
 			linux_proc_init(td, NULL, 0);
-		else
+		} else {
+			/*
+			 * We are switching the process to Linux emulator.
+			 */
 			linux_proc_init(td, td, 0);
+
+			/*
+			 * Create a transient td_emuldata for all suspended
+			 * threads, so that p->p_sysent->sv_thread_detach() ==
+			 * linux_thread_detach() can find expected but unused
+			 * emuldata.
+			 */
+			FOREACH_THREAD_IN_PROC(td->td_proc, othertd) {
+				if (othertd != td) {
+					linux_proc_init(td, othertd,
+					    LINUX_CLONE_THREAD);
+				}
+			}
+		}
 #if defined(__amd64__)
 		/*
 		 * An IA32 executable which has executable stack will have the


More information about the svn-src-head mailing list