From adf34cbd79bd3621e13d1be2cb28406460601fa1 Mon Sep 17 00:00:00 2001 From: "Jason T. Greene" Date: Tue, 22 Aug 2023 17:34:57 -0500 Subject: [PATCH] Share podman sock bindings with other WSL distros Registers a rootless and rootful socket underneath /mnt/wsl/podman-sockets/[machine name]/ This allows podman remote clients on other Linux distributions to access podman. This also registers the podman root socket under the wheel group, to allow for rootful linking against /var/run/docker.sock, a use case expected by some clients and APIs. While this is not recommended practice on a Linux host, a WSL guest is user-isolated and already enables escalation trivially. [NO NEW TESTS NEEDED] Signed-off-by: Jason T. Greene --- pkg/machine/wsl/machine.go | 112 ++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 94e609b5a9..9182fbd3b7 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -138,9 +138,69 @@ Wants=network-online.target podman.socket ExecStart=/usr/bin/sleep infinity ` -const lingerSetup = `mkdir -p /home/[USER]/.config/systemd/[USER]/default.target.wants -ln -fs /home/[USER]/.config/systemd/[USER]/linger-example.service \ - /home/[USER]/.config/systemd/[USER]/default.target.wants/linger-example.service +const lingerSetup = `mkdir -p /home/[USER]/.config/systemd/user/default.target.wants +ln -fs /home/[USER]/.config/systemd/user/linger-example.service \ + /home/[USER]/.config/systemd/user/default.target.wants/linger-example.service +` + +const bindMountSystemService = ` +[Unit] +Description=Bind mount for system podman sockets +After=podman.socket + +[Service] +RemainAfterExit=true +Type=oneshot +# Ensure user services can register sockets as well +ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets +ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets/%[1]s +ExecStartPre=touch /mnt/wsl/podman-sockets/%[1]s/podman-root.sock +ExecStart=mount --bind %%t/podman/podman.sock /mnt/wsl/podman-sockets/%[1]s/podman-root.sock +ExecStop=umount /mnt/wsl/podman-sockets/%[1]s/podman-root.sock +` + +const bindMountUserService = ` +[Unit] +Description=Bind mount for user podman sockets +After=podman.socket + +[Service] +RemainAfterExit=true +Type=oneshot +# Consistency with system service (supports racing) +ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets +ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets/%[1]s +ExecStartPre=touch /mnt/wsl/podman-sockets/%[1]s/podman-user.sock +# Relies on /etc/fstab entry for user mounting +ExecStart=mount /mnt/wsl/podman-sockets/%[1]s/podman-user.sock +ExecStop=umount /mnt/wsl/podman-sockets/%[1]s/podman-user.sock +` + +const bindMountFsTab = `/run/user/1000/podman/podman.sock /mnt/wsl/podman-sockets/%s/podman-user.sock none noauto,user,bind,defaults 0 0 +` +const ( + defaultTargetWants = "default.target.wants" + userSystemdPath = "/home/%[1]s/.config/systemd/user" + sysSystemdPath = "/etc/systemd/system" + userSystemdWants = userSystemdPath + "/" + defaultTargetWants + sysSystemdWants = sysSystemdPath + "/" + defaultTargetWants + bindUnitFileName = "podman-mnt-bindings.service" + bindUserUnitPath = userSystemdPath + "/" + bindUnitFileName + bindUserUnitWant = userSystemdWants + "/" + bindUnitFileName + bindSysUnitPath = sysSystemdPath + "/" + bindUnitFileName + bindSysUnitWant = sysSystemdWants + "/" + bindUnitFileName + podmanSocketDropin = "podman.socket.d" + podmanSocketDropinPath = sysSystemdPath + "/" + podmanSocketDropin +) + +const configBindServices = "mkdir -p " + userSystemdWants + " " + sysSystemdWants + " " + podmanSocketDropinPath + "\n" + + "ln -fs " + bindUserUnitPath + " " + bindUserUnitWant + "\n" + + "ln -fs " + bindSysUnitPath + " " + bindSysUnitWant + "\n" + +const overrideSocketGroup = ` +[Socket] +SocketMode=0660 +SocketGroup=wheel ` const proxyConfigSetup = `#!/bin/bash @@ -553,9 +613,55 @@ func configureSystem(v *MachineVM, dist string) error { return fmt.Errorf("could not create podman-machine file for guest OS: %w", err) } + if err := configureBindMounts(dist, user); err != nil { + return err + } + return changeDistUserModeNetworking(dist, user, "", v.UserModeNetworking) } +func configureBindMounts(dist string, user string) error { + if err := wslPipe(fmt.Sprintf(bindMountSystemService, dist), dist, "sh", "-c", "cat > /etc/systemd/system/podman-mnt-bindings.service"); err != nil { + return fmt.Errorf("could not create podman binding service file for guest OS: %w", err) + } + + catUserService := "cat > " + getUserUnitPath(user) + if err := wslPipe(getBindMountUserService(dist), dist, "sh", "-c", catUserService); err != nil { + return fmt.Errorf("could not create podman binding user service file for guest OS: %w", err) + } + + if err := wslPipe(getBindMountFsTab(dist), dist, "sh", "-c", "cat >> /etc/fstab"); err != nil { + return fmt.Errorf("could not create podman binding fstab entry for guest OS: %w", err) + } + + if err := wslPipe(getConfigBindServicesScript(user), dist, "sh"); err != nil { + return fmt.Errorf("could not configure podman binding services for guest OS: %w", err) + } + + catGroupDropin := fmt.Sprintf("cat > %s/%s", podmanSocketDropinPath, "10-group.conf") + if err := wslPipe(overrideSocketGroup, dist, "sh", "-c", catGroupDropin); err != nil { + return fmt.Errorf("could not configure podman socket group override: %w", err) + } + + return nil +} + +func getConfigBindServicesScript(user string) string { + return fmt.Sprintf(configBindServices, user) +} + +func getBindMountUserService(dist string) string { + return fmt.Sprintf(bindMountUserService, dist) +} + +func getUserUnitPath(user string) string { + return fmt.Sprintf(bindUserUnitPath, user) +} + +func getBindMountFsTab(dist string) string { + return fmt.Sprintf(bindMountFsTab, dist) +} + func (v *MachineVM) setupPodmanDockerSock(dist string, rootful bool) error { content := machine.GetPodmanDockerTmpConfig(1000, rootful, true)