See how systemd compares to other vendors in security performance
systemd, a system and service manager, (as PID 1) hits an assert and freezes execution when an unprivileged IPC API call is made with spurious data. On version v249 and older the effect is not an assert, but stack overwriting, with the attacker controlled content. From version v250 and newer this is not possible as the safety check causes an assert instead. This IPC call was added in v239, so versions older than that are not affected. Versions 260-rc1, 259.2, 258.5, and 257.11 contain patches. No known workarounds are available.
systemd, a system and service manager, (as PID 1) hits an assert and freezes execution when an unprivileged IPC API call is made with spurious data. On version v249 and older the effect is not an assert, but stack overwriting, with the attacker controlled content. From version v250 and newer this is not possible as the safety check causes an assert instead. This IPC call was added in v239, so versions older than that are not affected. Versions 260-rc1, 259.2, 258.5, and 257.11 contain patches. No known workarounds are available.
A race condidition in systemd-coredump allows a local attacker to crash a SUID program and gain read access to the resulting core dump
A race condidition in systemd-coredump allows a local attacker to crash a SUID program and gain read access to the resulting core dump
A flaw was found in systemd. The systemd-tmpfiles 'w' item type writes to its target file via writeonefile() in src/tmpfiles/tmpfiles.c, which resolves the parent directory through pathopenparentsafe()/chase() using the CHASESAFE mode, then opens the target leaf with OWRONLY but without ONOFOLLOW, so a terminal symlink at the target path is followed rather than rejected. Separately, uidunsafetransition() in src/basic/chase.c, consulted during the CHASESAFE parent-directory walk, treats any transition away from UID 0 as unconditionally safe ('if (a == 0) return false;'), so the walk never flags crossing from a root-owned directory into a directory owned by an unprivileged user. Because /run/user/<uid> is created automatically and owned by that user for any account with an active login session (via logind), an unprivileged local user can place a symlink at a predictable path under their own /run/user/<uid> directory pointing at an arbitrary root-owned file. If a tmpfiles.d configuration containing a 'w'-type entry targets that path and is later processed by a root-privileged systemd-tmpfiles run (at boot, on a timer, or via an administrator- or automation-triggered systemd-tmpfiles --create), the walk into /run/user/<uid> is not flagged as unsafe, writeonefile() follows the attacker's symlink, and root writes that entry's configured content into whichever root-owned file the symlink points to. The content written is determined by the pre-existing tmpfiles.d entry, not freely chosen by the unprivileged user placing the symlink; the unprivileged user controls the destination of the write, not its content, unless they separately have write access to the tmpfiles.d configuration itself. This was reproduced against the systemd package shipped in RHEL 9: an unprivileged test user's symlink under /run/user/<uid> pointing at a root-owned file was followed by systemd-tmpfiles running as root, with the target file's contents overwritten by the configured entry and no warning logged. The specific role of the UID-0 exception was isolated with a comparison case: when the same style of directory-ownership transition occurs between two non-root users instead of from root, systemd-tmpfiles correctly detects and rejects it with an explicit logged warning naming the two users and directories involved, which does not occur in the root-to-unprivileged case. Exploitation requires a tmpfiles.d 'w'-type entry that resolves through attacker-symlinkable space to exist and be processed as root; a systematic audit of every package shipping a tmpfiles.d configuration across RHEL 8, 9, and 10's open package repositories found exactly one such entry (from selinux-policy, targeting a sysfs path), and it does not qualify since its target is not reachable through user-writable directory space.
An access control bypass and information disclosure vulnerability exists in the base AppArmor security profile configuration of Canonical snapd. The abstraction rules located in /etc/apparmor.d/abstractions/nss-systemd (inherited via ) inadvertently permit strictly confined snap applications, which lack the privileged account-control interface, to interact directly with the io.systemd.Multiplexer and io.systemd.NameServiceSwitch UNIX domain sockets under /run/systemd/userdb/. On systems where the systemd-userdbd service is installed and operational, the service fails to distinguish between an unconfined root user on the host system and a restricted root user running within a snap application's sandbox (such as a daemon or configuration hook). Because systemd-userdbd returns "complete" user records—including sensitive hashed user passwords from /etc/shadow—when queried by a process running as root, a compromised or malicious strictly confined snap executing code as root can successfully query the Varlink interface to retrieve all system password hashes, bypassing intended snap sandbox restrictions. This issue is mitigated by the fact that systemd-userdbd is not installed by default on standard Ubuntu deployments.
A flaw was found in systemd. The systemd-tmpfiles 'w' item type writes to its target file via writeonefile() in src/tmpfiles/tmpfiles.c, which resolves the parent directory through pathopenparentsafe()/chase() using the CHASESAFE mode, then opens the target leaf with OWRONLY but without ONOFOLLOW, so a terminal symlink at the target path is followed rather than rejected. Separately, uidunsafetransition() in src/basic/chase.c, consulted during the CHASESAFE parent-directory walk, treats any transition away from UID 0 as unconditionally safe ('if (a == 0) return false;'), so the walk never flags crossing from a root-owned directory into a directory owned by an unprivileged user. Because /run/user/<uid> is created automatically and owned by that user for any account with an active login session (via logind), an unprivileged local user can place a symlink at a predictable path under their own /run/user/<uid> directory pointing at an arbitrary root-owned file. If a tmpfiles.d configuration containing a 'w'-type entry targets that path and is later processed by a root-privileged systemd-tmpfiles run (at boot, on a timer, or via an administrator- or automation-triggered systemd-tmpfiles --create), the walk into /run/user/<uid> is not flagged as unsafe, writeonefile() follows the attacker's symlink, and root writes that entry's configured content into whichever root-owned file the symlink points to. The content written is determined by the pre-existing tmpfiles.d entry, not freely chosen by the unprivileged user placing the symlink; the unprivileged user controls the destination of the write, not its content, unless they separately have write access to the tmpfiles.d configuration itself. This was reproduced against the systemd package shipped in RHEL 9: an unprivileged test user's symlink under /run/user/<uid> pointing at a root-owned file was followed by systemd-tmpfiles running as root, with the target file's contents overwritten by the configured entry and no warning logged. The specific role of the UID-0 exception was isolated with a comparison case: when the same style of directory-ownership transition occurs between two non-root users instead of from root, systemd-tmpfiles correctly detects and rejects it with an explicit logged warning naming the two users and directories involved, which does not occur in the root-to-unprivileged case. Exploitation requires a tmpfiles.d 'w'-type entry that resolves through attacker-symlinkable space to exist and be processed as root; a systematic audit of every package shipping a tmpfiles.d configuration across RHEL 8, 9, and 10's open package repositories found exactly one such entry (from selinux-policy, targeting a sysfs path), and it does not qualify since its target is not reachable through user-writable directory space.
In nspawn in systemd 233 through 259 before 260, an escape-to-host action can occur via a crafted optional config file.
In udev in systemd before 260, local root execution can occur via malicious hardware devices and unsanitized kernel output.
On Mon, 18 May 2026 at 22:01:16 -0400, Aaron Rainbolt wrote: Of these two, org.freedesktop.portal.OpenURI.OpenFile is probably more problematic. This is because access to the OpenURI portal seems to be implicitly allowed by Flatpak. Expanding on what Flatpak intends to allow here:
If all applications followed the xdg-mime manpage's advice to never execute code when opening a file, this wouldn't be that big of a problem. This is where Wine comes in; it ships a desktop file that registers Wine as a MIME handler for 'application/x-ms-dos-executable', 'application/x-msi', and 'application/x-bat'.
Unfortunately, I was able to find another program with an unsafe handler registered just while writing this email (which I intend on reporting privately once I've sent this). So while it seems like these kind of handlers aren't super common, they aren't that hard to find if you dig around for a while.
We're working on a sandboxing system (really a glorified systemd-nspawn frontend) that allows each sandbox to be self-sufficient enough to not need access to the host's D-Bus daemon. [9] That should prevent any possible way to leverage D-Bus as a sandbox escape mechanism.
smcv
In systemd 259, systemd-journald can send ANSI escape sequences to the terminals of arbitrary users when a "logger -p emerg" command is executed, if ForwardToWall=yes is set.
On Tue, 7 Apr 2026 20:09:06 -0400 Aaron Rainbolt <arraybolt3 () riseup net> wrote: Going over this semi-briefly: systemd-journald is configured with the ForwardToWall=yes and MaxWallLevel=emerg settings by default in Ubuntu 26.04 pre-release images and Arch Linux. (I think this is because these are enabled by default in systemd upstream but haven't tried to verify this.) In my testing, this will result in systemd-journald copying emerg-level log messages to all logged-in TTYs and at least some root-owned PTYs (if any exist). Any user on the system can write an emerg-level log message using logger -p emerg 'msg...'. Potentially dangerous character sequences in log messages (like ANSI escape sequences) are not sanitized by systemd-journald before it prints those messages to other user's terminals. Therefore, one can use systemd-journald to write malicious things to other people's terminals, which can be used to exploit terminal emulator vulnerabilities. There have been vulnerabilities in terminal emulators like XTerm in the past that would allow this to be used to execute arbitrary code as root if someone is unlucky enough to have a PTY to a root shell open in a vulnerable terminal when an attacker writes their malicious log message. Someone (not sure who) did the kind service of getting a CVE assigned for this: https://www.cve.org/CVERecord?id=CVE-2026-40228 To whoever that was, thank you :)
-- Aaron
A flaw was found in systemd. The systemd-machined service contains an Improper Access Control vulnerability due to insufficient validation of the class parameter in the RegisterMachine D-Bus (Desktop Bus) method. A local unprivileged user can exploit this by attempting to register a machine with a specific class value, which may leave behind a usable, attacker-controlled machine object. This allows the attacker to invoke methods on the privileged object, leading to the execution of arbitrary commands with root privileges on the host system.
In systemd 258 before 260, a local unprivileged user can trigger an assert when a Delegate=yes and User=<unset> unit exists and is running.
In systemd 259 before 260, there is local privilege escalation in systemd-machined because varlink can be used to reach the root namespace.
In systemd 260 before 261, a local unprivileged user can trigger an assert via an IPC API call with an array or map that has a null element.
On 2026-04-09 21:31:26 -0400, Aaron Rainbolt wrote: On Thu, 9 Apr 2026 08:11:03 +0200 Salvatore Bonaccorso <carnil () debian org> wrote: Hi Aaron,
On Tue, Apr 07, 2026 at 08:09:06PM -0400, Aaron Rainbolt wrote: [...] I discovered this while doing work for the Kicksecure and Whonix projects. This bug was reported privately to upstream on December 23, 2025. As per Kicksecure's Vulnerability Disclosure Policy [1], we're disclosing it publicly on April 7, 2026, 90 days + a 14-day grace period later. An upstream bug report can be seen at [2]. JFYI, the reference to the issue: It currently say: "This issue has been deleted.". Is the issue reference correct, was it really deleted or is there a typo? The issue reference is correct. systemd upstream didn't agree with Kicksecure's vulnerability disclosure policy, and elected to delete the bug report for being "irresponsible". I disagree with them, but in any event, the email contains all of the useful info that was in the upstream bug report. Note that ForwardToWall=yes can be problematic even if this bug is fixed, because wall messages may interfere with escape sequences that are normally sent to the terminal. So I would say that ForwardToWall=yes should be used only in trusted environments.
-- Vincent Lefèvre <vincent () vinc17 net> - Web: <https://www.vinc17.net/> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/> Work: CR INRIA - computer arithmetic / Pascaline project (LIP, ENS-Lyon)
On Thu, 9 Apr 2026 08:11:03 +0200 Salvatore Bonaccorso <carnil () debian org> wrote: Hi Aaron,
On Tue, Apr 07, 2026 at 08:09:06PM -0400, Aaron Rainbolt wrote: [...] I discovered this while doing work for the Kicksecure and Whonix projects. This bug was reported privately to upstream on December 23, 2025. As per Kicksecure's Vulnerability Disclosure Policy [1], we're disclosing it publicly on April 7, 2026, 90 days + a 14-day grace period later. An upstream bug report can be seen at [2]. JFYI, the reference to the issue: It currently say: "This issue has been deleted.". Is the issue reference correct, was it really deleted or is there a typo? The issue reference is correct. systemd upstream didn't agree with Kicksecure's vulnerability disclosure policy, and elected to delete the bug report for being "irresponsible". I disagree with them, but in any event, the email contains all of the useful info that was in the upstream bug report.
-- Aaron
Hi Aaron,
On Tue, Apr 07, 2026 at 08:09:06PM -0400, Aaron Rainbolt wrote: [...] I discovered this while doing work for the Kicksecure and Whonix projects. This bug was reported privately to upstream on December 23, 2025. As per Kicksecure's Vulnerability Disclosure Policy [1], we're disclosing it publicly on April 7, 2026, 90 days + a 14-day grace period later. An upstream bug report can be seen at [2]. JFYI, the reference to the issue: It currently say: "This issue has been deleted.". Is the issue reference correct, was it really deleted or is there a typo?
Regards, Salvatore
A minor correction: A more involved proof-of-concept that demonstrates how this can be used to escalate privileges is:
1. Compile a version of XTerm that is vulnerable to CVE-2022-45063. (XTerm patch #369 worked for me last time I tried this.) 2. Open two instances of XTerm at once as a non-root user. 3. In one XTerm window, open a root shell by running sudo -i. The root shell needs to be provided by ZSH, and ZSH needs to be put into vi line editing mode, for this to work. See [1]. 4. In the other XTerm window, as a non-root user, run pwned=$'\e]50;i$(cp /etc/shadow /home/user/shadow && chown user:user /home/user/shadow)\a\e]50;?\a\n' (replacing 'user' with your non-root user's username where appropriate). 5. In the same non-root XTerm window, run logger -p 'emerg' "$pwned". You should now have a copy of the system's shadow password file in your home directory, readable by your non-root user. [1] https://www.openwall.com/lists/oss-security/2022/11/10/1
-- Aaron
Going over this semi-briefly: systemd-journald is configured with the ForwardToWall=yes and MaxWallLevel=emerg settings by default in Ubuntu 26.04 pre-release images and Arch Linux. (I think this is because these are enabled by default in systemd upstream but haven't tried to verify this.) In my testing, this will result in systemd-journald copying emerg-level log messages to all logged-in TTYs and at least some root-owned PTYs (if any exist). Any user on the system can write an emerg-level log message using logger -p emerg 'msg...'. Potentially dangerous character sequences in log messages (like ANSI escape sequences) are not sanitized by systemd-journald before it prints those messages to other user's terminals. Therefore, one can use systemd-journald to write malicious things to other people's terminals, which can be used to exploit terminal emulator vulnerabilities. There have been vulnerabilities in terminal emulators like XTerm in the past that would allow this to be used to execute arbitrary code as root if someone is unlucky enough to have a PTY to a root shell open in a vulnerable terminal when an attacker writes their malicious log message.
An easy proof-of-concept for this (assuming your system has sudo configured to allocate a new PTY) is:
1. Open two terminal windows as a non-root user. 2. In one terminal window, open a root shell by running sudo -i. 3. In the other terminal window, run logger -p 'emerg' $'\033[31mHello!\033[0m' as a non-root user.
You will see a wall message printed in the terminal emulator window that you ran sudo -i in, with the word 'Hello' written in red.
A more involved proof-of-concept that demonstrates how this can be used to escalate privileges is:
1. Compile a version of XTerm that is vulnerable to CVE-2022-45063. (XTerm patch #369 worked for me last time I tried this.) 2. Open two instances of XTerm at once as a non-root user. 3. In one XTerm window, open a root shell by running sudo -i. 4. In the other XTerm window, as a non-root user, run pwned=$'\e]50;i$(cp /etc/shadow /home/user/shadow && chown user:user /home/user/shadow)\a\e]50;?\a\n' (replacing 'user' with your non-root user's username where appropriate). 5. In the same non-root XTerm window, run logger -p 'emerg' "$pwned". You should now have a copy of the system's shadow password file in your home directory, readable by your non-root user.
Affected users can mitigate this by setting ForwardToWall=no in systemd-journald's configuration (/etc/systemd/journald.conf), or by adding systemd.journald.forwardtowall=no to their kernel command line.
I discovered this while doing work for the Kicksecure and Whonix projects. This bug was reported privately to upstream on December 23, 2025. As per Kicksecure's Vulnerability Disclosure Policy [1], we're disclosing it publicly on April 7, 2026, 90 days + a 14-day grace period later. An upstream bug report can be seen at [2].
-- Aaron
[1] https://www.kicksecure.com/wiki/VulnerabilityDisclosurePolicy [2] https://github.com/systemd/systemd/issues/41549
Hi Alexander,
Note that the systemd socket activated sshd listener was the only really embargoed information. That information was on this list for a while, so you should consider it public and feel free to share with those impacted. I have included the known working, end-user mitigations below in a few locations and I have shared it with individuals I know in some larger sites.
I am holding off on a comprehensive blog post as I am waiting on a few other stakeholders. I expect it to be published soon, maybe this weekend, trying to only publish examples with known fixes. However as when crun was developed to replace lxc by the containerd team, there were no constraints or defaults at the crun level on callers that is proving challenging.
While I can add apparmor rules to crun/runc/podman/bwrap/etc... SElinux has proven to be more challenging, so those in k8s with mutating inlet controllers should ensure that they deny address family 40 at the control plane if possible.
Note: While local execution on a container host is problematic, restricting access to the vsock loopback and VM bus from containers/sandboxes is important.
I now have permission to share more information about one attack that I was informed of, which was internal.
========== Known attack ==========
A SAAS provider had a singleton container that originally allowed customers to upload assets for branding via git and rsync, over time they added the ability to pull assets from external tools which required them to allow customers to log in to troubleshoot and run python scripts. Their expectations was that this container was not shared between tenants, and that it was isolated. As this was a tiny container, they just co-hosted it with their app tier due to budget concerns.
An internal developer was approached by a customer. That developer then, claiming to be working on a new reporting engine container, added code to a chain of notification engines pushing to the vsock proxy. Any error being explained away as safe because that new container wasn't in the app layer pod.
That developer, either handed a time limited ansible key to the customer or used the customers key to ssh into the customer's container, used python/paramiko script to ssh to the container host, and launched a multi-hop proxy as the container host debian built in www-data user. That container listens for all customer events and using the vsock proxy and pushed targeted ones to the customer's asset container, allowing them to exfiltrate sensitive data.
While the above attack did use the systemd vsock sshd listener for Escape to Host <https://attack.mitre.org/tactics/TA0005/>, the attacker could have just directly listened over the vsock loopback. Unfortunately this orginization was only interested in a fix, and I don't expect more details to be made public.
============== Known mitigations ==============
Kernel boot string ==================
Disables systemd sshd vsock listener, will not protect the vsock loopback.
The official way to disable vsock sshd is through a kernel command line parameters or system credentials logic. [systemd-ssh-generator]
systemd.sshauto=no
Mask systemd socket ===================
This will disable the systemd sshd vsock listener, but will not protect the vsock loopback.
sudo systemctl mask sshd-vsock.socket
Note:
If another unit explicitly wants "sshd-vsock.socket" it may be started.
AppArmor ========
This will remove access to the vsock loopback, which will also remove access to the systemd sshd vsock listener for targeted binaries.
Add the following to "/etc/apparmor.d/local/<filename>" for each high risk command.
audit deny network vsock,
I will reply to this thread once I do publish a more indepth post and my time for testing is constrained.
If anyone has found reliable methods of constraining crun with SElinux by default without breaking the upstream callers it would be appreciated and accelerate that effort.
Thanks,
Greg
On Thu, Jan 8, 2026 at 2:20 PM Solar Designer <solar () openwall com> wrote: Hi Greg,
On Sat, Dec 27, 2025 at 08:46:49PM -0700, Greg Dahlman wrote: This information is to be publicly released on January 6 per requirements of the distro list. We're past this date now. Have you already disclosed everything in this thread, or do you have anything additional you had shared with distros that you're yet to disclose to oss-security? In the latter case, please do this ASAP! (Sorry I haven't kept track of all the detail.)
Thanks,
Alexander
Thanks for the reply, I have been busy trying to figure out what breaks with apparmor and other options.
Obviously runc is similar to the pain points of dbus, where it is call anywhere with no ability to set defaults, but I think a combo of the below works pretty well. Container runtimes should still set reasonable defaults in the long run IMHO, but a combo of the below seems to work, but it will probably break kata containers etc... You can launch a vsock C2 container with runc as nobody with no issue and just a few env vars as an example.
I am not sure if there are any hypervisor tools that are in flatpack/snap/bwrap etc... but pretty much everything that is given userns and unlabeled may need a apparmor.d/local file for users actually using vsock for critical use cases.
This qualsys post from earlier this year applies: https://seclists.org/oss-sec/2025/q1/253
I am still trying to do more testing, but crun/runc/podman/buildah/chrome/chromium/firefox/etc. don't seem to break with a container only workload I have tested with the apparmor addition. Unfortunately putting it in globals would break things.
Kernel boot string ==================
Disables systemd sshd vsock listener, will not protect the L4 bridge.
The official way to disable vsock sshd is through a kernel command line parameters or system credentials logic. [systemd-ssh-generator]
systemd.sshauto=no
Mask systemd socket ===================
This will disable the systemd sshd vsock listener, but will not protect the L4 bridge.
sudo systemctl mask sshd-vsock.socket
Note:
If another unit explicitly wants "sshd-vsock.socket" it may be started.
AppArmor ========
This will remove access to the L4 bridge, which will also remove access to the systemd sshd vsock listener for targeted binaries.
Add the following to "/etc/apparmor.d/local/<filename>" for each high risk command.
audit deny network vsock,
SElinux =======
TODO
Seccomp =======
CRIs and sandbox commands should probably follow the methods containerd used when containerd blocked vsock [7442]
[7442] https://github.com/containerd/containerd/issues/7442
On Fri, Jan 2, 2026 at 4:14 PM <wish42offcl98 () posteo org> wrote: I do not use Fedora, but I checked the update repo for f42. Neither openssh ¹, nor systemd ² have been updated for Fedora 42 in the last few weeks. Thus I have to guess that your method to setup/test the VM was different. Just in case, I have masked the vsock socket on all of my instances (no VMs though) and I will check on occasions if masking disappears.
Nonetheless, I dug deeper into systemd and checked their source code ³. systemd-vmspawn uses another service: systemd.unit-dropin.sshd-vsock@.service ⁴ And there is also sshd-vsock@.service ⁵ which might require another masking - same for sshd-unix-local@.service ⁶.
Since I do not use VMs, it was rather an addition for this list, thus I won't dig deeper for now. busctl is unknown to me (yet). The "RestrictAddressFamilies" option for services might be another idea to restrict sshd - but I don't know if it affects the unix-socket/vsock sockets generated by systemd - and whether this also influences access to local sockets (e.g. to control systemd itself).
I haven't understood the L4 bridge issue completely yet, so I would need to read more into it and test it. My guess on the L4 bridge problem: - Exposed vsocks are in global namespace. - VMs with enabled vsock feature (on hypervisor and inside VM) expose their services. - Containers (with unmitigated container runtimes) run on the hypervisor (not within VMs) are able to access the vsocks of VMs. That's a short description of my current understanding to it.
1 https://bodhi.fedoraproject.org/updates/FEDORA-2025-ad76584c00 2 https://bodhi.fedoraproject.org/updates/FEDORA-2025-61132a053f 3 https://github.com/systemd/systemd/ 4
https://github.com/systemd/systemd/blob/v259-stable/src/vmspawn/vmspawn.c#L2654 5
https://github.com/systemd/systemd/blob/v259-stable/src/ssh-generator/ssh-generator.c#L228 6
https://github.com/systemd/systemd/blob/v259-stable/src/ssh-generator/ssh-generator.c#L265
On 12/30/25 21:44, Greg Dahlman wrote: Thanks for the reply Alex,
I didn't include that option because I ran into an issue that I couldn't find the root cause for. Specifically on Fedora, a dnf upgrade resulted in the mask disappearing. I could find some complaints with Fedora version upgrades, but couldn't find anything on package upgrade.
As I don't have access to the RedHat support portal I decided to exclude it out of caution.
It looked like there was nothing in /usr/lib/systemd/system-preset for sshd-vsock.socket that I found, and those should respect the mask for sshd-vsock.socket and wouldn't remove the /etc/systemd/system/sshd-vsock.socket symlink as I understand it.
I think that because it doesn't show up in busctl --activatable, and no packages I can find "Wants" sshd-vsock.socket explicitly that would probably work.
I just tried a fresh install of Fedora Linux 42 workstation and didn't experience the unintended unmasking with a dnf upgrade. That was reliable a few weeks ago. Maybe I just was unlucky with a package that was fixed?
Either way I think it is an option for people who use configuration management tools that can periodically check sshd-vsock.socket is still disabled.
Also for normal systemd services that need isolation from the vsock bridge you can use:
RestrictAddressFamilies=none # disable all af families RestrictAddressFamilies=AFINET # only AFINET RestrictAddressFamilies=~AFVSOCK # not AFVSOCK
The L4 bridge problem will be harder for projects that use CRI's that are not containerd like the k8s/podman/crun/runc.
If anyone on here is involved with them, or sandboxing tools like bubblewrap etc... Filtering address family 40 will still be required by default to have any real intra-container/pod/process network isolation on a node.
Thanks,
Greg
On Tue, Dec 30, 2025 at 12:12 PM <wish42offcl98 () posteo org> wrote: I have searched for that - instead of blacklisting the vsock module, I did myself two measures: - systemctl mask --now sshd-unix-local.socket to kill and mask the sshd unix socket created by that generator, - systemctl mask sshd-vsock.socket to mask the sshd vsock created by that generator (use --now if the socket has started or use systemctl stop... ).
Though, vsock untested but I found that source mentioning that socket. https://linux-audit.com/system-administration/commands/systemd-analyze/ Masking the sockets should stop them from starting again.
The vsock kernel module should not be blacklisted if some hypervisor features are required: https://libvirt.org/ssh-proxy.html https://wiki.qemu.org/Features/VirtioVsock
Greetings Alex
On 12/29/25 05:11, Jacob Bachmeyer wrote: On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
Thanks for the reply Alex,
I didn't include that option because I ran into an issue that I couldn't find the root cause for. Specifically on Fedora, a dnf upgrade resulted in the mask disappearing. I could find some complaints with Fedora version upgrades, but couldn't find anything on package upgrade.
As I don't have access to the RedHat support portal I decided to exclude it out of caution.
It looked like there was nothing in /usr/lib/systemd/system-preset for sshd-vsock.socket that I found, and those should respect the mask for sshd-vsock.socket and wouldn't remove the /etc/systemd/system/sshd-vsock.socket symlink as I understand it.
I think that because it doesn't show up in busctl --activatable, and no packages I can find "Wants" sshd-vsock.socket explicitly that would probably work.
I just tried a fresh install of Fedora Linux 42 workstation and didn't experience the unintended unmasking with a dnf upgrade. That was reliable a few weeks ago. Maybe I just was unlucky with a package that was fixed?
Either way I think it is an option for people who use configuration management tools that can periodically check sshd-vsock.socket is still disabled.
Also for normal systemd services that need isolation from the vsock bridge you can use:
RestrictAddressFamilies=none # disable all af families RestrictAddressFamilies=AFINET # only AFINET RestrictAddressFamilies=~AFVSOCK # not AFVSOCK
The L4 bridge problem will be harder for projects that use CRI's that are not containerd like the k8s/podman/crun/runc.
If anyone on here is involved with them, or sandboxing tools like bubblewrap etc... Filtering address family 40 will still be required by default to have any real intra-container/pod/process network isolation on a node.
Thanks,
Greg
On Tue, Dec 30, 2025 at 12:12 PM <wish42offcl98 () posteo org> wrote: I have searched for that - instead of blacklisting the vsock module, I did myself two measures: - systemctl mask --now sshd-unix-local.socket to kill and mask the sshd unix socket created by that generator, - systemctl mask sshd-vsock.socket to mask the sshd vsock created by that generator (use --now if the socket has started or use systemctl stop... ).
Though, vsock untested but I found that source mentioning that socket. https://linux-audit.com/system-administration/commands/systemd-analyze/ Masking the sockets should stop them from starting again.
The vsock kernel module should not be blacklisted if some hypervisor features are required: https://libvirt.org/ssh-proxy.html https://wiki.qemu.org/Features/VirtioVsock
Greetings Alex
On 12/29/25 05:11, Jacob Bachmeyer wrote: On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
I did reach out to the systemd team, while I was working with the kernel security team and I encouraged others to do so if they think it will be productive.
There are sensitivities and frustrations that span all groups that make that conversation difficult, but I think someone with an established trust with the project could make forward progress.
That said, disabling this bridge will impact systemd's attempt to enable zero config for VMs. The container ecosystem as a whole hasn't exactly demonstrated that they will reciprocate. In a perfect world the container runtimes would protect their use case from the remainder of the shared kernel by default, unfortunately that is not what we have today.
I think if people with existing relationships reached out to the systemd team there could be a discussion on this specific issue, but it is completely understandable that when one use case appears to block your projects use case repeatedly, your willingness to make sacrifices will diminish over time.
I would just ask that people who reach out to the team take the above into account.
Greg
On Mon, Dec 29, 2025 at 11:44 AM Pat Gunn <pgunn01 () gmail com> wrote: Would it be productive to reach out to the systemd maintainers to ask them to have their software not do this and release a patch? This probably would break some software that depends on the bad behaviour, but the fallout from managing this may encourage them to think a little bit about security and good software design in the future (tempted to add several paragraphs of snark to this, but will omit).
On Mon, 29 Dec 2025 at 13:33, Greg Dahlman <dahlman () gmail com> wrote: Thank you Benjamin,
Yes, the kernel boot string is the only way to currently mitigate the listener. The L4 loopback issue, which is a trivial extension, can only be mitigated by patching the kernel the way chromeOS did or reliably filtering af address family 40 (afvsock) at the CRI, bubblewrap, etc… level with seccomp.
The current state of apparmor and SElinux will make filtering at that level opportunistic at best. It should also be noted that adding the kernel boot string will be a breaking change for users who expect the hypervisor to have ssh access to guests for administrative purposes. The trusted hypervisor, untrusted guest assumptions that vsock was based on are an important use case.
For the listener specifically, a fix that would support both use cases would require modifying systemd/systemd/src/ssh-generator/ssh-generator.c < https://github.com/systemd/systemd/blob/f76f0f99354b0485e3e13c2608bc26f969312687/src/ssh-generator/ssh-generator.c to allow control of the socket-activated sshd listener through a configuration file.
The ssh-generator is just emitting typical systemd socket activation unit files, and I think the path that would be most productive if the relevant stakeholders were willing or if the distro's were willing to to patch the upstream source.
As afvsock is a convenient socket() like interface, there are still some use cases/projects that will break, but the above is the path forward that seems to minimise the impact.
Greg
On Mon, Dec 29, 2025 at 10:17 AM Benjamin McMahon < benjamin.mcmahon () webpros com> wrote: To prevent the vsock-based sshd from auto-spawning, see
https://www.freedesktop.org/software/systemd/man/devel/systemd-ssh-generator.html In short: systemd.sshauto=no is the kernel-command-line setting which persists after reboots.
~Benjamin
From: Jacob Bachmeyer <jcb62281 () gmail com> Sent: Sunday, December 28, 2025 10:11 PM To: oss-security () lists openwall com <oss-security () lists openwall com>; Greg Dahlman <dahlman () gmail com> Subject: Re: [oss-security] Systemd vsock sshd
[You don't often get email from jcb62281 () gmail com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
Would it be productive to reach out to the systemd maintainers to ask them to have their software not do this and release a patch? This probably would break some software that depends on the bad behaviour, but the fallout from managing this may encourage them to think a little bit about security and good software design in the future (tempted to add several paragraphs of snark to this, but will omit).
On Mon, 29 Dec 2025 at 13:33, Greg Dahlman <dahlman () gmail com> wrote: Thank you Benjamin,
Yes, the kernel boot string is the only way to currently mitigate the listener. The L4 loopback issue, which is a trivial extension, can only be mitigated by patching the kernel the way chromeOS did or reliably filtering af address family 40 (afvsock) at the CRI, bubblewrap, etc… level with seccomp.
The current state of apparmor and SElinux will make filtering at that level opportunistic at best. It should also be noted that adding the kernel boot string will be a breaking change for users who expect the hypervisor to have ssh access to guests for administrative purposes. The trusted hypervisor, untrusted guest assumptions that vsock was based on are an important use case.
For the listener specifically, a fix that would support both use cases would require modifying systemd/systemd/src/ssh-generator/ssh-generator.c < https://github.com/systemd/systemd/blob/f76f0f99354b0485e3e13c2608bc26f969312687/src/ssh-generator/ssh-generator.c to allow control of the socket-activated sshd listener through a configuration file.
The ssh-generator is just emitting typical systemd socket activation unit files, and I think the path that would be most productive if the relevant stakeholders were willing or if the distro's were willing to to patch the upstream source.
As afvsock is a convenient socket() like interface, there are still some use cases/projects that will break, but the above is the path forward that seems to minimise the impact.
Greg
On Mon, Dec 29, 2025 at 10:17 AM Benjamin McMahon < benjamin.mcmahon () webpros com> wrote: To prevent the vsock-based sshd from auto-spawning, see https://www.freedesktop.org/software/systemd/man/devel/systemd-ssh-generator.html In short: systemd.sshauto=no is the kernel-command-line setting which persists after reboots.
~Benjamin
From: Jacob Bachmeyer <jcb62281 () gmail com> Sent: Sunday, December 28, 2025 10:11 PM To: oss-security () lists openwall com <oss-security () lists openwall com>; Greg Dahlman <dahlman () gmail com> Subject: Re: [oss-security] Systemd vsock sshd
[You don't often get email from jcb62281 () gmail com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
Thank you Benjamin,
Yes, the kernel boot string is the only way to currently mitigate the listener. The L4 loopback issue, which is a trivial extension, can only be mitigated by patching the kernel the way chromeOS did or reliably filtering af address family 40 (afvsock) at the CRI, bubblewrap, etc… level with seccomp.
The current state of apparmor and SElinux will make filtering at that level opportunistic at best. It should also be noted that adding the kernel boot string will be a breaking change for users who expect the hypervisor to have ssh access to guests for administrative purposes. The trusted hypervisor, untrusted guest assumptions that vsock was based on are an important use case.
For the listener specifically, a fix that would support both use cases would require modifying systemd/systemd/src/ssh-generator/ssh-generator.c <https://github.com/systemd/systemd/blob/f76f0f99354b0485e3e13c2608bc26f969312687/src/ssh-generator/ssh-generator.c> to allow control of the socket-activated sshd listener through a configuration file.
The ssh-generator is just emitting typical systemd socket activation unit files, and I think the path that would be most productive if the relevant stakeholders were willing or if the distro's were willing to to patch the upstream source.
As afvsock is a convenient socket() like interface, there are still some use cases/projects that will break, but the above is the path forward that seems to minimise the impact.
Greg
On Mon, Dec 29, 2025 at 10:17 AM Benjamin McMahon < benjamin.mcmahon () webpros com> wrote: To prevent the vsock-based sshd from auto-spawning, see https://www.freedesktop.org/software/systemd/man/devel/systemd-ssh-generator.html
In short: systemd.sshauto=no is the kernel-command-line setting which persists after reboots.
~Benjamin
From: Jacob Bachmeyer <jcb62281 () gmail com> Sent: Sunday, December 28, 2025 10:11 PM To: oss-security () lists openwall com <oss-security () lists openwall com>; Greg Dahlman <dahlman () gmail com> Subject: Re: [oss-security] Systemd vsock sshd
[You don't often get email from jcb62281 () gmail com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
The official way to disable this behavior requires appending "systemd.sshauto=no" to the kernel boot line.
https://man7.org/linux/man-pages/man8/systemd-ssh-generator.8.html
On Sun, Dec 28, 2025 at 9:11 PM Jacob Bachmeyer <jcb62281 () gmail com> wrote: On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
To prevent the vsock-based sshd from auto-spawning, see https://www.freedesktop.org/software/systemd/man/devel/systemd-ssh-generator.html
In short: systemd.sshauto=no is the kernel-command-line setting which persists after reboots.
~Benjamin
From: Jacob Bachmeyer <jcb62281 () gmail com> Sent: Sunday, December 28, 2025 10:11 PM To: oss-security () lists openwall com <oss-security () lists openwall com>; Greg Dahlman <dahlman () gmail com> Subject: Re: [oss-security] Systemd vsock sshd
[You don't often get email from jcb62281 () gmail com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
On 12/27/25 21:46, Greg Dahlman wrote: [...]
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration. Obvious question: what manual configuration is required to kill that listener?
-- Jacob
What did systemd say for the malicious vectors on this change?
Dec 28, 2025, 12:20 by dahlmanatgmail.comyen-mummify-yeah () duck com: This information is to be publicly released on January 6 per requirements of the distro list. This most likely impacts all recent VMs on most modern hypervisors. Thanks, Greg Dahlman Overview DuckDuckGo> did not detect any trackers. > > More <https://duckduckgo.com/-yPPlCVssOmY70ZnFvF-Wddd1QVblRSWUzjDgQW0TwaWlOck8n8Ygc4uUWFOC0MIJjOCjbYQbaDnBbkZETdwzuTGuVfdqEg6gB0ZExR5xaWYrVcTRoiFA6TclKbZwAFTyPnXg5X0PS0OyyEtjYQBJHEzpeSU-hRarcRIWDBFrNec0XCuV8O59Dplp9litlpyij8AzA8uvCO2VQI07SH4enlMeH4OCVIQSCgUfYvHtKDDZ9v0NuPkhurpI4yN5xx-Ac> Unable to verify sender identity Deactivate <https://duckduckgo.com/> This information is to be publicly released on January 6 per requirements of the distro list.
This most likely impacts all recent VMs on most modern hypervisors.
Thanks,
Greg Dahlman
Overview
Systemd v256 change - When the openssh-server package is installed on a VM with vsock support, systemd now automatically starts an sshd instance that listens on the afvsock socket in the global network namespace without any manual configuration.
vsock exists in the global namespace - Unlike "afinet" sockets, vsock connections are not bound to a particular network namespace. By default they are visible to every namespace on the host.
Violation of namespace isolation - Users normally expect that services bound in one namespace cannot be accessed from another namespace. The global‑namespace vsock listener breaks this expectation, allowing processes in any namespace to reach the sshd instance.
Enables malware and lateral movement - Malicious code that runs inside a container or sandbox can exploit the exposed vsock listener to connect to the host’s SSH daemon, thereby bypassing network‑segmentation rules and moving laterally across the host. This creates a powerful attack vector for malware that can spread from isolated workloads to the host or other guests without needing traditional network exposure.
Hard‑to‑audit data path - vsock provides a low‑level, kernel‑backed IPC channel that is opaque to many security tools. It can be used by sandboxed programs or containers to send commands or data to sandboxed programs or containers in a way that is difficult to monitor or audit.
vsock ss/netstat invisibility - The visibility feature is isolated in a network namespace, letting processes evade detection in an already hard‑to‑audit subsystem.
Trivial extension of active threats - If not already being leveraged, it would be trivial to extend [BRICKSTORM] and [shai- hulud] to take advantage of vsock as described above. As [BRICKSTORM] is already leveraging vsock on VmWare, it is unlikely it is not already being used by advanced threats.
[BRICKSTORM] > https://www.cisa.gov/news-events/analysis-reports/ar25-338a#AppC
[shai-hulud] > https://www.wiz.io/blog/shai-hulud-2-0-aftermath-ongoing-supply-chain-attack