oss-sec mailing list archives

Re: Systemd vsock sshd


From: Carlos Rodriguez-Fernandez <carlosrodrifernandez () gmail com>
Date: Fri, 2 Jan 2026 22:27:50 -0700

Greg,

I don't know if this is exactly what you are looking for in SELinux but here is an example of deny vsock for privileged and unprivileged containers with cil:


```

# on terminal 1

nc --vsock -l 4000


# on terminal 2

podman run -it fedora:latest /bin/bash

dnf install nmap-ncat

nc --vsock 1 4000

# Type here "Hello" and should show up on terminal 1

```


```

cat > container_vsock.cil <<EOF
(deny container_t self (vsock_socket (create read write bind connect getattr setattr ioctl getopt setopt shutdown sendto recvfrom accept listen)))

(deny spc_t self (vsock_socket (create read write bind connect getattr setattr ioctl getopt setopt shutdown sendto recvfrom accept listen)))

EOF

semodule -i container_vsock.cil

```

Now repeat the example before to validate that the container can't use vsock. You can remove the cil policy with `semodule -r container_vsock`.

This can be done for any selinux process context, not just container_t or spc_t.


Regards,

Carlos R.F.



On 1/2/26 5:48 PM, Greg Dahlman wrote:
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.ssh_auto=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=AF_INET # only AF_INET
RestrictAddressFamilies=~AF_VSOCK # not AF_VSOCK


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 **af_vsock** socket
in
    the **global network namespace** without any manual configuration.
Obvious question:  what manual configuration is required to kill that
listener?


-- Jacob


Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature


Current thread: