Skip to content

Commit 2077faa

Browse files
Merge pull request #25466 from baude/issue18230
Do not allow mounting to machine dir /tmp
2 parents b0077e0 + 5283f95 commit 2077faa

File tree

4 files changed

+121
-5
lines changed

4 files changed

+121
-5
lines changed

docs/source/markdown/podman-machine-init.1.md.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ options are:
149149
* **rw**: mount volume read/write (default)
150150
* **security_model=[model]**: specify 9p security model (see below)
151151

152+
Note: The following destinations are forbidden for volumes: `/bin`, `/boot`, `/dev`, `/etc`,
153+
`/home`, `/proc`, `/root`, `/run`, `/sbin`, `/sys`, `/tmp`, `/usr`, and `/var`. Subdirectories
154+
of these destinations are allowed but users should be careful to not mount to important directories
155+
as unexpected results may occur.
156+
157+
152158
The 9p security model [determines] https://wiki.qemu.org/Documentation/9psetup#Starting_the_Guest_directly
153159
if and how the 9p filesystem translates some filesystem operations before
154160
actual storage on the host.

pkg/machine/e2e/init_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,23 @@ var _ = Describe("podman machine init", func() {
7979
Expect(badMemSession).To(Exit(125))
8080
})
8181

82+
It("init volume check", func() {
83+
skipIfWSL("WSL does not use volume mounts")
84+
// Check that mounting to certain target directories like /tmp at the / level is NOT ok
85+
tmpVol := initMachine{}
86+
targetMount := "/tmp"
87+
tmpVolSession, err := mb.setCmd(tmpVol.withVolume(fmt.Sprintf("/whatever:%s", targetMount))).run()
88+
Expect(err).ToNot(HaveOccurred())
89+
Expect(tmpVolSession).To(Exit(125))
90+
Expect(tmpVolSession.errorToString()).To(ContainSubstring(fmt.Sprintf("Error: machine mount destination cannot be %q: consider another location or a subdirectory of an existing location", targetMount)))
91+
92+
// Mounting to /tmp/foo (subdirectory) is OK
93+
tmpSubdir := initMachine{}
94+
tmpSubDirSession, err := mb.setCmd(tmpSubdir.withVolume("/whatever:/tmp/foo")).run()
95+
Expect(err).ToNot(HaveOccurred())
96+
Expect(tmpSubDirSession).To(Exit(0))
97+
})
98+
8299
It("simple init", func() {
83100
i := new(initMachine)
84101
session, err := mb.setCmd(i.withImage(mb.imagePath)).run()

pkg/machine/shim/host.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"os"
9+
"path"
910
"path/filepath"
1011
"runtime"
1112
"strings"
@@ -118,6 +119,18 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) error {
118119
createOpts.UserModeNetworking = *umn
119120
}
120121

122+
// Mounts
123+
if mp.VMType() != machineDefine.WSLVirt {
124+
mc.Mounts = CmdLineVolumesToMounts(opts.Volumes, mp.MountType())
125+
}
126+
127+
// Issue #18230 ... do not mount over important directories at the / level (subdirs are fine)
128+
for _, mnt := range mc.Mounts {
129+
if err := validateDestinationPaths(mnt.Target); err != nil {
130+
return err
131+
}
132+
}
133+
121134
// Get Image
122135
// TODO This needs rework bigtime; my preference is most of below of not living in here.
123136
// ideally we could get a func back that pulls the image, and only do so IF everything works because
@@ -251,11 +264,6 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) error {
251264
}
252265
ignBuilder.WithUnit(readyUnit)
253266

254-
// Mounts
255-
if mp.VMType() != machineDefine.WSLVirt {
256-
mc.Mounts = CmdLineVolumesToMounts(opts.Volumes, mp.MountType())
257-
}
258-
259267
// TODO AddSSHConnectionToPodmanSocket could take an machineconfig instead
260268
if err := connection.AddSSHConnectionsToPodmanSocket(mc.HostUser.UID, mc.SSH.Port, mc.SSH.IdentityPath, mc.Name, mc.SSH.RemoteUsername, opts); err != nil {
261269
return err
@@ -774,3 +782,27 @@ func Reset(mps []vmconfigs.VMProvider, opts machine.ResetOptions) error {
774782
}
775783
return resetErrors.ErrorOrNil()
776784
}
785+
786+
func validateDestinationPaths(dest string) error {
787+
// illegalMounts are locations at the / level of the podman machine where we do want users mounting directly over
788+
illegalMounts := map[string]struct{}{
789+
"/bin": {},
790+
"/boot": {},
791+
"/dev": {},
792+
"/etc": {},
793+
"/home": {},
794+
"/proc": {},
795+
"/root": {},
796+
"/run": {},
797+
"/sbin": {},
798+
"/sys": {},
799+
"/tmp": {},
800+
"/usr": {},
801+
"/var": {},
802+
}
803+
mountTarget := path.Clean(dest)
804+
if _, ok := illegalMounts[mountTarget]; ok {
805+
return fmt.Errorf("machine mount destination cannot be %q: consider another location or a subdirectory of an existing location", mountTarget)
806+
}
807+
return nil
808+
}

pkg/machine/shim/host_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package shim
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_validateDestinationPaths(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
dest string
13+
wantErr bool
14+
}{
15+
{
16+
name: "Expect fail - /tmp",
17+
dest: "/tmp",
18+
wantErr: true,
19+
},
20+
{
21+
name: "Expect fail trailing /",
22+
dest: "/tmp/",
23+
wantErr: true,
24+
},
25+
{
26+
name: "Expect fail double /",
27+
dest: "//tmp",
28+
wantErr: true,
29+
},
30+
{
31+
name: "/var should fail",
32+
dest: "/var",
33+
wantErr: true,
34+
},
35+
{
36+
name: "/etc should fail",
37+
dest: "/etc",
38+
wantErr: true,
39+
},
40+
{
41+
name: "/tmp subdir OK",
42+
dest: "/tmp/foobar",
43+
wantErr: false,
44+
},
45+
{
46+
name: "/foobar OK",
47+
dest: "/foobar",
48+
wantErr: false,
49+
},
50+
}
51+
for _, tt := range tests {
52+
t.Run(tt.name, func(t *testing.T) {
53+
err := validateDestinationPaths(tt.dest)
54+
if tt.wantErr {
55+
assert.ErrorContainsf(t, err, "onsider another location or a subdirectory of an existing location", "illegal mount target")
56+
} else {
57+
assert.NoError(t, err, "mounts to subdirs or non-critical dirs should succeed")
58+
}
59+
})
60+
}
61+
}

0 commit comments

Comments
 (0)