diff options
-rw-r--r-- | .github/workflows/check.yml | 3 | ||||
-rw-r--r-- | README.md | 26 | ||||
-rw-r--r-- | bind-mount.c | 65 | ||||
-rw-r--r-- | bind-mount.h | 9 | ||||
-rw-r--r-- | bubblewrap.c | 15 | ||||
-rw-r--r-- | bwrap.xml | 26 | ||||
-rw-r--r-- | completions/bash/bwrap | 1 | ||||
-rw-r--r-- | completions/zsh/_bwrap | 1 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | meson.build | 37 | ||||
-rw-r--r-- | meson_options.txt | 21 | ||||
-rw-r--r-- | tests/meson.build | 1 | ||||
-rwxr-xr-x | tests/test-run.sh | 11 | ||||
-rwxr-xr-x | tests/test-specifying-pidns.sh | 3 | ||||
-rw-r--r-- | tests/try-syscall.c | 10 | ||||
-rwxr-xr-x | tests/use-as-subproject/assert-correct-rpath.py | 26 | ||||
-rw-r--r-- | tests/use-as-subproject/meson.build | 1 | ||||
-rw-r--r-- | utils.c | 8 | ||||
-rw-r--r-- | utils.h | 4 |
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() @@ -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 @@ -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-', ], ) @@ -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) @@ -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, |