Browse code

Maintain a whitelist of capabilities rather than droplist

This fixes 6/18 vulnerability

Docker-DCO-1.1-Signed-off-by: Dinesh Subhraveti <dineshs@altiscale.com> (github: dineshs-altiscale)

Dinesh Subhraveti authored on 2014/06/19 15:17:13
Showing 2 changed files
... ...
@@ -19,7 +19,6 @@ import (
19 19
 	"github.com/docker/libcontainer/label"
20 20
 	"github.com/docker/libcontainer/mount/nodes"
21 21
 	"github.com/dotcloud/docker/daemon/execdriver"
22
-	"github.com/dotcloud/docker/pkg/system"
23 22
 	"github.com/dotcloud/docker/utils"
24 23
 )
25 24
 
... ...
@@ -40,15 +39,6 @@ func init() {
40 40
 		if err := setupCapabilities(args); err != nil {
41 41
 			return err
42 42
 		}
43
-		if err := setupWorkingDirectory(args); err != nil {
44
-			return err
45
-		}
46
-		if err := system.CloseFdsFrom(3); err != nil {
47
-			return err
48
-		}
49
-		if err := changeUser(args); err != nil {
50
-			return err
51
-		}
52 43
 
53 44
 		path, err := exec.LookPath(args.Args[0])
54 45
 		if err != nil {
... ...
@@ -11,6 +11,7 @@ import (
11 11
 
12 12
 	"github.com/docker/libcontainer/netlink"
13 13
 	"github.com/dotcloud/docker/daemon/execdriver"
14
+	"github.com/dotcloud/docker/pkg/system"
14 15
 	"github.com/dotcloud/docker/pkg/user"
15 16
 	"github.com/syndtr/gocapability/capability"
16 17
 )
... ...
@@ -130,39 +131,100 @@ func changeUser(args *execdriver.InitArgs) error {
130 130
 	return nil
131 131
 }
132 132
 
133
-func setupCapabilities(args *execdriver.InitArgs) error {
134
-	if args.Privileged {
135
-		return nil
133
+var whiteList = []capability.Cap{
134
+	capability.CAP_MKNOD,
135
+	capability.CAP_SETUID,
136
+	capability.CAP_SETGID,
137
+	capability.CAP_CHOWN,
138
+	capability.CAP_NET_RAW,
139
+	capability.CAP_DAC_OVERRIDE,
140
+	capability.CAP_FOWNER,
141
+	capability.CAP_FSETID,
142
+	capability.CAP_KILL,
143
+	capability.CAP_SETGID,
144
+	capability.CAP_SETUID,
145
+	capability.CAP_LINUX_IMMUTABLE,
146
+	capability.CAP_NET_BIND_SERVICE,
147
+	capability.CAP_NET_BROADCAST,
148
+	capability.CAP_IPC_LOCK,
149
+	capability.CAP_IPC_OWNER,
150
+	capability.CAP_SYS_CHROOT,
151
+	capability.CAP_SYS_PTRACE,
152
+	capability.CAP_SYS_BOOT,
153
+	capability.CAP_LEASE,
154
+	capability.CAP_SETFCAP,
155
+	capability.CAP_WAKE_ALARM,
156
+	capability.CAP_BLOCK_SUSPEND,
157
+}
158
+
159
+func dropBoundingSet() error {
160
+	c, err := capability.NewPid(os.Getpid())
161
+	if err != nil {
162
+		return err
136 163
 	}
164
+	c.Clear(capability.BOUNDS)
165
+	c.Set(capability.BOUNDS, whiteList...)
137 166
 
138
-	drop := []capability.Cap{
139
-		capability.CAP_SETPCAP,
140
-		capability.CAP_SYS_MODULE,
141
-		capability.CAP_SYS_RAWIO,
142
-		capability.CAP_SYS_PACCT,
143
-		capability.CAP_SYS_ADMIN,
144
-		capability.CAP_SYS_NICE,
145
-		capability.CAP_SYS_RESOURCE,
146
-		capability.CAP_SYS_TIME,
147
-		capability.CAP_SYS_TTY_CONFIG,
148
-		capability.CAP_AUDIT_WRITE,
149
-		capability.CAP_AUDIT_CONTROL,
150
-		capability.CAP_MAC_OVERRIDE,
151
-		capability.CAP_MAC_ADMIN,
152
-		capability.CAP_NET_ADMIN,
153
-		capability.CAP_SYSLOG,
167
+	if err := c.Apply(capability.BOUNDS); err != nil {
168
+		return err
154 169
 	}
155 170
 
171
+	return nil
172
+}
173
+
174
+const allCapabilityTypes = capability.CAPS | capability.BOUNDS
175
+
176
+func dropCapabilities() error {
156 177
 	c, err := capability.NewPid(os.Getpid())
157 178
 	if err != nil {
158 179
 		return err
159 180
 	}
181
+	c.Clear(allCapabilityTypes)
182
+	c.Set(allCapabilityTypes, whiteList...)
160 183
 
161
-	c.Unset(capability.CAPS|capability.BOUNDS, drop...)
184
+	if err := c.Apply(allCapabilityTypes); err != nil {
185
+		return err
186
+	}
162 187
 
163
-	if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
188
+	return nil
189
+}
190
+
191
+func setupCapabilities(args *execdriver.InitArgs) error {
192
+	if err := system.CloseFdsFrom(3); err != nil {
164 193
 		return err
165 194
 	}
195
+
196
+	if !args.Privileged {
197
+		// drop capabilities in bounding set before changing user
198
+		if err := dropBoundingSet(); err != nil {
199
+			return fmt.Errorf("drop bounding set %s", err)
200
+		}
201
+
202
+		// preserve existing capabilities while we change users
203
+		if err := system.SetKeepCaps(); err != nil {
204
+			return fmt.Errorf("set keep caps %s", err)
205
+		}
206
+	}
207
+
208
+	if err := changeUser(args); err != nil {
209
+		return err
210
+	}
211
+
212
+	if !args.Privileged {
213
+		if err := system.ClearKeepCaps(); err != nil {
214
+			return fmt.Errorf("clear keep caps %s", err)
215
+		}
216
+
217
+		// drop all other capabilities
218
+		if err := dropCapabilities(); err != nil {
219
+			return fmt.Errorf("drop capabilities %s", err)
220
+		}
221
+	}
222
+
223
+	if err := setupWorkingDirectory(args); err != nil {
224
+		return err
225
+	}
226
+
166 227
 	return nil
167 228
 }
168 229