Commit 8420e08f authored by Benjamin Berg's avatar Benjamin Berg Committed by Johannes Berg
Browse files

um: Track userspace children dying in SECCOMP mode



When in seccomp mode, we would hang forever on the futex if a child has
died unexpectedly. In contrast, ptrace mode will notice it and kill the
corresponding thread when it fails to run it.

Fix this issue using a new IRQ that is fired after a SIGCHLD and keeping
an (internal) list of all MMs. In the IRQ handler, find the affected MM
and set its PID to -1 as well as the futex variable to FUTEX_IN_KERN.

This, together with futex returning -EINTR after the signal is
sufficient to implement a race-free detection of a child dying.

Note that this also enables IRQ handling while starting a userspace
process. This should be safe and SECCOMP requires the IRQ in case the
process does not come up properly.

Signed-off-by: default avatarBenjamin Berg <benjamin@sipsolutions.net>
Signed-off-by: default avatarBenjamin Berg <benjamin.berg@intel.com>
Link: https://patch.msgid.link/20250602130052.545733-5-benjamin@sipsolutions.net


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b1e1bd2e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -13,17 +13,18 @@
#define TELNETD_IRQ 		8
#define XTERM_IRQ 		9
#define RANDOM_IRQ 		10
#define SIGCHLD_IRQ		11

#ifdef CONFIG_UML_NET_VECTOR

#define VECTOR_BASE_IRQ		(RANDOM_IRQ + 1)
#define VECTOR_BASE_IRQ		(SIGCHLD_IRQ + 1)
#define VECTOR_IRQ_SPACE	8

#define UM_FIRST_DYN_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ)

#else

#define UM_FIRST_DYN_IRQ (RANDOM_IRQ + 1)
#define UM_FIRST_DYN_IRQ (SIGCHLD_IRQ + 1)

#endif

+3 −0
Original line number Diff line number Diff line
@@ -6,11 +6,14 @@
#ifndef __ARCH_UM_MMU_H
#define __ARCH_UM_MMU_H

#include "linux/types.h"
#include <mm_id.h>

typedef struct mm_context {
	struct mm_id id;

	struct list_head list;

	/* Address range in need of a TLB sync */
	unsigned long sync_tlb_range_from;
	unsigned long sync_tlb_range_to;
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ enum um_irq_type {
struct siginfo;
extern void sigio_handler(int sig, struct siginfo *unused_si,
			  struct uml_pt_regs *regs, void *mc);
extern void sigchld_handler(int sig, struct siginfo *unused_si,
			   struct uml_pt_regs *regs, void *mc);
void sigio_run_timetravel_handlers(void);
extern void free_irq_by_fd(int fd);
extern void deactivate_fd(int fd, int irqnum);
+1 −0
Original line number Diff line number Diff line
@@ -197,6 +197,7 @@ extern int create_mem_file(unsigned long long len);
extern void report_enomem(void);

/* process.c */
pid_t os_reap_child(void);
extern void os_alarm_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
+2 −0
Original line number Diff line number Diff line
@@ -14,4 +14,6 @@ struct mm_id {

void __switch_mm(struct mm_id *mm_idp);

void notify_mm_kill(int pid);

#endif
Loading