Skip to content

Commit

Permalink
Don't require mount point for a non-directory to be a regular file
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
smcv authored and brandsimon committed Mar 19, 2023
1 parent 7df8462 commit 2a62b78
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 3 deletions.
9 changes: 8 additions & 1 deletion tests/test-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
9 changes: 7 additions & 2 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 2a62b78

Please sign in to comment.