Skip to content

Commit 3b103d5

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 a3f3a60 commit 3b103d5

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-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_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,3 +429,38 @@ func TestValidateAgainstLatestConfig(t *testing.T) {
429429
})
430430
}
431431
}
432+
433+
func TestValidateMounts(t *testing.T) {
434+
yBase := `images: [{"location": "/dummy"}]`
435+
tests := []struct {
436+
name string
437+
mounts string
438+
wantErr string
439+
}{
440+
{
441+
name: "Valid",
442+
mounts: `mounts: [{location: "/foo", writable: false}, {location: "~/foo", writable: true}]`,
443+
wantErr: "",
444+
},
445+
{
446+
name: "Invalid (relative)",
447+
mounts: `mounts: [{location: ".", writable: false}]`,
448+
wantErr: func() string {
449+
return "must be an absolute path"
450+
}(),
451+
},
452+
}
453+
454+
for _, tt := range tests {
455+
t.Run(tt.name, func(t *testing.T) {
456+
y, err := Load(t.Context(), []byte(yBase+"\n"+tt.mounts), "lima.yaml")
457+
assert.NilError(t, err)
458+
err = Validate(y, false)
459+
if tt.wantErr != "" {
460+
assert.ErrorContains(t, err, tt.wantErr)
461+
} else {
462+
assert.NilError(t, err)
463+
}
464+
})
465+
}
466+
}

0 commit comments

Comments
 (0)