]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/namespace.c
Merge pull request #3956 from brauner/2021-08-27.list
[mirror_lxc.git] / src / lxc / namespace.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
5bb3ba8a 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
5bb3ba8a 6#include <errno.h>
a2028b8f 7#include <fcntl.h>
8ab93249 8#include <sched.h>
5bb3ba8a 9#include <signal.h>
81c75799 10#include <sys/param.h>
81c75799 11#include <sys/stat.h>
8ab93249 12#include <sys/syscall.h>
a2028b8f 13#include <sys/types.h>
d38dd64a 14#include <unistd.h>
5bb3ba8a 15
d38dd64a 16#include "config.h"
81c75799 17#include "log.h"
244f7f87 18#include "memory_utils.h"
a2028b8f
CB
19#include "namespace.h"
20#include "utils.h"
81c75799 21
ac2cecc4 22lxc_log_define(namespace, lxc);
5bb3ba8a 23
29ed9c13
CB
24/* Leave the user namespace at the first position in the array of structs so
25 * that we always attach to it first when iterating over the struct and using
26 * setns() to switch namespaces. This especially affects lxc_attach(): Suppose
27 * you cloned a new user namespace and mount namespace as an unprivileged user
28 * on the host and want to setns() to the mount namespace. This requires you to
29 * attach to the user namespace first otherwise the kernel will fail this check:
30 *
31 * if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
32 * !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
33 * !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
34 * return -EPERM;
35 *
36 * in
37 *
38 * linux/fs/namespace.c:mntns_install().
39 */
9662e444 40const struct ns_info ns_info[LXC_NS_MAX] = {
25c659d5
CB
41 [LXC_NS_USER] = { "user", "ns/user", CLONE_NEWUSER, "CLONE_NEWUSER", "LXC_USER_NS" },
42 [LXC_NS_MNT] = { "mnt", "ns/mnt", CLONE_NEWNS, "CLONE_NEWNS", "LXC_MNT_NS" },
43 [LXC_NS_PID] = { "pid", "ns/pid", CLONE_NEWPID, "CLONE_NEWPID", "LXC_PID_NS" },
44 [LXC_NS_UTS] = { "uts", "ns/uts", CLONE_NEWUTS, "CLONE_NEWUTS", "LXC_UTS_NS" },
45 [LXC_NS_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" },
46 [LXC_NS_NET] = { "net", "ns/net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" },
47 [LXC_NS_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" },
48 [LXC_NS_TIME] = { "time", "ns/time", CLONE_NEWTIME, "CLONE_NEWTIME", "LXC_TIME_NS" },
39a5d5fe
CS
49};
50
28d9e29e 51int lxc_namespace_2_cloneflag(const char *namespace)
39a5d5fe 52{
9662e444 53 int i;
727b9b16 54
9662e444
CB
55 for (i = 0; i < LXC_NS_MAX; i++)
56 if (!strcasecmp(ns_info[i].proc_name, namespace))
57 return ns_info[i].clone_flag;
39a5d5fe 58
28d9e29e
CB
59 ERROR("Invalid namespace name \"%s\"", namespace);
60 return -EINVAL;
61}
62
63int lxc_namespace_2_ns_idx(const char *namespace)
64{
c92bfdb0
CB
65 for (int i = 0; i < LXC_NS_MAX; i++) {
66 if (strequal(ns_info[i].proc_name, namespace))
28d9e29e 67 return i;
c92bfdb0 68 }
28d9e29e
CB
69
70 ERROR("Invalid namespace name \"%s\"", namespace);
71 return -EINVAL;
39a5d5fe
CS
72}
73
42067d18 74extern int lxc_namespace_2_std_identifiers(char *namespaces)
75{
76 char **it;
77 char *del;
78
79 /* The identifiers for namespaces used with lxc-attach and lxc-unshare
80 * as given on the manpage do not align with the standard identifiers.
81 * This affects network, mount, and uts namespaces. The standard identifiers
82 * are: "mnt", "uts", and "net" whereas lxc-attach and lxc-unshare uses
83 * "MOUNT", "UTSNAME", and "NETWORK". So let's use some cheap memmove()s
84 * to replace them by their standard identifiers.
85 * Let's illustrate this with an example:
86 * Assume the string:
87 *
88 * "IPC|MOUNT|PID"
89 *
90 * then we memmove()
91 *
92 * dest: del + 1 == OUNT|PID
93 * src: del + 3 == NT|PID
94 */
95 if (!namespaces)
96 return -1;
97
98 while ((del = strstr(namespaces, "MOUNT")))
99 memmove(del + 1, del + 3, strlen(del) - 2);
100
101 for (it = (char *[]){"NETWORK", "UTSNAME", NULL}; it && *it; it++)
102 while ((del = strstr(namespaces, *it)))
103 memmove(del + 3, del + 7, strlen(del) - 6);
104
105 return 0;
106}
107
39a5d5fe
CS
108int lxc_fill_namespace_flags(char *flaglist, int *flags)
109{
803fd7bf 110 char *token;
39a5d5fe
CS
111 int aflag;
112
113 if (!flaglist) {
9662e444 114 ERROR("At least one namespace is needed.");
39a5d5fe
CS
115 return -1;
116 }
117
803fd7bf 118 lxc_iterate_parts(token, flaglist, "|") {
39a5d5fe
CS
119 aflag = lxc_namespace_2_cloneflag(token);
120 if (aflag < 0)
121 return -1;
122
123 *flags |= aflag;
39a5d5fe 124 }
727b9b16 125
39a5d5fe
CS
126 return 0;
127}