Skip to content

Commit 9f0eb50

Browse files
committed
Integrate drive mounts with jailer.
The primary change required is for the Jailer to support exposing regular files to the jail in addition to the pre-existing support for block devices. Signed-off-by: Erik Sipsma <[email protected]>
1 parent 58a2d94 commit 9f0eb50

File tree

5 files changed

+47
-22
lines changed

5 files changed

+47
-22
lines changed

runtime/jailer.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ type jailer interface {
4747
// firecracker.Opt to be passed into firecracker.NewMachine which will allow
4848
// for the VM to be jailed.
4949
BuildJailedMachine(cfg *Config, machineCfg *firecracker.Config, vmID string) ([]firecracker.Opt, error)
50-
// ExposeDeviceToJail will expose the given device provided by the snapshotter
51-
// to the jailed filesystem
52-
ExposeDeviceToJail(path string) error
50+
// ExposeFileToJail will expose the given file to the jailed filesystem, including
51+
// regular files and block devices. An error is returned if provided a path to a file
52+
// with type that is not supported.
53+
ExposeFileToJail(path string) error
5354
// JailPath is used to return the directory we are supposed to be working in.
5455
JailPath() vm.Dir
5556
// StubDrivesOptions will return a set of options used to create a new stub

runtime/noop_jailer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ func (j noopJailer) JailPath() vm.Dir {
6363
return j.shimDir
6464
}
6565

66-
func (j noopJailer) ExposeDeviceToJail(path string) error {
67-
j.logger.Debug("noop operation for ExposeDeviceToJail")
66+
func (j noopJailer) ExposeFileToJail(path string) error {
67+
j.logger.Debug("noop operation for ExposeFileToJail")
6868
return nil
6969
}
7070

runtime/runc_jailer.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,33 +253,49 @@ func (j runcJailer) StubDrivesOptions() []stubDrivesOpt {
253253
}
254254
}
255255

256-
// ExposeDeviceToJail will inspect the given file, srcDevicePath, and based on the
256+
// ExposeFileToJail will inspect the given file, srcPath, and based on the
257257
// file type, proper handling will occur to ensure that the file is visible in
258258
// the jail. For block devices we will use mknod to create the device and then
259-
// set the correct permissions to ensure visibility in the jail.
260-
func (j runcJailer) ExposeDeviceToJail(srcDevicePath string) error {
259+
// set the correct permissions to ensure visibility in the jail. Regular files
260+
// will be copied into the jail.
261+
func (j runcJailer) ExposeFileToJail(srcPath string) error {
261262
uid := j.uid
262263
gid := j.gid
263264

264265
stat := syscall.Stat_t{}
265-
if err := syscall.Stat(srcDevicePath, &stat); err != nil {
266+
if err := syscall.Stat(srcPath, &stat); err != nil {
266267
return err
267268
}
268269

269270
// Checks file type using S_IFMT which is the bit mask for the file type.
270-
// Here we only care about block devices, ie S_IFBLK. If it is a block type
271-
// we will manually call mknod and create that device.
272-
if (stat.Mode & syscall.S_IFMT) == syscall.S_IFBLK {
273-
path := filepath.Join(j.RootPath(), filepath.Dir(srcDevicePath))
274-
if err := mkdirAllWithPermissions(path, 0700, uid, gid); err != nil {
271+
switch stat.Mode & syscall.S_IFMT {
272+
case syscall.S_IFBLK:
273+
parentDir := filepath.Join(j.RootPath(), filepath.Dir(srcPath))
274+
if err := mkdirAllWithPermissions(parentDir, 0700, uid, gid); err != nil {
275275
return err
276276
}
277277

278-
dst := filepath.Join(path, filepath.Base(srcDevicePath))
278+
dst := filepath.Join(parentDir, filepath.Base(srcPath))
279279
if err := exposeBlockDeviceToJail(dst, int(stat.Rdev), int(uid), int(gid)); err != nil {
280280
return err
281281
}
282-
} else {
282+
283+
case syscall.S_IFREG:
284+
parentDir := filepath.Join(j.RootPath(), filepath.Dir(srcPath))
285+
if err := mkdirAllWithPermissions(parentDir, 0700, uid, gid); err != nil {
286+
return err
287+
}
288+
289+
dst := filepath.Join(parentDir, filepath.Base(srcPath))
290+
if err := copyFile(srcPath, dst, os.FileMode(stat.Mode)); err != nil {
291+
return err
292+
}
293+
294+
if err := os.Chown(dst, int(uid), int(gid)); err != nil {
295+
return err
296+
}
297+
298+
default:
283299
return fmt.Errorf("unsupported mode: %v", stat.Mode)
284300
}
285301

runtime/service.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,11 @@ func (s *service) createVM(requestCtx context.Context, request *proto.CreateVMRe
524524

525525
func (s *service) mountDrives(requestCtx context.Context, driveMounts []*proto.FirecrackerDriveMount) error {
526526
for _, driveMount := range driveMounts {
527+
err := s.jailer.ExposeFileToJail(driveMount.HostPath)
528+
if err != nil {
529+
return errors.Wrapf(err, "failed to expose drive mount host path to jail %s", driveMount.HostPath)
530+
}
531+
527532
driveID, err := s.stubDriveHandler.PatchStubDrive(requestCtx, s.machine, driveMount.HostPath)
528533
if err != nil {
529534
return errors.Wrapf(err, "failed to patch drive mount stub")
@@ -768,7 +773,7 @@ func (s *service) Create(requestCtx context.Context, request *taskAPI.CreateTask
768773
}
769774

770775
for _, mnt := range request.Rootfs {
771-
if err := s.jailer.ExposeDeviceToJail(mnt.Source); err != nil {
776+
if err := s.jailer.ExposeFileToJail(mnt.Source); err != nil {
772777
return nil, errors.Wrapf(err, "failed to expose mount to jail %v", mnt.Source)
773778
}
774779

runtime/service_integ_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,9 @@ func TestCreateTooManyContainers_Isolated(t *testing.T) {
833833
}
834834

835835
func TestDriveMount_Isolated(t *testing.T) {
836-
prepareIntegTest(t)
836+
prepareIntegTest(t, func(cfg *Config) {
837+
cfg.JailerConfig.RuncBinaryPath = "/usr/local/bin/runc"
838+
})
837839

838840
testTimeout := 120 * time.Second
839841
ctx, cancel := context.WithTimeout(namespaces.WithNamespace(context.Background(), defaultNamespace), testTimeout)
@@ -845,7 +847,7 @@ func TestDriveMount_Isolated(t *testing.T) {
845847
fcClient, err := fcClient.New(containerdSockPath + ".ttrpc")
846848
require.NoError(t, err, "failed to create fccontrol client")
847849

848-
image, err := alpineImage(ctx, ctrdClient, naiveSnapshotterName)
850+
image, err := alpineImage(ctx, ctrdClient, defaultSnapshotterName())
849851
require.NoError(t, err, "failed to get alpine image")
850852

851853
vmID := "test-drive-mount"
@@ -903,8 +905,9 @@ func TestDriveMount_Isolated(t *testing.T) {
903905
}
904906

905907
_, err = fcClient.CreateVM(ctx, &proto.CreateVMRequest{
906-
VMID: vmID,
907-
DriveMounts: vmDriveMounts,
908+
VMID: vmID,
909+
DriveMounts: vmDriveMounts,
910+
JailerConfig: &proto.JailerConfig{},
908911
})
909912
require.NoError(t, err, "failed to create vm")
910913

@@ -913,7 +916,7 @@ func TestDriveMount_Isolated(t *testing.T) {
913916

914917
newContainer, err := ctrdClient.NewContainer(ctx,
915918
containerName,
916-
containerd.WithSnapshotter(naiveSnapshotterName),
919+
containerd.WithSnapshotter(defaultSnapshotterName()),
917920
containerd.WithNewSnapshot(snapshotName, image),
918921
containerd.WithNewSpec(
919922
oci.WithProcessArgs("/bin/sh", "-c", strings.Join(append(ctrCatCommands,

0 commit comments

Comments
 (0)