-
Notifications
You must be signed in to change notification settings - Fork 179
Expand file tree
/
Copy pathaskpass.rs
More file actions
58 lines (50 loc) · 1.77 KB
/
Copy pathaskpass.rs
File metadata and controls
58 lines (50 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use std::os::fd::{FromRawFd, OwnedFd};
use std::os::unix::process::CommandExt;
use std::path::Path;
use std::process::Command;
use std::{io, process};
use libc::O_CLOEXEC;
use crate::cutils::cerr;
use crate::log::user_error;
use crate::system::interface::ProcessId;
use crate::system::{ForkResult, audit, fork, mark_fds_as_cloexec};
pub(super) fn spawn_askpass(program: &Path, prompt: &str) -> io::Result<(ProcessId, OwnedFd)> {
// Create socket
let mut pipes = [-1, -1];
// SAFETY: A valid pointer to a mutable array of 2 fds is passed in.
unsafe {
cerr(libc::pipe2(pipes.as_mut_ptr(), O_CLOEXEC))?;
}
// SAFETY: pipe2 created two owned pipe fds
let (pipe_read, pipe_write) = unsafe {
(
OwnedFd::from_raw_fd(pipes[0]),
OwnedFd::from_raw_fd(pipes[1]),
)
};
// Spawn child
// SAFETY: There should be no other threads at this point.
let ForkResult::Parent(command_pid) = unsafe { fork() }.unwrap() else {
drop(pipe_read);
handle_child(program, prompt, pipe_write)
};
drop(pipe_write);
Ok((command_pid, pipe_read))
}
fn handle_child(program: &Path, prompt: &str, stdout: OwnedFd) -> ! {
if let Err(e) = mark_fds_as_cloexec() {
eprintln_ignore_io_error!("Failed to mark fds as CLOEXEC: {e}");
process::exit(1);
};
// root privileges are dangerous after this point, since we are about to
// execute a command under control of the user, so drop them
audit::irrevocably_drop_privileges();
// Exec askpass program
let error = Command::new(program).arg(prompt).stdout(stdout).exec();
user_error!(
"Failed to run askpass program {path}: {error}",
path = program.display(),
error = error
);
process::exit(1);
}