Skip to content

Commit a4232cb

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 c401244 commit a4232cb

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;
@@ -1191,6 +1192,24 @@ unsafe fn collapse_str_array(array: &[*const c_char]) -> Result<String, std::str
11911192
Ok(strvec.join(" "))
11921193
}
11931194

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

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

1265+
// KRUN_INIT_ARGVXX="<base64>" must have at most 128 bytes (KENV_MVALLEN on FreeBSD)
1266+
for (i, args_part) in args_raw.chunks(78).enumerate() {
1267+
env += &format!(" KRUN_INIT_ARGV{}={}", i, BASE64_STANDARD.encode(args_part));
1268+
}
1269+
12391270
match CTX_MAP.lock().unwrap().entry(ctx_id) {
12401271
Entry::Occupied(mut ctx_cfg) => {
12411272
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
@@ -578,11 +578,15 @@ pub fn build_microvm(
578578
)?;
579579

580580
let vcpu_config = vm_resources.vcpu_config();
581+
let mut kernel_is_freebsd = false;
581582

582583
// Clone the command-line so that a failed boot doesn't pollute the original.
583584
#[allow(unused_mut)]
584585
let mut kernel_cmdline = Cmdline::new(arch::CMDLINE_MAX_SIZE);
585586
if let Some(cmdline) = payload_config.kernel_cmdline {
587+
if cmdline.starts_with("FreeBSD:") {
588+
kernel_is_freebsd = true;
589+
}
586590
kernel_cmdline.insert_str(cmdline.as_str()).unwrap();
587591
} else if let Some(cmdline) = &vm_resources.kernel_cmdline.prolog {
588592
kernel_cmdline.insert_str(cmdline).unwrap();
@@ -1063,7 +1067,9 @@ pub fn build_microvm(
10631067
}
10641068

10651069
if let Some(s) = &vm_resources.kernel_cmdline.epilog {
1066-
vmm.kernel_cmdline.insert_str(s).unwrap();
1070+
if !kernel_is_freebsd {
1071+
vmm.kernel_cmdline.insert_str(s).unwrap();
1072+
}
10671073
};
10681074

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

0 commit comments

Comments
 (0)