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