The other three references to bash already use "bash" instead of
"/bin/bash". Similarly, "#!/bin/bash" has already been replaced with
"#!/usr/bin/env bash".
Signed-off-by: Jonathan Wright <quaggy@gmail.com>
Fixescontainers/bubblewrap#91
Add the ability to overwrite argv[0] when starting a process in a
container. Using --argv0 to be consistent with ld.so --argv0.
Overwriting argv[0] is useful as some tools change their behavior based
on the value of argv[0]. For example, when bash is symlinked to sh it
behaves as sh. Similarly, unxz is a symlink to xz and changes the
default from compressing to decompressing. An extreme example is on many
systems, date, df, cat and so on are all symlinks to the coreutils
binary.
Example usage: bwrap --bind / / --argv0 sh bash
Signed-off-by: Jonathan Wright <quaggy@gmail.com>
The test wants to mount /tmp on /mnt but /mnt comes from the host and
can be a symlink in which case the test fails. Skip the test in this
situation.
Signed-off-by: Sebastian Wick <sebastian.wick@redhat.com>
bubblewrap can provide a robust security boundary that severely limits
functionality, or it can provide full functionality without any attempt
at being a security boundary, or anything in between those extremes.
If a caller of bubblewrap chooses inappropriate command-line arguments
for their desired security model, then bubblewrap will not provide the
security model they are aiming for, but this is not a bubblewrap
vulnerability.
Apparently this isn't clear to everyone, so try to clarify.
The one place where bubblewrap *does* define some sort of security
policy for itself is when it's setuid root, in which case it's
responsible for preventing users from carrying out privilege escalation
attacks like CVE-2020-5291.
Resolves: https://github.com/containers/bubblewrap/issues/555
Signed-off-by: Simon McVittie <smcv@collabora.com>
Mention how to format capabilities for --add-cap, e.g.
CAP_DAC_READ_SEARCH instead of DAC_READ_SEARCH.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
load_file_data() closes the passed file descriptor in case of an read(2)
failure. The file descriptor is however owned by the caller and should
not be closed to avoid a double-close.
Since in this error branch NULL is always returned the only affected
caller is load_file_data(), as all other callers immediately abort via
die_with_error(). As bubblewrap is single-threaded the second close(2)
in load_file_data() will be well-defined and fail with EBADF, leading to
no unrelated file descriptor to be closed
Found by GCC analyzer:
./utils.c: In function ‘load_file_at’:
./utils.c:630:3: warning: double ‘close’ of file descriptor ‘fd’ [CWE-1341] [-Wanalyzer-fd-double-close]
630 | close (fd);
| ^~~~~~~~~~
...
| 596 | close (fd);
| | ~~~~~~~~~~
| | |
| | (15) first ‘close’ here
...
| 630 | close (fd);
| | ~~~~~~~~~~
| | |
| | (20) second ‘close’ here; first ‘close’ was at (15)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Found by running under pedantic UBSAN:
../bubblewrap.c:968:21: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uid_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
../bubblewrap.c:1210:28: runtime error: implicit conversion from type 'int' of value -41 (32-bit, signed) to type 'unsigned int' changed the value to 4294967255 (32-bit, unsigned)
../bubblewrap.c:1215:28: runtime error: implicit conversion from type 'int' of value -41 (32-bit, signed) to type 'unsigned int' changed the value to 4294967255 (32-bit, unsigned)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Comparisson of different signedness can result in unexpected results due
to implicit conversions.
../network.c:81:34: warning: comparison of integer expressions of different signedness: ‘__u32’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
81 | if (rheader->nlmsg_seq != seq_nr)
| ^~
../network.c:83:34: warning: comparison of integer expressions of different signedness: ‘__u32’ {aka ‘unsigned int’} and ‘__pid_t’ {aka ‘int’} [-Wsign-compare]
83 | if (rheader->nlmsg_pid != getpid ())
| ^~
../bind-mount.c:268:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
268 | assert (i < n_lines);
| ^
../bind-mount.c:309:13: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
309 | assert (i == n_lines);
| ^~
../bind-mount.c:318:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
318 | for (i = 0; i < n_lines; i++)
| ^
../bind-mount.c:321:17: warning: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Wsign-compare]
321 | for (i = 0; i < n_lines; i++)
| ^
../utils.c:818:19: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘ssize_t’ {aka ‘long int’} [-Wsign-compare]
818 | while (size - 2 < n);
| ^
../bubblewrap.c:489:13: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
489 | assert (j < sizeof(dont_close)/sizeof(*dont_close));
| ^
../bubblewrap.c:994:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘uid_t’ {aka ‘unsigned int’} [-Wsign-compare]
994 | if (setfsuid (-1) != real_uid)
| ^~
../bubblewrap.c:1042:61: warning: comparison of integer expressions of different signedness: ‘ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
1042 | if (write (privileged_op_socket, buffer, buffer_size) != buffer_size)
| ^~
../bubblewrap.c:1232:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
1232 | for (i = 0; i < N_ELEMENTS (cover_proc_dirs); i++)
| ^
../bubblewrap.c:1260:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
1260 | for (i = 0; i < N_ELEMENTS (devnodes); i++)
| ^
../bubblewrap.c:1272:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
1272 | for (i = 0; i < N_ELEMENTS (stdionodes); i++)
| ^
../bubblewrap.c: In function ‘read_priv_sec_op’:
../bubblewrap.c:1556:15: warning: comparison of integer expressions of different signedness: ‘ssize_t’ {aka ‘long int’} and ‘long unsigned int’ [-Wsign-compare]
1556 | if (rec_len < sizeof (PrivSepOp))
| ^
../bubblewrap.c:1626:28: warning: comparison of integer expressions of different signedness: ‘int’ and ‘uint32_t’ {aka ‘unsigned int’} [-Wsign-compare]
1626 | if (*total_parsed_argc_p > MAX_ARGS)
| ^
../bubblewrap.c:1681:40: warning: comparison of integer expressions of different signedness: ‘int’ and ‘uint32_t’ {aka ‘unsigned int’} [-Wsign-compare]
1681 | if (*total_parsed_argc_p > MAX_ARGS)
| ^
../bubblewrap.c:2265:31: warning: comparison of integer expressions of different signedness: ‘uid_t’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
2265 | if (opt_sandbox_uid != -1)
| ^~
../bubblewrap.c:2285:31: warning: comparison of integer expressions of different signedness: ‘gid_t’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
2285 | if (opt_sandbox_gid != -1)
| ^~
../bubblewrap.c:2678:23: warning: comparison of integer expressions of different signedness: ‘uid_t’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
2678 | if (opt_sandbox_uid == -1)
| ^~
../bubblewrap.c:2680:23: warning: comparison of integer expressions of different signedness: ‘gid_t’ {aka ‘unsigned int’} and ‘int’ [-Wsign-compare]
2680 | if (opt_sandbox_gid == -1)
| ^~
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The worst-case scenario in terms of enforcing --disable-userns is that
we're retaining all capabilities, so test that too, to make sure that
the option is genuinely restricting even a privileged user.
Signed-off-by: Simon McVittie <smcv@collabora.com>
If we're running the tests as uid 0 with capabilities, then bwrap will
not create a new user namespace by default, which means the limit won't
be exceeded and the test will fail. Make sure we always try to create
the new user namespace.
Signed-off-by: Simon McVittie <smcv@collabora.com>
General-purpose desktop distributions are compiled with CONFIG_SECCOMP
and CONFIG_SECCOMP_FILTER, but vendor kernels for phones and other
assorted embedded devices don't necessarily enable these options. These
kernels are unsuitable for running Flatpak, or anything else that relies
on `bwrap --seccomp` or `bwrap --add-seccomp-fd`.
Missing CONFIG_SECCOMP or CONFIG_SECCOMP_FILTER is not the *only* reason
why we could get EINVAL here: I think we'd also get EINVAL if the seccomp
program is syntatically invalid. However, it's a relatively likely reason,
so it seems worth providing a hint.
Helps: flatpak/flatpak#3069
Signed-off-by: Simon McVittie <smcv@collabora.com>
Older versions of capsh would only show the capabilities, which we
expect not to change when we don't drop capabilities; but newer
versions also display whether the NO_NEW_PRIVS bit is set, and we *do*
expect to change that.
Resolves: https://github.com/containers/bubblewrap/issues/544
Signed-off-by: Simon McVittie <smcv@collabora.com>
We can't combine --disable-userns with entering an existing user
namespace via --userns if the existing user namespace was created with
--disable-userns, because its ability to create nested user namespaces
has already been disabled. However, the next best thing is to verify
that we are already in the desired state.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Some use-cases of bubblewrap want to ensure that the subprocess can't
further re-arrange the filesystem namespace, or do other more complex
namespace modification. For example, Flatpak wants to prevent sandboxed
processes from altering their /proc/$pid/root/.flatpak-info, so that
/.flatpak-info can safely be used as an indicator that a process is part
of a Flatpak app.
This approach was suggested by lukts30 on containers/bubblewrap#452.
The sysctl-controlled maximum numbers of namespaces are themselves
namespaced, so we can disable nested user namespaces by setting the
limit to 1 and then entering a new, nested user namespace. The resulting
process loses its privileges in the namespace where the limit was set
to 1, so it is unable to move the limit back up.
Co-authored-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Simon McVittie <smcv@collabora.com>
df --output was new in coreutils 8.21 (2013), and non-GNU
implementations like busybox df don't have it.
This avoids a test failure in Steam Runtime 1 'scout', which is based
on Ubuntu 12.04 (2012). It'll also be helpful for anyone maintaining
an OS with non-GNU shell utilities.
Signed-off-by: Simon McVittie <smcv@collabora.com>