mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #72160 - slo1:libstd-setgroups, r=KodrAus
Add setgroups to std::os::unix::process::CommandExt Should fix #38527. I'm not sure groups is the greatest name though.
This commit is contained in:
commit
22ddcd1a13
@ -39,6 +39,15 @@ pub trait CommandExt {
|
||||
#[cfg(target_os = "vxworks")] id: u16,
|
||||
) -> &mut process::Command;
|
||||
|
||||
/// Sets the supplementary group IDs for the calling process. Translates to
|
||||
/// a `setgroups` call in the child process.
|
||||
#[unstable(feature = "setgroups", issue = "38527", reason = "")]
|
||||
fn groups(
|
||||
&mut self,
|
||||
#[cfg(not(target_os = "vxworks"))] groups: &[u32],
|
||||
#[cfg(target_os = "vxworks")] groups: &[u16],
|
||||
) -> &mut process::Command;
|
||||
|
||||
/// Schedules a closure to be run just before the `exec` function is
|
||||
/// invoked.
|
||||
///
|
||||
@ -149,6 +158,15 @@ impl CommandExt for process::Command {
|
||||
self
|
||||
}
|
||||
|
||||
fn groups(
|
||||
&mut self,
|
||||
#[cfg(not(target_os = "vxworks"))] groups: &[u32],
|
||||
#[cfg(target_os = "vxworks")] groups: &[u16],
|
||||
) -> &mut process::Command {
|
||||
self.as_inner_mut().groups(groups);
|
||||
self
|
||||
}
|
||||
|
||||
unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
|
||||
where
|
||||
F: FnMut() -> io::Result<()> + Send + Sync + 'static,
|
||||
|
@ -87,6 +87,7 @@ pub struct Command {
|
||||
gid: Option<gid_t>,
|
||||
saw_nul: bool,
|
||||
closures: Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>>,
|
||||
groups: Option<Box<[gid_t]>>,
|
||||
stdin: Option<Stdio>,
|
||||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
@ -148,6 +149,7 @@ impl Command {
|
||||
gid: None,
|
||||
saw_nul,
|
||||
closures: Vec::new(),
|
||||
groups: None,
|
||||
stdin: None,
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
@ -183,6 +185,9 @@ impl Command {
|
||||
pub fn gid(&mut self, id: gid_t) {
|
||||
self.gid = Some(id);
|
||||
}
|
||||
pub fn groups(&mut self, groups: &[gid_t]) {
|
||||
self.groups = Some(Box::from(groups));
|
||||
}
|
||||
|
||||
pub fn saw_nul(&self) -> bool {
|
||||
self.saw_nul
|
||||
@ -226,6 +231,10 @@ impl Command {
|
||||
pub fn get_gid(&self) -> Option<gid_t> {
|
||||
self.gid
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn get_groups(&self) -> Option<&[gid_t]> {
|
||||
self.groups.as_deref()
|
||||
}
|
||||
|
||||
pub fn get_closures(&mut self) -> &mut Vec<Box<dyn FnMut() -> io::Result<()> + Send + Sync>> {
|
||||
&mut self.closures
|
||||
|
@ -183,20 +183,26 @@ impl Command {
|
||||
|
||||
#[cfg(not(target_os = "l4re"))]
|
||||
{
|
||||
if let Some(_g) = self.get_groups() {
|
||||
//FIXME: Redox kernel does not support setgroups yet
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
cvt(libc::setgroups(_g.len().try_into().unwrap(), _g.as_ptr()))?;
|
||||
}
|
||||
if let Some(u) = self.get_gid() {
|
||||
cvt(libc::setgid(u as gid_t))?;
|
||||
}
|
||||
if let Some(u) = self.get_uid() {
|
||||
// When dropping privileges from root, the `setgroups` call
|
||||
// will remove any extraneous groups. If we don't call this,
|
||||
// then even though our uid has dropped, we may still have
|
||||
// groups that enable us to do super-user things. This will
|
||||
// fail if we aren't root, so don't bother checking the
|
||||
// return value, this is just done as an optimistic
|
||||
// privilege dropping function.
|
||||
// will remove any extraneous groups. We only drop groups
|
||||
// if the current uid is 0 and we weren't given an explicit
|
||||
// set of groups. If we don't call this, then even though our
|
||||
// uid has dropped, we may still have groups that enable us to
|
||||
// do super-user things.
|
||||
//FIXME: Redox kernel does not support setgroups yet
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
let _ = libc::setgroups(0, ptr::null());
|
||||
if libc::getuid() == 0 && self.get_groups().is_none() {
|
||||
cvt(libc::setgroups(0, ptr::null()))?;
|
||||
}
|
||||
cvt(libc::setuid(u as uid_t))?;
|
||||
}
|
||||
}
|
||||
@ -287,6 +293,7 @@ impl Command {
|
||||
|| self.get_uid().is_some()
|
||||
|| (self.env_saw_path() && !self.program_is_path())
|
||||
|| !self.get_closures().is_empty()
|
||||
|| self.get_groups().is_some()
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
|
26
src/test/ui/command/command-setgroups.rs
Normal file
26
src/test/ui/command/command-setgroups.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// run-pass
|
||||
// ignore-windows - this is a unix-specific test
|
||||
// ignore-cloudabi
|
||||
// ignore-emscripten
|
||||
// ignore-sgx
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(setgroups)]
|
||||
|
||||
extern crate libc;
|
||||
use std::process::Command;
|
||||
use std::os::unix::process::CommandExt;
|
||||
|
||||
fn main() {
|
||||
#[cfg(unix)]
|
||||
run()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn run() {
|
||||
let max_ngroups = unsafe { libc::sysconf(libc::_SC_NGROUPS_MAX) };
|
||||
let max_ngroups = max_ngroups as u32 + 1;
|
||||
let vec: Vec<u32> = (0..max_ngroups).collect();
|
||||
let p = Command::new("/bin/id").groups(&vec[..]).spawn();
|
||||
assert!(p.is_err());
|
||||
}
|
Loading…
Reference in New Issue
Block a user