diff --git a/bubblewrap.c b/bubblewrap.c index 0dabfa5..dced164 100644 --- a/bubblewrap.c +++ b/bubblewrap.c @@ -980,7 +980,7 @@ setup_newroot (bool unshare_pid, case SETUP_BIND_MOUNT: if (source_mode == S_IFDIR) { - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); } else if (ensure_file (dest, 0666) != 0) @@ -999,7 +999,7 @@ setup_newroot (bool unshare_pid, break; case SETUP_MOUNT_PROC: - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); if (unshare_pid) @@ -1036,7 +1036,7 @@ setup_newroot (bool unshare_pid, break; case SETUP_MOUNT_DEV: - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); privileged_op (privileged_op_socket, @@ -1112,7 +1112,7 @@ setup_newroot (bool unshare_pid, break; case SETUP_MOUNT_TMPFS: - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); privileged_op (privileged_op_socket, @@ -1121,7 +1121,7 @@ setup_newroot (bool unshare_pid, break; case SETUP_MOUNT_MQUEUE: - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); privileged_op (privileged_op_socket, @@ -1130,7 +1130,7 @@ setup_newroot (bool unshare_pid, break; case SETUP_MAKE_DIR: - if (mkdir (dest, 0755) != 0 && errno != EEXIST) + if (ensure_dir (dest, 0755) != 0) die_with_error ("Can't mkdir %s", op->dest); break; @@ -2081,11 +2081,11 @@ main (int argc, /* We need *some* mountpoint where we can mount the root tmpfs. We first try in /run, and if that fails, try in /tmp. */ base_path = xasprintf ("/run/user/%d/.bubblewrap", real_uid); - if (mkdir (base_path, 0755) && errno != EEXIST) + if (ensure_dir (base_path, 0755)) { free (base_path); base_path = xasprintf ("/tmp/.bubblewrap-%d", real_uid); - if (mkdir (base_path, 0755) && errno != EEXIST) + if (ensure_dir (base_path, 0755)) die_with_error ("Creating root mountpoint failed"); } diff --git a/utils.c b/utils.c index a74fa36..f43bc5e 100644 --- a/utils.c +++ b/utils.c @@ -434,7 +434,7 @@ ensure_file (const char *path, /* We check this ahead of time, otherwise the create file will fail in the read-only - case with EROFD instead of EEXIST */ + case with EROFS instead of EEXIST */ if (stat (path, &buf) == 0 && S_ISREG (buf.st_mode)) return 0; @@ -593,6 +593,34 @@ get_file_mode (const char *pathname) return buf.st_mode & S_IFMT; } +int +ensure_dir (const char *path, + mode_t mode) +{ + struct stat buf; + + /* We check this ahead of time, otherwise + the mkdir call can fail in the read-only + case with EROFS instead of EEXIST on some + filesystems (such as NFS) */ + if (stat (path, &buf) == 0) + { + if (!S_ISDIR (buf.st_mode)) + { + errno = ENOTDIR; + return -1; + } + + return 0; + } + + if (mkdir (path, mode) == -1 && errno != EEXIST) + return -1; + + return 0; +} + + /* Sets errno on error (!= 0) */ int mkdir_with_parents (const char *pathname, @@ -601,7 +629,6 @@ mkdir_with_parents (const char *pathname, { cleanup_free char *fn = NULL; char *p; - struct stat buf; if (pathname == NULL || *pathname == '\0') { @@ -628,16 +655,8 @@ mkdir_with_parents (const char *pathname, if (!create_last && p == NULL) break; - if (stat (fn, &buf) != 0) - { - if (mkdir (fn, mode) == -1 && errno != EEXIST) - return -1; - } - else if (!S_ISDIR (buf.st_mode)) - { - errno = ENOTDIR; - return -1; - } + if (ensure_dir (fn, mode) != 0) + return -1; if (p) { diff --git a/utils.h b/utils.h index c0b98bb..52cf772 100644 --- a/utils.h +++ b/utils.h @@ -101,6 +101,8 @@ int create_file (const char *path, const char *content); int ensure_file (const char *path, mode_t mode); +int ensure_dir (const char *path, + mode_t mode); int get_file_mode (const char *pathname); int mkdir_with_parents (const char *pathname, int mode,