Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use shorter virtiofsd and swtpm socket paths #13320

4 changes: 2 additions & 2 deletions lxd/device/device_utils_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const RBDFormatPrefix = "rbd"
const RBDFormatSeparator = " "

// DiskParseRBDFormat parses an rbd formatted string, and returns the pool name, volume name, and list of options.
func DiskParseRBDFormat(rbd string) (string, string, []string, error) {
func DiskParseRBDFormat(rbd string) (poolName string, volumeName string, options []string, err error) {
if !strings.HasPrefix(rbd, fmt.Sprintf("%s%s", RBDFormatPrefix, RBDFormatSeparator)) {
return "", "", nil, fmt.Errorf("Invalid rbd format, missing prefix")
}
Expand Down Expand Up @@ -465,7 +465,7 @@ func DiskVMVirtiofsdStart(execPath string, inst instance.Instance, socketPath st
return nil, nil, UnsupportedError{"SEV unsupported"}
}

// Trickery to handle paths > 107 chars.
// Trickery to handle paths > 108 chars.
socketFileDir, err := os.Open(filepath.Dir(socketPath))
if err != nil {
return nil, nil, err
Expand Down
18 changes: 16 additions & 2 deletions lxd/device/tpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,27 @@ func (d *tpm) startVM() (*deviceConfig.RunConfig, error) {
},
}

proc, err := subprocess.NewProcess("swtpm", []string{"socket", "--tpm2", "--tpmstate", fmt.Sprintf("dir=%s", tpmDevPath), "--ctrl", fmt.Sprintf("type=unixio,path=%s", socketPath)}, "", "")
var fdFiles []*os.File
hamistao marked this conversation as resolved.
Show resolved Hide resolved

// Ensure passed file is closed after swtpm start has returned.
defer func() {
for _, file := range fdFiles {
_ = file.Close()
}
}()

shortPath, err := util.ShortenedFilePath(socketPath, &fdFiles)
if err != nil {
return nil, err
}

proc, err := subprocess.NewProcess("swtpm", []string{"socket", "--tpm2", "--tpmstate", fmt.Sprintf("dir=%s", tpmDevPath), "--ctrl", fmt.Sprintf("type=unixio,path=%s", shortPath)}, "", "")
if err != nil {
return nil, err
}

// Start the TPM emulator.
err = proc.Start(context.Background())
err = proc.StartWithFiles(context.Background(), fdFiles)
if err != nil {
return nil, fmt.Errorf("Failed to start swtpm for device %q: %w", d.name, err)
}
Expand Down
53 changes: 34 additions & 19 deletions lxd/instance/drivers/driver_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ func (d *qemu) start(stateful bool, op *operationlock.InstanceOperation) error {
}

// Add allocated QEMU vhost file descriptor.
vsockFD := d.addFileDescriptor(&fdFiles, vsockF)
vsockFD := util.AddFileDescriptor(&fdFiles, vsockF)

volatileSet := make(map[string]string)

Expand Down Expand Up @@ -1851,7 +1851,7 @@ func (d *qemu) setupSEV(fdFiles *[]*os.File) (*qemuSevOpts, error) {
return nil, err
}

dhCertFD = d.addFileDescriptor(fdFiles, dhCert)
dhCertFD = util.AddFileDescriptor(fdFiles, dhCert)
}

if d.expandedConfig["security.sev.session.data"] != "" {
Expand All @@ -1870,7 +1870,7 @@ func (d *qemu) setupSEV(fdFiles *[]*os.File) (*qemuSevOpts, error) {
return nil, err
}

sessionDataFD = d.addFileDescriptor(fdFiles, sessionData)
sessionDataFD = util.AddFileDescriptor(fdFiles, sessionData)
}

sevOpts := &qemuSevOpts{}
Expand Down Expand Up @@ -2185,7 +2185,15 @@ func (d *qemu) deviceAttachPath(deviceName string, configCopy map[string]string,
return fmt.Errorf("Failed to connect to QMP monitor: %w", err)
}

hamistao marked this conversation as resolved.
Show resolved Hide resolved
addr, err := net.ResolveUnixAddr("unix", virtiofsdSockPath)
// Open a file descriptor to the socket file through O_PATH to avoid acessing the file descriptor to the sockfs inode.
socketFile, err := os.OpenFile(virtiofsdSockPath, unix.O_PATH|unix.O_CLOEXEC, 0)
if err != nil {
return fmt.Errorf("Failed to open device socket file %q: %w", virtiofsdSockPath, err)
}

shortPath := fmt.Sprintf("/dev/fd/%d", socketFile.Fd())

addr, err := net.ResolveUnixAddr("unix", shortPath)
if err != nil {
return err
}
Expand Down Expand Up @@ -3175,7 +3183,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo

driveFirmwareOpts := qemuDriveFirmwareOpts{
roPath: fwPath,
nvramPath: fmt.Sprintf("/dev/fd/%d", d.addFileDescriptor(fdFiles, nvRAMFile)),
nvramPath: fmt.Sprintf("/dev/fd/%d", util.AddFileDescriptor(fdFiles, nvRAMFile)),
}

cfg = append(cfg, qemuDriveFirmware(&driveFirmwareOpts)...)
Expand Down Expand Up @@ -3343,6 +3351,11 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
// where 9p isn't available in the VM guest OS.
configSockPath, _ := d.configVirtiofsdPaths()
if shared.PathExists(configSockPath) {
shortPath, err := util.ShortenedFilePath(configSockPath, fdFiles)
if err != nil {
return "", nil, err
}

devBus, devAddr, multi = bus.allocate(busFunctionGroup9p)
driveConfigVirtioOpts := qemuDriveConfigOpts{
dev: qemuDevOpts{
Expand All @@ -3352,7 +3365,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo
multifunction: multi,
},
protocol: "virtio-fs",
path: configSockPath,
path: shortPath,
}

cfg = append(cfg, qemuDriveConfig(&driveConfigVirtioOpts)...)
Expand Down Expand Up @@ -3501,7 +3514,7 @@ func (d *qemu) generateQemuConfigFile(cpuInfo *cpuTopology, mountInfo *storagePo

// Add TPM device.
if len(runConf.TPMDevice) > 0 {
err = d.addTPMDeviceConfig(&cfg, runConf.TPMDevice)
err = d.addTPMDeviceConfig(&cfg, runConf.TPMDevice, fdFiles)
if err != nil {
return "", nil, err
}
Expand Down Expand Up @@ -3661,14 +3674,6 @@ func (d *qemu) addCPUMemoryConfig(cfg *[]cfgSection, cpuInfo *cpuTopology) error
return nil
}

// addFileDescriptor adds a file path to the list of files to open and pass file descriptor to qemu.
// Returns the file descriptor number that qemu will receive.
func (d *qemu) addFileDescriptor(fdFiles *[]*os.File, file *os.File) int {
// Append the tap device file path to the list of files to be opened and passed to qemu.
*fdFiles = append(*fdFiles, file)
return 2 + len(*fdFiles) // Use 2+fdFiles count, as first user file descriptor is 3.
}

// addRootDriveConfig adds the qemu config required for adding the root drive.
func (d *qemu) addRootDriveConfig(qemuDev map[string]string, mountInfo *storagePools.MountInfo, bootIndexes map[string]int, rootDriveConf deviceConfig.MountEntryItem) (monitorHook, error) {
if rootDriveConf.TargetPath != "/" {
Expand Down Expand Up @@ -3754,6 +3759,11 @@ func (d *qemu) addDriveDirConfig(cfg *[]cfgSection, bus *qemuBus, fdFiles *[]*os

devBus, devAddr, multi := bus.allocate(busFunctionGroup9p)

shortPath, err := util.ShortenedFilePath(virtiofsdSockPath, fdFiles)
if err != nil {
return err
}

// Add virtio-fs device as this will be preferred over 9p.
driveDirVirtioOpts := qemuDriveDirOpts{
dev: qemuDevOpts{
Expand All @@ -3764,7 +3774,7 @@ func (d *qemu) addDriveDirConfig(cfg *[]cfgSection, bus *qemuBus, fdFiles *[]*os
},
devName: driveConf.DevName,
mountTag: mountTag,
path: virtiofsdSockPath,
path: shortPath,
protocol: "virtio-fs",
}
*cfg = append(*cfg, qemuDriveDir(&driveDirVirtioOpts)...)
Expand All @@ -3778,7 +3788,7 @@ func (d *qemu) addDriveDirConfig(cfg *[]cfgSection, bus *qemuBus, fdFiles *[]*os
return fmt.Errorf("Invalid file descriptor %q for drive %q: %w", driveConf.DevPath, driveConf.DevName, err)
}

proxyFD := d.addFileDescriptor(fdFiles, os.NewFile(uintptr(fd), driveConf.DevName))
proxyFD := util.AddFileDescriptor(fdFiles, os.NewFile(uintptr(fd), driveConf.DevName))

driveDir9pOpts := qemuDriveDirOpts{
dev: qemuDevOpts{
Expand Down Expand Up @@ -4695,7 +4705,7 @@ func (d *qemu) addUSBDeviceConfig(usbDev deviceConfig.USBDeviceItem) (monitorHoo
return monHook, nil
}

func (d *qemu) addTPMDeviceConfig(cfg *[]cfgSection, tpmConfig []deviceConfig.RunConfigItem) error {
func (d *qemu) addTPMDeviceConfig(cfg *[]cfgSection, tpmConfig []deviceConfig.RunConfigItem, fdFiles *[]*os.File) error {
hamistao marked this conversation as resolved.
Show resolved Hide resolved
var devName, socketPath string

for _, tpmItem := range tpmConfig {
Expand All @@ -4706,9 +4716,14 @@ func (d *qemu) addTPMDeviceConfig(cfg *[]cfgSection, tpmConfig []deviceConfig.Ru
}
}

shortPath, err := util.ShortenedFilePath(socketPath, fdFiles)
if err != nil {
return err
}

tpmOpts := qemuTPMOpts{
devName: devName,
path: socketPath,
path: shortPath,
}
*cfg = append(*cfg, qemuTPM(&tpmOpts)...)

Expand Down
21 changes: 21 additions & 0 deletions lxd/util/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,24 @@ func GetQemuFwPaths() ([]string, error) {

return qemuFwPaths, nil
}

// AddFileDescriptor adds a file path to the list of files to open and pass file descriptor to other processes.
// Returns the file descriptor number that the other process will receive.
func AddFileDescriptor(fdFiles *[]*os.File, file *os.File) int {
// Append the tap device file path to the list of files to be opened and passed to qemu.
*fdFiles = append(*fdFiles, file)
return 2 + len(*fdFiles) // Use 2+fdFiles count, as first user file descriptor is 3.
}

// ShortenedFilePath creates a shorter alternative path to a socket by using the file descriptor to the directory of the socket file.
// Used to handle paths > 108 chars.
// Files opened here must be closed outside this function once they are not needed anymore.
func ShortenedFilePath(originalSockPath string, fdFiles *[]*os.File) (string, error) {
// Open a file descriptor to the socket file through O_PATH to avoid acessing the file descriptor to the sockfs inode.
socketFile, err := os.OpenFile(originalSockPath, unix.O_PATH|unix.O_CLOEXEC, 0)
if err != nil {
return "", fmt.Errorf("Failed to open device socket file %q: %w", originalSockPath, err)
}

return fmt.Sprintf("/dev/fd/%d", AddFileDescriptor(fdFiles, socketFile)), nil
}
2 changes: 1 addition & 1 deletion test/suites/container_devices_tpm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test_container_devices_tpm() {
lxc launch testimage "${ctName}"

# Check adding a device with no path
! lxc config device add "${ctName}" test-dev-invalid
! lxc config device add "${ctName}" test-dev-invalid tpm

# Add device
lxc config device add "${ctName}" test-dev1 tpm path=/dev/tpm0 pathrm=/dev/tpmrm0
Expand Down
Loading