mirror of
https://github.com/wez/wezterm.git
synced 2024-12-22 04:41:34 +03:00
Take care to restore the original umask
wezterm sets a more restrictive umask (`0o077`) by default so that any files that it creates (eg: unix domain socket, log files) are more secure by default. However, some environments rely on the more general default of (`0o022`) without checking that it is set. This matters because programs spawned by wezterm inherit its more restricted umask. I hadn't noticed this because I've had `umask 022` in my shell RC files since sometime in the 1990's. This commit adds some plumbing to the pty layer to specify an optional umask for the child process, and some more to our umask saver helper so that any thread can determine the saved umask without needing a reference to the saver itself, which may be in a different crate. The logic in the config crate has been adjusted to connect the saved value to the default command builder arguments. The net result of this is that running `wezterm -n start bash -- --norc` and typing `umask` in the resultant window now prints `0022`. refs: #416
This commit is contained in:
parent
704dd9aa44
commit
db0d54cf44
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -693,6 +693,7 @@ dependencies = [
|
||||
"smol",
|
||||
"termwiz",
|
||||
"toml",
|
||||
"umask",
|
||||
"vergen",
|
||||
"wezterm-input-types",
|
||||
"wezterm-term",
|
||||
@ -3836,6 +3837,7 @@ dependencies = [
|
||||
name = "umask"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -32,6 +32,7 @@ serde = {version="1.0", features = ["rc", "derive"]}
|
||||
smol = "1.2"
|
||||
termwiz = { path = "../termwiz" }
|
||||
toml = "0.5"
|
||||
umask = { path = "../umask" }
|
||||
wezterm-input-types = { path = "../wezterm-input-types" }
|
||||
wezterm-term = { path = "../term", features=["use_serde"] }
|
||||
|
||||
|
@ -1241,6 +1241,9 @@ impl Config {
|
||||
for (k, v) in &self.set_environment_variables {
|
||||
cmd.env(k, v);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
cmd.umask(umask::UmaskSaver::saved_umask());
|
||||
cmd.env("TERM", &self.term);
|
||||
// TERM_PROGRAM and TERM_PROGRAM_VERSION are an emerging
|
||||
// de-facto standard for identifying the terminal.
|
||||
|
@ -14,6 +14,8 @@ pub struct CommandBuilder {
|
||||
args: Vec<OsString>,
|
||||
envs: Vec<(OsString, OsString)>,
|
||||
cwd: Option<OsString>,
|
||||
#[cfg(unix)]
|
||||
pub(crate) umask: Option<libc::mode_t>,
|
||||
}
|
||||
|
||||
impl CommandBuilder {
|
||||
@ -24,6 +26,7 @@ impl CommandBuilder {
|
||||
args: vec![program.as_ref().to_owned()],
|
||||
envs: vec![],
|
||||
cwd: None,
|
||||
umask: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +36,7 @@ impl CommandBuilder {
|
||||
args,
|
||||
envs: vec![],
|
||||
cwd: None,
|
||||
umask: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +47,7 @@ impl CommandBuilder {
|
||||
args: vec![],
|
||||
envs: vec![],
|
||||
cwd: None,
|
||||
umask: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,6 +93,11 @@ impl CommandBuilder {
|
||||
self.cwd = Some(dir.as_ref().to_owned());
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn umask(&mut self, mask: Option<libc::mode_t>) {
|
||||
self.umask = mask;
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssh")]
|
||||
pub(crate) fn iter_env_as_str(&self) -> impl Iterator<Item = (&str, &str)> {
|
||||
self.envs.iter().filter_map(|(key, val)| {
|
||||
|
@ -192,6 +192,8 @@ impl PtyFd {
|
||||
}
|
||||
|
||||
fn spawn_command(&self, builder: CommandBuilder) -> anyhow::Result<std::process::Child> {
|
||||
let configured_umask = builder.umask;
|
||||
|
||||
let mut cmd = builder.as_command()?;
|
||||
|
||||
unsafe {
|
||||
@ -235,6 +237,10 @@ impl PtyFd {
|
||||
|
||||
close_random_fds();
|
||||
|
||||
if let Some(mask) = configured_umask {
|
||||
libc::umask(mask);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
@ -7,4 +7,5 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4"
|
||||
libc = "0.2"
|
||||
|
@ -1,5 +1,12 @@
|
||||
#[cfg(unix)]
|
||||
use libc::{mode_t, umask};
|
||||
#[cfg(unix)]
|
||||
use std::sync::Mutex;
|
||||
|
||||
#[cfg(unix)]
|
||||
lazy_static::lazy_static! {
|
||||
static ref SAVED_UMASK: Mutex<Option<libc::mode_t>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
/// Unfortunately, novice unix users can sometimes be running
|
||||
/// with an overly permissive umask so we take care to install
|
||||
@ -14,10 +21,26 @@ pub struct UmaskSaver {
|
||||
|
||||
impl UmaskSaver {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
let me = Self {
|
||||
#[cfg(unix)]
|
||||
mask: unsafe { umask(0o077) },
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
SAVED_UMASK.lock().unwrap().replace(me.mask);
|
||||
}
|
||||
|
||||
me
|
||||
}
|
||||
|
||||
/// Retrieves the mask saved by a UmaskSaver, without
|
||||
/// having a reference to the UmaskSaver.
|
||||
/// This is only meaningful if a single UmaskSaver is
|
||||
/// used in a program.
|
||||
#[cfg(unix)]
|
||||
pub fn saved_umask() -> Option<mode_t> {
|
||||
SAVED_UMASK.lock().unwrap().clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +49,7 @@ impl Drop for UmaskSaver {
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
umask(self.mask);
|
||||
SAVED_UMASK.lock().unwrap().take();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use std::io::{Read, Write};
|
||||
use std::rc::Rc;
|
||||
use structopt::StructOpt;
|
||||
use tabout::{tabulate_output, Alignment, Column};
|
||||
use umask::UmaskSaver;
|
||||
use wezterm_client::client::{unix_connect_with_retry, Client};
|
||||
use wezterm_gui_subcommands::*;
|
||||
|
||||
@ -223,7 +224,7 @@ fn main() {
|
||||
fn run() -> anyhow::Result<()> {
|
||||
env_bootstrap::bootstrap();
|
||||
|
||||
let _saver = umask::UmaskSaver::new();
|
||||
let saver = UmaskSaver::new();
|
||||
|
||||
let opts = Opt::from_args();
|
||||
if !opts.skip_config {
|
||||
@ -240,16 +241,19 @@ fn run() -> anyhow::Result<()> {
|
||||
SubCommand::Start(_)
|
||||
| SubCommand::Ssh(_)
|
||||
| SubCommand::Serial(_)
|
||||
| SubCommand::Connect(_) => delegate_to_gui(),
|
||||
| SubCommand::Connect(_) => delegate_to_gui(saver),
|
||||
SubCommand::ImageCat(cmd) => cmd.run(),
|
||||
SubCommand::SetCwd(cmd) => cmd.run(),
|
||||
SubCommand::Cli(cli) => run_cli(config, cli),
|
||||
}
|
||||
}
|
||||
|
||||
fn delegate_to_gui() -> anyhow::Result<()> {
|
||||
fn delegate_to_gui(saver: UmaskSaver) -> anyhow::Result<()> {
|
||||
use std::process::Command;
|
||||
|
||||
// Restore the original umask
|
||||
drop(saver);
|
||||
|
||||
let exe_name = if cfg!(windows) {
|
||||
"wezterm-gui.exe"
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user