Browse code

nsinit.Init() restores parent death signal before exec

Docker-DCO-1.1-Signed-off-by: Bernerd Schaefer <bj.schaefer@gmail.com> (github: bernerdschaefer)

Bernerd Schaefer authored on 2014/05/14 18:49:06
Showing 1 changed files
... ...
@@ -85,12 +85,53 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string,
85 85
 			return err
86 86
 		}
87 87
 	}
88
+
89
+	pdeathSignal, err := system.GetParentDeathSignal()
90
+	if err != nil {
91
+		return fmt.Errorf("get parent death signal %s", err)
92
+	}
93
+
88 94
 	if err := FinalizeNamespace(container); err != nil {
89 95
 		return fmt.Errorf("finalize namespace %s", err)
90 96
 	}
97
+
98
+	// FinalizeNamespace can change user/group which clears the parent death
99
+	// signal, so we restore it here.
100
+	if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
101
+		return fmt.Errorf("restore parent death signal %s", err)
102
+	}
103
+
91 104
 	return system.Execv(args[0], args[0:], container.Env)
92 105
 }
93 106
 
107
+// RestoreParentDeathSignal sets the parent death signal to old.
108
+func RestoreParentDeathSignal(old int) error {
109
+	if old == 0 {
110
+		return nil
111
+	}
112
+
113
+	current, err := system.GetParentDeathSignal()
114
+	if err != nil {
115
+		return fmt.Errorf("get parent death signal %s", err)
116
+	}
117
+
118
+	if old == current {
119
+		return nil
120
+	}
121
+
122
+	if err := system.ParentDeathSignal(uintptr(old)); err != nil {
123
+		return fmt.Errorf("set parent death signal %s", err)
124
+	}
125
+
126
+	// Signal self if parent is already dead. Does nothing if running in a new
127
+	// PID namespace, as Getppid will always return 0.
128
+	if syscall.Getppid() == 1 {
129
+		return syscall.Kill(syscall.Getpid(), syscall.Signal(old))
130
+	}
131
+
132
+	return nil
133
+}
134
+
94 135
 // SetupUser changes the groups, gid, and uid for the user inside the container
95 136
 func SetupUser(u string) error {
96 137
 	uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid())