diff --git a/Cargo.lock b/Cargo.lock index a669f0e..fe456de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,7 +217,7 @@ checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" [[package]] name = "sudo" -version = "1.0.0" +version = "1.0.1" dependencies = [ "cc", "clap", diff --git a/owners.txt b/owners.txt new file mode 100644 index 0000000..5bad4eb --- /dev/null +++ b/owners.txt @@ -0,0 +1,9 @@ +; This owners file addition was requested by migrie@microsoft.com +; This owners.txt file was initially populated by Easy Start. Every code +; change inside of an Ownership Enforcer enabled branch (such as master) must be +; approved by at least one expert listed in an applicable owners.txt file. This +; root owners.txt file is applicable to every change. Targeted experts can be +; defined by placing an owners.txt file inside any subdirectory. More information +; about Ownership Enforcer can be found at https://aka.ms/ownershipenforcer. +migrie +duhowett \ No newline at end of file diff --git a/sudo/Cargo.toml b/sudo/Cargo.toml index 6d221b1..062cc22 100644 --- a/sudo/Cargo.toml +++ b/sudo/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sudo" -version = "1.0.0" +version = "1.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/sudo/src/elevate_handler.rs b/sudo/src/elevate_handler.rs index ffdbaf0..dda9c48 100644 --- a/sudo/src/elevate_handler.rs +++ b/sudo/src/elevate_handler.rs @@ -153,13 +153,14 @@ pub fn handle_elevation_request(request: &ElevateRequest) -> Result, _args: &[&String], ) -> Result { // TODO:48520593 In rust_handle_elevation_request, validate that the parent // process handle is the same one that we opened here. - let endpoint = generate_rpc_endpoint_name(parent_pid); + let endpoint = generate_rpc_endpoint_name(parent_pid, nonce); let endpoint = CString::new(endpoint).unwrap(); rpc_server_setup(&endpoint, parent_pid)?; diff --git a/sudo/src/helpers.rs b/sudo/src/helpers.rs index 299e10a..8e79b62 100644 --- a/sudo/src/helpers.rs +++ b/sudo/src/helpers.rs @@ -109,8 +109,8 @@ pub unsafe extern "system" fn ignore_ctrl_c(ctrl_type: u32) -> BOOL { } } -pub fn generate_rpc_endpoint_name(pid: u32) -> String { - format!(r"sudo_elevate_{pid}") +pub fn generate_rpc_endpoint_name(pid: u32, nonce: u32) -> String { + format!(r"sudo_elevate_{pid}_{nonce}") } pub fn is_running_elevated() -> Result { diff --git a/sudo/src/main.rs b/sudo/src/main.rs index 70409cc..5765012 100644 --- a/sudo/src/main.rs +++ b/sudo/src/main.rs @@ -74,6 +74,8 @@ fn sudo_cli(allowed_mode: i32) -> Command { .help(r::IDS_ELEVATE_PARENT.get()) .required(true), ) + // .arg(arg!(-n ).required(true)) + .arg(Arg::new("NONCE").short('n').required(true)) // .arg(arg!([COMMANDLINE] ... "")), .arg( Arg::new("COMMANDLINE") @@ -379,6 +381,7 @@ fn do_elevate(matches: &ArgMatches) -> Result { _ = check_enabled_or_bail(); let parent_pid = matches.get_one::("PARENT").unwrap().parse::(); + let nonce = matches.get_one::("NONCE").unwrap().parse::(); if let Err(e) = &parent_pid { eprintln!("{} {}", r::IDS_UNKNOWNERROR.get(), e); @@ -394,7 +397,12 @@ fn do_elevate(matches: &ArgMatches) -> Result { .flatten() .collect::>(); - let result = start_rpc_server(parent_pid.ok().unwrap(), None, &commandline); + let result = start_rpc_server( + parent_pid.ok().unwrap(), + nonce.ok().unwrap(), + None, + &commandline, + ); trace_log_message(&format!("elevate result: {result:?}")); result } diff --git a/sudo/src/run_handler.rs b/sudo/src/run_handler.rs index a2e956e..2c35193 100644 --- a/sudo/src/run_handler.rs +++ b/sudo/src/run_handler.rs @@ -343,10 +343,33 @@ fn do_request(req: ElevateRequest, copy_env: bool, manually_requested_dir: bool) } } +/// Generates a random nonce to include in the RPC endpoint name. We're using +/// `RtlGenRandom` to generate the number. This is how the core language does it: +/// https://github.com/rust-lang/rust/pull/45370 +fn random_nonce() -> u32 { + #[link(name = "advapi32")] + extern "system" { + // This function's real name is `RtlGenRandom`. + fn SystemFunction036(RandomBuffer: *mut u8, RandomBufferLength: u32) -> BOOLEAN; + } + + let mut nonce = 0u32; + unsafe { + SystemFunction036( + (&mut nonce as *mut u32) as *mut u8, + std::mem::size_of::() as _, + ); + } + nonce +} + fn handoff_to_elevated(req: &ElevateRequest) -> Result { // Build a single string from the request's application and args let parent_pid = std::process::id(); + // generate a pseudorandom nonce to include + let nonce = random_nonce(); + tracing::trace_log_message(&format!( "running as user: '{}'", get_current_user().as_ref().unwrap_or(h!("unknown")) @@ -354,7 +377,7 @@ fn handoff_to_elevated(req: &ElevateRequest) -> Result { let path = env::current_exe().unwrap(); let target_args = format!( - "elevate -p {parent_pid} {} {}", + "elevate -p {parent_pid} -n {nonce} {} {}", req.application, join_args(&req.args) ); @@ -369,7 +392,7 @@ fn handoff_to_elevated(req: &ElevateRequest) -> Result { _ = SetConsoleCtrlHandler(Some(ignore_ctrl_c), true); } - send_request_via_rpc(req) + send_request_via_rpc(req, nonce) } /// Connects to the elevated sudo instance via RPC, then makes a couple RPC @@ -386,8 +409,8 @@ fn handoff_to_elevated(req: &ElevateRequest) -> Result { /// process exited with an error. /// - Specifically be on the lookout for 1764 here, which is /// RPC_S_CANNOT_SUPPORT -fn send_request_via_rpc(req: &ElevateRequest) -> Result { - let endpoint = generate_rpc_endpoint_name(unsafe { GetCurrentProcessId() }); +fn send_request_via_rpc(req: &ElevateRequest, nonce: u32) -> Result { + let endpoint = generate_rpc_endpoint_name(unsafe { GetCurrentProcessId() }, nonce); let endpoint = CString::new(endpoint).unwrap(); // Attempt to connect to our RPC server, with a backoff. This will try 10 diff --git a/sudo/src/tests/mod.rs b/sudo/src/tests/mod.rs index 316c943..c2eec1d 100644 --- a/sudo/src/tests/mod.rs +++ b/sudo/src/tests/mod.rs @@ -21,6 +21,9 @@ mod tests { #[test] fn test_generate_rpc_endpoint_name() { - assert_eq!(generate_rpc_endpoint_name(1234), r"sudo_elevate_1234"); + assert_eq!( + generate_rpc_endpoint_name(1234, 2345), + r"sudo_elevate_1234_2345" + ); } }