Browse code

Merge pull request #6083 from bernerdschaefer/nsinit-drop-capabilities-after-changing-user

SETUID/SETGID not required for changing user

Victor Vieux authored on 2014/05/29 09:29:17
Showing 3 changed files
... ...
@@ -185,15 +185,33 @@ func setupRoute(container *libcontainer.Container) error {
185 185
 // and working dir, and closes any leaky file descriptors
186 186
 // before execing the command inside the namespace
187 187
 func FinalizeNamespace(container *libcontainer.Container) error {
188
-	if err := capabilities.DropCapabilities(container); err != nil {
189
-		return fmt.Errorf("drop capabilities %s", err)
190
-	}
191 188
 	if err := system.CloseFdsFrom(3); err != nil {
192 189
 		return fmt.Errorf("close open file descriptors %s", err)
193 190
 	}
191
+
192
+	// drop capabilities in bounding set before changing user
193
+	if err := capabilities.DropBoundingSet(container); err != nil {
194
+		return fmt.Errorf("drop bounding set %s", err)
195
+	}
196
+
197
+	// preserve existing capabilities while we change users
198
+	if err := system.SetKeepCaps(); err != nil {
199
+		return fmt.Errorf("set keep caps %s", err)
200
+	}
201
+
194 202
 	if err := SetupUser(container.User); err != nil {
195 203
 		return fmt.Errorf("setup user %s", err)
196 204
 	}
205
+
206
+	if err := system.ClearKeepCaps(); err != nil {
207
+		return fmt.Errorf("clear keep caps %s", err)
208
+	}
209
+
210
+	// drop all other capabilities
211
+	if err := capabilities.DropCapabilities(container); err != nil {
212
+		return fmt.Errorf("drop capabilities %s", err)
213
+	}
214
+
197 215
 	if container.WorkingDir != "" {
198 216
 		if err := system.Chdir(container.WorkingDir); err != nil {
199 217
 			return fmt.Errorf("chdir to %s %s", container.WorkingDir, err)
... ...
@@ -9,6 +9,25 @@ import (
9 9
 
10 10
 const allCapabilityTypes = capability.CAPS | capability.BOUNDS
11 11
 
12
+// DropBoundingSet drops the capability bounding set to those specified in the
13
+// container configuration.
14
+func DropBoundingSet(container *libcontainer.Container) error {
15
+	c, err := capability.NewPid(os.Getpid())
16
+	if err != nil {
17
+		return err
18
+	}
19
+
20
+	keep := getEnabledCapabilities(container)
21
+	c.Clear(capability.BOUNDS)
22
+	c.Set(capability.BOUNDS, keep...)
23
+
24
+	if err := c.Apply(capability.BOUNDS); err != nil {
25
+		return err
26
+	}
27
+
28
+	return nil
29
+}
30
+
12 31
 // DropCapabilities drops all capabilities for the current process expect those specified in the container configuration.
13 32
 func DropCapabilities(container *libcontainer.Container) error {
14 33
 	c, err := capability.NewPid(os.Getpid())
... ...
@@ -135,6 +135,22 @@ func GetParentDeathSignal() (int, error) {
135 135
 	return sig, nil
136 136
 }
137 137
 
138
+func SetKeepCaps() error {
139
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 1, 0); err != 0 {
140
+		return err
141
+	}
142
+
143
+	return nil
144
+}
145
+
146
+func ClearKeepCaps() error {
147
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_KEEPCAPS, 0, 0); err != 0 {
148
+		return err
149
+	}
150
+
151
+	return nil
152
+}
153
+
138 154
 func Setctty() error {
139 155
 	if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
140 156
 		return err