summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check.yml3
-rw-r--r--README.md26
-rw-r--r--bind-mount.c65
-rw-r--r--bind-mount.h9
-rw-r--r--bubblewrap.c15
-rw-r--r--bwrap.xml26
-rw-r--r--completions/bash/bwrap1
-rw-r--r--completions/zsh/_bwrap1
-rw-r--r--configure.ac2
-rw-r--r--meson.build37
-rw-r--r--meson_options.txt21
-rw-r--r--tests/meson.build1
-rwxr-xr-xtests/test-run.sh11
-rwxr-xr-xtests/test-specifying-pidns.sh3
-rw-r--r--tests/try-syscall.c10
-rwxr-xr-xtests/use-as-subproject/assert-correct-rpath.py26
-rw-r--r--tests/use-as-subproject/meson.build1
-rw-r--r--utils.c8
-rw-r--r--utils.h4
19 files changed, 220 insertions, 50 deletions
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 34b8771..d55d158 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -110,7 +110,7 @@ jobs:
( cd DESTDIR && find -ls )
- name: dist
run: |
- BWRAP_MUST_WORK=1 CI_MESON_DIST=1 meson dist -C _build
+ BWRAP_MUST_WORK=1 meson dist -C _build
- name: Collect dist test logs on failure
if: failure()
run: mv _build/meson-private/dist-build/meson-logs/testlog.txt test-logs/disttestlog.txt || true
@@ -127,6 +127,7 @@ jobs:
test -x DESTDIR-as-subproject/usr/local/libexec/not-flatpak-bwrap
test ! -e DESTDIR-as-subproject/usr/local/bin/bwrap
test ! -e DESTDIR-as-subproject/usr/local/libexec/bwrap
+ tests/use-as-subproject/assert-correct-rpath.py DESTDIR-as-subproject/usr/local/libexec/not-flatpak-bwrap
- name: Upload test logs
uses: actions/upload-artifact@v1
if: failure() || cancelled()
diff --git a/README.md b/README.md
index f7eb85f..d251fbd 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ user namespaces. Emphasis on subset - specifically relevant to the
above CVE, bubblewrap does not allow control over iptables.
The original bubblewrap code existed before user namespaces - it inherits code from
-[xdg-app helper](https://cgit.freedesktop.org/xdg-app/xdg-app/tree/common/xdg-app-helper.c)
+[xdg-app helper](https://cgit.freedesktop.org/xdg-app/xdg-app/tree/common/xdg-app-helper.c?id=4c3bf179e2e4a2a298cd1db1d045adaf3f564532)
which in turn distantly derives from
[linux-user-chroot](https://git.gnome.org/browse/linux-user-chroot).
@@ -62,6 +62,30 @@ clusters. Having the ability for unprivileged users to use container
features would make it significantly easier to do interactive
debugging scenarios and the like.
+Installation
+------------
+
+bubblewrap is available in the package repositories of the most Linux distributions
+and can be installed from there.
+
+If you need to build bubblewrap from source, you can do this with meson or autotools.
+
+meson:
+
+```
+meson _builddir
+meson compile -C _builddir
+meson install -C _builddir
+```
+
+autotools:
+
+```
+./autogen.sh
+make
+sudo make install
+```
+
Usage
-----
diff --git a/bind-mount.c b/bind-mount.c
index 877b095..488d85a 100644
--- a/bind-mount.c
+++ b/bind-mount.c
@@ -378,7 +378,8 @@ bind_mount_result
bind_mount (int proc_fd,
const char *src,
const char *dest,
- bind_option_t options)
+ bind_option_t options,
+ char **failing_path)
{
bool readonly = (options & BIND_READONLY) != 0;
bool devices = (options & BIND_DEVICES) != 0;
@@ -406,7 +407,12 @@ bind_mount (int proc_fd,
dest_fd = open (resolved_dest, O_PATH | O_CLOEXEC);
if (dest_fd < 0)
- return BIND_MOUNT_ERROR_REOPEN_DEST;
+ {
+ if (failing_path != NULL)
+ *failing_path = steal_pointer (&resolved_dest);
+
+ return BIND_MOUNT_ERROR_REOPEN_DEST;
+ }
/* If we are in a case-insensitive filesystem, mountinfo might contain a
* different case combination of the path we requested to mount.
@@ -422,11 +428,19 @@ bind_mount (int proc_fd,
oldroot_dest_proc = get_oldroot_path (dest_proc);
kernel_case_combination = readlink_malloc (oldroot_dest_proc);
if (kernel_case_combination == NULL)
- return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD;
+ {
+ if (failing_path != NULL)
+ *failing_path = steal_pointer (&resolved_dest);
+
+ return BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD;
+ }
mount_tab = parse_mountinfo (proc_fd, kernel_case_combination);
if (mount_tab[0].mountpoint == NULL)
{
+ if (failing_path != NULL)
+ *failing_path = steal_pointer (&kernel_case_combination);
+
errno = EINVAL;
return BIND_MOUNT_ERROR_FIND_DEST_MOUNT;
}
@@ -437,7 +451,12 @@ bind_mount (int proc_fd,
if (new_flags != current_flags &&
mount ("none", resolved_dest,
NULL, MS_SILENT | MS_BIND | MS_REMOUNT | new_flags, NULL) != 0)
- return BIND_MOUNT_ERROR_REMOUNT_DEST;
+ {
+ if (failing_path != NULL)
+ *failing_path = steal_pointer (&resolved_dest);
+
+ return BIND_MOUNT_ERROR_REMOUNT_DEST;
+ }
/* We need to work around the fact that a bind mount does not apply the flags, so we need to manually
* apply the flags to all submounts in the recursive case.
@@ -456,7 +475,12 @@ bind_mount (int proc_fd,
/* If we can't read the mountpoint we can't remount it, but that should
be safe to ignore because its not something the user can access. */
if (errno != EACCES)
- return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT;
+ {
+ if (failing_path != NULL)
+ *failing_path = xstrdup (mount_tab[i].mountpoint);
+
+ return BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT;
+ }
}
}
}
@@ -469,50 +493,53 @@ bind_mount (int proc_fd,
* If want_errno_p is non-NULL, *want_errno_p is used to indicate whether
* it would make sense to print strerror(saved_errno).
*/
-const char *
+static char *
bind_mount_result_to_string (bind_mount_result res,
+ const char *failing_path,
bool *want_errno_p)
{
- const char *string;
+ char *string = NULL;
bool want_errno = TRUE;
switch (res)
{
case BIND_MOUNT_ERROR_MOUNT:
- string = "Unable to mount source on destination";
+ string = xstrdup ("Unable to mount source on destination");
break;
case BIND_MOUNT_ERROR_REALPATH_DEST:
- string = "realpath(destination)";
+ string = xstrdup ("realpath(destination)");
break;
case BIND_MOUNT_ERROR_REOPEN_DEST:
- string = "open(destination, O_PATH)";
+ string = xasprintf ("open(\"%s\", O_PATH)", failing_path);
break;
case BIND_MOUNT_ERROR_READLINK_DEST_PROC_FD:
- string = "readlink(/proc/self/fd/<destination>)";
+ string = xasprintf ("readlink(/proc/self/fd/N) for \"%s\"", failing_path);
break;
case BIND_MOUNT_ERROR_FIND_DEST_MOUNT:
- string = "Unable to find destination in mount table";
+ string = xasprintf ("Unable to find \"%s\" in mount table", failing_path);
want_errno = FALSE;
break;
case BIND_MOUNT_ERROR_REMOUNT_DEST:
- string = "Unable to remount destination with correct flags";
+ string = xasprintf ("Unable to remount destination \"%s\" with correct flags",
+ failing_path);
break;
case BIND_MOUNT_ERROR_REMOUNT_SUBMOUNT:
- string = "Unable to remount recursively with correct flags";
+ string = xasprintf ("Unable to apply mount flags: remount \"%s\"",
+ failing_path);
break;
case BIND_MOUNT_SUCCESS:
- string = "Success";
+ string = xstrdup ("Success");
break;
default:
- string = "(unknown/invalid bind_mount_result)";
+ string = xstrdup ("(unknown/invalid bind_mount_result)");
break;
}
@@ -525,11 +552,13 @@ bind_mount_result_to_string (bind_mount_result res,
void
die_with_bind_result (bind_mount_result res,
int saved_errno,
+ const char *failing_path,
const char *format,
...)
{
va_list args;
bool want_errno = TRUE;
+ char *message;
fprintf (stderr, "bwrap: ");
@@ -537,7 +566,9 @@ die_with_bind_result (bind_mount_result res,
vfprintf (stderr, format, args);
va_end (args);
- fprintf (stderr, ": %s", bind_mount_result_to_string (res, &want_errno));
+ message = bind_mount_result_to_string (res, failing_path, &want_errno);
+ fprintf (stderr, ": %s", message);
+ /* message is leaked, but we're exiting unsuccessfully anyway, so ignore */
if (want_errno)
fprintf (stderr, ": %s", strerror (saved_errno));
diff --git a/bind-mount.h b/bind-mount.h
index 1fac3e5..8a361fb 100644
--- a/bind-mount.h
+++ b/bind-mount.h
@@ -42,14 +42,13 @@ typedef enum
bind_mount_result bind_mount (int proc_fd,
const char *src,
const char *dest,
- bind_option_t options);
-
-const char *bind_mount_result_to_string (bind_mount_result res,
- bool *want_errno);
+ bind_option_t options,
+ char **failing_path);
void die_with_bind_result (bind_mount_result res,
int saved_errno,
+ const char *failing_path,
const char *format,
...)
__attribute__((__noreturn__))
- __attribute__((format (printf, 3, 4)));
+ __attribute__((format (printf, 4, 5)));
diff --git a/bubblewrap.c b/bubblewrap.c
index 0f372eb..1d9f9ad 100644
--- a/bubblewrap.c
+++ b/bubblewrap.c
@@ -330,7 +330,7 @@ usage (int ecode, FILE *out)
" --ro-bind-data FD DEST Copy from FD to file which is readonly bind-mounted on DEST\n"
" --symlink SRC DEST Create symlink at DEST with target SRC\n"
" --seccomp FD Load and use seccomp rules from FD (not repeatable)\n"
- " --add-seccomp FD Load and use seccomp rules from FD (repeatable)\n"
+ " --add-seccomp-fd FD Load and use seccomp rules from FD (repeatable)\n"
" --block-fd FD Block on FD until some data to read is available\n"
" --userns-block-fd FD Block on FD until the user namespace is ready\n"
" --info-fd FD Write information about the running container to FD\n"
@@ -1005,6 +1005,7 @@ privileged_op (int privileged_op_socket,
const char *arg2)
{
bind_mount_result bind_result;
+ char *failing_path = NULL;
if (privileged_op_socket != -1)
{
@@ -1070,23 +1071,25 @@ privileged_op (int privileged_op_socket,
break;
case PRIV_SEP_OP_REMOUNT_RO_NO_RECURSIVE:
- bind_result = bind_mount (proc_fd, NULL, arg2, BIND_READONLY);
+ bind_result = bind_mount (proc_fd, NULL, arg2, BIND_READONLY, &failing_path);
if (bind_result != BIND_MOUNT_SUCCESS)
- die_with_bind_result (bind_result, errno,
+ die_with_bind_result (bind_result, errno, failing_path,
"Can't remount readonly on %s", arg2);
+ assert (failing_path == NULL); /* otherwise we would have died */
break;
case PRIV_SEP_OP_BIND_MOUNT:
/* We always bind directories recursively, otherwise this would let us
access files that are otherwise covered on the host */
- bind_result = bind_mount (proc_fd, arg1, arg2, BIND_RECURSIVE | flags);
+ bind_result = bind_mount (proc_fd, arg1, arg2, BIND_RECURSIVE | flags, &failing_path);
if (bind_result != BIND_MOUNT_SUCCESS)
- die_with_bind_result (bind_result, errno,
+ die_with_bind_result (bind_result, errno, failing_path,
"Can't bind mount %s on %s", arg1, arg2);
+ assert (failing_path == NULL); /* otherwise we would have died */
break;
case PRIV_SEP_OP_PROC_MOUNT:
@@ -2552,7 +2555,7 @@ main (int argc,
struct stat sbuf;
uint64_t val;
int res UNUSED;
- cleanup_free char *args_data = NULL;
+ cleanup_free char *args_data UNUSED = NULL;
int intermediate_pids_sockets[2] = {-1, -1};
/* Handle --version early on before we try to acquire/drop
diff --git a/bwrap.xml b/bwrap.xml
index 4768175..2baec5d 100644
--- a/bwrap.xml
+++ b/bwrap.xml
@@ -131,6 +131,10 @@
<listitem><para>Unshare all possible namespaces. Currently equivalent with: <option>--unshare-user-try</option> <option>--unshare-ipc</option> <option>--unshare-pid</option> <option>--unshare-net</option> <option>--unshare-uts</option> <option>--unshare-cgroup-try</option></para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--share-net</option></term>
+ <listitem><para>Retain the network namespace, overriding an earlier <option>--unshare-all</option> or <option>--unshare-net</option></para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--userns <arg choice="plain">FD</arg></option></term>
<listitem><para>Use an existing user namespace instead of creating a new one. The namespace must fulfil the permission requirements for setns(), which generally means that it must be a descendant of the currently active user namespace, owned by the same user. </para>
<para>This is incompatible with --unshare-user, and doesn't work in the setuid version of bubblewrap.</para></listitem>
@@ -382,6 +386,28 @@
</para></listitem>
</varlistentry>
<varlistentry>
+ <term><option>--json-status-fd <arg choice="plain">FD</arg></option></term>
+ <listitem><para>
+ Multiple JSON documents are written to <arg choice="plain">FD</arg>,
+ one per line (<ulink url="https://jsonlines.org/">"JSON lines" format</ulink>).
+ Each line is a single JSON object.
+ After <command>bwrap</command> has started the child process inside the sandbox,
+ it writes an object with a <literal>child-pid</literal> member to the
+ <option>--json-status-fd</option> (this duplicates the older <option>--info-fd</option>).
+ The corresponding value is the process ID of the child process in the pid namespace from
+ which <command>bwrap</command> was run.
+ If available, the namespace IDs are also included in the object with the <literal>child-pid</literal>;
+ again, this duplicates the older <option>--info-fd</option>.
+ When the child process inside the sandbox exits, <command>bwrap</command> writes an object
+ with an exit-code member, and then closes the <option>--json-status-fd</option>. The value
+ corresponding to <literal>exit-code</literal> is the exit status of the child, in the usual
+ shell encoding (n if it exited normally with status n, or 128+n if it was killed by signal n).
+ Other members may be added to those objects in future versions of <command>bwrap</command>,
+ and other JSON objects may be added before or after the current objects, so readers must
+ ignore members and objects that they do not understand.
+ </para></listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--new-session</option></term>
<listitem><para>
Create a new terminal session for the sandbox (calls setsid()). This
diff --git a/completions/bash/bwrap b/completions/bash/bwrap
index 59928a8..c57d9ab 100644
--- a/completions/bash/bwrap
+++ b/completions/bash/bwrap
@@ -28,6 +28,7 @@ _bwrap() {
# Please keep sorted in LC_ALL=C order
local options_with_args="
$boolean_optons
+ --add-seccomp-fd
--args
--bind
--bind-data
diff --git a/completions/zsh/_bwrap b/completions/zsh/_bwrap
index 5a9d2fd..1e365f0 100644
--- a/completions/zsh/_bwrap
+++ b/completions/zsh/_bwrap
@@ -14,6 +14,7 @@ _bwrap_args=(
$_bwrap_args_after_perms
# Please sort alphabetically (in LC_ALL=C order) by option name
+ '--add-seccomp-fd[Load and use seccomp rules from FD]: :_guard "[0-9]#" "file descriptor to read seccomp rules from"'
'--args[Parse NUL-separated args from FD]: :_guard "[0-9]#" "file descriptor with NUL-separated arguments"'
'--as-pid-1[Do not install a reaper process with PID=1]'
'--bind-try[Equal to --bind but ignores non-existent SRC]:source:_files:destination:_files'
diff --git a/configure.ac b/configure.ac
index d6b72f3..d74fb70 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.63])
-AC_INIT([bubblewrap], [0.6.1], [atomic-devel@projectatomic.io])
+AC_INIT([bubblewrap], [0.6.2], [atomic-devel@projectatomic.io])
AC_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/meson.build b/meson.build
index 5b63aa6..0e1f110 100644
--- a/meson.build
+++ b/meson.build
@@ -1,7 +1,7 @@
project(
'bubblewrap',
'c',
- version : '0.6.1',
+ version : '0.6.2',
meson_version : '>=0.49.0',
default_options : [
'warning_level=2',
@@ -101,12 +101,14 @@ configure_file(
configuration : cdata,
)
-if meson.is_subproject()
- bwrapdir = get_option('libexecdir')
+if meson.is_subproject() and get_option('program_prefix') == ''
+ error('program_prefix option must be set when bwrap is a subproject')
+endif
- if get_option('program_prefix') == ''
- error('program_prefix option must be set when bwrap is a subproject')
- endif
+if get_option('bwrapdir') != ''
+ bwrapdir = get_option('bwrapdir')
+elif meson.is_subproject()
+ bwrapdir = get_option('libexecdir')
else
bwrapdir = get_option('bindir')
endif
@@ -119,14 +121,31 @@ bwrap = executable(
'network.c',
'utils.c',
],
+ build_rpath : get_option('build_rpath'),
install : true,
install_dir : bwrapdir,
+ install_rpath : get_option('install_rpath'),
dependencies : [selinux_dep, libcap_dep],
)
+manpages_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
xsltproc = find_program('xsltproc', required : get_option('man'))
+build_man_page = false
if xsltproc.found() and not meson.is_subproject()
+ if run_command([
+ xsltproc, '--nonet', manpages_xsl,
+ ], check : false).returncode() == 0
+ message('Docbook XSL found, man page enabled')
+ build_man_page = true
+ elif get_option('man').enabled()
+ error('Man page requested, but Docbook XSL stylesheets not found')
+ else
+ message('Docbook XSL not found, man page disabled automatically')
+ endif
+endif
+
+if build_man_page
custom_target(
'bwrap.1',
output : 'bwrap.1',
@@ -140,7 +159,7 @@ if xsltproc.found() and not meson.is_subproject()
'--stringparam', 'man.authors.section.enabled', '0',
'--stringparam', 'man.copyright.section.enabled', '0',
'-o', '@OUTPUT@',
- 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
+ manpages_xsl,
'@INPUT@',
],
install : true,
@@ -152,4 +171,6 @@ if not meson.is_subproject()
subdir('completions')
endif
-subdir('tests')
+if get_option('tests')
+ subdir('tests')
+endif
diff --git a/meson_options.txt b/meson_options.txt
index 2fa3a8c..10a0a20 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -11,6 +11,21 @@ option(
value : '',
)
option(
+ 'bwrapdir',
+ type : 'string',
+ description : 'install bwrap in this directory [default: bindir, or libexecdir in subprojects]',
+)
+option(
+ 'build_rpath',
+ type : 'string',
+ description : 'set a RUNPATH or RPATH on the bwrap executable',
+)
+option(
+ 'install_rpath',
+ type : 'string',
+ description : 'set a RUNPATH or RPATH on the bwrap executable',
+)
+option(
'man',
type : 'feature',
description : 'generate man pages',
@@ -39,6 +54,12 @@ option(
value : 'auto',
)
option(
+ 'tests',
+ type : 'boolean',
+ description : 'build tests',
+ value : 'true',
+)
+option(
'zsh_completion',
type : 'feature',
description : 'install zsh completion script',
diff --git a/tests/meson.build b/tests/meson.build
index 0f32a37..87bf709 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -12,6 +12,7 @@ test_programs = [
executable(
'try-syscall',
'try-syscall.c',
+ override_options: ['b_sanitize=none'],
)
test_scripts = [
diff --git a/tests/test-run.sh b/tests/test-run.sh
index f25a9bc..c8de36d 100755
--- a/tests/test-run.sh
+++ b/tests/test-run.sh
@@ -39,9 +39,16 @@ for ALT in "" "--unshare-user-try" "--unshare-pid" "--unshare-user-try --unshare
CAP=""
fi
- if ! ${is_uidzero} && $RUN $CAP $ALT --unshare-net --proc /proc --bind /etc/shadow /tmp/foo cat /etc/shadow; then
+ if ! cat /etc/shadow >/dev/null &&
+ $RUN $CAP $ALT --unshare-net --proc /proc --bind /etc/shadow /tmp/foo cat /tmp/foo; then
+ assert_not_reached Could read /etc/shadow via /tmp/foo bind-mount
+ fi
+
+ if ! cat /etc/shadow >/dev/null &&
+ $RUN $CAP $ALT --unshare-net --proc /proc --bind /etc/shadow /tmp/foo cat /etc/shadow; then
assert_not_reached Could read /etc/shadow
fi
+
echo "ok - cannot read /etc/shadow with $ALT"
# Unreadable dir
if [ "x$UNREADABLE" != "x" ]; then
@@ -88,7 +95,7 @@ done
echo "ok namespace id info in info and json-status fd"
-if ! which strace >/dev/null 2>/dev/null || ! strace -h | grep -v -e default | grep -e fault >/dev/null; then
+if ! command -v strace >/dev/null || ! strace -h | grep -v -e default | grep -e fault >/dev/null; then
echo "ok - # SKIP no strace fault injection"
else
! strace -o /dev/null -f -e trace=prctl -e fault=prctl:when=39 $RUN --die-with-parent --json-status-fd 42 true 42>json-status.json
diff --git a/tests/test-specifying-pidns.sh b/tests/test-specifying-pidns.sh
index 5b88af4..de38b97 100755
--- a/tests/test-specifying-pidns.sh
+++ b/tests/test-specifying-pidns.sh
@@ -10,14 +10,13 @@ echo "1..1"
# This test needs user namespaces
if test -n "${bwrap_is_suid:-}"; then
echo "ok - # SKIP no setuid support for --unshare-user"
-elif test -n "${CI_MESON_DIST:-}"; then
- echo "not ok - # TODO this test hangs under 'meson dist' during Github Workflow CI"
else
mkfifo donepipe
$RUN --info-fd 42 --unshare-user --unshare-pid sh -c 'readlink /proc/self/ns/pid > sandbox-pidns; cat < donepipe' >/dev/null 42>info.json &
while ! test -f sandbox-pidns; do sleep 1; done
SANDBOX1PID=$(extract_child_pid info.json)
+ ASAN_OPTIONS=detect_leaks=0 LSAN_OPTIONS=detect_leaks=0 \
$RUN --userns 11 --pidns 12 readlink /proc/self/ns/pid > sandbox2-pidns 11< /proc/$SANDBOX1PID/ns/user 12< /proc/$SANDBOX1PID/ns/pid
echo foo > donepipe
diff --git a/tests/try-syscall.c b/tests/try-syscall.c
index df35054..6f2f112 100644
--- a/tests/try-syscall.c
+++ b/tests/try-syscall.c
@@ -24,11 +24,11 @@
#include <sys/types.h>
#if defined(_MIPS_SIM)
-# if _MIPS_SIM == _MIPS_SIM_ABI32
+# if _MIPS_SIM == _ABIO32
# define MISSING_SYSCALL_BASE 4000
-# elif _MIPS_SIM == _MIPS_SIM_ABI64
+# elif _MIPS_SIM == _ABI64
# define MISSING_SYSCALL_BASE 5000
-# elif _MIPS_SIM == _MIPS_SIM_NABI32
+# elif _MIPS_SIM == _ABIN32
# define MISSING_SYSCALL_BASE 6000
# else
# error "Unknown MIPS ABI"
@@ -71,6 +71,10 @@
*/
#define WRONG_POINTER ((char *) 1)
+#ifndef PR_GET_CHILD_SUBREAPER
+#define PR_GET_CHILD_SUBREAPER 37
+#endif
+
int
main (int argc, char **argv)
{
diff --git a/tests/use-as-subproject/assert-correct-rpath.py b/tests/use-as-subproject/assert-correct-rpath.py
new file mode 100755
index 0000000..10b0947
--- /dev/null
+++ b/tests/use-as-subproject/assert-correct-rpath.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python3
+# Copyright 2022 Collabora Ltd.
+# SPDX-License-Identifier: LGPL-2.0-or-later
+
+import subprocess
+import sys
+
+if __name__ == '__main__':
+ completed = subprocess.run(
+ ['objdump', '-T', '-x', sys.argv[1]],
+ stdout=subprocess.PIPE,
+ )
+ stdout = completed.stdout
+ assert stdout is not None
+ seen_rpath = False
+
+ for line in stdout.splitlines():
+ words = line.strip().split()
+
+ if words and words[0] in (b'RPATH', b'RUNPATH'):
+ print(line.decode(errors='backslashreplace'))
+ assert len(words) == 2, words
+ assert words[1] == b'${ORIGIN}/../lib', words
+ seen_rpath = True
+
+ assert seen_rpath
diff --git a/tests/use-as-subproject/meson.build b/tests/use-as-subproject/meson.build
index 802fd61..bc4781c 100644
--- a/tests/use-as-subproject/meson.build
+++ b/tests/use-as-subproject/meson.build
@@ -14,6 +14,7 @@ configure_file(
subproject(
'bubblewrap',
default_options : [
+ 'install_rpath=${ORIGIN}/../lib',
'program_prefix=not-flatpak-',
],
)
diff --git a/utils.c b/utils.c
index 117da31..693273b 100644
--- a/utils.c
+++ b/utils.c
@@ -82,7 +82,7 @@ die (const char *format, ...)
}
void
-die_unless_label_valid (const char *label)
+die_unless_label_valid (UNUSED const char *label)
{
#ifdef HAVE_SELINUX
if (is_selinux_enabled () == 1)
@@ -854,7 +854,7 @@ pivot_root (const char * new_root, const char * put_old)
}
char *
-label_mount (const char *opt, const char *mount_label)
+label_mount (const char *opt, UNUSED const char *mount_label)
{
#ifdef HAVE_SELINUX
if (mount_label)
@@ -871,7 +871,7 @@ label_mount (const char *opt, const char *mount_label)
}
int
-label_create_file (const char *file_label)
+label_create_file (UNUSED const char *file_label)
{
#ifdef HAVE_SELINUX
if (is_selinux_enabled () > 0 && file_label)
@@ -881,7 +881,7 @@ label_create_file (const char *file_label)
}
int
-label_exec (const char *exec_label)
+label_exec (UNUSED const char *exec_label)
{
#ifdef HAVE_SELINUX
if (is_selinux_enabled () > 0 && exec_label)
diff --git a/utils.h b/utils.h
index 55a9585..37d8c7c 100644
--- a/utils.h
+++ b/utils.h
@@ -48,6 +48,10 @@ typedef int bool;
#define PIPE_READ_END 0
#define PIPE_WRITE_END 1
+#ifndef PR_SET_CHILD_SUBREAPER
+#define PR_SET_CHILD_SUBREAPER 36
+#endif
+
void warn (const char *format,
...) __attribute__((format (printf, 1, 2)));
void die_with_error (const char *format,