diff --git a/docs/docs/stdlib.md b/docs/docs/stdlib.md index 161240e40..2fc29f354 100644 --- a/docs/docs/stdlib.md +++ b/docs/docs/stdlib.md @@ -253,6 +253,8 @@ object containing optional parameters: process. - `uid` - Integer. If present, the process uid with `setuid`. - `gid` - Integer. If present, the process gid with `setgid`. +- `groups` - Array of integer. If present, the supplementary + group IDs with `setgroup`. ### `waitpid(pid, options)` diff --git a/quickjs-libc.c b/quickjs-libc.c index 6082b7465..6c6ad2f53 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -66,6 +66,7 @@ #include #include #include +#include #endif #if defined(__APPLE__) @@ -3236,6 +3237,8 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, static const char *std_name[3] = { "stdin", "stdout", "stderr" }; int std_fds[3]; uint32_t uid = -1, gid = -1; + int ngroups = -1; + gid_t groups[64]; val = JS_GetPropertyStr(ctx, args, "length"); if (JS_IsException(val)) @@ -3339,6 +3342,40 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, if (ret) goto exception; } + + val = JS_GetPropertyStr(ctx, options, "groups"); + if (JS_IsException(val)) + goto exception; + if (!JS_IsUndefined(val)) { + int64_t idx, len; + JSValue prop; + uint32_t id; + ngroups = 0; + if (JS_GetLength(ctx, val, &len)) { + JS_FreeValue(ctx, val); + goto exception; + } + for (idx = 0; idx < len; idx++) { + prop = JS_GetPropertyInt64(ctx, val, idx); + if (JS_IsException(prop)) + break; + if (JS_IsUndefined(prop)) + continue; + ret = JS_ToUint32(ctx, &id, prop); + JS_FreeValue(ctx, prop); + if (ret) + break; + if (ngroups == countof(groups)) { + JS_ThrowRangeError(ctx, "too many groups"); + break; + } + groups[ngroups++] = id; + } + JS_FreeValue(ctx, val); + if (idx < len) + goto exception; + } + } #if !defined(EMSCRIPTEN) && !defined(__wasi__) @@ -3374,6 +3411,10 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, if (chdir(cwd) < 0) _exit(127); } + if (ngroups != -1) { + if (setgroups(ngroups, groups) < 0) + _exit(127); + } if (uid != -1) { if (setuid(uid) < 0) _exit(127);