rework secure boot override
This commit is contained in:
73
Cargo.lock
generated
73
Cargo.lock
generated
@ -4,7 +4,7 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "barnacle"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"uefi",
|
||||
@ -19,9 +19,9 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -31,18 +31,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.51"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -64,14 +61,14 @@ checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -87,6 +84,17 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucs2"
|
||||
version = "0.3.2"
|
||||
@ -98,33 +106,46 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uefi"
|
||||
version = "0.19.1"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5607fef843201070ed442fa257c7a944fae963fac7d4620612123192eb4d844"
|
||||
checksum = "07ead9f748a4646479b850add36b527113a80e80a7e0f44d7b0334291850dcc5"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"ptr_meta",
|
||||
"ucs2",
|
||||
"uefi-macros",
|
||||
"uefi-raw",
|
||||
"uguid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi-macros"
|
||||
version = "0.10.0"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8099684193f2d99f7f130951f4054a1591ff7da370e2b33d7a71f0434920499"
|
||||
checksum = "26a7b1c2c808c3db854a54d5215e3f7e7aaf5dcfbce095598cba6af29895695d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi-raw"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864ac69eadd877bfb34e7814be1928122ed0057d9f975169a56ee496aa7bdfd7"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"ptr_meta",
|
||||
"uguid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uefi-services"
|
||||
version = "0.16.0"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f75daa44f951cc1d9dc68d98cabc06ddbccc221d7bd21222271be5d7ac526a9d"
|
||||
checksum = "a79fcb420624743c895bad0f9480fbc2f64e7c8d8611fb1ada6bdd799942feb4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
@ -132,7 +153,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
name = "uguid"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
checksum = "1ef516f0806c5f61da6aa95125d0eb2d91cc95b2df426c06bde8be657282aee5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "barnacle"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
@ -15,6 +15,6 @@ bench = false
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.17"
|
||||
uefi = "0.19.1"
|
||||
uefi-services = "0.16.0"
|
||||
log = "0.4.20"
|
||||
uefi = "0.26.0"
|
||||
uefi-services = "0.23.0"
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
use core::{ffi::c_void, mem::MaybeUninit};
|
||||
|
||||
use uefi::{
|
||||
guid,
|
||||
prelude::BootServices,
|
||||
proto::device_path::{build, DevicePath},
|
||||
Identify, Status,
|
||||
Guid, Identify, Status,
|
||||
};
|
||||
|
||||
const LOADFILE2_GUID: uefi::Guid = guid!("4006c0c1-fcb3-403e-996d-4a6c8724e06d");
|
||||
const LINUX_INITRD_DEVICE_GUID: uefi::Guid = guid!("5568e427-68fc-4f3d-ac74-ca555231cc68");
|
||||
const LOADFILE2_GUID: Guid = Guid::parse_or_panic("4006c0c1-fcb3-403e-996d-4a6c8724e06d");
|
||||
const LINUX_INITRD_DEVICE_GUID: Guid = Guid::parse_or_panic("5568e427-68fc-4f3d-ac74-ca555231cc68");
|
||||
|
||||
/// Extends the LoadFile2 interface with initrd buffer location and size
|
||||
pub struct Loader {
|
||||
@ -71,7 +70,7 @@ pub fn make_initrd_device_path<'a>(buf: &'a mut [MaybeUninit<u8>; 256]) -> &'a D
|
||||
/// Copies data if valid
|
||||
fn initrd_loadfile2(
|
||||
this: *const Loader,
|
||||
_proto: *const c_void,
|
||||
_file_path: *const c_void,
|
||||
_boot_policy: bool,
|
||||
size: *mut usize,
|
||||
buf: *mut c_void,
|
||||
@ -83,7 +82,7 @@ fn initrd_loadfile2(
|
||||
*size = (*this).size;
|
||||
return Status::BUFFER_TOO_SMALL;
|
||||
}
|
||||
core::ptr::copy_nonoverlapping((*this).buf, buf, (*this).size);
|
||||
(*this).buf.copy_to(buf, (*this).size);
|
||||
}
|
||||
Status::SUCCESS
|
||||
}
|
||||
|
||||
17
src/linux.rs
17
src/linux.rs
@ -8,7 +8,7 @@ use uefi::{
|
||||
use crate::{
|
||||
initrd::{install_initrd, make_loader},
|
||||
pe::BootSections,
|
||||
secureboot::install_security_override,
|
||||
secureboot::run_in_security_override,
|
||||
unicode::convert_8_to_16,
|
||||
};
|
||||
|
||||
@ -20,11 +20,10 @@ pub fn start_linux(
|
||||
boot_services: &BootServices,
|
||||
sections: BootSections,
|
||||
) -> Result {
|
||||
// Override Secure Boot loader
|
||||
let uninstall = install_security_override(boot_services);
|
||||
|
||||
// Load kernel as image from memory
|
||||
// Load kernel as image from memory ignoring secure boot
|
||||
// Image is already trusted (signed) by being part of this EFI program
|
||||
let handle = unsafe {
|
||||
run_in_security_override(boot_services, || {
|
||||
boot_services
|
||||
.load_image(
|
||||
image_handle,
|
||||
@ -37,16 +36,14 @@ pub fn start_linux(
|
||||
},
|
||||
)
|
||||
.unwrap()
|
||||
})
|
||||
};
|
||||
|
||||
// Remove secure boot override
|
||||
uninstall();
|
||||
|
||||
let mut linux_image = boot_services
|
||||
.open_protocol_exclusive::<LoadedImage>(handle)
|
||||
.unwrap();
|
||||
|
||||
// Set cmdline for kernel image
|
||||
// Set cmdline for kernel image (expected as utf16)
|
||||
let (cmdline_utf16, cmdline_utf16_size) = convert_8_to_16(
|
||||
boot_services,
|
||||
sections.cmdline.pointer,
|
||||
@ -62,7 +59,7 @@ pub fn start_linux(
|
||||
);
|
||||
|
||||
// Install virtual initrd device
|
||||
// Buffer is used to build the device path
|
||||
// Buffer is used to build the device path, also needs to exist here for lifespan reasons
|
||||
let mut buf = [MaybeUninit::<u8>::uninit(); 256];
|
||||
install_initrd(boot_services, &mut buf, loader);
|
||||
|
||||
|
||||
@ -1,51 +1,33 @@
|
||||
use core::ffi::c_void;
|
||||
|
||||
use log::info;
|
||||
use uefi::{guid, prelude::BootServices, proto::Protocol, Identify};
|
||||
use uefi::{prelude::BootServices, proto::unsafe_protocol};
|
||||
|
||||
#[unsafe_protocol("A46423E3-4617-49F1-B9FF-D1BFA9115839")]
|
||||
struct SecurityArch {
|
||||
pub handler: *const c_void,
|
||||
}
|
||||
|
||||
unsafe impl Identify for SecurityArch {
|
||||
const GUID: uefi::Guid = guid!("A46423E3-4617-49F1-B9FF-D1BFA9115839");
|
||||
}
|
||||
|
||||
impl Protocol for SecurityArch {}
|
||||
|
||||
#[unsafe_protocol("94ab2f58-1438-4ef1-9152-18941a3a0e68")]
|
||||
struct Security2Arch {
|
||||
pub handler: *const c_void,
|
||||
}
|
||||
|
||||
unsafe impl Identify for Security2Arch {
|
||||
const GUID: uefi::Guid = guid!("94ab2f58-1438-4ef1-9152-18941a3a0e68");
|
||||
}
|
||||
|
||||
impl Protocol for Security2Arch {}
|
||||
|
||||
/// Most basic security handler, always returns true
|
||||
/// The ultimate yes-man
|
||||
fn security_handler() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Stores default security handlers to restore them when uninstalling
|
||||
struct DefaultSecurityHandlers {
|
||||
pub security1: Option<*mut *const c_void>,
|
||||
pub security1_handler: Option<*const c_void>,
|
||||
pub security2: Option<*mut *const c_void>,
|
||||
pub security2_handler: Option<*const c_void>,
|
||||
}
|
||||
|
||||
/// Secure Boot override to load kernel image from memory
|
||||
/// Runs a function with a blind secure boot validator
|
||||
/// Plagiarized from systemd-stub's "hack"
|
||||
/// Returns an override uninstaller to restore default handlers
|
||||
pub fn install_security_override(boot_services: &BootServices) -> impl Fn() -> () {
|
||||
let mut defaults = DefaultSecurityHandlers {
|
||||
security1: None,
|
||||
security1_handler: None,
|
||||
security2: None,
|
||||
security2_handler: None,
|
||||
};
|
||||
/// There must be a better way
|
||||
pub fn run_in_security_override<R, T: Fn() -> R>(boot_services: &BootServices, function: T) -> R {
|
||||
// Backup storage
|
||||
let mut df_security1 = None;
|
||||
let mut df_security1_handler = None;
|
||||
let mut df_security2 = None;
|
||||
let mut df_security2_handler = None;
|
||||
// Obtain SecurityArch protocol and replace handler
|
||||
boot_services
|
||||
.get_handle_for_protocol::<SecurityArch>()
|
||||
@ -53,8 +35,8 @@ pub fn install_security_override(boot_services: &BootServices) -> impl Fn() -> (
|
||||
boot_services
|
||||
.open_protocol_exclusive::<SecurityArch>(h)
|
||||
.and_then(|mut security| {
|
||||
defaults.security1 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||
defaults.security1_handler = Some(security.handler);
|
||||
df_security1 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||
df_security1_handler = Some(security.handler);
|
||||
security.handler = security_handler as *const c_void;
|
||||
Ok(())
|
||||
})
|
||||
@ -73,8 +55,8 @@ pub fn install_security_override(boot_services: &BootServices) -> impl Fn() -> (
|
||||
boot_services
|
||||
.open_protocol_exclusive::<Security2Arch>(h)
|
||||
.and_then(|mut security| {
|
||||
defaults.security2 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||
defaults.security2_handler = Some(security.handler);
|
||||
df_security2 = Some(core::ptr::addr_of_mut!(security.handler));
|
||||
df_security2_handler = Some(security.handler);
|
||||
security.handler = security_handler as *const c_void;
|
||||
Ok(())
|
||||
})
|
||||
@ -87,20 +69,13 @@ pub fn install_security_override(boot_services: &BootServices) -> impl Fn() -> (
|
||||
info!("security2 not found");
|
||||
});
|
||||
|
||||
// Returns restore function
|
||||
return move || {
|
||||
let x = function();
|
||||
|
||||
// Restore default SecurityArch handler
|
||||
defaults.security1.and_then(|s1| {
|
||||
defaults
|
||||
.security1_handler
|
||||
.and_then(|s1h| Some(unsafe { *s1 = s1h }))
|
||||
});
|
||||
df_security1.and_then(|s1| df_security1_handler.and_then(|s1h| Some(unsafe { *s1 = s1h })));
|
||||
|
||||
// Restore default SecurityArch2 handler
|
||||
defaults.security2.and_then(|s2| {
|
||||
defaults
|
||||
.security1_handler
|
||||
.and_then(|s2h| Some(unsafe { *s2 = s2h }))
|
||||
});
|
||||
};
|
||||
df_security2.and_then(|s2| df_security2_handler.and_then(|s2h| Some(unsafe { *s2 = s2h })));
|
||||
|
||||
x
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user