soma_codemode/
runner_exe.rs1use std::ffi::OsStr;
2use std::path::{Path, PathBuf};
3
4use crate::ToolError;
5
6const RUNNER_EXE_ENV: &str = "SOMA_CODE_MODE_RUNNER_EXE";
7
8pub fn resolve_runner_exe() -> Result<PathBuf, ToolError> {
9 let current = std::env::current_exe().map_err(|err| {
10 ToolError::internal_message(format!(
11 "failed to locate current executable for Code Mode runner: {err}"
12 ))
13 })?;
14 let override_exe = std::env::var_os(RUNNER_EXE_ENV).map(PathBuf::from);
15 resolve_runner_exe_from(current, override_exe)
16}
17
18pub fn resolve_runner_exe_from(
19 current_exe: PathBuf,
20 override_exe: Option<PathBuf>,
21) -> Result<PathBuf, ToolError> {
22 if let Some(path) = override_exe {
23 let path = validate_operator_override(path)?;
24 tracing::warn!(
25 runner_exe = %path.display(),
26 "using SOMA_CODE_MODE_RUNNER_EXE override for Code Mode runner"
27 );
28 return Ok(path);
29 }
30
31 if is_runner_binary_path(¤t_exe) && is_usable_exe(¤t_exe) {
32 return Ok(current_exe);
33 }
34 for candidate in sibling_runner_candidates(¤t_exe) {
35 if is_usable_exe(&candidate) {
36 return Ok(candidate);
37 }
38 }
39
40 Err(ToolError::internal_message(format!(
41 "Code Mode runner executable is stale or unavailable near `{}`; restart the soma service or set SOMA_CODE_MODE_RUNNER_EXE to a validated soma-codemode-runner binary",
42 current_exe.display()
43 )))
44}
45
46fn validate_operator_override(path: PathBuf) -> Result<PathBuf, ToolError> {
47 if !path.is_absolute() {
48 return Err(ToolError::Sdk {
49 sdk_kind: "invalid_param".to_string(),
50 message: "SOMA_CODE_MODE_RUNNER_EXE must be an absolute path".to_string(),
51 });
52 }
53 let canonical = std::fs::canonicalize(&path).map_err(|err| {
54 ToolError::internal_message(format!(
55 "SOMA_CODE_MODE_RUNNER_EXE points at `{}`, but it cannot be resolved: {err}",
56 path.display()
57 ))
58 })?;
59 if !is_usable_exe(&canonical) {
60 return Err(ToolError::internal_message(format!(
61 "SOMA_CODE_MODE_RUNNER_EXE points at `{}`, but that file is not executable",
62 canonical.display()
63 )));
64 }
65 reject_untrusted_permissions(&canonical)?;
66 Ok(canonical)
67}
68
69fn is_usable_exe(path: &Path) -> bool {
70 if path.to_string_lossy().ends_with(" (deleted)") {
71 return false;
72 }
73 let Ok(meta) = std::fs::metadata(path) else {
74 return false;
75 };
76 if !meta.is_file() {
77 return false;
78 }
79 #[cfg(unix)]
80 {
81 use std::os::unix::fs::PermissionsExt;
82 meta.permissions().mode() & 0o111 != 0
83 }
84 #[cfg(not(unix))]
85 {
86 true
87 }
88}
89
90fn sibling_runner_candidates(current_exe: &Path) -> Vec<PathBuf> {
91 let mut candidates = Vec::new();
92 if let Some(dir) = current_exe.parent() {
93 candidates.push(dir.join(runner_binary_name()));
94 if dir.file_name() == Some(OsStr::new("deps")) {
95 if let Some(parent) = dir.parent() {
96 candidates.push(parent.join(runner_binary_name()));
97 }
98 }
99 }
100 candidates
101}
102
103fn is_runner_binary_path(path: &Path) -> bool {
104 path.file_name() == Some(OsStr::new(runner_binary_name()))
105}
106
107fn runner_binary_name() -> &'static str {
108 if cfg!(windows) {
109 "soma-codemode-runner.exe"
110 } else {
111 "soma-codemode-runner"
112 }
113}
114
115fn reject_untrusted_permissions(path: &Path) -> Result<(), ToolError> {
116 #[cfg(unix)]
117 {
118 use std::os::unix::fs::MetadataExt;
119 let meta = std::fs::metadata(path).map_err(|err| {
120 ToolError::internal_message(format!("failed to inspect `{}`: {err}", path.display()))
121 })?;
122 if meta.mode() & 0o022 != 0 {
123 return Err(ToolError::internal_message(format!(
124 "SOMA_CODE_MODE_RUNNER_EXE points at `{}`, but the file is group/world writable",
125 path.display()
126 )));
127 }
128 let current_uid = nix::unistd::Uid::current().as_raw();
129 if meta.uid() != current_uid && meta.uid() != 0 {
130 return Err(ToolError::internal_message(format!(
131 "SOMA_CODE_MODE_RUNNER_EXE points at `{}`, but the file is not owned by the current user or root",
132 path.display()
133 )));
134 }
135 }
136 #[cfg(not(unix))]
137 {
138 let _ = path;
139 }
140 Ok(())
141}