#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include int enter_mount_namespace(void) { if (geteuid() != 0) { fprintf(stderr, "E Must run as root\n"); return -1; } // Do some minimal verification to check that oz-daemon is the parent pid_t ppid = getppid(); if (checkProcessName(ppid, "oz-daemon") != 0) { fprintf(stderr, "E unable to verify that oz-daemon is parent\n"); return -1; } // Parse namespace pid from environment char *envv, *envvend; long nspid; envv = getenv("_OZ_NSPID"); if (envv == NULL) { fprintf(stderr, "E unable to get namespace pid from environment\n"); return -1; } errno = 0; nspid = strtol(envv, &envvend, 10); if ((errno == ERANGE && (nspid == LONG_MAX || nspid == LONG_MIN)) || (errno != 0 && nspid == 0)) { fprintf(stderr, "E unable to parse namespace pid from environment\n"); return -1; } if (envvend == envv || nspid < 0) { fprintf(stderr, "E unable to parse namespace pid from environment\n"); return -1; } // Verify that the target is an instance of oz-init if (checkProcessName(nspid, "oz-init") != 0) { fprintf(stderr, "E unable to verify that oz-init is the target\n"); return -1; } char nspath[PATH_MAX]; if (snprintf(nspath, PATH_MAX-1, "/proc/%ld/ns", nspid) < 0) { fprintf(stderr, "E unable to parse namespace path `/proc/%ld/ns`\n", nspid); return -1; } printf("D Opening: %s\n", nspath); // Start opening the namespace struct stat st; int tfd, fd; tfd = open(nspath, O_DIRECTORY | O_RDONLY); if (tfd == -1) { fprintf(stderr, "E failed to open child namespace\n"); return -1; } // Symlinks on all namespaces exist for dead processes, but they can't be opened if (fstatat(tfd, "mnt", &st, AT_SYMLINK_NOFOLLOW) == -1) { if (errno == ENOENT) { fprintf(stderr, "E failed to open child namespace\n"); return -1; } } fd = openat(tfd, "mnt", O_RDONLY); if (fd == -1) { fprintf(stderr, "E failed to open child mount namespace: %s\n", nspath); return -1; } // Set the namespace. if (setns(fd, 0) == -1) { fprintf(stderr, "E failed to setns for: %s\n", nspath); return -1; } close(fd); } int checkProcessName(pid_t pid, char *pname) { FILE *fp; char *line = NULL; char pproc[PATH_MAX]; char cline[PATH_MAX]; size_t len = 0; ssize_t read; if (snprintf(cline, PATH_MAX-1, "Name: %s\n", pname) < 0) { return -1; } if (snprintf(pproc, PATH_MAX-1, "/proc/%ld/status", pid) < 0) { return -1; } fp = fopen(pproc, "r"); if (fp == NULL) { return -1; } int retval = -1; while (retval == -1 && (read = getline(&line, &len, fp)) != -1) { if (hasPrefix(line, "Name:") >= 0) { retval = strcmp(cline, line); break; } } fclose(fp); if (line) { free(line); } return retval; } int hasPrefix(const char *str, const char *pre) { size_t lenpre = strlen(pre), lenstr = strlen(str); return lenstr < lenpre ? -1 : strncmp(pre, str, lenpre); }