+ if (mount("/dev", "/run/initramfs/dev", NULL, MS_BIND, NULL) < 0) {
+ log_error("Failed to mount bind /dev on /run/initramfs/dev: %m");
+ return -errno;
+ }
+
+ if (mount("/run", "/run/initramfs/run", NULL, MS_BIND, NULL) < 0) {
+ log_error("Failed to mount bind /run on /run/initramfs/run: %m");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int pivot_to_new_root(void) {
+ int fd;
+
+ chdir("/run/initramfs");
+
+ /*
+ In case some evil process made "/" MS_SHARED
+ It works for pivot_root, but the ref count for the root device
+ is not decreasing :-/
+ */
+ if (mount(NULL, "/", NULL, MS_PRIVATE, NULL) < 0) {
+ log_error("Failed to make \"/\" private mount %m");
+ return -errno;
+ }
+
+ if (pivot_root(".", "oldroot") < 0) {
+ log_error("pivot failed: %m");
+ /* only chroot if pivot root succeded */
+ return -errno;
+ }
+
+ chroot(".");
+ log_info("Successfully changed into root pivot.");
+
+ fd = open("/dev/console", O_RDWR);
+ if (fd < 0)
+ log_error("Failed to open /dev/console: %m");
+ else {
+ make_stdio(fd);
+
+ /* Initialize the controlling terminal */
+ setsid();
+ ioctl(STDIN_FILENO, TIOCSCTTY, NULL);
+ }
+
+ return 0;