From 2a62b7838e44ba8ceeb8210ac584a5efe2313b77 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 11 Mar 2021 19:52:28 +0000 Subject: [PATCH] Don't require mount point for a non-directory to be a regular file Previously, mounting a socket over the top of an existing socket would fail, because create_file() opens it with creat(): $ test -e /run/systemd/resolve/io.systemd.Resolve && echo exists exists $ bwrap \ --bind / / \ --bind /run/systemd/resolve/io.systemd.Resolve \ /run/systemd/resolve/io.systemd.Resolve \ /bin/true bwrap: Can't create file at /run/systemd/resolve/io.systemd.Resolve: No such device or address Tolerate the file existing as any type that we will be able to mount a non-directory onto. Signed-off-by: Simon McVittie --- tests/test-run.sh | 9 ++++++++- utils.c | 9 +++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/test-run.sh b/tests/test-run.sh index 4fb5e226..da7265f5 100755 --- a/tests/test-run.sh +++ b/tests/test-run.sh @@ -80,7 +80,7 @@ if [ -z "${BWRAP_MUST_WORK-}" ] && ! $RUN true; then skip Seems like bwrap is not working at all. Maybe setuid is not working fi -echo "1..50" +echo "1..51" # Test help ${BWRAP} --help > help.txt @@ -398,4 +398,11 @@ command stat -c '%a' new-file-mountpoint > new-file-permissions assert_file_has_content new-file-permissions 444 echo "ok - Files and directories created as mount points have expected permissions" +if [ -S /dev/log ]; then + $RUN --bind / / --bind "$(realpath /dev/log)" "$(realpath /dev/log)" true + echo "ok - Can bind-mount a socket (/dev/log) onto a socket" +else + echo "ok # SKIP - /dev/log is not a socket, cannot test bubblewrap#409" +fi + echo "ok - End of test" diff --git a/utils.c b/utils.c index a99a8650..ea15158a 100644 --- a/utils.c +++ b/utils.c @@ -448,9 +448,14 @@ ensure_file (const char *path, /* We check this ahead of time, otherwise the create file will fail in the read-only - case with EROFS instead of EEXIST */ + case with EROFS instead of EEXIST. + + We're trying to set up a mount point for a non-directory, so any + non-directory, non-symlink is acceptable - it doesn't necessarily + have to be a regular file. */ if (stat (path, &buf) == 0 && - S_ISREG (buf.st_mode)) + !S_ISDIR (buf.st_mode) && + !S_ISLNK (buf.st_mode)) return 0; if (create_file (path, mode, NULL) != 0 && errno != EEXIST)