Skip to content

Commit

Permalink
Remove colons in VOLUME mappings on Windows.
Browse files Browse the repository at this point in the history
Attempting to run Windows images with VOLUME declarations which are
absolute paths would lead to `securejoin.SecureJoin()` concatenating
two absolute paths when determining the host mount dir and then
failing to `os.Lstat()` the resulting path, as it contained an
illegal second `:`.

Signed-off-by: Nashwan Azhari <nazhari@cloudbasesolutions.com>
  • Loading branch information
aznashwan committed Apr 6, 2023
1 parent 1525035 commit 8f2940e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
5 changes: 2 additions & 3 deletions cmd/nerdctl/container_run_mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import (
"github.com/containerd/nerdctl/pkg/mountutil"
"github.com/containerd/nerdctl/pkg/mountutil/volumestore"
"github.com/containerd/nerdctl/pkg/strutil"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/opencontainers/image-spec/identity"
"github.com/opencontainers/runtime-spec/specs-go"

Expand Down Expand Up @@ -228,7 +227,7 @@ func generateMountOpts(ctx context.Context, cmd *cobra.Command, client *containe
ociMounts[i] = x.Mount
mounted[filepath.Clean(x.Mount.Destination)] = struct{}{}

target, err := securejoin.SecureJoin(tempDir, x.Mount.Destination)
target, err := joinHostPath(tempDir, x.Mount.Destination)
if err != nil {
return nil, nil, nil, err
}
Expand Down Expand Up @@ -269,7 +268,7 @@ func generateMountOpts(ctx context.Context, cmd *cobra.Command, client *containe
return nil, nil, nil, err
}

target, err := securejoin.SecureJoin(tempDir, imgVol)
target, err := joinHostPath(tempDir, imgVol)
if err != nil {
return nil, nil, nil, err
}
Expand Down
30 changes: 30 additions & 0 deletions cmd/nerdctl/container_run_mount_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build !windows

/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
securejoin "github.com/cyphar/filepath-securejoin"
)

// Joins the given host path with the given guest path while guaranteeing the provided
// path is scoped within the host path. (i.e. joining with `../..` or symlinks cannot
// lead to a higher level path than the provided hostPath, and are simply ignored)
func joinHostPath(hostPath string, guestPath string) (string, error) {
return securejoin.SecureJoin(hostPath, guestPath)
}
40 changes: 40 additions & 0 deletions cmd/nerdctl/container_run_mount_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"path/filepath"
"strings"

securejoin "github.com/cyphar/filepath-securejoin"
)

// Joins the given host path with the given guest path while guaranteeing the provided
// path is scoped within the host path. (i.e. joining with `../..` or symlinks cannot
// lead to a higher level path than the provided hostPath, and are simply ignored)
// Any colons in the guest path will be removed completely in order to have a valid
// host path while maining the guest path's drive letter.
func joinHostPath(hostPath string, guestPath string) (string, error) {
if filepath.IsAbs(guestPath) {
// NOTE: both `filepath.Join()` and `securepath.SecureJoin()` concatenate
// absolute paths on Windows, so we must check and substitute the imfVol drive.
// This will lead to SecureJoin("C:\c1\c2", "D\d1\d2") => "C:\c1\c2\D\d1\d2".
guestPath = strings.ReplaceAll(guestPath, ":", "")
}

return securejoin.SecureJoin(hostPath, guestPath)
}

0 comments on commit 8f2940e

Please sign in to comment.