Skip to content

Commit 0cd9308

Browse files
committed
krun_set_exec now also preserves raw argv (passed as base64-encoded variables) which is needed when booting FreeBSD
Signed-off-by: Jan Noha <nohajc@gmail.com>
1 parent 3455eff commit 0cd9308

4 files changed

Lines changed: 41 additions & 2 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/libkrun/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ polly = { path = "../polly" }
3333
utils = { path = "../utils" }
3434
vmm = { path = "../vmm" }
3535
rand = "0.9.2"
36+
base64 = "0.22.1"
3637

3738
[target.'cfg(target_os = "macos")'.dependencies]
3839
hvf = { path = "../hvf" }

src/libkrun/src/lib.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[macro_use]
22
extern crate log;
33

4+
use base64::prelude::*;
45
use crossbeam_channel::unbounded;
56
#[cfg(feature = "blk")]
67
use devices::virtio::block::ImageType;
@@ -1190,6 +1191,24 @@ unsafe fn collapse_str_array(array: &[*const c_char]) -> Result<String, std::str
11901191
Ok(strvec.join(" "))
11911192
}
11921193

1194+
// unlike collapse_str_array, this doesn't do the UTF-8 conversion
1195+
// and just keeps the null-terminated strings as raw bytes
1196+
unsafe fn flatten_cstr_array(array: &[*const c_char]) -> Vec<u8> {
1197+
let mut bytevec = Vec::new();
1198+
1199+
for item in array.iter().take(MAX_ARGS) {
1200+
if item.is_null() {
1201+
break;
1202+
} else {
1203+
let cs = CStr::from_ptr(*item);
1204+
bytevec.extend_from_slice(cs.to_bytes());
1205+
bytevec.push(0);
1206+
}
1207+
}
1208+
1209+
bytevec
1210+
}
1211+
11931212
#[allow(clippy::format_collect)]
11941213
#[allow(clippy::missing_safety_doc)]
11951214
#[no_mangle]
@@ -1220,7 +1239,14 @@ pub unsafe extern "C" fn krun_set_exec(
12201239
"".to_string()
12211240
};
12221241

1223-
let env = if !c_envp.is_null() {
1242+
let args_raw = if !c_argv.is_null() {
1243+
let argv_array: &[*const c_char] = slice::from_raw_parts(c_argv, MAX_ARGS);
1244+
flatten_cstr_array(argv_array)
1245+
} else {
1246+
vec![]
1247+
};
1248+
1249+
let mut env = if !c_envp.is_null() {
12241250
let envp_array: &[*const c_char] = slice::from_raw_parts(c_envp, MAX_ARGS);
12251251
match collapse_str_array(envp_array) {
12261252
Ok(s) => s,
@@ -1235,6 +1261,11 @@ pub unsafe extern "C" fn krun_set_exec(
12351261
.collect()
12361262
};
12371263

1264+
// KRUN_INIT_ARGVXX="<base64>" must have at most 128 bytes (KENV_MVALLEN on FreeBSD)
1265+
for (i, args_part) in args_raw.chunks(78).enumerate() {
1266+
env += &format!(" KRUN_INIT_ARGV{}={}", i, BASE64_STANDARD.encode(args_part));
1267+
}
1268+
12381269
match CTX_MAP.lock().unwrap().entry(ctx_id) {
12391270
Entry::Occupied(mut ctx_cfg) => {
12401271
let cfg = ctx_cfg.get_mut();

src/vmm/src/builder.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,11 +572,15 @@ pub fn build_microvm(
572572
)?;
573573

574574
let vcpu_config = vm_resources.vcpu_config();
575+
let mut kernel_is_freebsd = false;
575576

576577
// Clone the command-line so that a failed boot doesn't pollute the original.
577578
#[allow(unused_mut)]
578579
let mut kernel_cmdline = Cmdline::new(arch::CMDLINE_MAX_SIZE);
579580
if let Some(cmdline) = payload_config.kernel_cmdline {
581+
if cmdline.starts_with("FreeBSD:") {
582+
kernel_is_freebsd = true;
583+
}
580584
kernel_cmdline.insert_str(cmdline.as_str()).unwrap();
581585
} else if let Some(cmdline) = &vm_resources.kernel_cmdline.prolog {
582586
kernel_cmdline.insert_str(cmdline).unwrap();
@@ -1042,7 +1046,9 @@ pub fn build_microvm(
10421046
}
10431047

10441048
if let Some(s) = &vm_resources.kernel_cmdline.epilog {
1045-
vmm.kernel_cmdline.insert_str(s).unwrap();
1049+
if !kernel_is_freebsd {
1050+
vmm.kernel_cmdline.insert_str(s).unwrap();
1051+
}
10461052
};
10471053

10481054
// Write the kernel command line to guest memory. This is x86_64 specific, since on

0 commit comments

Comments
 (0)