junixsocket-vsock
Use AF_VSOCK sockets from Java!
junixsocket is an Apache 2.0-licensed Java/JNI library that allows the use of Unix Domain Sockets (AF_UNIX sockets), and other address/protocol families (such as TIPC and VSOCK), from Java.
What is AF_VSOCK?
Virtual sockets (“Vsock”) allow communication between virtual machines (VMs, “guests”) and their hosts, using practically the same API that is used for Internet (AF_INET), Unix Domain (AF_UNIX), etc., sockets.
Addressing
The addressing schemee, in C it's struct sockaddr_vm
, mainly has two address parameters, the port
(an unsigned 32-bit integer value) and a CID (Context identifier, also a 32-bit integer).
Ports between 0 and 1023 are privileged ports, so they can only be created with the correct set of
permissions. There is a wildcard port “any” (VMADDR_PORT_ANY
), indicating that a random port
should be bound to.
There are some special CID values, such as “hypervisor” (the programming running the VM,
VMADDR_CID_HYPERVISOR
) and “host” (the machine the hypervisor runs on, VMADDR_CID_HOST
), as well
as a wildcard CID (“any available CID”, VMADDR_CID_ANY
).
Some implementations, such as Linux, provide a “local-only” CID for loopback testing
(VMADDR_CID_RESERVED
), other systems, such as macOS, allow retrieving the CID of the guest in lieu
of a constant (junixsocket provides wrapper code for macOS to handle a local-only CID transparently
to the user).
Limitations
AF_VSOCK
sockets are not available on all Operating systems, and may only be available from within
a VM. Moreover, not all connection types (such as datagrams) may be available.
Generally, support for AF_VSOCK
may differ from a system that is not set up for virtualization, a
system that is a host running a hypervisor, and a system being run as a guest on such a host.
On Linux, depending on kernel version and configuration, no support may be available, some support
(stream sockets only), or both streams and datagrams. Host kernel and guest kernel implementations
may be different (VHOST vs VIRTIO). Permissions may prevent a user from accessing VSOCK (e.g., when
/dev/vsock
is inaccessible).
In some Linux environments, you may need to modprobe vsock_loopback
for junixsocket-selftest
to pass.
On macOS, AF_VSOCK
is currently only available from within a virtual machine, and, when using
Virtualization.framework
, a VZVirtioSocketDeviceConfiguration
must be present. In that case,
the communication with the outside world is implementation-specific (via a VZVirtioSocketDevice
configured for a VZVirtualMachine
.). Communication with the guest from the host is then
facilitated via custom means, for example via a shared host-side AF_UNIX
socket that acts as a
proxy to the guest-side AF_VSOCK
sockets.
When using qemu from Linux, add -device vhost-vsock-pci,guest-cid=3
to enable VSOCK in the guest
VM (optionally, change 3 to the desired guest CID). Make sure that, on the host, /dev/vhost-vsock
is accessible by your process, and maybe use modprobe vhost_vsock
to ensure that the host-side
vsock implementation is loaded.
How can I use AF_VSOCK
sockets in Java with junixsocket?
Selftest
First of all, please run the junixsocket selftest to make sure everything works as expected.
Maven dependencies
Add the following dependency to your project (replace X.Y.Z. with the latest junixsocket version).
<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
<artifactId>junixsocket-core</artifactId>
<version>X.Y.Z</version> <type>pom</type>
</dependency>
<dependency>
<groupId>com.kohlschutter.junixsocket</groupId>
<artifactId>junixsocket-vsock</artifactId>
<version>X.Y.Z</version>
</dependency>
Working with AF_VSOCK
sockets: AFVSOCKSocketAddress
One starting point to using VSOCK with junixsocket is a custom SocketAddress
class,
AFVSOCKSocketAddress
.
Having such an address lets you work with with AFVSOCKSocket
, AFVSOCKServerSocket
,
AFVSOCKSocketChannel
, etc.
There are several ways of creating an AFVSOCKSocketAddress
, such as:
-
AFVSOCKSocketAddress.ofPortAndCID
(takes aport
andCID
value, as well as an optional, precedingjavaPort
). CID constants are available throughAFVSOCKSocketAddress
. -
AFVSOCKSocketAddress.ofHostPort
(ofHypervisorPort
,ofLocalPort
,ofPortWithAnyCID
) (takes aport
and uses the corresponding CID). -
AFVSOCKSocketAddress.ofAnyPort
(takes a random port for binding)
ofPortAndCID
allows specifying a javaPort
value, which emulates an InetSocketAddress
port
very much like AFUNIXSocketAddress
does, to enable using these addresses in Java programs that
rely on port numbers. Such javaPort
values are not carried over to the file descriptor.
Please file a New Issue if you encounter any problems.
“Local CID”
Inspired by support in modern Linux kernels, a special CID of VMADDR_CID_HOST
(=1
) is available
in junixsocket.
If no native support for this CID is available in the kernel, an attempt is made to use the system's local CID instead (which is resolved upon initialization of the native library).
The resolved local CID can be obtained via AFVSOCKSocket.getLocalCID()
.
If the system's local CID cannot be resolved, VMADDR_CID_ANY
(=-1
) is used as a fallback, unless
access to /dev/vsock
was denied, which implies VMADDR_CID_HOST
(=2
).
Capabilities, Exceptions
junixsocket provides capability checks (via AFSocketCapability
, CAPABILITY_VSOCK
and
CAPABILITY_VSOCK_DGRAM
) to ensure that the environment the program runs in is well-understood
before execution.
Moreover, if some known issues are detected during connect
or bind
, a custom
InvalidSocketException
may be thrown.
Security aspects, known vulnerabilities
AF_VSOCK
connections were not designed to be reachable from the public Internet.
There are known security vulnerabilities in older Linux kernels and hypervisors related to VSOCK
,
but not to junixsocket's adaptation.
It is generally recommended to use up-to-date versions of the kernel/hypervisors.
Recent known Linux Kernel / qemu issues related to VSOCK
(list is non-exhausive):
-
CVE-2022-26354: memory leakage in vhost-vsock :— Affected QEMU versions <= 6.2.0.
-
CVE-2021-26708: local privilege escalation in Linux before 5.10.13
-
CVE-2019-18960: buffer overflow in Firecracker version 0.18/0.19.0.
-
CVE-2018-14625: uncontrolled kernel read from VM guest in Linux kernel
NOTE: These security issues are not related to junixsocket's implementation. They refer to vulnerabilities in older versions of the Linux/qemu/Firecracker kernel.
References
-
vsock(7) Linux manual
-
VSOCK(4) macOS Device Drivers Manual (xcode man-page, mirror)
-
Features/VirtioVsock QEMU Wiki
-
AF_VSOCK: nested VMs and loopback support available … since Linux 5.5/5.6
See also
- Hyper-V (related technology); Wikipedia page