in runtime/runc_jailer.go [213:303]
func (j *runcJailer) BuildJailedRootHandler(cfg *config.Config, machineConfig *firecracker.Config, vmID string) firecracker.Handler {
ociBundlePath := j.OCIBundlePath()
rootPath := j.RootPath()
machineConfig.SocketPath = filepath.Join(rootfsFolder, "api.socket")
return firecracker.Handler{
Name: jailerHandlerName,
Fn: func(ctx context.Context, m *firecracker.Machine) error {
rootPathToConfig := filepath.Join(ociBundlePath, "config.json")
j.logger.WithField("rootPathToConfig", rootPathToConfig).Debug("Copying config")
if err := copyFile(j.Config.RuncConfigPath, rootPathToConfig, 0400); err != nil {
return errors.Wrapf(err, "failed to copy config from %v to %v", j.Config.RuncConfigPath, rootPathToConfig)
}
// copy the firecracker binary
j.logger.WithField("root path", rootPath).Debug("copying firecracker binary")
newFirecrackerBinPath := filepath.Join(rootPath, firecrackerFileName)
if err := j.copyFileToJail(cfg.FirecrackerBinaryPath, newFirecrackerBinPath, 0500); err != nil {
return err
}
// copy the kernel image
newKernelImagePath := filepath.Join(rootPath, kernelImageFileName)
j.logger.WithField("newKernelImagePath", newKernelImagePath).Debug("copying kernel image")
if err := j.copyFileToJail(m.Cfg.KernelImagePath, newKernelImagePath, 0400); err != nil {
return err
}
m.Cfg.KernelImagePath = kernelImageFileName
// copy drives to new contents path
for i, d := range m.Cfg.Drives {
drivePath := firecracker.StringValue(d.PathOnHost)
fileName := filepath.Base(drivePath)
newDrivePath := filepath.Join(rootPath, fileName)
f, err := os.Open(drivePath)
if err != nil {
return errors.Wrap(err, "failed to open drive file")
}
// This closes the file in the event an error occurred, otherwise we
// call close down below.
defer f.Close()
if !internal.IsStubDrive(f) {
mode := 0600
if firecracker.BoolValue(d.IsReadOnly) {
mode = 0400
}
if err := j.exposeFileToJail(drivePath, newDrivePath, os.FileMode(mode)); err != nil {
return err
}
}
if err := f.Close(); err != nil {
j.logger.WithError(err).Debug("failed to close drive file")
}
j.logger.WithField("drive", newDrivePath).Debug("Adding drive")
m.Cfg.Drives[i].PathOnHost = firecracker.String(fileName)
}
// Setting the proper path to where the vsock path should be
for i, v := range m.Cfg.VsockDevices {
j.logger.WithField("vsock path", v.Path).Debug("vsock device path being set relative to jailed directory")
filename := filepath.Base(v.Path)
v.Path = filepath.Join("/", filename)
m.Cfg.VsockDevices[i] = v
}
if err := j.setupCacheTopology(rootPath); err != nil {
return err
}
j.logger.Debugf("Writing %q for runc", rootPathToConfig)
// we pass m.Cfg as opposed to machineConfig as we want the populated
// config defaults when calling NewMachine
if err := j.overwriteConfig(&m.Cfg, filepath.Base(m.Cfg.SocketPath), rootPathToConfig); err != nil {
return errors.Wrap(err, "failed to overwrite config.json")
}
j.logger.Info("Successfully ran jailer handler")
j.started = true
return nil
},
}
}