Page MenuHomeFreeBSD

Fix execution of linux binary from multithreaded process.
ClosedPublic

Authored by kib on Jun 16 2020, 9:40 AM.

Details

Summary

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 threads in post_execve(). Since at that time the process is already switched to linux ABI, linuxolator is involved in the thread termination but cannot find the emul data.

Handle it by pre-creating emuldata for all threads in the execing process.

NB. There is (was) a code in linux_proc_exec() handler that cleared emul data for other threads when execing from multithreaded Linux process. I do not see how could it work, or why it was needed at all.

PR: 247020
Reported by: Martin FIlla <freebsd@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

Test Plan

Not tested at all, somebody else should.

Interesting cases are:

  • exec from multithreaded Linux process to:
    • Linux binary
    • non-Linux binary
  • exec from multhreaded non-Linux process to Linux binary.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

kib requested review of this revision.Jun 16 2020, 9:40 AM

Now-removed code was added in rS284051, described as a followon to rS282708.

sys/compat/linux/linux_emul.c
308 ↗(On Diff #73163)

I don't really understand. proc->p_sysent is set after the call to exec_new_vmspace(), so in the case where a non-Linux process execs a Linux binary, won't this check be false?

312 ↗(On Diff #73163)

I think this deserves a comment.

kib marked 2 inline comments as done.Jun 16 2020, 7:43 PM
kib added inline comments.
sys/compat/linux/linux_emul.c
308 ↗(On Diff #73163)

Yes, I did it in wrong branch of if().

kib marked an inline comment as done.

Move creation of the emuldata to the proper branch (else).
Add comments.

Do you want me to try testing it?

This revision is now accepted and ready to land.Jun 16 2020, 7:52 PM

Done testing. Previously it would trigger panic when execing Linux sh from FreeBSD, with the patch it works ok. Remaining two cases (exec from the code below built as Linux binary) are the same - they work as expected, both with and without the patch. Test case follows:

#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void *
stuff(void *dummy)
{
	for (;;) {
		fprintf(stderr, "-");
		usleep(90000);
	}
}

static void *
stuff2(void *dummy)
{
	for (int i = 0; i < 5; i++) {
		fprintf(stderr, "=");
		usleep(70000);
	}

	execlp("/compat/linux/bin/sh", "-", NULL);
	perror("execlp");
	exit(-1);
}

int
main(int argc, char **argv)
{
	static pthread_t thr, thr2;
	int error;

	error = pthread_create(&thr, NULL, stuff, NULL);
	if (error != 0)
		err(1, "pthread_create");

	error = pthread_create(&thr2, NULL, stuff2, NULL);
	if (error != 0)
		err(1, "pthread_create");

	sleep(10);

	return (0);
}

I think for metadata we probably have:

PR: 247040
Reported by: Martin FIlla <freebsd@sysctl.cz>
Reported by: Henrique L. Amorim, Independent Security Researcher
Reported by: Rodrigo Rubira Branco (BSDaemon), Amazon Web Services