From b8b56c0f322d88f4669b17e4ca90b9b1cbc5cb5e Mon Sep 17 00:00:00 2001 From: DuProcess <273172371+DuProcess@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:26:08 -0400 Subject: [PATCH] Honor configured shell for remote exec --- src/bin/dosh-server/unix.rs | 16 +++++++++++++--- tests/integration_smoke.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/bin/dosh-server/unix.rs b/src/bin/dosh-server/unix.rs index e8080a3..4c96ba3 100644 --- a/src/bin/dosh-server/unix.rs +++ b/src/bin/dosh-server/unix.rs @@ -3271,15 +3271,25 @@ async fn run_exec_stream_service( continue; } }; - let output = TokioCommand::new("sh") - .arg("-lc") + let shell = { + state + .lock() + .expect("server state poisoned") + .config + .shell + .clone() + }; + let output = TokioCommand::new(&shell) + .arg("-c") .arg(&request.command) .stdin(Stdio::null()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .output() .await - .with_context(|| format!("run command {:?}", request.command))?; + .with_context(|| { + format!("run command {:?} with shell {shell}", request.command) + })?; for chunk in output.stdout.chunks(CHUNK_SIZE) { send_exec_response_to_client( &state, diff --git a/tests/integration_smoke.rs b/tests/integration_smoke.rs index 31154c9..dfc9d67 100644 --- a/tests/integration_smoke.rs +++ b/tests/integration_smoke.rs @@ -1355,6 +1355,22 @@ fn native_exec_command_smoke() { let dir = tempfile::tempdir().unwrap(); let port = free_udp_port(); let config = write_server_config(&dir, port); + let shell_log = dir.path().join("exec-shell.log"); + let shell = dir.path().join("exec-shell"); + fs::write( + &shell, + format!( + "#!/bin/sh\nprintf '%s\\n' \"$*\" >> '{}'\nexec /bin/sh \"$@\"\n", + shell_log.display() + ), + ) + .unwrap(); + fs::set_permissions(&shell, fs::Permissions::from_mode(0o700)).unwrap(); + let raw = fs::read_to_string(&config).unwrap().replace( + "shell = \"/bin/sh\"", + &format!("shell = {:?}", shell.display().to_string()), + ); + fs::write(&config, raw).unwrap(); write_native_client_auth(&dir, &config); let mut server = start_server(&dir, &config); let client_bin = env!("CARGO_BIN_EXE_dosh-client"); @@ -1380,6 +1396,19 @@ fn native_exec_command_smoke() { ); assert_eq!(String::from_utf8_lossy(&output.stdout), "out"); assert_eq!(String::from_utf8_lossy(&output.stderr), "err"); + let shell_invocations = fs::read_to_string(shell_log).unwrap(); + assert!( + shell_invocations + .lines() + .any(|line| line.starts_with("-c ")), + "configured shell was not used for exec: {shell_invocations:?}" + ); + assert!( + !shell_invocations + .lines() + .any(|line| line.starts_with("-lc ")), + "exec must not start a login shell: {shell_invocations:?}" + ); } #[test]