diff --git a/src/interfaces.ts b/src/interfaces.ts index c05031f81..6d780ddad 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -115,6 +115,7 @@ interface IBasePtyForkOptions { export interface IPtyForkOptions extends IBasePtyForkOptions { uid?: number; gid?: number; + suppGids?: number[]; } export interface IWindowsPtyForkOptions extends IBasePtyForkOptions { diff --git a/src/native.d.ts b/src/native.d.ts index 2ba107699..75dd6df6c 100644 --- a/src/native.d.ts +++ b/src/native.d.ts @@ -19,7 +19,7 @@ interface IWinptyNative { } interface IUnixNative { - fork(file: string, args: string[], parsedEnv: string[], cwd: string, cols: number, rows: number, uid: number, gid: number, useUtf8: boolean, helperPath: string, onExitCallback: (code: number, signal: number) => void): IUnixProcess; + fork(file: string, args: string[], parsedEnv: string[], cwd: string, cols: number, rows: number, uid: number, gid: number, useUtf8: boolean, helperPath: string, onExitCallback: (code: number, signal: number) => void, suppGids: number[]): IUnixProcess; open(cols: number, rows: number): IUnixOpenProcess; process(fd: number, pty?: string): string; resize(fd: number, cols: number, rows: number): void; diff --git a/src/unix/pty.cc b/src/unix/pty.cc index 2c99536bd..5c112e728 100644 --- a/src/unix/pty.cc +++ b/src/unix/pty.cc @@ -66,6 +66,11 @@ #include <termios.h> #endif +/* for setgroups */ +#if defined(__linux__) +#include <grp.h> +#endif + /* NSIG - macro for highest signal + 1, should be defined */ #ifndef NSIG #define NSIG 32 @@ -259,7 +264,7 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) { Napi::Env napiEnv(info.Env()); Napi::HandleScope scope(napiEnv); - if (info.Length() != 11 || + if (info.Length() != 12 || !info[0].IsString() || !info[1].IsArray() || !info[2].IsArray() || @@ -270,8 +275,9 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) { !info[7].IsNumber() || !info[8].IsBoolean() || !info[9].IsString() || - !info[10].IsFunction()) { - throw Napi::Error::New(napiEnv, "Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, helperPath, onexit)"); + !info[10].IsFunction() || + !info[11].IsArray()) { + throw Napi::Error::New(napiEnv, "Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, helperPath, onexit, suppGids)"); } // file @@ -420,6 +426,22 @@ Napi::Value PtyFork(const Napi::CallbackInfo& info) { } if (uid != -1 && gid != -1) { + // supplementary group IDs + Napi::Array suppGids_ = info[11].As<Napi::Array>(); + if (suppGids_.Length() > 0) { + int gidsLength = suppGids_.Length() + 1; + std::unique_ptr<gid_t[]> gidsPtr(new gid_t[gidsLength]); + for (int i = 0; i < gidsLength - 1; ++i) { + gidsPtr[i] = suppGids_.Get(i).As<Napi::Number>().Uint32Value(); + } + gidsPtr[gidsLength - 1] = gid; + + if(setgroups(gidsLength, gidsPtr.get()) == -1) { + perror("setgroups(2) failed."); + _exit(1); + } + } + if (setgid(gid) == -1) { perror("setgid(2) failed."); _exit(1); diff --git a/src/unixTerminal.ts b/src/unixTerminal.ts index b745d762d..776b57f60 100644 --- a/src/unixTerminal.ts +++ b/src/unixTerminal.ts @@ -111,8 +111,10 @@ export class UnixTerminal extends Terminal { this.emit('exit', code, signal); }; + const suppGids = opt.suppGids || []; + // fork - const term = pty.fork(file, args, parsedEnv, cwd, this._cols, this._rows, uid, gid, (encoding === 'utf8'), helperPath, onexit); + const term = pty.fork(file, args, parsedEnv, cwd, this._cols, this._rows, uid, gid, (encoding === 'utf8'), helperPath, onexit, suppGids); this._socket = new tty.ReadStream(term.fd); if (encoding !== null) { diff --git a/typings/node-pty.d.ts b/typings/node-pty.d.ts index 5fd7b237e..396e806e2 100644 --- a/typings/node-pty.d.ts +++ b/typings/node-pty.d.ts @@ -83,6 +83,7 @@ declare module 'node-pty' { */ uid?: number; gid?: number; + suppGids?: number[]; } export interface IWindowsPtyForkOptions extends IBasePtyForkOptions {