Skip to content

Commit 749c879

Browse files
committed
mounts: prohibit relative paths in YAML
Relative paths are still allowed in CLI: `limactl create --mount=DIR` Fix issue 3948 Signed-off-by: Akihiro Suda <[email protected]>
1 parent 55754da commit 749c879

File tree

4 files changed

+74
-7
lines changed

4 files changed

+74
-7
lines changed

cmd/limactl/editflags/editflags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/spf13/cobra"
1717
flag "github.com/spf13/pflag"
1818

19+
"github.com/lima-vm/lima/v2/pkg/localpathutil"
1920
"github.com/lima-vm/lima/v2/pkg/registry"
2021
)
2122

@@ -174,6 +175,10 @@ func buildMountListExpression(ss []string) (string, error) {
174175
for i, s := range ss {
175176
writable := strings.HasSuffix(s, ":w")
176177
loc := strings.TrimSuffix(s, ":w")
178+
loc, err := localpathutil.Expand(loc)
179+
if err != nil {
180+
return "", err
181+
}
177182
expr += fmt.Sprintf(`{"location": %q, "writable": %v}`, loc, writable)
178183
if i < len(ss)-1 {
179184
expr += ","

cmd/limactl/editflags/editflags_test.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
package editflags
55

66
import (
7+
"strings"
78
"testing"
89

910
"github.com/spf13/cobra"
1011
"gotest.tools/v3/assert"
12+
13+
"github.com/lima-vm/lima/v2/pkg/localpathutil"
1114
)
1215

1316
func TestCompleteCPUs(t *testing.T) {
@@ -160,6 +163,13 @@ func TestParsePortForward(t *testing.T) {
160163
}
161164

162165
func TestYQExpressions(t *testing.T) {
166+
expand := func(s string) string {
167+
s, err := localpathutil.Expand(s)
168+
assert.NilError(t, err)
169+
// `D:\foo` -> `D:\\foo` (appears in YAML)
170+
s = strings.ReplaceAll(s, "\\", "\\\\")
171+
return s
172+
}
163173
tests := []struct {
164174
name string
165175
args []string
@@ -169,15 +179,15 @@ func TestYQExpressions(t *testing.T) {
169179
}{
170180
{
171181
name: "mount",
172-
args: []string{"--mount", "/foo", "--mount", "/bar:w"},
182+
args: []string{"--mount", "/foo", "--mount", "./bar:w"},
173183
newInstance: false,
174-
expected: []string{`.mounts += [{"location": "/foo", "writable": false},{"location": "/bar", "writable": true}] | .mounts |= unique_by(.location)`},
184+
expected: []string{`.mounts += [{"location": "` + expand("/foo") + `", "writable": false},{"location": "` + expand("./bar") + `", "writable": true}] | .mounts |= unique_by(.location)`},
175185
},
176186
{
177187
name: "mount-only",
178188
args: []string{"--mount-only", "/foo", "--mount-only", "/bar:w"},
179189
newInstance: false,
180-
expected: []string{`.mounts = [{"location": "/foo", "writable": false},{"location": "/bar", "writable": true}]`},
190+
expected: []string{`.mounts = [{"location": "` + expand("/foo") + `", "writable": false},{"location": "` + expand("/bar") + `", "writable": true}]`},
181191
},
182192
{
183193
name: "mixture of mount and mount-only",

pkg/limayaml/defaults.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,14 @@ func FillDefault(ctx context.Context, y, d, o *limatype.LimaYAML, filePath strin
713713
mounts[i].NineP.Cache = ptr.Of(Default9pCacheForRO)
714714
}
715715
}
716-
if location, err := localpathutil.Expand(mount.Location); err == nil {
717-
mounts[i].Location = location
718-
} else {
719-
logrus.WithError(err).Warnf("Couldn't expand location %q", mount.Location)
716+
717+
// Expand a path that begins with `~`. Relative paths are not modified, and rejected by Validate() later.
718+
if localpathutil.IsTildePath(mount.Location) {
719+
if location, err := localpathutil.Expand(mount.Location); err == nil {
720+
mounts[i].Location = location
721+
} else {
722+
logrus.WithError(err).Warnf("Couldn't expand location %q", mount.Location)
723+
}
720724
}
721725
if mount.MountPoint == nil {
722726
mountLocation := mounts[i].Location

pkg/limayaml/validate_unix_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//go:build !windows
2+
3+
// SPDX-FileCopyrightText: Copyright The Lima Authors
4+
// SPDX-License-Identifier: Apache-2.0
5+
6+
package limayaml
7+
8+
import (
9+
"testing"
10+
11+
"gotest.tools/v3/assert"
12+
)
13+
14+
func TestValidateMounts(t *testing.T) {
15+
yBase := `images: [{"location": "/dummy"}]`
16+
tests := []struct {
17+
name string
18+
mounts string
19+
skipOnWindows bool
20+
wantErr string
21+
}{
22+
{
23+
name: "Valid",
24+
mounts: `mounts: [{location: "/foo", writable: false}, {location: "~/foo", writable: true}]`,
25+
wantErr: "",
26+
},
27+
{
28+
name: "Invalid (relative)",
29+
mounts: `mounts: [{location: ".", writable: false}]`,
30+
wantErr: func() string {
31+
return "must be an absolute path"
32+
}(),
33+
},
34+
}
35+
36+
for _, tt := range tests {
37+
t.Run(tt.name, func(t *testing.T) {
38+
y, err := Load(t.Context(), []byte(yBase+"\n"+tt.mounts), "lima.yaml")
39+
assert.NilError(t, err)
40+
err = Validate(y, false)
41+
if tt.wantErr != "" {
42+
assert.ErrorContains(t, err, tt.wantErr)
43+
} else {
44+
assert.NilError(t, err)
45+
}
46+
})
47+
}
48+
}

0 commit comments

Comments
 (0)