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_execclosure is called, the directory has already been changed, which is incorrect when presented with
chroot(2), since it will leave it at the same physical working directory (which may be outside the new root directory), so in order to use
chroot, you also have to use
chdir, 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
.uidif you plan to do anything that needs elevation because if it occurs before
pre_exec, all privileged operations will be all but guaranteed to EPERM, including
pre_execalso cannot use closures that capture by-move, which is understandable, but prevents taking ownership of the
CString(which could then be
forgotten 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).
groupsclosely mirrors the presence of
gid. It doesn't necessarily make sense to set the primary group idea while leaving all suplementary group ids untouched.
chrootis 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:
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
fn root_directory<S: AsRef<Path>>(&mut self,dir: S) -> &mut Self;
Sets the Root directory of the the child process.
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