Skip to content

Commit 2cab984

Browse files
committed
fix(mmserver): use putenv instead of Command::env
Ref: rust-lang/rust#130756
1 parent afc4195 commit 2cab984

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

mm-server/src/compositor/child/container.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ pub struct Container {
152152

153153
// Note: we don't use Command::env or Command::env_clear, because those
154154
// cause Command::exec to allocate, which we don't want to do after forking.
155-
envs: Vec<(OsString, OsString)>,
155+
envs: Vec<CString>,
156156

157157
tmp_stderr: Option<OwnedFd>,
158158

@@ -180,21 +180,26 @@ impl Container {
180180
let exe_path =
181181
find_executable_in_path(&exe).ok_or(anyhow!("command {:?} not in PATH", &exe))?;
182182

183-
let mut envs: Vec<(OsString, OsString)> = app_config.env.clone().into_iter().collect();
183+
let mut envs: Vec<CString> = app_config
184+
.env
185+
.clone()
186+
.into_iter()
187+
.map(|(k, v)| make_putenv(k, v))
188+
.collect();
184189

185190
let mut child_cmd = Command::new(exe_path);
186191
child_cmd.current_dir("/");
187192
child_cmd.args(args);
188193

189194
if let Some(path) = std::env::var_os("PATH") {
190-
envs.push(("PATH".into(), path));
195+
envs.push(make_putenv("PATH", path));
191196
}
192197

193198
let uid = getuid();
194199
let gid = getgid();
195200

196201
let intern_run_path: OsString = format!("/run/user/{}", uid.as_raw()).try_into().unwrap();
197-
envs.push(("XDG_RUNTIME_DIR".into(), intern_run_path.clone()));
202+
envs.push(make_putenv("XDG_RUNTIME_DIR", intern_run_path.clone()));
198203

199204
let extern_run_path = std::env::temp_dir().join(format!(
200205
"mm.{}",
@@ -203,7 +208,7 @@ impl Container {
203208
std::fs::create_dir_all(&extern_run_path)?;
204209

205210
let intern_home_path: OsString = std::env::var_os("HOME").unwrap_or("/home/mm".into());
206-
envs.push(("HOME".into(), intern_home_path.clone()));
211+
envs.push(make_putenv("HOME", intern_home_path.clone()));
207212

208213
debug!(home_mode = ?app_config.home_isolation_mode, "using home mode");
209214
let (extern_home_path, clear_home) = match app_config.home_isolation_mode {
@@ -270,8 +275,7 @@ impl Container {
270275
K: AsRef<OsStr>,
271276
V: AsRef<OsStr>,
272277
{
273-
self.envs
274-
.push((key.as_ref().to_owned(), val.as_ref().to_owned()))
278+
self.envs.push(make_putenv(key, val))
275279
}
276280

277281
pub fn set_stdout<T: AsFd>(&mut self, stdio: T) -> anyhow::Result<()> {
@@ -321,8 +325,6 @@ impl Container {
321325
.flag_newns()
322326
.flag_newpid();
323327

324-
// TODO
325-
self.child_cmd.env_clear().envs(self.envs.clone());
326328
debug!(cmd = ?self.child_cmd, "spawning child process");
327329

328330
let (barrier, child_barrier) = ipc::EventfdBarrier::new()?;
@@ -584,10 +586,10 @@ impl Container {
584586

585587
// We don't trust std::os::Command's env handling, because sometimes
586588
// it allocates.
587-
// libc::clearenv();
588-
// for (k, v) in &self.envs {
589-
// libc::setenv
590-
// }
589+
libc::clearenv();
590+
for v in &mut self.envs {
591+
libc::putenv(v.as_ptr() as *mut _);
592+
}
591593

592594
// If successful, this never returns.
593595
let _e = self.child_cmd.exec();
@@ -823,6 +825,16 @@ fn sync_barrier(barrier: &ipc::EventfdBarrier) -> rustix::io::Result<()> {
823825
barrier.sync(time::Duration::from_secs(1))
824826
}
825827

828+
/// Generates a CString in the format key=value, for putenv(3).
829+
fn make_putenv(k: impl AsRef<OsStr>, v: impl AsRef<OsStr>) -> CString {
830+
CString::new(format!(
831+
"{}={}",
832+
k.as_ref().to_str().unwrap(),
833+
v.as_ref().to_str().unwrap()
834+
))
835+
.unwrap()
836+
}
837+
826838
#[cfg(test)]
827839
mod test {
828840
use std::{fs::File, io::Read as _};

0 commit comments

Comments
 (0)