Skip to content

Commit 95c43cd

Browse files
committed
prepareBindMounts must not modify files outside of the jail
Since m.HostPath could take arbitrary strings, the result of filepath.Join() could point files outside of the jail (j.RootPath). Signed-off-by: Kazuyoshi Kato <[email protected]>
1 parent d7eeea7 commit 95c43cd

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

runtime/runc_jailer.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"syscall"
2626
"time"
2727

28+
"github.com/containerd/continuity/fs"
2829
"github.com/containerd/go-runc"
2930
"github.com/hashicorp/go-multierror"
3031
"github.com/opencontainers/runtime-spec/specs-go"
@@ -144,7 +145,11 @@ func (j *runcJailer) prepareBindMounts(mounts []*proto.FirecrackerDriveMount) er
144145
// Only bindMount regular file.
145146
// To avoid duplicate files, for block device, we will use system call to create device file for it.
146147
if stat.Mode&syscall.S_IFMT == syscall.S_IFREG {
147-
err := j.bindMountFileToJail(m.HostPath, filepath.Join(j.RootPath(), m.HostPath))
148+
dest, err := fs.RootPath(j.RootPath(), m.HostPath)
149+
if err != nil {
150+
return err
151+
}
152+
err = j.bindMountFileToJail(m.HostPath, dest)
148153
if err != nil {
149154
return err
150155
}

runtime/runc_jailer_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,57 @@ func TestFifoHandler(t *testing.T) {
223223
})
224224
}
225225
}
226+
227+
func TestPrepareBindMount(t *testing.T) {
228+
// Because of chown(2).
229+
internal.RequiresRoot(t)
230+
231+
t.Run("no mounts", func(t *testing.T) {
232+
j := &runcJailer{}
233+
err := j.prepareBindMounts([]*proto.FirecrackerDriveMount{})
234+
require.NoError(t, err)
235+
})
236+
237+
dir, err := ioutil.TempDir("", t.Name())
238+
require.NoError(t, err)
239+
defer os.RemoveAll(dir)
240+
241+
j := &runcJailer{Config: runcJailerConfig{
242+
OCIBundlePath: filepath.Join(dir, "bundle"),
243+
UID: 1234,
244+
GID: 5678,
245+
}}
246+
247+
err = ioutil.WriteFile(dir+"/foobar", []byte("hello"), 0700)
248+
require.NoError(t, err)
249+
250+
testcases := []struct {
251+
name string
252+
hostPath string
253+
}{
254+
{
255+
name: "absolute path",
256+
hostPath: dir + "/foobar",
257+
},
258+
{
259+
name: "use dots to access the original directory",
260+
hostPath: "/../../../../../.." + dir + "/foobar",
261+
},
262+
}
263+
for _, tc := range testcases {
264+
t.Run(tc.name, func(t *testing.T) {
265+
err = j.prepareBindMounts([]*proto.FirecrackerDriveMount{{
266+
HostPath: tc.hostPath,
267+
FilesystemType: "ext4",
268+
VMPath: "/mnt",
269+
}})
270+
require.NoError(t, err)
271+
stat, err := os.Stat(dir)
272+
require.NoError(t, err)
273+
274+
s := stat.Sys().(*syscall.Stat_t)
275+
assert.Equal(t, 0, int(s.Uid), "UID")
276+
assert.Equal(t, 0, int(s.Gid), "GID")
277+
})
278+
}
279+
}

0 commit comments

Comments
 (0)