Moved isolation related code to "nxt_isolation.c".

This commit is contained in:
Tiago Natel de Moura
2020-08-20 15:22:58 +01:00
parent 9bf6efc55a
commit a8a7eeb1fc
7 changed files with 990 additions and 980 deletions

View File

@@ -17,10 +17,6 @@
#include <sys/prctl.h>
#endif
#if (NXT_HAVE_PIVOT_ROOT)
#include <mntent.h>
#endif
static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process);
static nxt_int_t nxt_process_child_fixup(nxt_task_t *task,
nxt_process_t *process);
@@ -33,16 +29,6 @@ static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg,
static void nxt_process_created_error(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
#if (NXT_HAVE_ISOLATION_ROOTFS)
static nxt_int_t nxt_process_chroot(nxt_task_t *task, const char *path);
#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
static nxt_int_t nxt_process_pivot_root(nxt_task_t *task, const char *rootfs);
static nxt_int_t nxt_process_private_mount(nxt_task_t *task,
const char *rootfs);
static int nxt_pivot_root(const char *new_root, const char *old_root);
#endif
#endif
/* A cached process pid. */
nxt_pid_t nxt_pid;
@@ -398,51 +384,6 @@ nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process)
}
#if (NXT_HAVE_CLONE_NEWUSER)
nxt_int_t
nxt_process_vldt_isolation_creds(nxt_task_t *task, nxt_process_t *process)
{
nxt_int_t ret;
nxt_clone_t *clone;
nxt_credential_t *creds;
clone = &process->isolation.clone;
creds = process->user_cred;
if (clone->uidmap.size == 0 && clone->gidmap.size == 0) {
return NXT_OK;
}
if (!nxt_is_clone_flag_set(clone->flags, NEWUSER)) {
if (nxt_slow_path(clone->uidmap.size > 0)) {
nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but "
"\"isolation.namespaces.credential\" is false or unset");
return NXT_ERROR;
}
if (nxt_slow_path(clone->gidmap.size > 0)) {
nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but "
"\"isolation.namespaces.credential\" is false or unset");
return NXT_ERROR;
}
return NXT_OK;
}
ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, creds);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, creds);
}
#endif
nxt_int_t
nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, nxt_str_t *user,
nxt_str_t *group)
@@ -525,329 +466,6 @@ nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process)
}
#if (NXT_HAVE_ISOLATION_ROOTFS)
#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
nxt_int_t
nxt_process_change_root(nxt_task_t *task, nxt_process_t *process)
{
char *rootfs;
nxt_int_t ret;
rootfs = (char *) process->isolation.rootfs;
nxt_debug(task, "change root: %s", rootfs);
if (NXT_CLONE_MNT(process->isolation.clone.flags)) {
ret = nxt_process_pivot_root(task, rootfs);
} else {
ret = nxt_process_chroot(task, rootfs);
}
if (nxt_fast_path(ret == NXT_OK)) {
if (nxt_slow_path(chdir("/") < 0)) {
nxt_alert(task, "chdir(\"/\") %E", nxt_errno);
return NXT_ERROR;
}
}
return ret;
}
#else
nxt_int_t
nxt_process_change_root(nxt_task_t *task, nxt_process_t *process)
{
char *rootfs;
rootfs = (char *) process->isolation.rootfs;
nxt_debug(task, "change root: %s", rootfs);
if (nxt_fast_path(nxt_process_chroot(task, rootfs) == NXT_OK)) {
if (nxt_slow_path(chdir("/") < 0)) {
nxt_alert(task, "chdir(\"/\") %E", nxt_errno);
return NXT_ERROR;
}
return NXT_OK;
}
return NXT_ERROR;
}
#endif
static nxt_int_t
nxt_process_chroot(nxt_task_t *task, const char *path)
{
if (nxt_slow_path(chroot(path) < 0)) {
nxt_alert(task, "chroot(%s) %E", path, nxt_errno);
return NXT_ERROR;
}
return NXT_OK;
}
void
nxt_process_unmount_all(nxt_task_t *task, nxt_process_t *process)
{
size_t i, n;
nxt_array_t *mounts;
nxt_fs_mount_t *mnt;
nxt_debug(task, "unmount all (%s)", process->name);
mounts = process->isolation.mounts;
n = mounts->nelts;
mnt = mounts->elts;
for (i = 0; i < n; i++) {
nxt_fs_unmount(mnt[i].dst);
}
}
#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
/*
* pivot_root(2) can only be safely used with containers, otherwise it can
* umount(2) the global root filesystem and screw up the machine.
*/
static nxt_int_t
nxt_process_pivot_root(nxt_task_t *task, const char *path)
{
/*
* This implementation makes use of a kernel trick that works for ages
* and now documented in Linux kernel 5.
* https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/
*/
if (nxt_slow_path(mount("", "/", "", MS_SLAVE|MS_REC, "") != 0)) {
nxt_alert(task, "failed to make / a slave mount %E", nxt_errno);
return NXT_ERROR;
}
if (nxt_slow_path(nxt_process_private_mount(task, path) != NXT_OK)) {
return NXT_ERROR;
}
if (nxt_slow_path(mount(path, path, "bind", MS_BIND|MS_REC, "") != 0)) {
nxt_alert(task, "error bind mounting rootfs %E", nxt_errno);
return NXT_ERROR;
}
if (nxt_slow_path(chdir(path) != 0)) {
nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno);
return NXT_ERROR;
}
if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) {
nxt_alert(task, "failed to pivot_root %E", nxt_errno);
return NXT_ERROR;
}
/*
* Make oldroot a slave mount to avoid unmounts getting propagated to the
* host.
*/
if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) {
nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno);
return NXT_ERROR;
}
if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) {
nxt_alert(task, "failed to umount old root directory %E", nxt_errno);
return NXT_ERROR;
}
return NXT_OK;
}
static nxt_int_t
nxt_process_private_mount(nxt_task_t *task, const char *rootfs)
{
char *parent_mnt;
FILE *procfile;
u_char **mounts;
size_t len;
uint8_t *shared;
nxt_int_t ret, index, nmounts;
struct mntent *ent;
static const char *mount_path = "/proc/self/mounts";
ret = NXT_ERROR;
ent = NULL;
shared = NULL;
procfile = NULL;
parent_mnt = NULL;
nmounts = 256;
mounts = nxt_malloc(nmounts * sizeof(uintptr_t));
if (nxt_slow_path(mounts == NULL)) {
goto fail;
}
shared = nxt_malloc(nmounts);
if (nxt_slow_path(shared == NULL)) {
goto fail;
}
procfile = setmntent(mount_path, "r");
if (nxt_slow_path(procfile == NULL)) {
nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno);
goto fail;
}
index = 0;
again:
for ( ; index < nmounts; index++) {
ent = getmntent(procfile);
if (ent == NULL) {
nmounts = index;
break;
}
mounts[index] = (u_char *) strdup(ent->mnt_dir);
shared[index] = hasmntopt(ent, "shared") != NULL;
}
if (ent != NULL) {
/* there are still entries to be read */
nmounts *= 2;
mounts = nxt_realloc(mounts, nmounts);
if (nxt_slow_path(mounts == NULL)) {
goto fail;
}
shared = nxt_realloc(shared, nmounts);
if (nxt_slow_path(shared == NULL)) {
goto fail;
}
goto again;
}
for (index = 0; index < nmounts; index++) {
if (nxt_strcmp(mounts[index], rootfs) == 0) {
parent_mnt = (char *) rootfs;
break;
}
}
if (parent_mnt == NULL) {
len = nxt_strlen(rootfs);
parent_mnt = nxt_malloc(len + 1);
if (parent_mnt == NULL) {
goto fail;
}
nxt_memcpy(parent_mnt, rootfs, len);
parent_mnt[len] = '\0';
if (parent_mnt[len - 1] == '/') {
parent_mnt[len - 1] = '\0';
len--;
}
for ( ;; ) {
for (index = 0; index < nmounts; index++) {
if (nxt_strcmp(mounts[index], parent_mnt) == 0) {
goto found;
}
}
if (len == 1 && parent_mnt[0] == '/') {
nxt_alert(task, "parent mount not found");
goto fail;
}
/* parent dir */
while (parent_mnt[len - 1] != '/' && len > 0) {
len--;
}
if (nxt_slow_path(len == 0)) {
nxt_alert(task, "parent mount not found");
goto fail;
}
if (len == 1) {
parent_mnt[len] = '\0'; /* / */
} else {
parent_mnt[len - 1] = '\0'; /* /<path> */
}
}
}
found:
if (shared[index]) {
if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) {
nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt,
nxt_errno);
goto fail;
}
}
ret = NXT_OK;
fail:
if (procfile != NULL) {
endmntent(procfile);
}
if (mounts != NULL) {
for (index = 0; index < nmounts; index++) {
nxt_free(mounts[index]);
}
nxt_free(mounts);
}
if (shared != NULL) {
nxt_free(shared);
}
if (parent_mnt != NULL && parent_mnt != rootfs) {
nxt_free(parent_mnt);
}
return ret;
}
static int
nxt_pivot_root(const char *new_root, const char *old_root)
{
return syscall(__NR_pivot_root, new_root, old_root);
}
#endif
#endif
static nxt_int_t
nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
{