Skip to content

Commit baf71bd

Browse files
change std::process to drop supplementary groups based on CAP_SETGID
1 parent 2a83fbc commit baf71bd

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

library/std/src/os/unix/process.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ pub trait CommandExt: Sealed {
2121
/// Sets the child process's user ID. This translates to a
2222
/// `setuid` call in the child process. Failure in the `setuid`
2323
/// call will cause the spawn to fail.
24+
///
25+
/// # Notes
26+
///
27+
/// This will also trigger a call to `setgroups(0, NULL)` in the child
28+
/// process if no groups have been specified.
29+
/// This removes supplementary groups that might have given the child
30+
/// unwanted permissions.
2431
#[stable(feature = "rust1", since = "1.0.0")]
2532
fn uid(
2633
&mut self,

library/std/src/sys/unix/process/process_unix.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,22 @@ impl Command {
304304
if let Some(u) = self.get_uid() {
305305
// When dropping privileges from root, the `setgroups` call
306306
// will remove any extraneous groups. We only drop groups
307-
// if the current uid is 0 and we weren't given an explicit
307+
// if we have CAP_SETGID and we weren't given an explicit
308308
// set of groups. If we don't call this, then even though our
309309
// uid has dropped, we may still have groups that enable us to
310310
// do super-user things.
311311
//FIXME: Redox kernel does not support setgroups yet
312312
#[cfg(not(target_os = "redox"))]
313-
if libc::getuid() == 0 && self.get_groups().is_none() {
314-
cvt(libc::setgroups(0, ptr::null()))?;
313+
if self.get_groups().is_none() {
314+
let res = cvt(libc::setgroups(0, ptr::null()));
315+
if let Err(e) = res {
316+
// Here we ignore the case of not having CAP_SETGID.
317+
// An alternative would be to require CAP_SETGID (in
318+
// addition to CAP_SETUID) for setting the UID.
319+
if e.raw_os_error() != Some(libc::EPERM) {
320+
return Err(e.into());
321+
}
322+
}
315323
}
316324
cvt(libc::setuid(u as uid_t))?;
317325
}

0 commit comments

Comments
 (0)