Skip to content

Commit 18aabb1

Browse files
authored
Merge branch 'main' into add-github-action-for-nix
2 parents e0b44d8 + 67aab04 commit 18aabb1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1676
-258
lines changed

codex-rs/Cargo.lock

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

codex-rs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ clap = "4"
7272
clap_complete = "4"
7373
color-eyre = "0.6.3"
7474
crossterm = "0.28.1"
75+
ctor = "0.5.0"
7576
derive_more = "2"
7677
diffy = "0.4.2"
7778
dirs = "6"

codex-rs/cli/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ codex-mcp-server = { workspace = true }
2828
codex-protocol = { workspace = true }
2929
codex-protocol-ts = { workspace = true }
3030
codex-tui = { workspace = true }
31+
ctor = { workspace = true }
3132
owo-colors = { workspace = true }
3233
serde_json = { workspace = true }
3334
supports-color = { workspace = true }
@@ -41,6 +42,15 @@ tokio = { workspace = true, features = [
4142
tracing = { workspace = true }
4243
tracing-subscriber = { workspace = true }
4344

45+
[target.'cfg(target_os = "linux")'.dependencies]
46+
libc = { workspace = true }
47+
48+
[target.'cfg(target_os = "android")'.dependencies]
49+
libc = { workspace = true }
50+
51+
[target.'cfg(target_os = "macos")'.dependencies]
52+
libc = { workspace = true }
53+
4454
[dev-dependencies]
4555
assert_cmd = { workspace = true }
4656
predicates = { workspace = true }

codex-rs/cli/src/main.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::path::PathBuf;
2121
use supports_color::Stream;
2222

2323
mod mcp_cmd;
24+
mod pre_main_hardening;
2425

2526
use crate::mcp_cmd::McpCli;
2627
use crate::proto::ProtoCli;
@@ -194,6 +195,34 @@ fn print_exit_messages(exit_info: AppExitInfo) {
194195
}
195196
}
196197

198+
pub(crate) const CODEX_SECURE_MODE_ENV_VAR: &str = "CODEX_SECURE_MODE";
199+
200+
/// As early as possible in the process lifecycle, apply hardening measures
201+
/// if the CODEX_SECURE_MODE environment variable is set to "1".
202+
#[ctor::ctor]
203+
fn pre_main_hardening() {
204+
let secure_mode = match std::env::var(CODEX_SECURE_MODE_ENV_VAR) {
205+
Ok(value) => value,
206+
Err(_) => return,
207+
};
208+
209+
if secure_mode == "1" {
210+
#[cfg(any(target_os = "linux", target_os = "android"))]
211+
crate::pre_main_hardening::pre_main_hardening_linux();
212+
213+
#[cfg(target_os = "macos")]
214+
crate::pre_main_hardening::pre_main_hardening_macos();
215+
216+
#[cfg(windows)]
217+
crate::pre_main_hardening::pre_main_hardening_windows();
218+
}
219+
220+
// Always clear this env var so child processes don't inherit it.
221+
unsafe {
222+
std::env::remove_var(CODEX_SECURE_MODE_ENV_VAR);
223+
}
224+
}
225+
197226
fn main() -> anyhow::Result<()> {
198227
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
199228
cli_main(codex_linux_sandbox_exe).await?;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#[cfg(any(target_os = "linux", target_os = "android"))]
2+
const PRCTL_FAILED_EXIT_CODE: i32 = 5;
3+
4+
#[cfg(target_os = "macos")]
5+
const PTRACE_DENY_ATTACH_FAILED_EXIT_CODE: i32 = 6;
6+
7+
#[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))]
8+
const SET_RLIMIT_CORE_FAILED_EXIT_CODE: i32 = 7;
9+
10+
#[cfg(any(target_os = "linux", target_os = "android"))]
11+
pub(crate) fn pre_main_hardening_linux() {
12+
// Disable ptrace attach / mark process non-dumpable.
13+
let ret_code = unsafe { libc::prctl(libc::PR_SET_DUMPABLE, 0, 0, 0, 0) };
14+
if ret_code != 0 {
15+
eprintln!(
16+
"ERROR: prctl(PR_SET_DUMPABLE, 0) failed: {}",
17+
std::io::Error::last_os_error()
18+
);
19+
std::process::exit(PRCTL_FAILED_EXIT_CODE);
20+
}
21+
22+
// For "defense in depth," set the core file size limit to 0.
23+
set_core_file_size_limit_to_zero();
24+
25+
// Official Codex releases are MUSL-linked, which means that variables such
26+
// as LD_PRELOAD are ignored anyway, but just to be sure, clear them here.
27+
let ld_keys: Vec<String> = std::env::vars()
28+
.filter_map(|(key, _)| {
29+
if key.starts_with("LD_") {
30+
Some(key)
31+
} else {
32+
None
33+
}
34+
})
35+
.collect();
36+
37+
for key in ld_keys {
38+
unsafe {
39+
std::env::remove_var(key);
40+
}
41+
}
42+
}
43+
44+
#[cfg(target_os = "macos")]
45+
pub(crate) fn pre_main_hardening_macos() {
46+
// Prevent debuggers from attaching to this process.
47+
let ret_code = unsafe { libc::ptrace(libc::PT_DENY_ATTACH, 0, std::ptr::null_mut(), 0) };
48+
if ret_code == -1 {
49+
eprintln!(
50+
"ERROR: ptrace(PT_DENY_ATTACH) failed: {}",
51+
std::io::Error::last_os_error()
52+
);
53+
std::process::exit(PTRACE_DENY_ATTACH_FAILED_EXIT_CODE);
54+
}
55+
56+
// Set the core file size limit to 0 to prevent core dumps.
57+
set_core_file_size_limit_to_zero();
58+
59+
// Remove all DYLD_ environment variables, which can be used to subvert
60+
// library loading.
61+
let dyld_keys: Vec<String> = std::env::vars()
62+
.filter_map(|(key, _)| {
63+
if key.starts_with("DYLD_") {
64+
Some(key)
65+
} else {
66+
None
67+
}
68+
})
69+
.collect();
70+
71+
for key in dyld_keys {
72+
unsafe {
73+
std::env::remove_var(key);
74+
}
75+
}
76+
}
77+
78+
#[cfg(unix)]
79+
fn set_core_file_size_limit_to_zero() {
80+
let rlim = libc::rlimit {
81+
rlim_cur: 0,
82+
rlim_max: 0,
83+
};
84+
85+
let ret_code = unsafe { libc::setrlimit(libc::RLIMIT_CORE, &rlim) };
86+
if ret_code != 0 {
87+
eprintln!(
88+
"ERROR: setrlimit(RLIMIT_CORE) failed: {}",
89+
std::io::Error::last_os_error()
90+
);
91+
std::process::exit(SET_RLIMIT_CORE_FAILED_EXIT_CODE);
92+
}
93+
}
94+
95+
#[cfg(windows)]
96+
pub(crate) fn pre_main_hardening_windows() {
97+
// TODO(mbolin): Perform the appropriate configuration for Windows.
98+
}

0 commit comments

Comments
 (0)