Beispiel #1
1
static int set_ct_root(struct container *ct)
{
	char put_root[] = "libct-root.XXXXXX";

	if (!(ct->nsmask & CLONE_NEWNS))
		return set_current_root(ct->root_path);

	/*
	 * We're in new mount namespace. No need in
	 * just going into chroot, do pivot root, that
	 * gives us the ability to umount old tree.
	 */

	if (mount(ct->root_path, ct->root_path, NULL, MS_BIND | MS_REC, NULL) == -1)
		return -1;

	if (chdir(ct->root_path))
		return -1;

	if (mkdtemp(put_root) == NULL)
		return -1;

	if (pivot_root(".", put_root)) {
		rmdir(put_root);
		return -1;
	}

	if (umount2(put_root, MNT_DETACH))
		return -1;

	rmdir(put_root);
	return 0;
}
Beispiel #2
0
static int pivot_to_new_root(void) {

        if (chdir("/run/initramfs") < 0) {
                log_error("Failed to change directory to /run/initramfs: %m");
                return -errno;
        }

        /* Work-around for a kernel bug: for some reason the kernel
         * refuses switching root if any file systems are mounted
         * MS_SHARED. Hence remount them MS_PRIVATE here as a
         * work-around.
         *
         * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */
        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
                log_warning("Failed to make \"/\" private mount: %m");

        if (pivot_root(".", "oldroot") < 0) {
                log_error("pivot failed: %m");
                /* only chroot if pivot root succeeded */
                return -errno;
        }

        chroot(".");

        setsid();
        make_console_stdio();

        log_info("Successfully changed into root pivot.");

        return 0;
}
Beispiel #3
0
static int pivot_to_new_root(void) {

        if (chdir("/run/initramfs") < 0) {
                log_error("Failed to change directory to /run/initramfs: %m");
                return -errno;
        }

        /*
          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 succeeded */
                return -errno;
        }

        chroot(".");

        setsid();
        make_console_stdio();

        log_info("Successfully changed into root pivot.");

        return 0;
}
Beispiel #4
0
int main(int argc, char **argv)
{
	int ch;
	static const struct option longopts[] = {
		{"version", no_argument, NULL, 'V'},
		{"help", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
		switch (ch) {
		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case 'h':
			usage(stdout);
		default:
			usage(stderr);
		}

	if (argc != 3)
		usage(stderr);

	if (pivot_root(argv[1], argv[2]) < 0)
		err(EXIT_FAILURE, _("failed to change root from `%s' to `%s'"),
		    argv[1], argv[2]);

	return EXIT_SUCCESS;
}
Beispiel #5
0
void pivot() {
  char *pivot = jail_dir(".pivot_root");

  // Bind root to itself so it becomes a pivotable mount.
  mount(new_root, new_root, "bind", MS_BIND | MS_REC, NULL);
  mkdir(pivot, S_IRWXU);
  check("pivot_root", pivot_root(new_root, pivot));
  check("chdir_root", chdir("/"));
  check("umount_pivot_root", umount2("/.pivot_root", MNT_DETACH));
  check("rmdir_pivot_root", rmdir("/.pivot_root"));
};
Beispiel #6
0
int pivot_root_main(int argc, char **argv)
{
    if (argc != 3)
	bb_show_usage();

	if (pivot_root(argv[1],argv[2]) < 0)
		bb_perror_msg_and_die("pivot_root");

    return EXIT_SUCCESS;

}
Beispiel #7
0
int main(int argc, const char **argv)
{
	if (argc != 3) {
		fprintf(stderr, "usage: %s new_root put_old\n", argv[0]);
		return 1;
	}
	if (pivot_root(argv[1], argv[2]) < 0) {
		perror("pivot_root");
		return 1;
	}
	return 0;
}
Beispiel #8
0
void syscall_helper(int argc, char **argv) {
    (void) argc;

    if (strcmp(argv[2], "mount") == 0) {
        int rv = mount(NULL, NULL, NULL, 0, NULL);
        (void) rv;
        printf("\nUGLY: mount syscall permitted.\n");
    }
    else if (strcmp(argv[2], "umount2") == 0) {
        umount2(NULL, 0);
        printf("\nUGLY: umount2 syscall permitted.\n");
    }
    else if (strcmp(argv[2], "ptrace") == 0) {
        ptrace(0, 0, NULL, NULL);
        printf("\nUGLY: ptrace syscall permitted.\n");
    }
    else if (strcmp(argv[2], "swapon") == 0) {
        swapon(NULL, 0);
        printf("\nUGLY: swapon syscall permitted.\n");
    }
    else if (strcmp(argv[2], "swapoff") == 0) {
        swapoff(NULL);
        printf("\nUGLY: swapoff syscall permitted.\n");
    }
    else if (strcmp(argv[2], "init_module") == 0) {
        init_module(NULL, 0, NULL);
        printf("\nUGLY: init_module syscall permitted.\n");
    }
    else if (strcmp(argv[2], "delete_module") == 0) {
        delete_module(NULL, 0);
        printf("\nUGLY: delete_module syscall permitted.\n");
    }
    else if (strcmp(argv[2], "chroot") == 0) {
        int rv = chroot("/blablabla-57281292");
        (void) rv;
        printf("\nUGLY: chroot syscall permitted.\n");
    }
    else if (strcmp(argv[2], "pivot_root") == 0) {
        pivot_root(NULL, NULL);
        printf("\nUGLY: pivot_root syscall permitted.\n");
    }
#if defined(__i386__) || defined(__x86_64__)
    else if (strcmp(argv[2], "iopl") == 0) {
        iopl(0L);
        printf("\nUGLY: iopl syscall permitted.\n");
    }
    else if (strcmp(argv[2], "ioperm") == 0) {
        ioperm(0, 0, 0);
        printf("\nUGLY: ioperm syscall permitted.\n");
    }
#endif
    exit(0);
}
Beispiel #9
0
void do_pivot(setup_vals *s)
{
    char * oldroot = safemalloc(sizeof(char) * (strlen(s->newroot) + 1 + strlen("oldroot") + 1));
    strcpy(oldroot, s->newroot);
    strcat(oldroot, "/");
    strcat(oldroot, "oldroot");

    if(!dir_exists(oldroot))
        mkdir(oldroot, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    pivot_root(s->newroot, oldroot);
    chdir("/");

}
Beispiel #10
0
int child_run(void *data) {
  wshd_t *w = (wshd_t *)data;
  int rv;
  char pivoted_lib_path[PATH_MAX];
  size_t pivoted_lib_path_len;

  /* Wait for parent */
  rv = barrier_wait(&w->barrier_parent);
  assert(rv == 0);

  rv = run(w->lib_path, "hook-child-before-pivot.sh");
  assert(rv == 0);

  /* Prepare lib path for pivot */
  strcpy(pivoted_lib_path, "/mnt");
  pivoted_lib_path_len = strlen(pivoted_lib_path);
  realpath(w->lib_path, pivoted_lib_path + pivoted_lib_path_len);

  rv = chdir(w->root_path);
  if (rv == -1) {
    perror("chdir");
    abort();
  }

  rv = mkdir("mnt", 0700);
  if (rv == -1 && errno != EEXIST) {
    perror("mkdir");
    abort();
  }

  rv = pivot_root(".", "mnt");
  if (rv == -1) {
    perror("pivot_root");
    abort();
  }

  rv = chdir("/");
  if (rv == -1) {
    perror("chdir");
    abort();
  }

  rv = run(pivoted_lib_path, "hook-child-after-pivot.sh");
  assert(rv == 0);

  child_save_to_shm(w);

  execl("/sbin/wshd", "/sbin/wshd", "--continue", NULL);
  perror("exec");
  abort();
}
Beispiel #11
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;
}
Beispiel #12
0
/**
 * li_run_env_enter:
 *
 * Enter (pivot_root) a previously prepared application environment.
 *
 * Returns: %TRUE on success.
 */
gboolean
li_run_env_enter (const gchar *newroot)
{
	/* now move into the application's private environment */
	chdir (newroot);
	if (pivot_root (newroot, ".oldroot") != 0) {
		g_printerr ("pivot_root failed: %s\n", strerror(errno));
		return FALSE;
	}
	chdir ("/");

	/* The old root better be rprivate or we will send unmount events to the parent namespace */
	if (mount (".oldroot", ".oldroot", NULL, MS_REC | MS_PRIVATE, NULL) != 0) {
		g_printerr ("Failed to make old root rprivate: %s\n", strerror (errno));
		return FALSE;
	}

	if (umount2 (".oldroot", MNT_DETACH)) {
		g_printerr ("unmount oldroot failed: %s\n", strerror (errno));
		return FALSE;
	}

	return TRUE;
}
Beispiel #13
0
static int lxcContainerPivotRoot(virDomainFSDefPtr root)
{
    int rc, ret;
    char *oldroot = NULL, *newroot = NULL;

    ret = -1;

    /* root->parent must be private, so make / private. */
    if (mount("", "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0) {
        virReportSystemError(errno, "%s",
                             _("Failed to make root private"));
        goto err;
    }

    if (virAsprintf(&oldroot, "%s/.oldroot", root->src) < 0) {
        virReportOOMError();
        goto err;
    }

    if ((rc = virFileMakePath(oldroot)) != 0) {
        virReportSystemError(rc,
                             _("Failed to create %s"),
                             oldroot);
        goto err;
    }

    /* Create a tmpfs root since old and new roots must be
     * on separate filesystems */
    if (mount("tmprootfs", oldroot, "tmpfs", 0, NULL) < 0) {
        virReportSystemError(errno,
                             _("Failed to mount empty tmpfs at %s"),
                             oldroot);
        goto err;
    }

    /* Create a directory called 'new' in tmpfs */
    if (virAsprintf(&newroot, "%s/new", oldroot) < 0) {
        virReportOOMError();
        goto err;
    }

    if ((rc = virFileMakePath(newroot)) != 0) {
        virReportSystemError(rc,
                             _("Failed to create %s"),
                             newroot);
        goto err;
    }

    /* ... and mount our root onto it */
    if (mount(root->src, newroot, NULL, MS_BIND|MS_REC, NULL) < 0) {
        virReportSystemError(errno,
                             _("Failed to bind new root %s into tmpfs"),
                             root->src);
        goto err;
    }

    /* Now we chroot into the tmpfs, then pivot into the
     * root->src bind-mounted onto '/new' */
    if (chdir(newroot) < 0) {
        virReportSystemError(errno,
                             _("Failed to chroot into %s"), newroot);
        goto err;
    }

    /* The old root directory will live at /.oldroot after
     * this and will soon be unmounted completely */
    if (pivot_root(".", ".oldroot") < 0) {
        virReportSystemError(errno, "%s",
                             _("Failed to pivot root"));
        goto err;
    }

    /* CWD is undefined after pivot_root, so go to / */
    if (chdir("/") < 0)
        goto err;

    ret = 0;

err:
    VIR_FREE(oldroot);
    VIR_FREE(newroot);

    return ret;
}
Beispiel #14
0
void pivot_host(const gchar *guest) {
  g_autofree gchar *point = g_build_filename(guest, "host", NULL);
  fail_if(g_mkdir(point, 0755));
  fail_if(pivot_root(guest, point));
}
Beispiel #15
0
int main(int argc, char **argv)
{	int	x = 0;
	char	*args[10];

	setuid(2);

	signal(SIGCHLD, sigchld);
	do_signals();

	x += getpid();
	x += getppid();
	x += getuid();
	x += getgid();
	x += setsid();
	x += seteuid();
	x += setegid();
	lseek(0, 0, -1);
	kill(0, 0);
	signal(99, 0);
	signal(SIGINT, int_handler);
	signal(SIGSEGV, segv_handler);
//	*(int *) 0 = 0;
	pipe(0);
	munmap(0, 0);
	mincore(0, 0);
	shmget(0);
	shmat(0);

	line = __LINE__;
	poll(-1, 0, 0);
	signal(SIGSEGV, SIG_IGN);
//	ppoll(-1, -1, -1, 0);
	signal(SIGSEGV, SIG_DFL);
	sched_yield();
	readv(-1, 0, 0, 0);
	writev(-1, 0, 0, 0);
	msync(0, 0, 0);
	fsync(-1);
	fdatasync(-1);
	semget(0, 0, 0);
	semctl(0, 0, 0);
	uselib(NULL);
	pivot_root(0, 0);
	personality(-1);
	setfsuid(-1);
	flock(-1, 0);
	shmdt(0, 0, 0);
	times(0);
	mremap(0, 0, 0, 0, 0);
	madvise(0, 0, 0);
	fchown(-1, 0, 0);
	lchown(0, 0, 0);
	setreuid();
	setregid();
	link("/nonexistant", "/also-nonexistant");

	do_slow();

	symlink("/nothing", "/");
	rename("/", "/");
	mkdir("/junk/stuff////0", 0777);
	geteuid();
	getsid();
	getpgid();
	getresuid();
	getresgid();
	getpgid();
	ptrace(-1, 0, 0, 0);
	semop(0, 0, 0);
	capget(0, 0);

	line = __LINE__;
	gettimeofday(0, 0);
	settimeofday(0, 0);
	dup(-1);
	dup2(-1, -1);
	shmctl(0, 0, 0, 0);
	execve("/bin/nothing", "/bin/nothing", 0);
	alarm(9999);
	bind(0, 0, 0);
	socket(0, 0, 0);
	accept(0, 0, 0);
	listen(0);
	shutdown(0);
	getsockname(0, 0, 0);
	getpeername(0, 0, 0);
	truncate(0, 0);
	ftruncate(0, 0);
	line = __LINE__;
	if (vfork() == 0)
		exit(0);
	line = __LINE__;
	x = opendir("/", 0, 0);
	line = __LINE__;
	readdir(x, 0, 0);
	line = __LINE__;
	closedir(x);
	line = __LINE__;
	chroot("/");
	line = __LINE__;
	sigaction(0, 0, 0);
	line = __LINE__;
	sigprocmask(0, 0, 0);
	x += open("/nothing", 0);
	x += chdir("/nothing");
	x += mknod("/nothing/nothing", 0);
	x += ioctl();
	execve("/nothing", NULL, NULL);
	line = __LINE__;
	x += close(-2);
	line = __LINE__;
	if (fork() == 0)
		exit(0);
	line = __LINE__;
	clone(clone_func, 0, 0, 0);
	line = __LINE__;
	brk(0);
	sbrk(0);
	line = __LINE__;
	mmap(0, 0, 0, 0, 0);
	line = __LINE__;
	uname(0);
	line = __LINE__;
	getcwd(0, 0);
	line = __LINE__;
	iopl(3);
	ioperm(0, 0, 0);
	mount(0, 0, 0, 0, 0);
	umount(0, 0);
	umount(0, 0, 0);
	swapon(0, 0);
	swapoff(0);
	sethostname(0);
	line = __LINE__;
	time(NULL);
	unlink("/nothing");
	line = __LINE__;
	rmdir("/nothing");
	chmod(0, 0);
	line = __LINE__;
# if defined(__i386) || defined(__amd64)
	modify_ldt(0);
# endif

	stat("/doing-nice", 0);
	nice(0);

	args[0] = "/bin/df";
	args[1] = "-l";
	args[2] = NULL;
	close(1);
	open("/dev/null", O_WRONLY);
	/***********************************************/
	/*   Some  syscalls  arent  available  direct  */
	/*   from  libc,  so get them here. We mostly  */
	/*   care  about  the  ones which have caused  */
	/*   implementation   difficulty  and  kernel  */
	/*   crashes - eventually we can be complete.  */
	/***********************************************/
	line = __LINE__;
	open("/system-dependent-syscalls-follow", 0);
	line = __LINE__;
	if (fork() == 0)
		exit(0);

	{int status;
	while (wait(&status) >= 0)
		;
	}

	sigaltstack(0, 0);

	/*vm86(0, 0);*/

	/***********************************************/
	/*   Some syscalls arent directly accessible,  */
	/*   e.g. legacy.			       */
	/***********************************************/
#if defined(__x86_64__)
	trace(__LINE__, "x64 syscalls");
	syscall(174, 0, 0, 0); // create_module
	syscall(176, 0, 0, 0); // delete_module
	syscall(178, 0, 0, 0); // query_module
#else
	trace(__LINE__, "x32 syscalls");
	syscall(0, 0, 0, 0); // restart_syscall
	syscall(34, 0, 0, 0); // nice
	syscall(59, 0, 0, 0); // oldolduname	
	syscall(109, 0, 0, 0); // olduname	
	if (fork() == 0)
		syscall(1, 0, 0, 0); // exit
#endif
	line = __LINE__;
	execve("/bin/df", args, NULL);

	fprintf(stderr, "Error: should not get here -- %s\n", strerror(errno));

	exit(1);
}
Beispiel #16
0
Datei: ns.c Projekt: blindFS/criu
static int prepare_mntns()
{
	int dfd;
	char *root;

	root = getenv("ZDTM_ROOT");
	if (!root) {
		fprintf(stderr, "ZDTM_ROOT isn't set\n");
		return -1;
	}

		dfd = open(".", O_RDONLY);
		if (dfd == -1) {
			fprintf(stderr, "open(.) failed: %m\n");
			return -1;
		}

		if (chdir(root)) {
			fprintf(stderr, "chdir(%s) failed: %m\n", root);
			return -1;
		}
		if (mkdir("old", 0777) && errno != EEXIST) {
			fprintf(stderr, "mkdir(old) failed: %m\n");
			return -1;
		}

		if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) {
			fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n");
			return -1;
		}

		if (pivot_root(".", "./old")) {
			fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
			return -1;
		}
		if (umount2("./old", MNT_DETACH)) {
			fprintf(stderr, "umount(./old) failed: %m\n");
			return -1;
		}
		if (mkdir("proc", 0777) && errno != EEXIST) {
			fprintf(stderr, "mkdir(proc) failed: %m\n");
			return -1;
		}
		if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) {
			fprintf(stderr, "mount(/proc) failed: %m\n");
			return -1;
		}
		if (mkdir("/dev", 0755) && errno != EEXIST) {
			fprintf(stderr, "mkdir(/dev) failed: %m\n");
			return -1;
		}
		if (mkdir("/dev/pts", 0755) && errno != EEXIST) {
			fprintf(stderr, "mkdir(/dev/pts) failed: %m\n");
			return -1;
		}
		if (symlink("/dev/pts/ptmx", "/dev/ptmx") && errno != EEXIST) {
			fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n");
			return -1;
		}
		chmod("/dev/ptmx", 0666);
		if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) {
			fprintf(stderr, "mount(/dev/pts) failed: %m\n");
			return -1;
		}
		if (mount("/dev/pts/ptmx", "/dev/ptmx", NULL, MS_BIND, NULL)) {
			fprintf(stderr, "mount(/dev/pts) failed: %m\n");
			return -1;
		}
		if (fchdir(dfd)) {
			fprintf(stderr, "fchdir() failed: %m\n");
			return -1;
		}
		close(dfd);

	mkdir("/dev", 0777);
	mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3));
	chmod("/dev/null", 0777);
	mkdir("/dev/net", 0777);
	mknod("/dev/net/tun", 0777 | S_IFCHR, makedev(10, 200));
	chmod("/dev/net/tun", 0777);
	mknod("/dev/rtc", 0777 | S_IFCHR, makedev(254, 0));
	chmod("/dev/rtc", 0777);
	return 0;
}
Beispiel #17
0
void linux_namespace_jail() {

	char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;

	if (getpid() != 1) {
		uwsgi_log("your kernel does not support linux pid namespace\n");
		exit(1);
	}

	char *ns_hostname = strchr(uwsgi.ns, ':');
	if (ns_hostname) {
		ns_hostname[0] = 0;
		ns_hostname++;
		if (sethostname(ns_hostname, strlen(ns_hostname))) {
			uwsgi_error("sethostname()");
		}
	}

	FILE *procmounts;
	char line[1024];
	int unmounted = 1;
	char *delim0, *delim1;

	if (chdir(uwsgi.ns)) {
		uwsgi_error("chdir()");
		exit(1);
	}

	if (strcmp(uwsgi.ns, "/")) {
		ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
		mkdir(ns_tmp_mountpoint, S_IRWXU);

		ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
		mkdir(ns_tmp_mountpoint2, S_IRWXU);

		if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
			uwsgi_error("mount()");
		}
		if (chdir(ns_tmp_mountpoint)) {
			uwsgi_error("chdir()");
		}

		if (pivot_root(".", ns_tmp_mountpoint2)) {
			uwsgi_error("pivot_root()");
			exit(1);
		}



		if (chdir("/")) {
			uwsgi_error("chdir()");
			exit(1);
		}

	}

	uwsgi_log("remounting /proc\n");
	if (mount("proc", "/proc", "proc", 0, NULL)) {
		uwsgi_error("mount()");
	}

	struct uwsgi_string_list *usl = uwsgi.ns_keep_mount;
	while(usl) {
		// bind mounting keep-mount items
		char *keep_mountpoint = usl->value;
		char *destination = strchr(usl->value, ':');
		if (destination) {
			keep_mountpoint = uwsgi_concat2n(usl->value, destination - usl->value, "", 0);
		}
		char *ks = uwsgi_concat2("/.uwsgi_ns_tmp_mountpoint", keep_mountpoint);
		if (!destination) {
			destination = usl->value;
			// skip first part of the name if under the jail
			if (!uwsgi_startswith(destination, uwsgi.ns, strlen(uwsgi.ns))) {
				if (uwsgi.ns[strlen(uwsgi.ns)-1] == '/') {
					destination += strlen(uwsgi.ns)-1;
				}
				else {
					destination += strlen(uwsgi.ns);
				}
			}
		}
		else {
			free(keep_mountpoint);
			destination++;
		}

		uwsgi_log("remounting %s to %s\n", ks+25, destination);
		if (mount(ks, destination, "none", MS_BIND, NULL)) {
			uwsgi_error("mount()");
		}
		free(ks);
		usl = usl->next;
	}

	while (unmounted) {

		unmounted = 0;
		procmounts = fopen("/proc/self/mounts", "r");
		while (fgets(line, 1024, procmounts) != NULL) {
			delim0 = strchr(line, ' ');
			delim0++;
			delim1 = strchr(delim0, ' ');
			*delim1 = 0;
			// and now check for keep-mounts
			if (uwsgi_is_a_keep_mount(delim0)) continue;
			if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
				continue;
			if (!umount(delim0)) {
				unmounted++;
			}
		}
		fclose(procmounts);
	}

	if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
		uwsgi_error("rmdir()");
	}
	if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
		uwsgi_error("rmdir()");
	}

	if (strcmp(uwsgi.ns, "/")) {
		free(ns_tmp_mountpoint2);
		free(ns_tmp_mountpoint);
	}



}
Beispiel #18
0
int
main (int argc,
      char **argv)
{
  mode_t old_umask;
  cleanup_free char *base_path = NULL;
  int clone_flags;
  char *old_cwd = NULL;
  pid_t pid;
  int event_fd = -1;
  const char *new_cwd;
  uid_t ns_uid;
  gid_t ns_gid;

  /* Get the (optional) capabilities we need, drop root */
  acquire_caps ();

  /* Never gain any more privs during exec */
  if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
    die_with_error ("prctl(PR_SET_NO_NEW_CAPS) failed");

  /* The initial code is run with high permissions
     (i.e. CAP_SYS_ADMIN), so take lots of care. */

  argv0 = argv[0];

  if (isatty (1))
    host_tty_dev = ttyname (1);

  argv++;
  argc--;

  if (argc == 0)
    usage (EXIT_FAILURE);

  parse_args (&argc, &argv);

  /* We have to do this if we weren't installed setuid, so let's just DWIM */
  if (!is_privileged)
    opt_unshare_user = TRUE;

  if (argc == 0)
    usage (EXIT_FAILURE);

  __debug__(("Creating root mount point\n"));

  uid = getuid ();
  if (opt_sandbox_uid == -1)
    opt_sandbox_uid = uid;
  gid = getgid ();
  if (opt_sandbox_gid == -1)
    opt_sandbox_gid = gid;

  if (!opt_unshare_user && opt_sandbox_uid != uid)
    die ("Specifying --uid requires --unshare-user");

  if (!opt_unshare_user && opt_sandbox_gid != gid)
    die ("Specifying --gid requires --unshare-user");

  /* We need to read stuff from proc during the pivot_root dance, etc.
     Lets keep a fd to it open */
  proc_fd = open ("/proc", O_RDONLY | O_PATH);
  if (proc_fd == -1)
    die_with_error ("Can't open /proc");

  /* 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", uid);
  if (mkdir (base_path, 0755) && errno != EEXIST)
    {
      free (base_path);
      base_path = xasprintf ("/tmp/.bubblewrap-%d", uid);
      if (mkdir (base_path, 0755) && errno != EEXIST)
        die_with_error ("Creating root mountpoint failed");
    }

  __debug__(("creating new namespace\n"));

  if (opt_unshare_pid)
    {
      event_fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
      if (event_fd == -1)
	die_with_error ("eventfd()");
    }

  /* We block sigchild here so that we can use signalfd in the monitor. */
  block_sigchild ();

  clone_flags = SIGCHLD | CLONE_NEWNS;
  if (opt_unshare_user)
    clone_flags |= CLONE_NEWUSER;
  if (opt_unshare_pid)
    clone_flags |= CLONE_NEWPID;
  if (opt_unshare_net)
    clone_flags |= CLONE_NEWNET;
  if (opt_unshare_ipc)
    clone_flags |= CLONE_NEWIPC;
  if (opt_unshare_uts)
    clone_flags |= CLONE_NEWUTS;

  pid = raw_clone (clone_flags, NULL);
  if (pid == -1)
    {
      if (opt_unshare_user)
        {
          if (errno == EINVAL)
            die ("Creating new namespace failed, likely because the kernel does not support user namespaces.  bwrap must be installed setuid on such systems.");
          else if (errno == EPERM && !is_privileged)
            die ("No permissions to creating new namespace, likely because the kernel does not allow non-privileged user namespaces. On e.g. debian this can be enabled with 'sysctl kernel.unprivileged_userns_clone=1'.");
        }

      die_with_error ("Creating new namespace failed");
    }

  if (pid != 0)
    {
      /* Initial launched process, wait for exec:ed command to exit */

      /* We don't need any caps in the launcher, drop them immediately. */
      drop_caps ();
      monitor_child (event_fd);
      exit (0); /* Should not be reached, but better safe... */
    }

  if (opt_unshare_net && loopback_setup () != 0)
    die ("Can't create loopback device");

  ns_uid = opt_sandbox_uid;
  ns_gid = opt_sandbox_gid;
  if (opt_unshare_user)
    {
      if (opt_needs_devpts)
        {
          /* This is a bit hacky, but we need to first map the real uid/gid to
             0, otherwise we can't mount the devpts filesystem because root is
             not mapped. Later we will create another child user namespace and
             map back to the real uid */
          ns_uid = 0;
          ns_gid = 0;
        }

      write_uid_gid_map (ns_uid, uid,
                         ns_gid, gid,
                         TRUE);
    }

  old_umask = umask (0);

  /* Mark everything as slave, so that we still
   * receive mounts from the real root, but don't
   * propagate mounts to the real root. */
  if (mount (NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
    die_with_error ("Failed to make / slave");

  /* Create a tmpfs which we will use as / in the namespace */
  if (mount ("", base_path, "tmpfs", MS_NODEV|MS_NOSUID, NULL) != 0)
    die_with_error ("Failed to mount tmpfs");

  old_cwd = get_current_dir_name ();

  /* Chdir to the new root tmpfs mount. This will be the CWD during
     the entire setup. Access old or new root via "oldroot" and "newroot". */
  if (chdir (base_path) != 0)
      die_with_error ("chdir base_path");

  /* We create a subdir "$base_path/newroot" for the new root, that
   * way we can pivot_root to base_path, and put the old root at
   * "$base_path/oldroot". This avoids problems accessing the oldroot
   * dir if the user requested to bind mount something over / */

  if (mkdir ("newroot", 0755))
    die_with_error ("Creating newroot failed");

  if (mkdir ("oldroot", 0755))
    die_with_error ("Creating oldroot failed");

  if (pivot_root (base_path, "oldroot"))
    die_with_error ("pivot_root");

  if (chdir ("/") != 0)
    die_with_error ("chdir / (base path)");

  if (is_privileged)
    {
      pid_t child;
      int privsep_sockets[2];

      if (socketpair (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, privsep_sockets) != 0)
        die_with_error ("Can't create privsep socket");

      child = fork ();
      if (child == -1)
        die_with_error ("Can't fork unprivileged helper");

      if (child == 0)
        {
          /* Unprivileged setup process */
          drop_caps ();
          close (privsep_sockets[0]);
          setup_newroot (opt_unshare_pid, privsep_sockets[1]);
          exit (0);
        }
      else
        {
          uint32_t buffer[2048];  /* 8k, but is int32 to guarantee nice alignment */
          uint32_t op, flags;
          const char *arg1, *arg2;
          cleanup_fd int unpriv_socket = -1;

          unpriv_socket = privsep_sockets[0];
          close (privsep_sockets[1]);

          do
            {
              op = read_priv_sec_op (unpriv_socket, buffer, sizeof (buffer),
                                     &flags, &arg1, &arg2);
              privileged_op (-1, op, flags, arg1, arg2);
              if (write (unpriv_socket, buffer, 1) != 1)
                die ("Can't write to op_socket");
            }
          while (op != PRIV_SEP_OP_DONE);

          /* Continue post setup */
        }
    }
  else
    setup_newroot (opt_unshare_pid, -1);

  /* The old root better be rprivate or we will send unmount events to the parent namespace */
  if (mount ("oldroot", "oldroot", NULL, MS_REC|MS_PRIVATE, NULL) != 0)
    die_with_error ("Failed to make old root rprivate");

  if (umount2 ("oldroot", MNT_DETACH))
    die_with_error ("unmount old root");

  if (opt_unshare_user &&
      (ns_uid != opt_sandbox_uid || ns_gid != opt_sandbox_gid))
    {
      /* Now that devpts is mounted and we've no need for mount
         permissions we can create a new userspace and map our uid
         1:1 */

      if (unshare (CLONE_NEWUSER))
        die_with_error ("unshare user ns");

      write_uid_gid_map (opt_sandbox_uid, ns_uid,
                         opt_sandbox_gid, ns_gid,
                         FALSE);
    }

  /* Now make /newroot the real root */
  if (chdir ("/newroot") != 0)
    die_with_error ("chdir newroot");
  if (chroot ("/newroot") != 0)
    die_with_error ("chroot /newroot");
  if (chdir ("/") != 0)
    die_with_error ("chdir /");

  /* Now we have everything we need CAP_SYS_ADMIN for, so drop it */
  drop_caps ();

  if (opt_seccomp_fd != -1)
    {
      cleanup_free char *seccomp_data = NULL;
      size_t seccomp_len;
      struct sock_fprog prog;

      seccomp_data = load_file_data (opt_seccomp_fd, &seccomp_len);
      if (seccomp_data == NULL)
        die_with_error ("Can't read seccomp data");

      if (seccomp_len % 8 != 0)
        die ("Invalide seccomp data, must be multiple of 8");

      prog.len = seccomp_len / 8;
      prog.filter = (struct sock_filter *)seccomp_data;

      close (opt_seccomp_fd);

      if (prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) != 0)
	die_with_error ("prctl(PR_SET_SECCOMP)");
    }

  umask (old_umask);

  new_cwd = "/";
  if (opt_chdir_path)
    {
      if (chdir (opt_chdir_path))
        die_with_error ("Can't chdir to %s", opt_chdir_path);
      new_cwd = opt_chdir_path;
    }
  else if (chdir (old_cwd) == 0)
    {
      /* If the old cwd is mapped in the sandbox, go there */
      new_cwd = old_cwd;
    }
  else
    {
      /* If the old cwd is not mapped, go to home */
      const char *home = getenv ("HOME");
      if (home != NULL &&
          chdir (home) == 0)
        new_cwd = home;
    }
  xsetenv ("PWD", new_cwd, 1);
  free (old_cwd);

  __debug__(("forking for child\n"));

  if (opt_unshare_pid || lock_files != NULL || opt_sync_fd != -1)
    {
      /* We have to have a pid 1 in the pid namespace, because
       * otherwise we'll get a bunch of zombies as nothing reaps
       * them. Alternatively if we're using sync_fd or lock_files we
       * need some process to own these.
       */

      pid = fork ();
      if (pid == -1)
        die_with_error("Can't fork for pid 1");

      if (pid != 0)
        {
          /* Close fds in pid 1, except stdio and optionally event_fd
             (for syncing pid 2 lifetime with monitor_child) and
             opt_sync_fd (for syncing sandbox lifetime with outside
             process).
             Any other fds will been passed on to the child though. */
          {
            int dont_close[3];
            int j = 0;
            if (event_fd != -1)
              dont_close[j++] = event_fd;
            if (opt_sync_fd != -1)
              dont_close[j++] = opt_sync_fd;
            dont_close[j++] = -1;
            fdwalk (proc_fd, close_extra_fds, dont_close);
          }

          return do_init (event_fd, pid);
        }
    }

  __debug__(("launch executable %s\n", argv[0]));

  if (proc_fd != -1)
    close (proc_fd);

  if (opt_sync_fd != -1)
    close (opt_sync_fd);

  /* We want sigchild in the child */
  unblock_sigchild ();

  if (label_exec (opt_exec_label) == -1)
    die_with_error ("label_exec %s", argv[0]);

  if (execvp (argv[0], argv) == -1)
    die_with_error ("execvp %s", argv[0]);

  return 0;
}
Beispiel #19
0
int bootup_main(int argc, char **argv) {
    FILE *fp;
    DIR *dp;
    struct dirent *dt;
    int t=0, rc;
    char cmd[1024], buf[1024], name[1024];
    time_t curtime;
    struct tm *loctime;
    signal(SIGINT,SIG_IGN);
    putenv("PATH=/bin");
    putenv("TERM=linux");
    umask(0770);
    chdir("/");
    putchar('\n');
    print_banner();
    putchar('\n');
    xsystem("mount -t proc -o ro virtual /proc");
    xsystem("mount -t sysfs -o ro virtual /sys");

    // STAGE 1
    calculate_mem();
    fprintf_stdout("* Creating Mybox filesystem (%d kB) on shared memory...\n",RAMSIZE);
    xsystem("mount -t tmpfs -o \"rw,size=%dk\" virtual /ramd",RAMSIZE);
    chmod("/ramd",S_IREAD | S_IWRITE | S_IEXEC);
    chdir("/ramd");
    if((dp=opendir("/")) == NULL) {
        perror("opendir");
        exit(1);
    }
    while((dt=readdir(dp))!=NULL) {
        if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..") ||
                !strcmp(dt->d_name,"lost+found") ||
                !strcmp(dt->d_name,"ramd") ||
                !strcmp(dt->d_name,"proc") ||
                !strcmp(dt->d_name,"dev") ||
                !strcmp(dt->d_name,"sys")) continue;
        xsystem("cp -dpR /%s /ramd/",dt->d_name);
    }
    closedir(dp);
    xmkdir("dev/pts");
    xmkdir("initrd");
    umount("/proc");
    umount("/sys");

    // STAGE 2
    rc=pivot_root(".","initrd");
    if(rc==-1) {
        fprintf_stdout("#### ERROR: Change root file system failed!\n");
        exit(1);
    }
    chdir("/");
    xmkdir("proc");
    xmkdir("sys");
    xsystem("mount -t proc -o rw virtual /proc");
    xsystem("mount -t sysfs -o rw virtual /sys");
    save_to_file("/proc/sys/kernel/printk","0 0 0 0\n");
    if((dp=opendir("/tmp")) == NULL) {
        perror("opendir");
        exit(1);
    }
    fprintf_stdout("-> Extracting base tools: ");
    while((dt=readdir(dp))!=NULL) {
        if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..")) continue;
        if(strstr(dt->d_name,".mpk")) {
            fprintf_stdout("#");
            xsystem("tar -C / -axf /tmp/%s",dt->d_name);
        }
    }
    free(dt);
    closedir(dp);
    fprintf_stdout("\r* Extracting base tools. Done.%s\n",SPACE);
    save_to_file("/proc/sys/kernel/modprobe","/bin/modprobe\n");
    xsystem("depmod -a");

    // STAGE 3
    chdir("/");
    xsystem("mdev -s");
    xsystem("mount -t devpts /dev/devpts /dev/pts -o \"rw,gid=0,mode=620\"");
    rename("/dev/random","/dev/random-block");
    symlink("/dev/urandom","/dev/random");
    xsystem("chmod 700 *");
    if((fp=fopen("/etc/inittab","w"))!=NULL) {
        fprintf(fp,"::sysinit:/etc/init.boot/rc.init\n");
        fprintf(fp,"tty1::respawn:/bin/getty -h -n -L tty1 115200 linux\n");
        fprintf(fp,"ttyS0::respawn:/bin/getty -h -n -L ttyS0 115200 vt100\n");
        fprintf(fp,"tty7::respawn:/bin/chkprog\n");
        fprintf(fp,"tty8::respawn:/bin/trafficd\n");
        fprintf(fp,"::restart:/bin/init\n");
        fprintf(fp,"::ctrlaltdel:/bin/bootdown\n");
        fprintf(fp,"::ctrlaltdel:/bin/reset\n");
        fprintf(fp,"::ctrlaltdel:/bin/reboot\n");
        fprintf(fp,"::shutdown:/bin/bootdown\n");
        fclose(fp);
    }
    curtime=time(NULL);
    loctime=localtime(&curtime);
    strftime(cmd, sizeof(cmd), "[%d/%m/%Y %T] TYPE=INFO MSG=****** SYSTEM LOADING ******\n",loctime);
    append_to_file("/tmp/bootup",cmd);
    if(file_exists("/bin/getkey")) {
        if(system("getkey -c 3 -m \"-> Starting Init: %d\" R")==0) {
            fprintf_stdout("\r#### WARNING: LOGIN DISABLED\n");
            xtouch("/etc/noconsole");
        } else {
            fprintf_stdout("\r* Starting Init. Done.\n");
        }
    }
    memset(buf,0x0,sizeof(buf));
    snprintf(buf,sizeof(buf),"%s\n","/bin/mdev");
    save_to_file("/proc/sys/kernel/hotplug",buf);
    do_chroot();
    signal(SIGINT,SIG_DFL);
    fprintf_stdout("#### ERROR: Failed to boot file system!\n");
    fprintf_stdout("#### ERROR: Press Ctrl+Alt+Del or switch off/on for reboot.\n");
    while(1);
    exit(0);
}
Beispiel #20
0
static int prepare_mntns()
{
	int fd, ret;
	char *root;
	char path[PATH_MAX];

	root = getenv("ZDTM_ROOT");
	if (!root) {
		fprintf(stderr, "ZDTM_ROOT isn't set\n");
		return -1;
	}

	if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) {
		fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n");
		return -1;
	}

	if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	printf("chdir(%s)\n", root);
	if (chdir(root)) {
		fprintf(stderr, "chdir(%s) failed: %m\n", root);
		return -1;
	}
	if (mkdir("old", 0777) && errno != EEXIST) {
		fprintf(stderr, "mkdir(old) failed: %m\n");
		return -1;
	}

	printf("pivot_root(., ./old)\n");
	if (pivot_root(".", "./old")) {
		fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
		return -1;
	}
	chdir("/");
	if (mkdir("proc", 0777) && errno != EEXIST) {
		fprintf(stderr, "mkdir(proc) failed: %m\n");
		return -1;
	}

	printf("Mount /proc\n");
	if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) {
		fprintf(stderr, "mount(/proc) failed: %m\n");
		return -1;
	}
	printf("Open the mount point, where is a target file\n");
	fd = open("/old/tmp/xxx", O_DIRECTORY | O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "open(/old/mnt/xxx) failed: %m\n");
		return -1;
	}

	printf("Detach mounts from the previous mount namespace\n");
	if (umount2("./old", MNT_DETACH)) {
		fprintf(stderr, "umount(./old) failed: %m\n");
		return -1;
	}

	printf("Try to read the target file\n");
	snprintf(path, sizeof(path), "/proc/self/fd/%d/yyy/zzz", fd);
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return 0;

	printf("We have done this\n");
	ret = read(fd, path, sizeof(path) - 1);
	if (ret < 0) {
		fprintf(stderr, "read() failed: %m\n");
		return -1;
	}
	path[ret] = 0;
	fprintf(stderr, "%s\n", path);

	return -1;
}
Beispiel #21
0
void stage2(void) {
	DIR *dp;
	struct dirent *dt;
	FILE *fp;
	char **xargv;
	char buf[1024], name[150];
	int rc;
	rc=pivot_root(".","initrd");
	if(rc==-1) {
		perror("pivot_root");
		exit(1);
	}
	chdir("/");
	xmkdir("proc");
	xmkdir("sys");
	xmkdir("config");
	xmkdir("config/download");
	xmkdir("config/localsave");
	xmkdir("config/logs");
	xsystem("mount -t proc -o rw virtual /proc");
	xsystem("mount -t sysfs -o rw virtual /sys");
	save_to_file("/proc/sys/kernel/printk","0 0 0 0\n");
	if((dp=opendir("/tmp")) == NULL) {
		perror("opendir");
		exit(1);
        }
	fprintf_stdout("-> Extracting base tools.");
	while((dt=readdir(dp))!=NULL) {
		if(!strcmp(dt->d_name,".") || !strcmp(dt->d_name,"..")) continue;
		if(strstr(dt->d_name,".bz2")) {
			fprintf_stdout(".");
			xsystem("tar -C / -jxf /tmp/%s",dt->d_name);
			usleep(10000);
		}
	}
	free(dt);
	closedir(dp);
	fprintf_stdout("\r* Extracting base tools. Done.%s\n",SPACE);
	save_to_file("/proc/sys/kernel/modprobe","/bin/modprobe\n");
	xsystem("depmod -a");
	if(file_exists("/lib/modules/drivers.txt")) {
		memset(buf,0x0,sizeof(buf));
		if((fp=fopen("/lib/modules/drivers.txt","r"))!=NULL) {
			while(fgets(buf,sizeof(buf),fp)!=NULL) {
				trim(buf);
				if(buf[0]=='\0') continue;
				xargv[0]=NULL;xargv[1]=NULL;
				memset(name,0x0,sizeof(name));
				xargv[0]=buf;
				xargv[1]=".ko";
				snprintf(name,sizeof(name),"%s",base_name(xargv));
				fprintf_stdout("-> Scanning for %s..%s\r",name,SPACE);
				if(!strcmp(name,"ne")) {
					memset(name,0x0,sizeof(name));
					strncpy(name,"ne io=0x300,0x340",sizeof(name));
				}
				xsystem("modprobe -q -k %s",name);
				usleep(1000);
			}
			fclose(fp);
			fprintf_stdout("%s\r* Scanning. Done.\n",SPACE);
		}
	}
}
Beispiel #22
0
void linux_namespace_jail() {

	char *ns_tmp_mountpoint = NULL, *ns_tmp_mountpoint2 = NULL;

	if (getpid() != 1) {
		uwsgi_log("your kernel does not support linux pid namespace\n");
		exit(1);
	}

	char *ns_hostname = strchr(uwsgi.ns, ':');
	if (ns_hostname) {
		ns_hostname[0] = 0;
		ns_hostname++;
		if (sethostname(ns_hostname, strlen(ns_hostname))) {
			uwsgi_error("sethostname()");
		}
	}

	FILE *procmounts;
	char line[1024];
	int unmounted = 1;
	char *delim0, *delim1;

	if (chdir(uwsgi.ns)) {
		uwsgi_error("chdir()");
		exit(1);
	}

	if (strcmp(uwsgi.ns, "/")) {
		ns_tmp_mountpoint = uwsgi_concat2(uwsgi.ns, "/.uwsgi_ns_tmp_mountpoint");
		mkdir(ns_tmp_mountpoint, S_IRWXU);

		ns_tmp_mountpoint2 = uwsgi_concat2(ns_tmp_mountpoint, "/.uwsgi_ns_tmp_mountpoint");
		mkdir(ns_tmp_mountpoint2, S_IRWXU);

		if (mount(uwsgi.ns, ns_tmp_mountpoint, "none", MS_BIND, NULL)) {
			uwsgi_error("mount()");
		}
		if (chdir(ns_tmp_mountpoint)) {
			uwsgi_error("chdir()");
		}

		if (pivot_root(".", ns_tmp_mountpoint2)) {
			uwsgi_error("pivot_root()");
			exit(1);
		}



		if (chdir("/")) {
			uwsgi_error("chdir()");
			exit(1);
		}

	}

	uwsgi_log("remounting /proc\n");
	if (mount("proc", "/proc", "proc", 0, NULL)) {
		uwsgi_error("mount()");
	}

	while (unmounted) {

		unmounted = 0;
		procmounts = fopen("/proc/self/mounts", "r");
		while (fgets(line, 1024, procmounts) != NULL) {
			delim0 = strchr(line, ' ');
			delim0++;
			delim1 = strchr(delim0, ' ');
			*delim1 = 0;
			if (!strcmp(delim0, "/") || !strcmp(delim0, "/proc"))
				continue;
			if (!umount(delim0)) {
				unmounted++;
			}
		}
		fclose(procmounts);
	}

	if (rmdir("/.uwsgi_ns_tmp_mountpoint/.uwsgi_ns_tmp_mountpoint")) {
		uwsgi_error("rmdir()");
	}
	if (rmdir("/.uwsgi_ns_tmp_mountpoint")) {
		uwsgi_error("rmdir()");
	}

	if (strcmp(uwsgi.ns, "/")) {
		free(ns_tmp_mountpoint2);
		free(ns_tmp_mountpoint);
	}



}
static int child(void *arg)
{
	errno = 0;
	pivot_root("/proc", proc_policy_dir);
	return errno;
}
Beispiel #24
0
static int prepare_mntns(void)
{
	int dfd, ret;
	char *root, *criu_path;
	char path[PATH_MAX];

	root = getenv("ZDTM_ROOT");
	if (!root) {
		fprintf(stderr, "ZDTM_ROOT isn't set\n");
		return -1;
	}

	/*
	 * In a new userns all mounts are locked to protect what is
	 * under them. So we need to create another mount for the
	 * new root.
	 */
	if (mount(root, root, NULL, MS_SLAVE , NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	criu_path = getenv("ZDTM_CRIU");
	if (criu_path) {
		snprintf(path, sizeof(path), "%s%s", root, criu_path);
		if (mount(criu_path, path, NULL, MS_BIND, NULL) ||
		    mount(NULL, path, NULL, MS_PRIVATE, NULL)) {
			pr_perror("Unable to mount %s", path);
			return -1;
		}
	}

	/* Move current working directory to the new root */
	ret = readlink("/proc/self/cwd", path, sizeof(path) - 1);
	if (ret < 0)
		return -1;
	path[ret] = 0;

	dfd = open(path, O_RDONLY | O_DIRECTORY);
	if (dfd == -1) {
		fprintf(stderr, "open(.) failed: %m\n");
		return -1;
	}

	if (chdir(root)) {
		fprintf(stderr, "chdir(%s) failed: %m\n", root);
		return -1;
	}
	if (mkdir("old", 0777) && errno != EEXIST) {
		fprintf(stderr, "mkdir(old) failed: %m\n");
		return -1;
	}

	if (pivot_root(".", "./old")) {
		fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
		return -1;
	}

	if (mount("./old", "./old", NULL, MS_SLAVE | MS_REC , NULL)) {
		fprintf(stderr, "Can't bind-mount root: %m\n");
		return -1;
	}

	/*
	 * proc and sysfs can be mounted in an unprivileged namespace,
	 * if they are already mounted when the user namespace is created.
	 * So ./old must be umounted after mounting /proc and /sys.
	 */
	if (mount("proc", "/proc", "proc", MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL)) {
		fprintf(stderr, "mount(/proc) failed: %m\n");
		return -1;
	}

	if (mount("zdtm_run", "/run", "tmpfs", 0, NULL)) {
		fprintf(stderr, "Unable to mount /run: %m\n");
		return -1;
	}

	if (umount2("./old", MNT_DETACH)) {
		fprintf(stderr, "umount(./old) failed: %m\n");
		return -1;
	}

	if (mount("pts", "/dev/pts", "devpts", MS_MGC_VAL, "mode=666,ptmxmode=666,newinstance")) {
		fprintf(stderr, "mount(/dev/pts) failed: %m\n");
		return -1;
	}
	/*
	 * If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, then /dev/pts/ptmx
	 * does not exist. Fall back to creating the device with
	 * mknod() in that case.
	 */
	if (access("/dev/pts/ptmx", F_OK) == 0) {
		if (symlink("pts/ptmx", "/dev/ptmx") && errno != EEXIST) {
			fprintf(stderr, "symlink(/dev/ptmx) failed: %m\n");
			return -1;
		}
	} else {
		if (mknod("/dev/ptmx", 0666 | S_IFCHR, makedev(5, 2)) == 0) {
			chmod("/dev/ptmx", 0666);
		} else if (errno != EEXIST) {
			fprintf(stderr, "mknod(/dev/ptmx) failed: %m\n");
			return -1;
		}
	}

	if (fchdir(dfd)) {
		fprintf(stderr, "fchdir() failed: %m\n");
		return -1;
	}
	close(dfd);

	return 0;
}
Beispiel #25
0
int ps_daemon_change_rootfs(char *newroot)
{
    ps_log(0, LOG_INFO("change root dir to [%s]"), newroot);

    if (ps_daemon_rootfs_changed)
    {
        ps_log(0, LOG_ERROR("rootfs already changed!"));
        return EXIT_FAILURE;
    }

    if (chdir(newroot) == -1)
    {
        ps_log(0, LOG_ERROR("failed to change rootdir to [%s] - error [%s]"), newroot, strerror(errno));
        return EXIT_FAILURE;
    }

    // create a directory where pivot_root can attach us_root

    if (mkdir("./us_rootfs", 0755) == -1)
    {
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create directory /us_rootfs - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }
    }

    if (unshare(CLONE_NEWNS) == -1)
    {
        ps_log(0, LOG_ERROR("unable to unshare mount namespace - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

	if (pivot_root(".", "./us_rootfs") == -1)
    {
		ps_log(0, LOG_ERROR("pivot_root failed - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
	}

    // unmount user space rootfs

    if (mount("", "/us_rootfs", "none", MS_REC | MS_PRIVATE, "") == -1)
    {
        ps_log(0, LOG_ERROR("failed to re-mount /us_rootfs as private - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (umount2("/us_rootfs", MNT_DETACH) == -1)
    {
        ps_log(0, LOG_ERROR("failed to unmount /us_rootfs - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (rmdir("/us_rootfs") == -1)
        ps_log(0, LOG_ERROR("failed to remove directory /us_rootfs - error [%s]"), strerror(errno));


	if (chdir("/") == -1)
    {
        ps_log(0, LOG_ERROR("failed to change to / - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
	}

    if (mkdir("/proc", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /proc directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

    if (mount("", "/proc","proc", MS_NODEV | MS_NOEXEC | MS_NOSUID,"") == -1)
    {
        ps_log(0, LOG_ERROR("failed to re-mount /proc - error [%s]"), strerror(errno));
        return EXIT_FAILURE;
    }

    if (mkdir("/dev", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /dev directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

    if (mkdir("/dev/pts", 0755) == -1);
        if (errno != EEXIST)
        {
            ps_log(0, LOG_ERROR("failed to create /dev/pts directory - error [%s]"), strerror(errno));
            return EXIT_FAILURE;
        }

	if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL , "newinstance,ptmxmode=0666") == -1)
    {
		ps_log(0, LOG_ERROR("unable to mount /dev/pts - error [%s]"), strerror(errno));
		return EXIT_FAILURE;
	}

	if (access("/dev/ptmx", F_OK) == -1)
    {
		if (symlink("/dev/pts/ptmx", "/dev/ptmx") == -1)
            ps_log(0, LOG_ERROR("unable to create /dev/ptmx symlink - error [%s]"), strerror(errno));
	}

    ps_daemon_rootfs_changed=1;
    return EXIT_SUCCESS;
}