From c110ec7a8888ac4ecb1e677f8655b59100085014 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Mon, 18 Nov 2024 22:27:53 -0500 Subject: [PATCH] Add `krun_add_disk2` API Adds an enum that describes the supported disk image variants. Adds the `krun_add_disk2` API that requires the user to specify the format of the disk image they're providing. The following formats are supported: - KRUN_DISK_FORMAT_RAW - KRUN_DISK_FORMAT_QCOW2 Signed-off-by: Jake Correnti --- include/libkrun.h | 58 +++++++++++++++++++++++++++++++++++++++--- src/libkrun/src/lib.rs | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/include/libkrun.h b/include/libkrun.h index 16619aac..d96a8c04 100644 --- a/include/libkrun.h +++ b/include/libkrun.h @@ -95,16 +95,25 @@ int32_t krun_set_root_disk(uint32_t ctx_id, const char *disk_path); int32_t krun_set_data_disk(uint32_t ctx_id, const char *disk_path); /** - * Adds a disk image to be used as a general partition for the microVM. + * Adds a disk image to be used as a general partition for the microVM. The only supported image + * format is "raw". * * This API is mutually exclusive with the deprecated krun_set_root_disk and * krun_set_data_disk methods and must not be used together. * + * SECURITY NOTE: + * Libkrun is not responsible for probing the disk image provided, as probing a disk image should + * be avoided. However, if one must probe the disk image, it falls onto the user. The disk image + * must only be probed once, and the probe of the image must be done before the first boot of the + * microVM. + * + * The disk image is assumed to be a Raw disk image, and trust is put into the user to + * correctly and securely probe the disk image, if at all. + * * Arguments: * "ctx_id" - the configuration context ID. * "block_id" - a null-terminated string representing the partition. - * "disk_path" - a null-terminated string representing the path leading to the disk image that - * contains the root file-system. + * "disk_path" - a null-terminated string representing the path leading to the disk image. * "read_only" - whether the mount should be read-only. Required if the caller does not have * write permissions (for disk images in /usr/share). * @@ -113,6 +122,49 @@ int32_t krun_set_data_disk(uint32_t ctx_id, const char *disk_path); */ int32_t krun_add_disk(uint32_t ctx_id, const char *block_id, const char *disk_path, bool read_only); +/* Supported disk image formats */ +#define KRUN_DISK_FORMAT_RAW 0 +#define KRUN_DISK_FORMAT_QCOW2 1 +/** + * Adds a disk image to be used as a general partition for the microVM. The supported + * image formats are: "raw" and "qcow2". + * + * This API is mutually exclusive with the deprecated krun_set_root_disk and + * krun_set_data_disk methods and must not be used together. + * + * SECURITY NOTE: + * Libkrun is not responsible for probing the disk image provided, as probing a disk image should + * be avoided. However, if one must probe the disk image, it falls onto the user. The disk image + * must only be probed once, and the probe of the image must be done before the first boot of the + * microVM. + * + * The disk image may be in the Raw or Qcow2 format, but trust is put into the user to + * correctly and securely probe the disk image, if at all. + * + * It is possible for a Raw disk image to be probed, and have the guest write a Qcow2 + * image header into the Raw file's first sector. If the disk image is then re-probed, and the + * user tells libkrun it is a Qcow2, then libkrun will boot the disk image as a Qcow2. Qcow2 + * files can, and will, open other files. The guest will most likely have access to the data in those + * files, essentially giving the guest access to any file on the host system the disk emulation + * has access to. + * + * Arguments: + * "ctx_id" - the configuration context ID. + * "block_id" - a null-terminated string representing the partition. + * "disk_path" - a null-terminated string representing the path leading to the disk image. + * "disk_format" - the disk image format (i.e. KRUN_DISK_FORMAT_{RAW, QCOW2}) + * "read_only" - whether the mount should be read-only. Required if the caller does not have + * write permissions (for disk images in /usr/share). + * + * Returns: + * Zero on success or a negative error number on failure. + */ +int32_t krun_add_disk2(uint32_t ctx_id, + const char *block_id, + const char *disk_path, + uint32_t disk_format, + bool read_only); + /** * NO LONGER SUPPORTED. DO NOT USE. * diff --git a/src/libkrun/src/lib.rs b/src/libkrun/src/lib.rs index 058353fe..0f864f17 100644 --- a/src/libkrun/src/lib.rs +++ b/src/libkrun/src/lib.rs @@ -534,6 +534,53 @@ pub unsafe extern "C" fn krun_add_disk( KRUN_SUCCESS } +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +#[cfg(feature = "blk")] +pub unsafe extern "C" fn krun_add_disk2( + ctx_id: u32, + c_block_id: *const c_char, + c_disk_path: *const c_char, + disk_format: u32, + read_only: bool, +) -> i32 { + let disk_path = match CStr::from_ptr(c_disk_path).to_str() { + Ok(disk) => disk, + Err(_) => return -libc::EINVAL, + }; + + let block_id = match CStr::from_ptr(c_block_id).to_str() { + Ok(block_id) => block_id, + Err(_) => return -libc::EINVAL, + }; + + let format = match disk_format { + 0 => ImageType::Raw, + 1 => ImageType::Qcow2, + _ => { + // Do not continue if the user cannot specify a valid disk format + return -libc::EINVAL; + } + }; + + match CTX_MAP.lock().unwrap().entry(ctx_id) { + Entry::Occupied(mut ctx_cfg) => { + let cfg = ctx_cfg.get_mut(); + let block_device_config = BlockDeviceConfig { + block_id: block_id.to_string(), + cache_type: CacheType::Writeback, + disk_image_path: disk_path.to_string(), + disk_image_format: format, + is_disk_read_only: read_only, + }; + cfg.add_block_cfg(block_device_config); + } + Entry::Vacant(_) => return -libc::ENOENT, + } + + KRUN_SUCCESS +} + #[allow(clippy::missing_safety_doc)] #[no_mangle] #[cfg(feature = "blk")]