<feed xmlns='http://www.w3.org/2005/Atom'>
<title>passt/pasta.h, branch 2026_09_25.df90211</title>
<subtitle>Plug A Simple Socket Transport</subtitle>
<link rel='alternate' type='text/html' href='https://passt.top/passt/'/>
<entry>
<title>isolation: Don't create our userns as nobody</title>
<updated>2026-09-08T14:00:23+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-08-20T05:30:33+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=7bf1595c924271b74e924426765fa0b5524e4e57'/>
<id>7bf1595c924271b74e924426765fa0b5524e4e57</id>
<content type='text'>
In isolate_user(), we set[ug]id() to our final UID/GID, then join or
create our userns.  This makes sense when we're going to use an already
existing userns, that is, with the --userns option, a PID passed to pasta
or with --netns-only (we use our current userns).  However, it causes a
problem when we create our own new userns.

The set[ug]id() is most often a no-op, but when it isn't it's generally a
switch from root to nobody.  If we create our userns after this, we will
create it owned by nobody.  That means that anything which can operate as
nobody can enter our userns with full capabilities, potentially allowing
it to attack a running passt or pasta.  This sort of attach is unlikely
in practice: something else on the system must have a security defect to
allow arbitrary actions as nobody, and even then it will probably be caught
by LSMs.

Still, it's better to avoid this.  So, rearrange the creation of our
userns so that it is owned by the original user (e.g. root).  This requires
us to always create a UID &amp; GID mapping within the userns so that we can
switch to the correct final user after we've entered the namespace.

Since we now always create that user mapping when we create the ns, we no
longer need to do so as we spawn the pasta shell or command.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In isolate_user(), we set[ug]id() to our final UID/GID, then join or
create our userns.  This makes sense when we're going to use an already
existing userns, that is, with the --userns option, a PID passed to pasta
or with --netns-only (we use our current userns).  However, it causes a
problem when we create our own new userns.

The set[ug]id() is most often a no-op, but when it isn't it's generally a
switch from root to nobody.  If we create our userns after this, we will
create it owned by nobody.  That means that anything which can operate as
nobody can enter our userns with full capabilities, potentially allowing
it to attack a running passt or pasta.  This sort of attach is unlikely
in practice: something else on the system must have a security defect to
allow arbitrary actions as nobody, and even then it will probably be caught
by LSMs.

Still, it's better to avoid this.  So, rearrange the creation of our
userns so that it is owned by the original user (e.g. root).  This requires
us to always create a UID &amp; GID mapping within the userns so that we can
switch to the correct final user after we've entered the namespace.

Since we now always create that user mapping when we create the ns, we no
longer need to do so as we spawn the pasta shell or command.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pasta: Include pasta.h in pasta.c</title>
<updated>2026-09-08T14:00:05+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2026-08-20T05:30:30+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=5b4bdc8c0362c1e0926a8f0eeb6e63f89c0ec7d5'/>
<id>5b4bdc8c0362c1e0926a8f0eeb6e63f89c0ec7d5</id>
<content type='text'>
pasta.c doesn't include its own header, meaning the compiler hasn't caught
some mismatches between functions and their prototypes.  Fix the oversight.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
pasta.c doesn't include its own header, meaning the compiler hasn't caught
some mismatches between functions and their prototypes.  Fix the oversight.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pasta: Do not configure ID mappings when invoked with --netns-only</title>
<updated>2026-07-23T09:46:49+00:00</updated>
<author>
<name>Dwayne B. Bent</name>
<email>dbb@dbb.dev</email>
</author>
<published>2026-07-22T15:32:41+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=ffa5cee6bb781d7ced19a69659c3d443ea734163'/>
<id>ffa5cee6bb781d7ced19a69659c3d443ea734163</id>
<content type='text'>
Add a `bool` argument `config_idmaps` to `pasta_start_ns()` that guards
the logic to configure user and group ID mappings. It is set to `false`
when `netns_only` is `true`. Fixes bug 216.

Link: https://bugs.passt.top/show_bug.cgi?id=216
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Dwayne B. Bent &lt;dbb@dbb.dev&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Add a `bool` argument `config_idmaps` to `pasta_start_ns()` that guards
the logic to configure user and group ID mappings. It is set to `false`
when `netns_only` is `true`. Fixes bug 216.

Link: https://bugs.passt.top/show_bug.cgi?id=216
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Dwayne B. Bent &lt;dbb@dbb.dev&gt;
Reviewed-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add missing includes to headers</title>
<updated>2026-03-04T16:39:57+00:00</updated>
<author>
<name>Peter Foley</name>
<email>pefoley@google.com</email>
</author>
<published>2026-02-23T18:11:19+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=adbf5c135f19db5b6751393b7f5cbf516031bde8'/>
<id>adbf5c135f19db5b6751393b7f5cbf516031bde8</id>
<content type='text'>
Support build systems like bazel that check that headers are
self-contained.

Also update includes so that clang-include-cleaner succeeds.

Tested with:
clang-include-cleaner-19 --extra-arg=-D_GNU_SOURCE --extra-arg=-DPAGE_SIZE=4096 --extra-arg=-DVERSION=\"git\" --extra-arg=-DHAS_GETRANDOM *.h *.c

Signed-off-by: Peter Foley &lt;pefoley@google.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Support build systems like bazel that check that headers are
self-contained.

Also update includes so that clang-include-cleaner succeeds.

Tested with:
clang-include-cleaner-19 --extra-arg=-D_GNU_SOURCE --extra-arg=-DPAGE_SIZE=4096 --extra-arg=-DVERSION=\"git\" --extra-arg=-DHAS_GETRANDOM *.h *.c

Signed-off-by: Peter Foley &lt;pefoley@google.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pasta: Add fallback timer mechanism to check if namespace is gone</title>
<updated>2024-02-16T07:47:14+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2024-02-15T22:24:32+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=8f3f8e190c43fc6a3adc7912aaa262e86f9d0748'/>
<id>8f3f8e190c43fc6a3adc7912aaa262e86f9d0748</id>
<content type='text'>
We don't know how frequently this happens, but hitting
fs.inotify.max_user_watches or similar sysctl limits is definitely
not out of question, and Paul mentioned that, for example, Podman's
CI environments hit similar issues in the past.

Introduce a fallback mechanism based on a timer file descriptor: we
grab the directory handle at startup, and we can then use openat(),
triggered periodically, to check if the (network) namespace directory
still exists. If openat() fails at some point, exit.

Link: https://github.com/containers/podman/pull/21563#issuecomment-1943505707
Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We don't know how frequently this happens, but hitting
fs.inotify.max_user_watches or similar sysctl limits is definitely
not out of question, and Paul mentioned that, for example, Podman's
CI environments hit similar issues in the past.

Introduce a fallback mechanism based on a timer file descriptor: we
grab the directory handle at startup, and we can then use openat(),
triggered periodically, to check if the (network) namespace directory
still exists. If openat() fails at some point, exit.

Link: https://github.com/containers/podman/pull/21563#issuecomment-1943505707
Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>cppcheck: Make many pointers const</title>
<updated>2023-10-04T21:23:35+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2023-09-29T05:50:19+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=6471c7d01b0aad9d144448290557fcd783562228'/>
<id>6471c7d01b0aad9d144448290557fcd783562228</id>
<content type='text'>
Newer versions of cppcheck (as of 2.12.0, at least) added a warning for
pointers which could be declared to point at const data, but aren't.
Based on that, make many pointers throughout the codebase const.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Newer versions of cppcheck (as of 2.12.0, at least) added a warning for
pointers which could be declared to point at const data, but aren't.
Based on that, make many pointers throughout the codebase const.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>passt: Relicense to GPL 2.0, or any later version</title>
<updated>2023-04-06T16:00:33+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2023-04-05T18:11:44+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=ca2749e1bd520c6a1dbca24f1561ee31dd833a54'/>
<id>ca2749e1bd520c6a1dbca24f1561ee31dd833a54</id>
<content type='text'>
In practical terms, passt doesn't benefit from the additional
protection offered by the AGPL over the GPL, because it's not
suitable to be executed over a computer network.

Further, restricting the distribution under the version 3 of the GPL
wouldn't provide any practical advantage either, as long as the passt
codebase is concerned, and might cause unnecessary compatibility
dilemmas.

Change licensing terms to the GNU General Public License Version 2,
or any later version, with written permission from all current and
past contributors, namely: myself, David Gibson, Laine Stump, Andrea
Bolognani, Paul Holzinger, Richard W.M. Jones, Chris Kuhn, Florian
Weimer, Giuseppe Scrivano, Stefan Hajnoczi, and Vasiliy Ulyanov.

Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In practical terms, passt doesn't benefit from the additional
protection offered by the AGPL over the GPL, because it's not
suitable to be executed over a computer network.

Further, restricting the distribution under the version 3 of the GPL
wouldn't provide any practical advantage either, as long as the passt
codebase is concerned, and might cause unnecessary compatibility
dilemmas.

Change licensing terms to the GNU General Public License Version 2,
or any later version, with written permission from all current and
past contributors, namely: myself, David Gibson, Laine Stump, Andrea
Bolognani, Paul Holzinger, Richard W.M. Jones, Chris Kuhn, Florian
Weimer, Giuseppe Scrivano, Stefan Hajnoczi, and Vasiliy Ulyanov.

Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pasta: Wait for tap to be set up before spawning command</title>
<updated>2023-02-12T11:22:59+00:00</updated>
<author>
<name>Stefano Brivio</name>
<email>sbrivio@redhat.com</email>
</author>
<published>2023-02-12T11:22:59+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=d8921dafe506599fd7ff723b211f9113faff9ada'/>
<id>d8921dafe506599fd7ff723b211f9113faff9ada</id>
<content type='text'>
Adapted from a patch by Paul Holzinger: when pasta spawns a command,
operating without a pre-existing user and network namespace, it needs
to wait for the tap device to be configured and its handler ready,
before the command is actually executed.

Otherwise, something like:
  pasta --config-net nslookup passt.top

usually fails as the nslookup command is issued before the network
interface is ready.

We can't adopt a simpler approach based on SIGSTOP and SIGCONT here:
the child runs in a separate PID namespace, so it can't send SIGSTOP
to itself as the kernel sees the child as init process and blocks
the delivery of the signal.

We could send SIGSTOP from the parent, but this wouldn't avoid the
possible condition where the child isn't ready to wait for it when
the parent sends it, also raised by Paul -- and SIGSTOP can't be
blocked, so it can never be pending.

Use SIGUSR1 instead: mask it before clone(), so that the child starts
with it blocked, and can safely wait for it. Once the parent is
ready, it sends SIGUSR1 to the child. If SIGUSR1 is sent before the
child is waiting for it, the kernel will queue it for us, because
it's blocked.

Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Fixes: 1392bc5ca002 ("Allow pasta to take a command to execute")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Adapted from a patch by Paul Holzinger: when pasta spawns a command,
operating without a pre-existing user and network namespace, it needs
to wait for the tap device to be configured and its handler ready,
before the command is actually executed.

Otherwise, something like:
  pasta --config-net nslookup passt.top

usually fails as the nslookup command is issued before the network
interface is ready.

We can't adopt a simpler approach based on SIGSTOP and SIGCONT here:
the child runs in a separate PID namespace, so it can't send SIGSTOP
to itself as the kernel sees the child as init process and blocks
the delivery of the signal.

We could send SIGSTOP from the parent, but this wouldn't avoid the
possible condition where the child isn't ready to wait for it when
the parent sends it, also raised by Paul -- and SIGSTOP can't be
blocked, so it can never be pending.

Use SIGUSR1 instead: mask it before clone(), so that the child starts
with it blocked, and can safely wait for it. Once the parent is
ready, it sends SIGUSR1 to the child. If SIGUSR1 is sent before the
child is waiting for it, the kernel will queue it for us, because
it's blocked.

Reported-by: Paul Holzinger &lt;pholzing@redhat.com&gt;
Fixes: 1392bc5ca002 ("Allow pasta to take a command to execute")
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>isolation: Only configure UID/GID mappings in userns when spawning shell</title>
<updated>2022-10-15T00:10:36+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2022-10-14T04:25:36+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=eb3d03a588e8a246a30017add08c79527fa9a6a3'/>
<id>eb3d03a588e8a246a30017add08c79527fa9a6a3</id>
<content type='text'>
When in passt mode, or pasta mode spawning a command, we create a userns
for ourselves.  This is used both to isolate the pasta/passt process itself
and to run the spawned command, if any.

Since eed17a47 "Handle userns isolation and dropping root at the same time"
we've handled both cases the same, configuring the UID and GID mappings in
the new userns to map whichever UID we're running as to root within the
userns.

This mapping is desirable when spawning a shell or other command, so that
the user gets a root shell with reasonably clear abilities within the
userns and netns.  It's not necessarily essential, though.  When not
spawning a shell, it doesn't really have any purpose: passt itself doesn't
need to be root and can operate fine with an unmapped user (using some of
the capabilities we get when entering the userns instead).

Configuring the uid_map can cause problems if passt is running with any
capabilities in the initial namespace, such as CAP_NET_BIND_SERVICE to
allow it to forward low ports.  In this case the kernel makes files in
/proc/pid owned by root rather than the starting user to prevent the user
from interfering with the operation of the capability-enhanced process.
This includes uid_map meaning we are not able to write to it.

Whether this behaviour is correct in the kernel is debatable, but in any
case we might as well avoid problems by only initializing the user mappings
when we really want them.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When in passt mode, or pasta mode spawning a command, we create a userns
for ourselves.  This is used both to isolate the pasta/passt process itself
and to run the spawned command, if any.

Since eed17a47 "Handle userns isolation and dropping root at the same time"
we've handled both cases the same, configuring the UID and GID mappings in
the new userns to map whichever UID we're running as to root within the
userns.

This mapping is desirable when spawning a shell or other command, so that
the user gets a root shell with reasonably clear abilities within the
userns and netns.  It's not necessarily essential, though.  When not
spawning a shell, it doesn't really have any purpose: passt itself doesn't
need to be root and can operate fine with an unmapped user (using some of
the capabilities we get when entering the userns instead).

Configuring the uid_map can cause problems if passt is running with any
capabilities in the initial namespace, such as CAP_NET_BIND_SERVICE to
allow it to forward low ports.  In this case the kernel makes files in
/proc/pid owned by root rather than the starting user to prevent the user
from interfering with the operation of the capability-enhanced process.
This includes uid_map meaning we are not able to write to it.

Whether this behaviour is correct in the kernel is debatable, but in any
case we might as well avoid problems by only initializing the user mappings
when we really want them.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
Signed-off-by: Stefano Brivio &lt;sbrivio@redhat.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Handle userns isolation and dropping root at the same time</title>
<updated>2022-09-13T03:31:51+00:00</updated>
<author>
<name>David Gibson</name>
<email>david@gibson.dropbear.id.au</email>
</author>
<published>2022-09-12T12:24:07+00:00</published>
<link rel='alternate' type='text/html' href='https://passt.top/passt/commit/?id=eed17a47fe8291d449fd505d9a6b1f4a72be8d09'/>
<id>eed17a47fe8291d449fd505d9a6b1f4a72be8d09</id>
<content type='text'>
passt/pasta can interact with user namespaces in a number of ways:
   1) With --netns-only we'll remain in our original user namespace
   2) With --userns or a PID option to pasta we'll join either the given
      user namespace or that of the PID
   3) When pasta spawns a shell or command we'll start a new user namespace
      for the command and then join it
   4) With passt we'll create a new user namespace when we sandbox()
      ourself

However (3) and (4) turn out to have essentially the same effect.  In both
cases we create one new user namespace.  The spawned command starts there,
and passt/pasta itself will live there from sandbox() onwards.

Because of this, we can simplify user namespace handling by moving the
userns handling earlier, to the same point we drop root in the original
namespace.  Extend the drop_user() function to isolate_user() which does
both.

After switching UID and GID in the original userns, isolate_user() will
either join or create the userns we require.  When we spawn a command with
pasta_start_ns()/pasta_setup_ns() we no longer need to create a userns,
because we're already made one.  sandbox() likewise no longer needs to
create (or join) an userns because we're already in the one we need.

We no longer need c-&gt;pasta_userns_fd, since the fd is only used locally
in isolate_user().  Likewise we can replace c-&gt;netns_only with a local
in conf(), since it's not used outside there.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
passt/pasta can interact with user namespaces in a number of ways:
   1) With --netns-only we'll remain in our original user namespace
   2) With --userns or a PID option to pasta we'll join either the given
      user namespace or that of the PID
   3) When pasta spawns a shell or command we'll start a new user namespace
      for the command and then join it
   4) With passt we'll create a new user namespace when we sandbox()
      ourself

However (3) and (4) turn out to have essentially the same effect.  In both
cases we create one new user namespace.  The spawned command starts there,
and passt/pasta itself will live there from sandbox() onwards.

Because of this, we can simplify user namespace handling by moving the
userns handling earlier, to the same point we drop root in the original
namespace.  Extend the drop_user() function to isolate_user() which does
both.

After switching UID and GID in the original userns, isolate_user() will
either join or create the userns we require.  When we spawn a command with
pasta_start_ns()/pasta_setup_ns() we no longer need to create a userns,
because we're already made one.  sandbox() likewise no longer needs to
create (or join) an userns because we're already in the one we need.

We no longer need c-&gt;pasta_userns_fd, since the fd is only used locally
in isolate_user().  Likewise we can replace c-&gt;netns_only with a local
in conf(), since it's not used outside there.

Signed-off-by: David Gibson &lt;david@gibson.dropbear.id.au&gt;
</pre>
</div>
</content>
</entry>
</feed>
