Skip to content

Commit

Permalink
docker: disallow volume mounts from host by default (#9321)
Browse files Browse the repository at this point in the history
The default behavior for `docker.volumes.enabled` is intended to be `false`,
but the HCL schema defaults to `true` if the value is unset. Set the default
literal value to `true`.

Additionally, Docker driver mounts of type "volume" (but not "bind") are not
being properly sandboxed with that setting. Disable Docker mounts with type
"volume" entirely whenever the `docker.volumes.enabled` flag is set to
false. Note this is unrelated to the `volume_mount` feature, which is
constrained to preconfigured host volumes or whatever is mounted by a CSI
plugin.

This changeset includes updates to unit tests that should have been failing
under the documented behavior but were not.
  • Loading branch information
tgross committed Nov 11, 2020
1 parent 057241d commit 306cfab
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 7 deletions.
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ BUG FIXES:
* core: Fixed a bug where ACL handling prevented cross-namespace allocation listing [[GH-9278](https://github.com/hashicorp/nomad/issues/9278)]
* core: Fixed a bug where a request to scale a job would fail if the job was not in the default namespace. [[GH-9296](https://github.com/hashicorp/nomad/pull/9296)]
* config (Enterprise): Fixed default enterprise config merging. [[GH-9083](https://github.com/hashicorp/nomad/pull/9083)]
* client: Fixed an issue with the Java fingerprinter on macOS causing pop-up notifications when no JVM installed. [[GH-9225](https://github.com/hashicorp/nomad/pull/9225)]
* client: Fixed an issue with the Java fingerprinter on macOS causing pop-up notifications when no JVM installed. [[GH-9225](https://github.com/hashicorp/nomad/pull/9225)]
* client: Fixed an fingerprinter issue detecting bridge kernel module [[GH-9299](https://github.com/hashicorp/nomad/pull/9299)]
* client: Fixed an in-place upgrade bug, where a Nomad client may fail to manage tasks that were started with pre-0.9 Nomad client. [[GH-9304](https://github.com/hashicorp/nomad/pull/9304)]
* consul: Fixed a bug to correctly validate task when using script-checks in group-level services [[GH-8952](https://github.com/hashicorp/nomad/issues/8952)]
Expand All @@ -53,6 +53,12 @@ BUG FIXES:
* csi: Fixed a bug where `nomad volume detach` would not accept prefixes for the node ID parameter. [[GH-9041](https://github.com/hashicorp/nomad/issues/9041)]
* driver/docker: Fixed a bug where the default `image_delay` configuration was ignored if the `gc` configuration was not set. [[GH-9101](https://github.com/hashicorp/nomad/issues/9101)]

## 0.12.8 (November 10, 2020)

SECURITY:
* docker: Fixed a bug where the `docker.volumes.enabled` configuration was not set to the default `false` if left unset. CVE-2020-28348 [[GH-9303](https://github.com/hashicorp/nomad/issues/9303)]
* docker: Fixed a bug where Docker driver mounts of type "volume" (but not "bind") were not sandboxed when `docker.volumes.enabled` is set to `false`. The `docker.volumes.enabled` configuration will now disable Docker mounts with type "volume" when set to `false`. CVE-2020-28348 [[GH-9303](https://github.com/hashicorp/nomad/issues/9303)]

## 0.12.7 (October 23, 2020)

BUG FIXES:
Expand Down Expand Up @@ -228,6 +234,11 @@ BUG FIXES:
* ui: The task group detail page no longer makes excessive requests to the allocation and stats endpoints. [[GH-8216](https://github.com/hashicorp/nomad/issues/8216)]
* ui: Polling endpoints that have yet to be fetched normally works as expected (regression from 0.11.3). [[GH-8207](https://github.com/hashicorp/nomad/issues/8207)]

## 0.11.7 (November 10, 2020)

SECURITY:
* docker: _Backport from v0.12.8_ - Fixed a bug where Docker driver mounts of type "volume" (but not "bind") were not sandboxed when `docker.volumes.enabled` is set to `false`. The `docker.volumes.enabled` configuration will now disable Docker mounts with type "volume" when set to `false`. CVE-2020-28348 [[GH-9303](https://github.com/hashicorp/nomad/issues/9303)]

## 0.11.6 (October 23, 2020)

BUG FIXES:
Expand Down Expand Up @@ -386,6 +397,11 @@ BUG FIXES:
* scheduler: Fixed a bug where changes to task group `shutdown_delay` were not persisted or displayed in plan output [[GH-7618](https://github.com/hashicorp/nomad/issues/7618)]
* ui: Fixed handling of multi-byte unicode characters in allocation log view [[GH-7470](https://github.com/hashicorp/nomad/issues/7470)] [[GH-7551](https://github.com/hashicorp/nomad/pull/7551)]

## 0.10.8 (November 10, 2020)

SECURITY:
* docker: _Backport from v0.12.8_ - Fixed a bug where Docker driver mounts of type "volume" (but not "bind") were not sandboxed when `docker.volumes.enabled` is set to `false`. The `docker.volumes.enabled` configuration will now disable Docker mounts with type "volume" when set to `false`. CVE-2020-28348 [[GH-9303](https://github.com/hashicorp/nomad/issues/9303)]

## 0.10.7 (October 23, 2020)

BUG FIXES:
Expand Down
2 changes: 1 addition & 1 deletion drivers/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ var (
"volumes": hclspec.NewDefault(hclspec.NewBlock("volumes", false, hclspec.NewObject(map[string]*hclspec.Spec{
"enabled": hclspec.NewAttr("enabled", "bool", false),
"selinuxlabel": hclspec.NewAttr("selinuxlabel", "string", false),
})), hclspec.NewLiteral("{ enabled = true }")),
})), hclspec.NewLiteral("{ enabled = false }")),
"allow_privileged": hclspec.NewAttr("allow_privileged", "bool", false),
"allow_caps": hclspec.NewDefault(
hclspec.NewAttr("allow_caps", "list(string)", false),
Expand Down
17 changes: 14 additions & 3 deletions drivers/docker/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -944,12 +944,23 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T
return c, err
}

if hm.Type == "bind" {
switch hm.Type {
case "bind":
hm.Source = expandPath(task.TaskDir().Dir, hm.Source)

// paths inside alloc dir are always allowed as they mount within a container, and treated as relative to task dir
// paths inside alloc dir are always allowed as they mount within
// a container, and treated as relative to task dir
if !d.config.Volumes.Enabled && !isParentPath(task.AllocDir, hm.Source) {
return c, fmt.Errorf("volumes are not enabled; cannot mount host path: %q %q", hm.Source, task.AllocDir)
return c, fmt.Errorf(
"volumes are not enabled; cannot mount host path: %q %q",
hm.Source, task.AllocDir)
}
case "tmpfs":
// no source, so no sandbox check required
default: // "volume", but also any new thing that comes along
if !d.config.Volumes.Enabled {
return c, fmt.Errorf(
"volumes are not enabled; cannot mount volume: %q", hm.Source)
}
}

Expand Down
14 changes: 13 additions & 1 deletion drivers/docker/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2022,14 +2022,23 @@ func TestDockerDriver_VolumesEnabled(t *testing.T) {
}
testutil.DockerCompatible(t)

cfg := map[string]interface{}{
"volumes": map[string]interface{}{
"enabled": true,
},
"gc": map[string]interface{}{
"image": false,
},
}

tmpvol, err := ioutil.TempDir("", "nomadtest_docker_volumesenabled")
require.NoError(t, err)

// Evaluate symlinks so it works on MacOS
tmpvol, err = filepath.EvalSymlinks(tmpvol)
require.NoError(t, err)

task, driver, _, hostpath, cleanup := setupDockerVolumes(t, nil, tmpvol)
task, driver, _, hostpath, cleanup := setupDockerVolumes(t, cfg, tmpvol)
defer cleanup()

_, _, err = driver.StartTask(task)
Expand Down Expand Up @@ -2094,6 +2103,9 @@ func TestDockerDriver_Mounts(t *testing.T) {
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
d := dockerDriverHarness(t, nil)
driver := d.Impl().(*Driver)
driver.config.Volumes.Enabled = true

// Build the task
task, cfg, ports := dockerTask(t)
defer freeport.Return(ports)
Expand Down
4 changes: 3 additions & 1 deletion drivers/docker/driver_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,8 @@ func TestDockerDriver_MountsSerialization(t *testing.T) {
expectedMounts []docker.HostMount
}{
{
name: "basic volume",
name: "basic volume",
requiresVolumes: true,
passedMounts: []DockerMount{
{
Target: "/nomad",
Expand Down Expand Up @@ -606,6 +607,7 @@ func TestDockerDriver_CreateContainerConfig_MountsCombined(t *testing.T) {

dh := dockerDriverHarness(t, nil)
driver := dh.Impl().(*Driver)
driver.config.Volumes.Enabled = true

c, err := driver.createContainerConfig(task, cfg, "org/repo:0.1")
require.NoError(t, err)
Expand Down
110 changes: 110 additions & 0 deletions website/pages/docs/upgrade/upgrade-specific.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,44 @@ the time of the upgrade for each node will ensure Connect workloads are properly
rescheduled onto nodes in such a way that the Nomad Clients, Consul agents, and
Envoy sidecar tasks maintain compatibility with one another.

## Nomad 0.12.8

### Docker volume mounts

Nomad 0.12.8 includes security fixes for the handling of Docker volume mounts:

- The `docker.volumes.enabled` flag now defaults to `false` as documented.
- Docker driver mounts of type "volume" (but not "bind") were not sandboxed
and could mount arbitrary locations from the client host. The
`docker.volumes.enabled` configuration will now disable Docker mounts with
type "volume" when set to `false` (the default).

This change Docker impacts jobs that use a `mounts` with type "volume", as
shown below. This job will fail when placed unless `docker.volumes.enabled =
true`.

```hcl
mounts = [
{
type = "volume"
target = "/path/in/container"
source = "docker_volume"
volume_options = {
driver_config = {
name = "local"
options = [
{
device = "/"
o = "ro,bind"
type = "ext4"
}
]
}
}
}
]
```

## Nomad 0.12.6

### Artifact and Template Paths
Expand Down Expand Up @@ -193,6 +231,42 @@ plugin "qemu" {
}
```

## Nomad 0.11.7

### Docker volume mounts

Nomad 0.11.7 includes a security fix for the handling of Docker volume
mounts. Docker driver mounts of type "volume" (but not "bind") were not
sandboxed and could mount arbitrary locations from the client host. The
`docker.volumes.enabled` configuration will now disable Docker mounts with
type "volume" when set to `false`.

This change Docker impacts jobs that use a `mounts` with type "volume", as
shown below. This job will fail when placed unless `docker.volumes.enabled =
true`.

```hcl
mounts = [
{
type = "volume"
target = "/path/in/container"
source = "docker_volume"
volume_options = {
driver_config = {
name = "local"
options = [
{
device = "/"
o = "ro,bind"
type = "ext4"
}
]
}
}
}
]
```

## Nomad 0.11.5

### Artifact and Template Paths
Expand Down Expand Up @@ -273,6 +347,42 @@ it will not be maintained as `rkt` is [no longer being developed
upstream](https://github.com/rkt/rkt). We encourage all `rkt` users to find a
new task driver as soon as possible.

## Nomad 0.10.8

### Docker volume mounts

Nomad 0.10.8 includes a security fix for the handling of Docker volume
mounts. Docker driver mounts of type "volume" (but not "bind") were not
sandboxed and could mount arbitrary locations from the client host. The
`docker.volumes.enabled` configuration will now disable Docker mounts with
type "volume" when set to `false`.

This change Docker impacts jobs that use a `mounts` with type "volume", as
shown below. This job will fail when placed unless `docker.volumes.enabled =
true`.

```hcl
mounts = [
{
type = "volume"
target = "/path/in/container"
source = "docker_volume"
volume_options = {
driver_config = {
name = "local"
options = [
{
device = "/"
o = "ro,bind"
type = "ext4"
}
]
}
}
}
]
```

## Nomad 0.10.6

### Artifact and Template Paths
Expand Down

0 comments on commit 306cfab

Please sign in to comment.