Skip to content

Commit c443e9b

Browse files
committed
pinns: pin to /var/run/*ns instead of /var/run/crio/ns/*
This change is largely needed for third party networking plugins. These plugins often bind mount /var/run/netns and expect to be able to operate on the namespaces of the pods. Unfortunately, by pinning to /var/run/crio/ns*, we lose this capability. Rather than pinning everything to /var/run/netns/ns/uts or something odd, change the way pinns builds the pinned namespace. Now, we bind namespaces to /var/run/$NS_NAMEns/$ID Signed-off-by: Peter Hunt <[email protected]>
1 parent be25728 commit c443e9b

File tree

5 files changed

+70
-43
lines changed

5 files changed

+70
-43
lines changed

docs/crio.8.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ crio [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...]
232232

233233
**--metrics-port**="": Port for the metrics endpoint (default: 9090)
234234

235-
**--namespaces-dir**="": The directory where the state of the managed namespaces gets tracked. Only used when manage-ns-lifecycle is true (default: /var/run/crio/ns)
235+
**--namespaces-dir**="": The directory where the state of the managed namespaces gets tracked. Only used when manage-ns-lifecycle is true (default: /var/run)
236236

237237
**--no-pivot**: If true, the runtime will not use `pivot_root`, but instead use `MS_MOVE` (default: false)
238238

docs/crio.conf.5.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ The `crio.runtime` table contains settings pertaining to the OCI runtime used an
210210
**manage_ns_lifecycle**=false
211211
Determines whether we pin and remove namespaces and manage their lifecycle
212212

213-
**namespaces_dir**="/var/run/crio/ns"
213+
**namespaces_dir**="/var/run"
214214
The directory where the state of the managed namespaces gets tracked. Only used when manage_ns_lifecycle is true
215215

216216
**pinns_path**=""

internal/lib/sandbox/namespaces_linux.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,11 @@ func pinNamespaces(nsTypes []NSType, cfg *config.Config) ([]NamespaceIface, erro
6363
NETNS: "-n",
6464
}
6565

66-
pinDir := filepath.Join(cfg.NamespacesDir, uuid.New().String())
67-
68-
if err := os.MkdirAll(pinDir, 0755); err != nil {
69-
return nil, err
66+
pinnedNamespace := uuid.New().String()
67+
pinnsArgs := []string{
68+
"-d", cfg.NamespacesDir,
69+
"-f", pinnedNamespace,
7070
}
71-
72-
pinnsArgs := []string{"-d", pinDir}
7371
type namespaceInfo struct {
7472
path string
7573
nsType NSType
@@ -83,7 +81,7 @@ func pinNamespaces(nsTypes []NSType, cfg *config.Config) ([]NamespaceIface, erro
8381
}
8482
pinnsArgs = append(pinnsArgs, arg)
8583
mountedNamespaces = append(mountedNamespaces, namespaceInfo{
86-
path: filepath.Join(pinDir, string(nsType)),
84+
path: filepath.Join(cfg.NamespacesDir, fmt.Sprintf("%sns", string(nsType)), pinnedNamespace),
8785
nsType: nsType,
8886
})
8987
}

pinns/pinns.c

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,15 @@
1414

1515
#include "utils.h"
1616

17-
static int bind_ns(const char *pin_path, const char *ns_name) {
18-
char bind_path[PATH_MAX];
19-
char ns_path[PATH_MAX];
20-
int fd;
21-
22-
snprintf(bind_path, PATH_MAX - 1, "%s/%s", pin_path, ns_name);
23-
fd = open(bind_path, O_RDONLY | O_CREAT | O_EXCL, 0);
24-
if (fd < 0) {
25-
pwarn("Failed to create ns file");
26-
return -1;
27-
}
28-
close(fd);
29-
30-
snprintf(ns_path, PATH_MAX - 1, "/proc/self/ns/%s", ns_name);
31-
if (mount(ns_path, bind_path, NULL, MS_BIND, NULL) < 0) {
32-
pwarnf("Failed to bind mount ns: %s", ns_path);
33-
return -1;
34-
}
35-
36-
return 0;
37-
}
17+
static int bind_ns(const char *pin_path, const char *filename, const char *ns_name);
18+
static int directory_exists_or_create(const char* path);
3819

3920
int main(int argc, char **argv) {
4021
int num_unshares = 0;
4122
int unshare_flags = 0;
4223
int c;
4324
char *pin_path = NULL;
25+
char *filename = NULL;
4426
bool bind_net = false;
4527
bool bind_uts = false;
4628
bool bind_ipc = false;
@@ -55,9 +37,10 @@ int main(int argc, char **argv) {
5537
{"user", optional_argument, NULL, 'U'},
5638
{"cgroup", optional_argument, NULL, 'c'},
5739
{"dir", required_argument, NULL, 'd'},
40+
{"filename", required_argument, NULL, 'f'},
5841
};
5942

60-
while ((c = getopt_long(argc, argv, "pchuUind:", long_options, NULL)) != -1) {
43+
while ((c = getopt_long(argc, argv, "pchuUind:f:", long_options, NULL)) != -1) {
6144
switch (c) {
6245
case 'u':
6346
unshare_flags |= CLONE_NEWUTS;
@@ -90,6 +73,9 @@ int main(int argc, char **argv) {
9073
case 'd':
9174
pin_path = optarg;
9275
break;
76+
case 'f':
77+
filename = optarg;
78+
break;
9379
case 'h':
9480
// usage();
9581
default:
@@ -102,13 +88,12 @@ int main(int argc, char **argv) {
10288
pexit("Path for pinning namespaces not specified");
10389
}
10490

105-
struct stat sb;
106-
if (stat(pin_path, &sb) != 0) {
107-
pexitf("Failed to check if directory %s exists", pin_path);
91+
if (!filename) {
92+
pexit("Filename for pinning namespaces not specified");
10893
}
10994

110-
if (!S_ISDIR(sb.st_mode)) {
111-
nexitf("%s is not a directory", pin_path);
95+
if (directory_exists_or_create(pin_path) < 0) {
96+
nexitf("%s exists but is not a directory", pin_path);
11297
}
11398

11499
if (num_unshares == 0) {
@@ -120,34 +105,78 @@ int main(int argc, char **argv) {
120105
}
121106

122107
if (bind_uts) {
123-
if (bind_ns(pin_path, "uts") < 0) {
108+
if (bind_ns(pin_path, filename, "uts") < 0) {
124109
return EXIT_FAILURE;
125110
}
126111
}
127112

128113
if (bind_ipc) {
129-
if (bind_ns(pin_path, "ipc") < 0) {
114+
if (bind_ns(pin_path, filename, "ipc") < 0) {
130115
return EXIT_FAILURE;
131116
}
132117
}
133118

134119
if (bind_net) {
135-
if (bind_ns(pin_path, "net") < 0) {
120+
if (bind_ns(pin_path, filename, "net") < 0) {
136121
return EXIT_FAILURE;
137122
}
138123
}
139124

140125
if (bind_user) {
141-
if (bind_ns(pin_path, "user") < 0) {
126+
if (bind_ns(pin_path, filename, "user") < 0) {
142127
return EXIT_FAILURE;
143128
}
144129
}
145130

146131
if (bind_cgroup) {
147-
if (bind_ns(pin_path, "cgroup") < 0) {
132+
if (bind_ns(pin_path, filename, "cgroup") < 0) {
148133
return EXIT_FAILURE;
149134
}
150135
}
151136

152137
return EXIT_SUCCESS;
153138
}
139+
140+
static int bind_ns(const char *pin_path, const char *filename, const char *ns_name) {
141+
char bind_path[PATH_MAX];
142+
char ns_path[PATH_MAX];
143+
int fd;
144+
145+
// first, verify the /$PATH/$NSns directory exists
146+
snprintf(bind_path, PATH_MAX - 1, "%s/%sns", pin_path, ns_name);
147+
if (directory_exists_or_create(bind_path) < 0) {
148+
pwarnf("%s exists and is not a directory", bind_path);
149+
return -1;
150+
}
151+
152+
// now, get the real path we want
153+
snprintf(bind_path, PATH_MAX - 1, "%s/%sns/%s", pin_path, ns_name, filename);
154+
155+
fd = open(bind_path, O_RDONLY | O_CREAT | O_EXCL, 0);
156+
if (fd < 0) {
157+
pwarn("Failed to create ns file");
158+
return -1;
159+
}
160+
close(fd);
161+
162+
snprintf(ns_path, PATH_MAX - 1, "/proc/self/ns/%s", ns_name);
163+
if (mount(ns_path, bind_path, NULL, MS_BIND, NULL) < 0) {
164+
pwarnf("Failed to bind mount ns: %s", ns_path);
165+
return -1;
166+
}
167+
168+
return 0;
169+
}
170+
171+
static int directory_exists_or_create(const char* path) {
172+
struct stat sb;
173+
if (stat(path, &sb) != 0) {
174+
mkdir(path, 0755);
175+
return 0;
176+
}
177+
178+
if (!S_ISDIR(sb.st_mode)) {
179+
return -1;
180+
}
181+
return 0;
182+
}

pkg/config/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ func DefaultConfig() (*Config, error) {
552552
DefaultCapabilities: DefaultCapabilities,
553553
LogLevel: "info",
554554
HooksDir: []string{hooks.DefaultDir},
555-
NamespacesDir: "/var/run/crio/ns",
555+
NamespacesDir: "/var/run",
556556
seccompConfig: seccomp.New(),
557557
apparmorConfig: apparmor.New(),
558558
},
@@ -787,7 +787,7 @@ func (c *RuntimeConfig) Validate(systemContext *types.SystemContext, onExecution
787787
return errors.Wrap(err, "pinns validation")
788788
}
789789

790-
if err := os.MkdirAll(c.NamespacesDir, 0700); err != nil {
790+
if err := os.MkdirAll(c.NamespacesDir, 0755); err != nil {
791791
return errors.Wrap(err, "invalid namespaces_dir")
792792
}
793793

0 commit comments

Comments
 (0)