Having looked at the Command and unix::CommandExt docs, I find that they are actually lacking. Currently, in rust, you need to use .pre_exec
to set a list of groups or to chroot
before executing the command. Both are suboptimal for the following reasons:
- You need to allocate in order to call
chroot(2)
(I will not start a rant about OsStr being entirely useless, but suffice it to say, I am not the biggest fan of it). - You almost always need to allocate in order to set a suplementary groups list.
- When the
pre_exec
closure is called, the directory has already been changed, which is incorrect when presented withchroot(2)
, since it will leave it at the same physical working directory (which may be outside the new root directory), so in order to usechroot
, you also have to usechdir
, requiring more allocations. - It is also not defined the order that changes of uid and gid will take place wrt.
pre_exec
, which means that you can't use.uid
if you plan to do anything that needs elevation because if it occurs beforepre_exec
, all privileged operations will be all but guaranteed to EPERM, includingroot_directory
andgroups
. -
pre_exec
also cannot use closures that capture by-move, which is understandable, but prevents taking ownership of theVec
orCString
(which could then beforgot
ten in the child), which could be dropped in the parent (To avoid having to leak or borrow, which limits or prevents returning the Command, in forwarding methods that operate on Command). -
groups
closely mirrors the presence ofgid
. It doesn't necessarily make sense to set the primary group idea while leaving all suplementary group ids untouched. -
chroot
is potetionally useful in privileged code, and is very difficult to use correctly as-is with CommandExt, for the reasons described above.
Thus, I propose two additional functions be added to std::os::unix::process::CommandExt
as follows:
groups
fn groups<A: AsRef<[u32]>>(&mut self,groups: A) -> &mut Self
Sets the supplementary groups of the child process to the the list provided by groups
.
root_directory
fn root_directory<S: AsRef<Path>>(&mut self,dir: S) -> &mut Self;
Sets the Root directory of the the child process.
Notes
root_directory
applies to both current_directory
and the program name for the command. The new directory is the path name within the root directory. If the path passed to current_directory
is relative, it is resolved relative to /
. If no call to self.current_directory
is made, then the working directory in the child will be /
.