Skip to content

Commit 73ba097

Browse files
committed
Merge pull request docker-archive#336 from dqminh/execin-wait
nsenter waits for parent signal before forking
2 parents 29ba9b3 + 5a87153 commit 73ba097

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

namespaces/execin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs
7373
return terminate(err)
7474
}
7575

76+
// finish cgroups' setup, unblock the child process.
77+
if _, err := parent.WriteString("1"); err != nil {
78+
return terminate(err)
79+
}
80+
7681
if err := json.NewEncoder(parent).Encode(container); err != nil {
7782
return terminate(err)
7883
}

namespaces/nsenter/nsenter.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ void get_args(int *argc, char ***argv)
2828
pr_perror("Unable to open /proc/self/cmdline");
2929
exit(1);
3030
}
31-
3231
// Read the whole commandline.
3332
ssize_t contents_size = 0;
3433
ssize_t contents_offset = 0;
@@ -98,13 +97,12 @@ void nsenter()
9897
if (strncmp(argv[0], kNsEnter, strlen(kNsEnter)) != 0) {
9998
return;
10099
}
101-
102-
#ifdef PR_SET_CHILD_SUBREAPER
100+
#ifdef PR_SET_CHILD_SUBREAPER
103101
if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) == -1) {
104102
pr_perror("Failed to set child subreaper");
105103
exit(1);
106104
}
107-
#endif
105+
#endif
108106

109107
static const struct option longopts[] = {
110108
{"nspid", required_argument, NULL, 'n'},
@@ -134,7 +132,7 @@ void nsenter()
134132
init_pid = strtol(init_pid_str, NULL, 10);
135133
if ((init_pid == 0 && errno == EINVAL) || errno == ERANGE) {
136134
pr_perror("Failed to parse PID from \"%s\" with output \"%d\"",
137-
init_pid_str, init_pid);
135+
init_pid_str, init_pid);
138136
print_usage();
139137
exit(1);
140138
}
@@ -155,6 +153,12 @@ void nsenter()
155153
exit(1);
156154
}
157155
}
156+
// blocking until the parent placed the process inside correct cgroups.
157+
unsigned char s;
158+
if (read(3, &s, 1) != 1 || s != '1') {
159+
pr_perror("failed to receive synchronization data from parent");
160+
exit(1);
161+
}
158162
// Setns on all supported namespaces.
159163
char ns_dir[PATH_MAX];
160164
memset(ns_dir, 0, PATH_MAX);
@@ -173,18 +177,19 @@ void nsenter()
173177
for (i = 0; i < num; i++) {
174178
// A zombie process has links on namespaces, but they can't be opened
175179
struct stat st;
176-
if (fstatat(ns_dir_fd, namespaces[i], &st, AT_SYMLINK_NOFOLLOW) == -1) {
180+
if (fstatat(ns_dir_fd, namespaces[i], &st, AT_SYMLINK_NOFOLLOW)
181+
== -1) {
177182
if (errno == ENOENT)
178183
continue;
179184
pr_perror("Failed to stat ns file %s for ns %s",
180-
ns_dir, namespaces[i]);
185+
ns_dir, namespaces[i]);
181186
exit(1);
182187
}
183188

184189
int fd = openat(ns_dir_fd, namespaces[i], O_RDONLY);
185190
if (fd == -1) {
186191
pr_perror("Failed to open ns file %s for ns %s",
187-
ns_dir, namespaces[i]);
192+
ns_dir, namespaces[i]);
188193
exit(1);
189194
}
190195
// Set the namespace.

namespaces/nsenter/nsenter_test.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,29 @@ import (
1212

1313
func TestNsenterAlivePid(t *testing.T) {
1414
args := []string{"nsenter-exec", "--nspid", fmt.Sprintf("%d", os.Getpid())}
15+
r, w, err := os.Pipe()
16+
if err != nil {
17+
t.Fatalf("failed to create pipe %v", err)
18+
}
1519

1620
cmd := &exec.Cmd{
17-
Path: os.Args[0],
18-
Args: args,
21+
Path: os.Args[0],
22+
Args: args,
23+
ExtraFiles: []*os.File{r},
1924
}
2025

21-
err := cmd.Run()
22-
if err != nil {
23-
t.Fatal("nsenter exits with a non-zero exit status")
26+
if err := cmd.Start(); err != nil {
27+
t.Fatalf("nsenter failed to start %v", err)
28+
}
29+
r.Close()
30+
31+
// unblock the child process
32+
if _, err := w.WriteString("1"); err != nil {
33+
t.Fatalf("parent failed to write synchronization data %v", err)
34+
}
35+
36+
if err := cmd.Wait(); err != nil {
37+
t.Fatalf("nsenter exits with a non-zero exit status")
2438
}
2539
}
2640

0 commit comments

Comments
 (0)