Skip to content

Commit

Permalink
VM: Use virtiofsd chroot sandbox mode on pre pidfd_open kernels (cano…
Browse files Browse the repository at this point in the history
…nical#13794)

Otherwise virtiofsd doesn't start and this causes VMs to hang on start
up when used on Ubuntu 18.04 generic kernels (4.15) with QEMU >= 8.0
(which replaced the bundled virtiofsd with an external one written in
rust which defaults to namespace sandbox mode relying on pidfd_open
syscall).

Fixes canonical#12856

Tested on Ubuntu 18.04 4.15 kernel and Ubuntu 22.04 6.5 HWE kernel.
  • Loading branch information
tomponline authored Jul 22, 2024
2 parents 523d045 + b358527 commit c0d6d24
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 4 deletions.
16 changes: 14 additions & 2 deletions lxd/device/device_utils_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/canonical/lxd/shared"
"github.com/canonical/lxd/shared/osarch"
"github.com/canonical/lxd/shared/revert"
"github.com/canonical/lxd/shared/version"
)

// RBDFormatPrefix is the prefix used in disk paths to identify RBD.
Expand Down Expand Up @@ -424,7 +425,7 @@ func DiskVMVirtfsProxyStop(pidPath string) error {
// Returns UnsupportedError error if the host system or instance does not support virtiosfd, returns normal error
// type if process cannot be started for other reasons.
// Returns revert function and listener file handle on success.
func DiskVMVirtiofsdStart(execPath string, inst instance.Instance, socketPath string, pidPath string, logPath string, sharePath string, idmaps []idmap.IdmapEntry) (func(), net.Listener, error) {
func DiskVMVirtiofsdStart(kernelVersion version.DottedVersion, inst instance.Instance, socketPath string, pidPath string, logPath string, sharePath string, idmaps []idmap.IdmapEntry) (func(), net.Listener, error) {
revert := revert.New()
defer revert.Fail()

Expand Down Expand Up @@ -502,7 +503,18 @@ func DiskVMVirtiofsdStart(execPath string, inst instance.Instance, socketPath st
defer func() { _ = unixFile.Close() }()

// Start the virtiofsd process in non-daemon mode.
args := []string{"--fd=3", "-o", fmt.Sprintf("source=%s", sharePath)}
args := []string{
"--fd=3",
"-o", fmt.Sprintf("source=%s", sharePath),
}

// Virtiofsd defaults to namespace sandbox mode which requires pidfd_open support.
// This was added in Linux 5.3, so if running an earlier kernel fallback to chroot sandbox mode.
minVer, _ := version.NewDottedVersion("5.3.0")
if kernelVersion.Compare(minVer) < 0 {
args = append(args, "--sandbox=chroot")
}

proc, err := subprocess.NewProcess(cmd, args, logPath, logPath)
if err != nil {
return nil, nil, err
Expand Down
2 changes: 1 addition & 1 deletion lxd/device/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@ func (d *disk) startVM() (*deviceConfig.RunConfig, error) {
logPath := filepath.Join(d.inst.LogPath(), fmt.Sprintf("disk.%s.log", filesystem.PathNameEncode(d.name)))
_ = os.Remove(logPath) // Remove old log if needed.

revertFunc, unixListener, err := DiskVMVirtiofsdStart(d.state.OS.ExecPath, d.inst, sockPath, pidPath, logPath, mount.DevPath, rawIDMaps)
revertFunc, unixListener, err := DiskVMVirtiofsdStart(d.state.OS.KernelVersion, d.inst, sockPath, pidPath, logPath, mount.DevPath, rawIDMaps)
if err != nil {
var errUnsupported UnsupportedError
if errors.As(err, &errUnsupported) {
Expand Down
2 changes: 1 addition & 1 deletion lxd/instance/drivers/driver_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,7 @@ func (d *qemu) start(stateful bool, op *operationlock.InstanceOperation) error {
// This is used by the lxd-agent in preference to 9p (due to its improved performance) and in scenarios
// where 9p isn't available in the VM guest OS.
configSockPath, configPIDPath := d.configVirtiofsdPaths()
revertFunc, unixListener, err := device.DiskVMVirtiofsdStart(d.state.OS.ExecPath, d, configSockPath, configPIDPath, "", configMntPath, nil)
revertFunc, unixListener, err := device.DiskVMVirtiofsdStart(d.state.OS.KernelVersion, d, configSockPath, configPIDPath, "", configMntPath, nil)
if err != nil {
var errUnsupported device.UnsupportedError
if !errors.As(err, &errUnsupported) {
Expand Down

0 comments on commit c0d6d24

Please sign in to comment.