From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=T3d/9ujd; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTPS id 61E785A0262 for ; Tue, 08 Sep 2026 11:45:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1788860723; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sWvd5T65ujzx93uLVxyMD+W9mdfVAQEiKXW+wG0O5Z8=; b=T3d/9ujdr1LrHh0C4j0SK+0a2FAMVDAUCDWxltmV8QfOPjI4NTCQrMqZvcNR+pZGKrjHYF kE+yMMH0zPfJP8d7A4VYAzhrspm1YrWuX1tKEUz3l4iCQ3fLpCaIH7hbLyCCAgeBZxfsy9 ubwEDMepO179SQElSU0NDyXGqeCaKPc= Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-186-HPqEhinGPn-f9Vi-oRpoFg-1; Tue, 08 Sep 2026 05:45:22 -0400 X-MC-Unique: HPqEhinGPn-f9Vi-oRpoFg-1 X-Mimecast-MFC-AGG-ID: HPqEhinGPn-f9Vi-oRpoFg_1788860721 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-499913d1a79so29796065e9.0 for ; Tue, 08 Sep 2026 02:45:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788860721; x=1789465521; h=date:content-transfer-encoding:content-type:mime-version :organization:references:in-reply-to:message-id:subject:cc:to:from :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to:content-type; bh=sWvd5T65ujzx93uLVxyMD+W9mdfVAQEiKXW+wG0O5Z8=; b=otf1aTAQPFmIH3Al9PddRFcX0Xt/ouMbx/LcsnFjgKIYpgvHqvOSpq8XmyltR3zTEC Sv1aExJWFbPcbcnOQuyR4CU80vagywtwf3crnzJsykRGw3LAH05vr0xLCVApDlNC5Gfn KVo8fQRaGDYjHVBEe0nz6cUjYYQvzW0d8haBr6+v6XlKTcfWV0hvwn8koEsB3Ncy0+bs byLGMg1lEdiqKISRqlQYjEt4t3ypdJ59JlucCz33jRxsz5bddgPRVhQwTfJd2/q2mSIs GiDCdX27izVysw3hvYHKb6deINwmHAuI3fpBWCCEPg9gsFKSuMuaPIqzsSGikGaSTBTe 5HtQ== X-Gm-Message-State: AFuF++lC3Sc0DwzadZMxu0WqOs0ft3+om8VRZRvHPo2s2qhG7CjX13hE YSYh9uLJTYOxD7KW1X1rl8tjtXHI5pzwkiVEVyYKAolTDtc3e7F16NmH5rhPaiLq896f197JNLP q6rWa+eh92gdR0QHWmEgZ1jy31DcPekPrHMuvMMPiFBJiumc8fBA3/ao/lVwJmRTe X-Gm-Gg: AYBFou3aaF4ghv5lJuO7bIQA7bC+jfDLe+NOHijbkfQmT8/auFYQNWfRvIDjz1uMsnu n28lGa68QGY41YM5Ioo3wUxhUGwNuaaQewLQfUJWNP+bgR3wZCl15HZkr9hzE42Tx7x9x/6pLzW TcLlQr7gtnI2VyrTGv9Q34UO/1/oL8IwBJP6Idn9XSOxcU2cj4o4UGBpkgqhHFJRQUl/nG7LQC4 XUyqZq1V7T+Rx5a2vfUG+yIbsesYT0rAxSazclYjxv215tEtG5X6rh+vR8m34NjlZ01hk8D5XiN s+mQIXNSGctG+O6C8qExlkjxjJ5w0we3foUNMazfGYQwWuYFjxjKJ8rrRhP/7wOh4JNAklu9H1H i5bOLvdUfXmTrasajICDc8i+KiCwq X-Received: by 2002:a05:600c:a00a:b0:49c:ed94:cdd8 with SMTP id 5b1f17b1804b1-49cf81f6736mr576214455e9.6.1788860720592; Tue, 08 Sep 2026 02:45:20 -0700 (PDT) X-Received: by 2002:a05:600c:a00a:b0:49c:ed94:cdd8 with SMTP id 5b1f17b1804b1-49cf81f6736mr576213325e9.6.1788860719915; Tue, 08 Sep 2026 02:45:19 -0700 (PDT) Received: from maya.myfinge.rs (ifcgrfdd.trafficplex.cloud. [176.103.220.4]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cf7740d44sm835411425e9.15.2026.09.08.02.45.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2026 02:45:19 -0700 (PDT) From: Stefano Brivio To: Christian Korneck Subject: Re: [PATCH] pasta: Add --no-pidns to keep spawned command in caller's PID namespace Message-ID: <20260908114518.3af2d1c2@elisabeth> In-Reply-To: <20260906131758.121019-1-christian@korneck.de> References: <20260906131758.121019-1-christian@korneck.de> Organization: Red Hat X-Mailer: Claws Mail 4.2.0 (GTK 3.24.49; x86_64-pc-linux-gnu) MIME-Version: 1.0 Date: Tue, 08 Sep 2026 11:45:18 +0200 (CEST) X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: K9I6JXoL2lOHJBCpwA-bT5t_PvilmQymMnVvKuLRwiM_1788860721 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Message-ID-Hash: EIT6RHBXGKL346OLZCBKZ6LKTJZQFQEV X-Message-ID-Hash: EIT6RHBXGKL346OLZCBKZ6LKTJZQFQEV X-MailFrom: sbrivio@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Christian, thanks for the patch. At a glance, it looks pretty good to me (see also my reply to David). There's just one thing I wanted to mention for your awareness before continuing with it, though: in the past couple of months, we had several reports of bubblewrap being started by pasta (directly or indirectly), see in particular: https://archives.passt.top/passt-user/671252c8-88f6-45b7-b719-b82786e84bb7@gnedt.at/ https://bugs.passt.top/show_bug.cgi?id=204 https://archives.passt.top/passt-dev/20260731132601.422518-1-rlawrence@tamu.edu/ (still pending) so, while these kind of changes obviously appear useful for somebody, there's still the question of whether you want to consider spawning bubblewrap separately and make it join a network namespace connected by pasta (might need changes in bubblewrap, or something like https://github.com/reubenfirmin/bubblewrap-tui#why-pasta). -- Stefano On Sun, 6 Sep 2026 15:17:58 +0200 Christian Korneck wrote: > This is to allow running pasta inside a container without unmasking > /proc for the whole container (Docker's --security-opt > systempaths=unconfined, Podman's --security-opt unmask=ALL), which is > undesirable as it exposes /proc/sysrq-trigger and other masked paths. > > In spawn mode, pasta clones the command with CLONE_NEWPID and mounts a > new procfs instance on /proc, so that it matches the new PID namespace. > > Mounting procfs in a new user namespace requires a fully visible, > unobstructed procfs. Container runtimes deliberately obstruct /proc > (Docker, for example, masks /proc/kcore and friends and mounts > /proc/sys read-only), so the mount is refused: > > Couldn't mount /proc: Operation not permitted > > We only warn and continue, leaving the command in a new PID namespace > while the visible /proc still numbers processes in the outer one. > Anything resolving its own PID through /proc then fails, for example > bubblewrap: > > bwrap: open /proc/22/ns/ns failed: No such file or directory > > Add a --no-pidns option: skip CLONE_NEWPID for the spawned command and > don't mount /proc, which is then not needed. User, network, mount, UTS > and IPC namespaces, --config-net and port forwarding are unaffected. > The option is rejected together with PID or --netns, as it only makes > sense when we spawn the command ourselves. > > Add a test checking that, by default, the command runs in a new PID > namespace, and that --no-pidns keeps it in the caller's one. > > Signed-off-by: Christian Korneck > --- > conf.c | 11 +++++++++++ > passt.1 | 12 ++++++++++++ > passt.h | 2 ++ > pasta.c | 18 +++++++++++------- > test/pasta_options/no_pidns | 25 +++++++++++++++++++++++++ > test/run | 1 + > 6 files changed, 62 insertions(+), 7 deletions(-) > create mode 100644 test/pasta_options/no_pidns > > diff --git a/conf.c b/conf.c > index faf2681..16b2f40 100644 > --- a/conf.c > +++ b/conf.c > @@ -742,6 +742,7 @@ pasta_opts: > " implied if PATH or NAME are given without --userns\n" > " --no-netns-quit Don't quit if filesystem-bound target\n" > " network namespace is deleted\n" > + " --no-pidns Don't spawn command in a new PID namespace\n" > " --config-net Configure tap interface in namespace\n" > " --no-copy-routes DEPRECATED:\n" > " Don't copy all routes to namespace\n" > @@ -1348,6 +1349,7 @@ void conf(struct ctx *c, int argc, char **argv) > {"stats", required_argument, NULL, 31 }, > {"conf-path", required_argument, NULL, 'c' }, > {"chroot-fallback", no_argument, NULL, 32 }, > + {"no-pidns", no_argument, NULL, 33 }, > { 0 }, > }; > const char *optstring = "+dqfel:hs:c:F:I:p:P:m:a:n:M:g:i:o:D:S:H:461t:u:T:U:"; > @@ -1589,6 +1591,12 @@ void conf(struct ctx *c, int argc, char **argv) > case 32: > c->chroot_fallback = true; > break; > + case 33: > + if (c->mode != MODE_PASTA) > + die("--no-pidns is for pasta mode only"); > + > + c->no_pidns = true; > + break; > case 'd': > c->debug = 1; > c->quiet = 0; > @@ -1948,6 +1956,9 @@ void conf(struct ctx *c, int argc, char **argv) > else if (optind != argc) > die("Extra non-option argument: %s", argv[optind]); > > + if (c->no_pidns && *netns) > + die("--no-pidns is incompatible with PID or --netns"); > + > conf_open_files(c); /* Before any possible setuid() / setgid() */ > > isolate_user(c, uid, gid, !netns_only, userns); > diff --git a/passt.1 b/passt.1 > index 53e072a..0b780fe 100644 > --- a/passt.1 > +++ b/passt.1 > @@ -704,6 +704,18 @@ is bound to the filesystem, and the given path is deleted, or if the target > network namespace is represented by a procfs entry, and that entry is deleted, > representing the fact that a process with the given PID terminated. > > +.TP > +.BR \-\-no-pidns > +Don't create a new PID namespace for the spawned command or shell: keep it in > +the PID namespace \fBpasta\fR itself runs in, and don't mount a new > +\fIprocfs\fR instance on \fI/proc\fR for it. This is useful in environments > +where mounting \fIprocfs\fR is not permitted, such as containers, where the > +command would otherwise get a \fI/proc\fR view that doesn't match its own PID > +namespace. Note that, without a PID namespace, processes started by the > +command are not terminated once the command exits. > + > +This option can't be specified with a PID or with \-\-netns. > + > .TP > .BR \-\-config-net > Configure networking in the namespace: set up addresses and routes as configured > diff --git a/passt.h b/passt.h > index 51ccd4f..afd8e9f 100644 > --- a/passt.h > +++ b/passt.h > @@ -195,6 +195,7 @@ struct ip6_ctx { > * @pasta_ifn: Name of namespace interface for pasta > * @pasta_ifi: Index of namespace interface for pasta > * @pasta_conf_ns: Configure namespace after creating it > + * @no_pidns: Don't create a new PID namespace for spawned command > * @fwd: Forwarding tables > * @fwd_pending: Pending forward tables > * @no_tcp: Disable TCP operation > @@ -278,6 +279,7 @@ struct ctx { > char pasta_ifn[IF_NAMESIZE]; > unsigned int pasta_ifi; > int pasta_conf_ns; > + bool no_pidns; > > struct fwd_table *fwd[PIF_NUM_TYPES]; > struct fwd_table *fwd_pending[PIF_NUM_TYPES]; > diff --git a/pasta.c b/pasta.c > index 5aa56b7..2d916e1 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -194,15 +194,17 @@ static int pasta_spawn_cmd(void *arg) > if (prctl(PR_SET_PDEATHSIG, SIGKILL)) > die_perror("Couldn't set PR_SET_PDEATHSIG"); > > - /* We run in a detached PID and mount namespace: mount /proc over */ > - if (mount("", "/proc", "proc", 0, NULL)) > + a = (const struct pasta_spawn_cmd_arg *)arg; > + > + /* We run in a detached mount namespace, and, unless --no-pidns was > + * given, in a detached PID namespace: mount /proc over > + */ > + if (!a->c->no_pidns && mount("", "/proc", "proc", 0, NULL)) > warn_perror("Couldn't mount /proc"); > > if (write_file("/proc/sys/net/ipv4/ping_group_range", "0 0")) > warn("Cannot set ping_group_range, ICMP requests might fail"); > > - a = (const struct pasta_spawn_cmd_arg *)arg; > - > conf_hostname_len = strlen(a->c->hostname); > if (conf_hostname_len > 0) { > if (sethostname(a->c->hostname, conf_hostname_len)) > @@ -243,6 +245,7 @@ static int pasta_spawn_cmd(void *arg) > void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid, bool config_idmaps, > int argc, char *argv[]) > { > + int flags = CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWNS; > char ns_fn_stack[NS_FN_STACK_SIZE] > __attribute__ ((aligned(__alignof__(max_align_t)))); > struct pasta_spawn_cmd_arg arg = { > @@ -293,10 +296,11 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid, bool config_idmaps, > sigaddset(&set, SIGUSR1); > sigprocmask(SIG_BLOCK, &set, NULL); > > + if (!c->no_pidns) > + flags |= CLONE_NEWPID; > + > pasta_child_pid = do_clone(pasta_spawn_cmd, ns_fn_stack, > - sizeof(ns_fn_stack), > - CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNET | > - CLONE_NEWUTS | CLONE_NEWNS | SIGCHLD, > + sizeof(ns_fn_stack), flags | SIGCHLD, > (void *)&arg); > > if (pasta_child_pid == -1) > diff --git a/test/pasta_options/no_pidns b/test/pasta_options/no_pidns > new file mode 100644 > index 0000000..f565b2f > --- /dev/null > +++ b/test/pasta_options/no_pidns > @@ -0,0 +1,25 @@ > +# SPDX-License-Identifier: GPL-2.0-or-later > +# > +# PASST - Plug A Simple Socket Transport > +# for qemu/UNIX domain socket mode > +# > +# PASTA - Pack A Subtle Tap Abstraction > +# for network namespace/tap device mode > +# > +# test/pasta_options/no_pidns - Check --no-pidns handling > + > +htools readlink > + > +test Command is spawned in a new PID namespace by default > +set PIDNS __STATEDIR__/pidns > +set OUT __STATEDIR__/no-pidns.out > +set ERR __STATEDIR__/no-pidns.err > + > +passt readlink /proc/self/ns/pid > __PIDNS__ > +passt ./pasta -q -- readlink /proc/self/ns/pid > __OUT__ 2> __ERR__ > +check [ "$(cat __PIDNS__)" != "$(cat __OUT__)" ] > + > +test --no-pidns keeps command in the caller's PID namespace > +passt ./pasta -q --no-pidns -- readlink /proc/self/ns/pid > __OUT__ 2> __ERR__ > +check [ "$(cat __PIDNS__)" = "$(cat __OUT__)" ] > +check [ ! -s __ERR__ ] > diff --git a/test/run b/test/run > index c4073cc..14ddbbf 100755 > --- a/test/run > +++ b/test/run > @@ -86,6 +86,7 @@ run() { > setup pasta_options > test pasta_options/log_to_file > test pasta_options/netns_only > + test pasta_options/no_pidns > teardown pasta_options > > setup build