Skip to content

Commit

Permalink
feat(unstable): allow specifing gid and uid for subprocess (denoland#…
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats committed Sep 13, 2021
1 parent 274ff6c commit a655a0f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
6 changes: 6 additions & 0 deletions cli/dts/lib.deno.ns.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2034,6 +2034,12 @@ declare namespace Deno {
* Environmental variables for subprocess can be specified using `opt.env`
* mapping.
*
* `opt.uid` sets the child process’s user ID. This translates to a setuid call
* in the child process. Failure in the setuid call will cause the spawn to fail.
*
* `opt.gid` is similar to `opt.uid`, but sets the group ID of the child process.
* This has the same semantics as the uid field.
*
* By default subprocess inherits stdio of parent process. To change that
* `opt.stdout`, `opt.stderr` and `opt.stdin` can be specified independently -
* they can be set to either an rid of open file or set to "inherit" "piped"
Expand Down
4 changes: 4 additions & 0 deletions cli/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,12 @@ declare namespace Deno {
export function run<
T extends RunOptions & {
clearEnv?: boolean;
gid?: number;
uid?: number;
} = RunOptions & {
clearEnv?: boolean;
gid?: number;
uid?: number;
},
>(opt: T): Process<T>;

Expand Down
56 changes: 56 additions & 0 deletions cli/tests/unit/process_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,59 @@ unitTest(
p.close();
},
);

unitTest(
{ perms: { run: true, read: true }, ignore: Deno.build.os === "windows" },
async function uid(): Promise<void> {
const p = Deno.run({
cmd: [
"id",
"-u",
],
stdout: "piped",
});

const currentUid = new TextDecoder().decode(await p.output());
p.close();

if (currentUid !== "0") {
assertThrows(() => {
Deno.run({
cmd: [
"echo",
"fhqwhgads",
],
uid: 0,
});
}, Deno.errors.PermissionDenied);
}
},
);

unitTest(
{ perms: { run: true, read: true }, ignore: Deno.build.os === "windows" },
async function gid(): Promise<void> {
const p = Deno.run({
cmd: [
"id",
"-g",
],
stdout: "piped",
});

const currentGid = new TextDecoder().decode(await p.output());
p.close();

if (currentGid !== "0") {
assertThrows(() => {
Deno.run({
cmd: [
"echo",
"fhqwhgads",
],
gid: 0,
});
}, Deno.errors.PermissionDenied);
}
},
);
4 changes: 4 additions & 0 deletions runtime/js/40_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@
cwd = undefined,
clearEnv = false,
env = {},
gid = undefined,
uid = undefined,
stdout = "inherit",
stderr = "inherit",
stdin = "inherit",
Expand All @@ -114,6 +116,8 @@
cwd,
clearEnv,
env: ObjectEntries(env),
gid,
uid,
stdin: isRid(stdin) ? "" : stdin,
stdout: isRid(stdout) ? "" : stdout,
stderr: isRid(stderr) ? "" : stderr,
Expand Down
20 changes: 20 additions & 0 deletions runtime/ops/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub struct RunArgs {
cwd: Option<String>,
clear_env: bool,
env: Vec<(String, String)>,
gid: Option<u32>,
uid: Option<u32>,
stdin: String,
stdout: String,
stderr: String,
Expand Down Expand Up @@ -123,6 +125,24 @@ fn op_run(
c.env(key, value);
}

#[cfg(unix)]
if let Some(gid) = run_args.gid {
super::check_unstable(state, "Deno.run.gid");
c.gid(gid);
}
#[cfg(unix)]
if let Some(uid) = run_args.uid {
super::check_unstable(state, "Deno.run.uid");
c.uid(uid);
}
#[cfg(unix)]
unsafe {
c.pre_exec(|| {
libc::setgroups(0, std::ptr::null());
Ok(())
});
}

// TODO: make this work with other resources, eg. sockets
if !run_args.stdin.is_empty() {
c.stdin(subprocess_stdio_map(run_args.stdin.as_ref())?);
Expand Down

0 comments on commit a655a0f

Please sign in to comment.