X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnspawn%2Fnspawn.c;h=7e96efd425425f4f2d196356a38201774ff5b06e;hb=fddbb89c46ea5d39e52e361b390ea34a06cbb67c;hp=5af89c9b3238560e064d51fff46795ddb2a8e4bd;hpb=3125b3ef5db70d45882c7d6f617705802c5f939e;p=elogind.git diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 5af89c9b3..7e96efd42 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -675,7 +675,18 @@ static int mount_all(const char *dest) { if (mount_table[k].what && t > 0) continue; - mkdir_p(where, 0755); + t = mkdir_p(where, 0755); + if (t < 0) { + if (mount_table[k].fatal) { + log_error("Failed to create directory %s: %s", where, strerror(-t)); + + if (r == 0) + r = t; + } else + log_warning("Failed to create directory %s: %s", where, strerror(-t)); + + continue; + } #ifdef HAVE_SELINUX if (arg_selinux_apifs_context && @@ -694,13 +705,15 @@ static int mount_all(const char *dest) { where, mount_table[k].type, mount_table[k].flags, - o) < 0 && - mount_table[k].fatal) { + o) < 0) { - log_error("mount(%s) failed: %m", where); + if (mount_table[k].fatal) { + log_error("mount(%s) failed: %m", where); - if (r == 0) - r = -errno; + if (r == 0) + r = -errno; + } else + log_warning("mount(%s) failed: %m", where); } } @@ -743,15 +756,35 @@ static int mount_binds(const char *dest, char **l, bool ro) { /* Create the mount point, but be conservative -- refuse to create block * and char devices. */ - if (S_ISDIR(source_st.st_mode)) - mkdir_label(where, 0755); - else if (S_ISFIFO(source_st.st_mode)) - mkfifo(where, 0644); - else if (S_ISSOCK(source_st.st_mode)) - mknod(where, 0644 | S_IFSOCK, 0); - else if (S_ISREG(source_st.st_mode)) - touch(where); - else { + if (S_ISDIR(source_st.st_mode)) { + r = mkdir_label(where, 0755); + if (r < 0 && errno != EEXIST) { + log_error("Failed to create mount point %s: %s", where, strerror(-r)); + + return r; + } + } else if (S_ISFIFO(source_st.st_mode)) { + r = mkfifo(where, 0644); + if (r < 0 && errno != EEXIST) { + log_error("Failed to create mount point %s: %m", where); + + return -errno; + } + } else if (S_ISSOCK(source_st.st_mode)) { + r = mknod(where, 0644 | S_IFSOCK, 0); + if (r < 0 && errno != EEXIST) { + log_error("Failed to create mount point %s: %m", where); + + return -errno; + } + } else if (S_ISREG(source_st.st_mode)) { + r = touch(where); + if (r < 0) { + log_error("Failed to create mount point %s: %s", where, strerror(-r)); + + return r; + } + } else { log_error("Refusing to create mountpoint for file: %s", *x); return -ENOTSUP; } @@ -778,12 +811,18 @@ static int mount_tmpfs(const char *dest) { STRV_FOREACH_PAIR(i, o, arg_tmpfs) { _cleanup_free_ char *where = NULL; + int r; where = strappend(dest, *i); if (!where) return log_oom(); - mkdir_label(where, 0755); + r = mkdir_label(where, 0755); + if (r < 0) { + log_error("creating mount point for tmpfs %s failed: %s", where, strerror(-r)); + + return r; + } if (mount("tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, *o) < 0) { log_error("tmpfs mount to %s failed: %m", where); @@ -844,8 +883,19 @@ static int setup_timezone(const char *dest) { if (!what) return log_oom(); - mkdir_parents(where, 0755); - unlink(where); + r = mkdir_parents(where, 0755); + if (r < 0) { + log_error("Failed to create directory for timezone info %s in container: %s", where, strerror(-r)); + + return 0; + } + + r = unlink(where); + if (r < 0 && errno != ENOENT) { + log_error("Failed to remove existing timezone info %s in container: %m", where); + + return 0; + } if (symlink(what, where) < 0) { log_error("Failed to correct timezone of container: %m"); @@ -857,6 +907,7 @@ static int setup_timezone(const char *dest) { static int setup_resolv_conf(const char *dest) { _cleanup_free_ char *where = NULL; + int r; assert(dest); @@ -870,8 +921,19 @@ static int setup_resolv_conf(const char *dest) { /* We don't really care for the results of this really. If it * fails, it fails, but meh... */ - mkdir_parents(where, 0755); - copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644); + r = mkdir_parents(where, 0755); + if (r < 0) { + log_warning("Failed to create parent directory for resolv.conf %s: %s", where, strerror(-r)); + + return 0; + } + + r = copy_file("/etc/resolv.conf", where, O_TRUNC|O_NOFOLLOW, 0644); + if (r < 0) { + log_warning("Failed to copy /etc/resolv.conf to %s: %s", where, strerror(-r)); + + return 0; + } return 0; } @@ -895,7 +957,11 @@ static int setup_volatile_state(const char *directory) { } p = strappenda(directory, "/var"); - mkdir(p, 0755); + r = mkdir(p, 0755); + if (r < 0 && errno != EEXIST) { + log_error("Failed to create %s: %m", directory); + return -errno; + } if (mount("tmpfs", p, "tmpfs", MS_STRICTATIME, "mode=755") < 0) { log_error("Failed to mount tmpfs to /var: %m"); @@ -935,7 +1001,13 @@ static int setup_volatile(const char *directory) { f = strappenda(directory, "/usr"); t = strappenda(template, "/usr"); - mkdir(t, 0755); + r = mkdir(t, 0755); + if (r < 0 && errno != EEXIST) { + log_error("Failed to create %s: %m", t); + r = -errno; + goto fail; + } + if (mount(f, t, "bind", MS_BIND|MS_REC, NULL) < 0) { log_error("Failed to create /usr bind mount: %m"); r = -errno; @@ -1029,7 +1101,8 @@ static int copy_devnodes(const char *dest) { "full\0" "random\0" "urandom\0" - "tty\0"; + "tty\0" + "net/tun\0"; const char *d; int r = 0; @@ -1060,10 +1133,17 @@ static int copy_devnodes(const char *dest) { log_error("%s is not a char or block device, cannot copy", from); return -EIO; - } else if (mknod(to, st.st_mode, st.st_rdev) < 0) { + } else { + r = mkdir_parents(to, 0775); + if (r < 0) { + log_error("Failed to create parent directory of %s: %s", to, strerror(-r)); + return -r; + } - log_error("mknod(%s) failed: %m", dest); - return -errno; + if (mknod(to, st.st_mode, st.st_rdev) < 0) { + log_error("mknod(%s) failed: %m", dest); + return -errno; + } } } @@ -1209,7 +1289,7 @@ static int setup_hostname(void) { if (arg_share_system) return 0; - if (sethostname(arg_machine, strlen(arg_machine)) < 0) + if (sethostname_idempotent(arg_machine) < 0) return -errno; return 0; @@ -1294,7 +1374,7 @@ static int setup_journal(const char *directory) { r = mkdir_p(q, 0755); if (r < 0) - log_warning("failed to create directory %s: %m", q); + log_warning("Failed to create directory %s: %m", q); return 0; } @@ -1329,7 +1409,7 @@ static int setup_journal(const char *directory) { r = mkdir_p(q, 0755); if (r < 0) - log_warning("failed to create directory %s: %m", q); + log_warning("Failed to create directory %s: %m", q); return 0; } @@ -1465,7 +1545,7 @@ static int register_machine(pid_t pid, int local_ifindex) { return r; } - r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 10, + r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 11, /* Allow the container to * access and create the API * device nodes, so that @@ -1478,6 +1558,7 @@ static int register_machine(pid_t pid, int local_ifindex) { "/dev/random", "rwm", "/dev/urandom", "rwm", "/dev/tty", "rwm", + "/dev/net/tun", "rwm", /* Allow the container * access to ptys. However, * do not permit the @@ -1657,7 +1738,7 @@ static int setup_veth(pid_t pid, char iface_name[IFNAMSIZ], int *ifi) { /* Use two different interface name prefixes depending whether * we are in bridge mode or not. */ - snprintf(iface_name, IFNAMSIZ, "%s-%s", + snprintf(iface_name, IFNAMSIZ - 1, "%s-%s", arg_network_bridge ? "vb" : "ve", arg_machine); r = generate_mac(&mac_container, CONTAINER_HASH_KEY); @@ -2535,20 +2616,27 @@ static int mount_devices( static void loop_remove(int nr, int *image_fd) { _cleanup_close_ int control = -1; + int r; if (nr < 0) return; if (image_fd && *image_fd >= 0) { - ioctl(*image_fd, LOOP_CLR_FD); + r = ioctl(*image_fd, LOOP_CLR_FD); + if (r < 0) + log_warning("Failed to close loop image: %m"); *image_fd = safe_close(*image_fd); } control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); - if (control < 0) + if (control < 0) { + log_warning("Failed to open /dev/loop-control: %m"); return; + } - ioctl(control, LOOP_CTL_REMOVE, nr); + r = ioctl(control, LOOP_CTL_REMOVE, nr); + if (r < 0) + log_warning("Failed to remove loop %d: %m", nr); } static int spawn_getent(const char *database, const char *key, pid_t *rpid) { @@ -2843,33 +2931,30 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) { } switch (status.si_code) { + case CLD_EXITED: r = status.si_status; if (r == 0) { if (!arg_quiet) - log_debug("Container %s exited successfully.", - arg_machine); + log_debug("Container %s exited successfully.", arg_machine); *container = CONTAINER_TERMINATED; - } else { - log_error("Container %s failed with error code %i.", - arg_machine, status.si_status); - } + } else + log_error("Container %s failed with error code %i.", arg_machine, status.si_status); + break; case CLD_KILLED: if (status.si_status == SIGINT) { if (!arg_quiet) - log_info("Container %s has been shut down.", - arg_machine); + log_info("Container %s has been shut down.", arg_machine); *container = CONTAINER_TERMINATED; r = 0; break; } else if (status.si_status == SIGHUP) { if (!arg_quiet) - log_info("Container %s is being rebooted.", - arg_machine); + log_info("Container %s is being rebooted.", arg_machine); *container = CONTAINER_REBOOTED; r = 0; @@ -2878,15 +2963,13 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) { /* CLD_KILLED fallthrough */ case CLD_DUMPED: - log_error("Container %s terminated by signal %s.", - arg_machine, signal_to_string(status.si_status)); - r = -1; + log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status)); + r = -EIO; break; default: - log_error("Container %s failed due to unknown reason.", - arg_machine); - r = -1; + log_error("Container %s failed due to unknown reason.", arg_machine); + r = -EIO; break; }