Skip to content

Commit a9a286d

Browse files
committed
libkrun, vsock: Add explicit vsock configuration API
Refactor the vsock device to explicitly configure usage of INET and UNIX proxies. Add new public API functions for explicit vsock control: - krun_disable_implicit_vsock(): Disable the implicit vsock device - krun_add_vsock(): Add vsock with explicit TSI feature flags krun_add_vsock() requires krun_disable_implicit_vsock() to be called first, otherwise an error is returned - we only support 1 vsock device. Add a check in krun_set_port_map() and krun_add_vsock_port() to ensure vsock is enabled. Signed-off-by: Matej Hrica <[email protected]>
1 parent 06b8a50 commit a9a286d

File tree

8 files changed

+223
-90
lines changed

8 files changed

+223
-90
lines changed

include/libkrun.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,10 @@ int32_t krun_add_virtiofs2(uint32_t ctx_id,
327327
as required by gvproxy in vfkit mode. */
328328
#define NET_FLAG_VFKIT 1 << 0
329329

330+
/* TSI (Transparent Socket Impersonation) feature flags for vsock */
331+
#define KRUN_TSI_HIJACK_INET (1 << 0)
332+
#define KRUN_TSI_HIJACK_UNIX (1 << 1)
333+
330334
/* Taken from uapi/linux/virtio_net.h */
331335
#define NET_FEATURE_CSUM 1 << 0
332336
#define NET_FEATURE_GUEST_CSUM 1 << 1
@@ -862,6 +866,27 @@ int32_t krun_add_vsock_port2(uint32_t ctx_id,
862866
uint32_t port,
863867
const char *c_filepath,
864868
bool listen);
869+
870+
/**
871+
* Add a vsock device with specified TSI features.
872+
*
873+
* By default, libkrun creates a vsock device implicitly with TSI hijacking
874+
* enabled based on heuristics. Calling this function overrides the implicit
875+
* behavior and explicitly configures the vsock device.
876+
*
877+
* Currently only one vsock device is supported. Calling this function
878+
* multiple times will return an error.
879+
*
880+
* Arguments:
881+
* "ctx_id" - the configuration context ID.
882+
* "tsi_features" - bitmask of TSI features (KRUN_TSI_HIJACK_INET, KRUN_TSI_HIJACK_UNIX)
883+
* Use 0 to add vsock without any TSI hijacking.
884+
*
885+
* Returns:
886+
* Zero on success or a negative error number on failure.
887+
*/
888+
int32_t krun_add_vsock(uint32_t ctx_id, uint32_t tsi_features);
889+
865890
/**
866891
* Returns the eventfd file descriptor to signal the guest to shut down orderly. This must be
867892
* called before starting the microVM with "krun_start_event". Only available in libkrun-efi.
@@ -1009,6 +1034,20 @@ int32_t krun_nitro_set_start_flags(uint32_t ctx_id, uint64_t start_flags);
10091034
*/
10101035
int32_t krun_disable_implicit_console(uint32_t ctx_id);
10111036

1037+
/**
1038+
* Disable the implicit vsock device.
1039+
*
1040+
* By default, libkrun creates a vsock device automatically. This function
1041+
* disables that behavior entirely - no vsock device will be created.
1042+
*
1043+
* Arguments:
1044+
* "ctx_id" - the configuration context ID.
1045+
*
1046+
* Returns:
1047+
* Zero on success or a negative error number on failure.
1048+
*/
1049+
int32_t krun_disable_implicit_vsock(uint32_t ctx_id);
1050+
10121051
/*
10131052
* Specify the value of `console=` in the kernel commandline.
10141053
*

src/devices/src/virtio/vsock/device.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::super::{
1818
};
1919
use super::muxer::VsockMuxer;
2020
use super::packet::VsockPacket;
21+
use super::TsiFlags;
2122
use super::{defs, defs::uapi};
2223
use crate::virtio::InterruptTransport;
2324

@@ -52,8 +53,7 @@ impl Vsock {
5253
host_port_map: Option<HashMap<u16, u16>>,
5354
queues: Vec<VirtQueue>,
5455
unix_ipc_port_map: Option<HashMap<u32, (PathBuf, bool)>>,
55-
enable_tsi: bool,
56-
enable_tsi_unix: bool,
56+
tsi_flags: TsiFlags,
5757
) -> super::Result<Vsock> {
5858
let mut queue_events = Vec::new();
5959
for _ in 0..queues.len() {
@@ -66,13 +66,7 @@ impl Vsock {
6666

6767
Ok(Vsock {
6868
cid,
69-
muxer: VsockMuxer::new(
70-
cid,
71-
host_port_map,
72-
unix_ipc_port_map,
73-
enable_tsi,
74-
enable_tsi_unix,
75-
),
69+
muxer: VsockMuxer::new(cid, host_port_map, unix_ipc_port_map, tsi_flags),
7670
queue_rx,
7771
queue_tx,
7872
queues,
@@ -90,21 +84,13 @@ impl Vsock {
9084
cid: u64,
9185
host_port_map: Option<HashMap<u16, u16>>,
9286
unix_ipc_port_map: Option<HashMap<u32, (PathBuf, bool)>>,
93-
enable_tsi: bool,
94-
enable_tsi_unix: bool,
87+
tsi_flags: TsiFlags,
9588
) -> super::Result<Vsock> {
9689
let queues: Vec<VirtQueue> = defs::QUEUE_SIZES
9790
.iter()
9891
.map(|&max_size| VirtQueue::new(max_size))
9992
.collect();
100-
Self::with_queues(
101-
cid,
102-
host_port_map,
103-
queues,
104-
unix_ipc_port_map,
105-
enable_tsi,
106-
enable_tsi_unix,
107-
)
93+
Self::with_queues(cid, host_port_map, queues, unix_ipc_port_map, tsi_flags)
10894
}
10995

11096
pub fn id(&self) -> &str {

src/devices/src/virtio/vsock/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,39 @@ mod tsi_stream;
2121
mod unix;
2222

2323
pub use self::defs::uapi::VIRTIO_ID_VSOCK as TYPE_VSOCK;
24+
pub use self::defs::TsiFlags;
2425
pub use self::device::Vsock;
2526

27+
use bitflags::bitflags;
2628
use vm_memory::GuestMemoryError;
2729

2830
mod defs {
31+
use super::bitflags;
32+
33+
bitflags! {
34+
/// TSI (Transparent Socket Impersonation) feature flags.
35+
///
36+
/// These flags control which socket families are hijacked by TSI.
37+
pub struct TsiFlags: u32 {
38+
/// Hijack AF_INET and AF_INET6 sockets
39+
const HIJACK_INET = 1 << 0;
40+
/// Hijack AF_UNIX sockets
41+
const HIJACK_UNIX = 1 << 1;
42+
}
43+
}
44+
45+
impl TsiFlags {
46+
/// Returns true if any TSI hijacking is enabled.
47+
pub fn tsi_enabled(&self) -> bool {
48+
!self.is_empty()
49+
}
50+
}
51+
52+
impl Default for TsiFlags {
53+
fn default() -> Self {
54+
TsiFlags::empty()
55+
}
56+
}
2957
/// Device ID used in MMIO device identification.
3058
/// Because Vsock is unique per-vm, this ID can be hardcoded.
3159
pub const VSOCK_DEV_ID: &str = "vsock";

src/devices/src/virtio/vsock/muxer.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use super::timesync::TimesyncThread;
1616
use super::tsi_dgram::TsiDgramProxy;
1717
use super::tsi_stream::TsiStreamProxy;
1818
use super::unix::UnixProxy;
19+
use super::TsiFlags;
1920
use super::VsockError;
2021
use crossbeam_channel::{unbounded, Sender};
2122
use utils::epoll::{ControlOperation, Epoll, EpollEvent, EventSet};
@@ -106,17 +107,15 @@ pub struct VsockMuxer {
106107
proxy_map: ProxyMap,
107108
reaper_sender: Option<Sender<u64>>,
108109
unix_ipc_port_map: Option<HashMap<u32, (PathBuf, bool)>>,
109-
enable_tsi: bool,
110-
enable_tsi_unix: bool,
110+
tsi_flags: TsiFlags,
111111
}
112112

113113
impl VsockMuxer {
114114
pub(crate) fn new(
115115
cid: u64,
116116
host_port_map: Option<HashMap<u16, u16>>,
117117
unix_ipc_port_map: Option<HashMap<u32, (PathBuf, bool)>>,
118-
enable_tsi: bool,
119-
enable_tsi_unix: bool,
118+
tsi_flags: TsiFlags,
120119
) -> Self {
121120
VsockMuxer {
122121
cid,
@@ -129,8 +128,7 @@ impl VsockMuxer {
129128
proxy_map: Arc::new(RwLock::new(HashMap::new())),
130129
reaper_sender: None,
131130
unix_ipc_port_map,
132-
enable_tsi,
133-
enable_tsi_unix,
131+
tsi_flags,
134132
}
135133
}
136134

@@ -285,8 +283,16 @@ impl VsockMuxer {
285283
defs::SOCK_STREAM => {
286284
debug!("proxy create stream");
287285
let id = ((req.peer_port as u64) << 32) | (defs::TSI_PROXY_PORT as u64);
288-
if req.family as i32 == libc::AF_UNIX && !self.enable_tsi_unix {
289-
warn!("rejecting tcp unix proxy because tsi_unix is disabled");
286+
if req.family as i32 == libc::AF_UNIX
287+
&& !self.tsi_flags.contains(TsiFlags::HIJACK_UNIX)
288+
{
289+
warn!("rejecting stream unix proxy because HIJACK_UNIX is disabled");
290+
return;
291+
}
292+
if (req.family as i32 == libc::AF_INET || req.family as i32 == libc::AF_INET6)
293+
&& !self.tsi_flags.contains(TsiFlags::HIJACK_INET)
294+
{
295+
warn!("rejecting stream inet proxy because HIJACK_INET is disabled");
290296
return;
291297
}
292298
match TsiStreamProxy::new(
@@ -312,8 +318,16 @@ impl VsockMuxer {
312318
defs::SOCK_DGRAM => {
313319
debug!("proxy create dgram");
314320
let id = ((req.peer_port as u64) << 32) | (defs::TSI_PROXY_PORT as u64);
315-
if req.family as i32 == libc::AF_UNIX && !self.enable_tsi_unix {
316-
warn!("rejecting udp unix proxy because tsi_unix is disabled");
321+
if req.family as i32 == libc::AF_UNIX
322+
&& !self.tsi_flags.contains(TsiFlags::HIJACK_UNIX)
323+
{
324+
warn!("rejecting dgram unix proxy because HIJACK_UNIX is disabled");
325+
return;
326+
}
327+
if (req.family as i32 == libc::AF_INET || req.family as i32 == libc::AF_INET6)
328+
&& !self.tsi_flags.contains(TsiFlags::HIJACK_INET)
329+
{
330+
warn!("rejecting dgram inet proxy because HIJACK_INET is disabled");
317331
return;
318332
}
319333
match TsiDgramProxy::new(
@@ -498,14 +512,18 @@ impl VsockMuxer {
498512
}
499513

500514
match pkt.dst_port() {
501-
defs::TSI_PROXY_CREATE if self.enable_tsi => self.process_proxy_create(pkt),
502-
defs::TSI_CONNECT if self.enable_tsi => self.process_connect(pkt),
503-
defs::TSI_GETNAME if self.enable_tsi => self.process_getname(pkt),
504-
defs::TSI_SENDTO_ADDR if self.enable_tsi => self.process_sendto_addr(pkt),
505-
defs::TSI_SENDTO_DATA if self.enable_tsi => self.process_sendto_data(pkt),
506-
defs::TSI_LISTEN if self.enable_tsi => self.process_listen_request(pkt),
507-
defs::TSI_ACCEPT if self.enable_tsi => self.process_accept_request(pkt),
508-
defs::TSI_PROXY_RELEASE if self.enable_tsi => self.process_proxy_release(pkt),
515+
defs::TSI_PROXY_CREATE if self.tsi_flags.tsi_enabled() => {
516+
self.process_proxy_create(pkt)
517+
}
518+
defs::TSI_CONNECT if self.tsi_flags.tsi_enabled() => self.process_connect(pkt),
519+
defs::TSI_GETNAME if self.tsi_flags.tsi_enabled() => self.process_getname(pkt),
520+
defs::TSI_SENDTO_ADDR if self.tsi_flags.tsi_enabled() => self.process_sendto_addr(pkt),
521+
defs::TSI_SENDTO_DATA if self.tsi_flags.tsi_enabled() => self.process_sendto_data(pkt),
522+
defs::TSI_LISTEN if self.tsi_flags.tsi_enabled() => self.process_listen_request(pkt),
523+
defs::TSI_ACCEPT if self.tsi_flags.tsi_enabled() => self.process_accept_request(pkt),
524+
defs::TSI_PROXY_RELEASE if self.tsi_flags.tsi_enabled() => {
525+
self.process_proxy_release(pkt)
526+
}
509527
_ => {
510528
if pkt.op() == uapi::VSOCK_OP_RW {
511529
self.process_dgram_rw(pkt);

0 commit comments

Comments
 (0)