Moved isolation related code to "nxt_isolation.c".
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user