mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
fix process-uid-gid.test.js
This commit is contained in:
@@ -45,6 +45,8 @@
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#else
|
||||
#include <uv.h>
|
||||
#include <io.h>
|
||||
@@ -2100,6 +2102,101 @@ JSC_DEFINE_HOST_FUNCTION(Process_functiongetgroups, (JSGlobalObject * globalObje
|
||||
|
||||
return JSValue::encode(groups);
|
||||
}
|
||||
|
||||
static JSValue maybe_uid_by_name(JSC::ThrowScope& throwScope, JSGlobalObject* globalObject, JSValue value)
|
||||
{
|
||||
if (!value.isNumber() && !value.isString()) return JSValue::decode(Bun::ERR::INVALID_ARG_TYPE(throwScope, globalObject, "id"_s, "number or string"_s, value));
|
||||
if (!value.isString()) return value;
|
||||
|
||||
auto str = value.getString(globalObject);
|
||||
if (!str.is8Bit()) {
|
||||
auto message = makeString("User identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
auto name = (const char*)(str.span8().data());
|
||||
struct passwd pwd;
|
||||
struct passwd* pp = nullptr;
|
||||
char buf[8192];
|
||||
|
||||
if (getpwnam_r(name, &pwd, buf, sizeof(buf), &pp) == 0 && pp != nullptr) {
|
||||
return jsNumber(pp->pw_uid);
|
||||
}
|
||||
|
||||
auto message = makeString("User identifier does not exist: "_s, str);
|
||||
throwScope.throwException(globalObject, createError(globalObject, ErrorCode::ERR_UNKNOWN_CREDENTIAL, message));
|
||||
return {};
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetuid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 32)));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
auto result = setuid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setuid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionseteuid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 32)));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
auto result = seteuid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "seteuid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetegid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 32)));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
auto result = setegid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setegid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetgid, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
auto& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
auto value = callFrame->argument(0);
|
||||
value = maybe_uid_by_name(scope, globalObject, value);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
Bun::V::validateInteger(scope, globalObject, value, jsString(vm, String("id"_s)), jsNumber(0), jsNumber(std::pow(2, 32)));
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
auto id = value.toUInt32(globalObject);
|
||||
auto result = setgid(id);
|
||||
if (result != 0) throwSystemError(scope, globalObject, "setgid"_s, errno);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
return JSValue::encode(jsNumber(result));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionsetgroups, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
{
|
||||
return JSValue::encode(jsNumber(0)); // TODO:
|
||||
}
|
||||
#endif
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, CallFrame* callFrame))
|
||||
@@ -3044,12 +3141,19 @@ extern "C" void Process__emitErrorEvent(Zig::GlobalObject* global, EncodedJSValu
|
||||
_stopProfilerIdleNotifier Process_stubEmptyFunction Function 0
|
||||
_tickCallback Process_stubEmptyFunction Function 0
|
||||
_kill Process_functionReallyKill Function 2
|
||||
|
||||
#if !OS(WINDOWS)
|
||||
getegid Process_functiongetegid Function 0
|
||||
geteuid Process_functiongeteuid Function 0
|
||||
getgid Process_functiongetgid Function 0
|
||||
getgroups Process_functiongetgroups Function 0
|
||||
getuid Process_functiongetuid Function 0
|
||||
|
||||
setegid Process_functionsetegid Function 1
|
||||
seteuid Process_functionseteuid Function 1
|
||||
setgid Process_functionsetgid Function 1
|
||||
setgroups Process_functionsetgroups Function 1
|
||||
setuid Process_functionsetuid Function 1
|
||||
#endif
|
||||
@end
|
||||
*/
|
||||
|
||||
@@ -46,6 +46,7 @@ export default [
|
||||
["ERR_UNKNOWN_SIGNAL", TypeError, "TypeError"],
|
||||
["ERR_SOCKET_BAD_PORT", RangeError, "RangeError"],
|
||||
["ERR_IPC_ONE_PIPE", Error, "Error"],
|
||||
["ERR_UNKNOWN_CREDENTIAL", Error, "Error"],
|
||||
|
||||
// Bun-specific
|
||||
["ERR_FORMDATA_PARSE_ERROR", TypeError, "TypeError"],
|
||||
|
||||
@@ -1,6 +1,260 @@
|
||||
#include "root.h"
|
||||
#include "helpers.h"
|
||||
#include "BunClientData.h"
|
||||
#include <string.h>
|
||||
|
||||
const char* errno_string(int errorno)
|
||||
{
|
||||
#define ERRNO_CASE(e) \
|
||||
case e: \
|
||||
return #e;
|
||||
switch (errorno) {
|
||||
#ifdef EACCES
|
||||
ERRNO_CASE(EACCES);
|
||||
#endif
|
||||
#ifdef EADDRINUSE
|
||||
ERRNO_CASE(EADDRINUSE);
|
||||
#endif
|
||||
#ifdef EADDRNOTAVAIL
|
||||
ERRNO_CASE(EADDRNOTAVAIL);
|
||||
#endif
|
||||
#ifdef EAFNOSUPPORT
|
||||
ERRNO_CASE(EAFNOSUPPORT);
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
ERRNO_CASE(EAGAIN);
|
||||
#endif
|
||||
#ifdef EWOULDBLOCK
|
||||
#if EAGAIN != EWOULDBLOCK
|
||||
ERRNO_CASE(EWOULDBLOCK);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef EALREADY
|
||||
ERRNO_CASE(EALREADY);
|
||||
#endif
|
||||
#ifdef EBADF
|
||||
ERRNO_CASE(EBADF);
|
||||
#endif
|
||||
#ifdef EBADMSG
|
||||
ERRNO_CASE(EBADMSG);
|
||||
#endif
|
||||
#ifdef EBUSY
|
||||
ERRNO_CASE(EBUSY);
|
||||
#endif
|
||||
#ifdef ECANCELED
|
||||
ERRNO_CASE(ECANCELED);
|
||||
#endif
|
||||
#ifdef ECHILD
|
||||
ERRNO_CASE(ECHILD);
|
||||
#endif
|
||||
#ifdef ECONNABORTED
|
||||
ERRNO_CASE(ECONNABORTED);
|
||||
#endif
|
||||
#ifdef ECONNREFUSED
|
||||
ERRNO_CASE(ECONNREFUSED);
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
ERRNO_CASE(ECONNRESET);
|
||||
#endif
|
||||
#ifdef EDEADLK
|
||||
ERRNO_CASE(EDEADLK);
|
||||
#endif
|
||||
#ifdef EDESTADDRREQ
|
||||
ERRNO_CASE(EDESTADDRREQ);
|
||||
#endif
|
||||
#ifdef EDOM
|
||||
ERRNO_CASE(EDOM);
|
||||
#endif
|
||||
#ifdef EDQUOT
|
||||
ERRNO_CASE(EDQUOT);
|
||||
#endif
|
||||
#ifdef EEXIST
|
||||
ERRNO_CASE(EEXIST);
|
||||
#endif
|
||||
#ifdef EFAULT
|
||||
ERRNO_CASE(EFAULT);
|
||||
#endif
|
||||
#ifdef EFBIG
|
||||
ERRNO_CASE(EFBIG);
|
||||
#endif
|
||||
#ifdef EHOSTUNREACH
|
||||
ERRNO_CASE(EHOSTUNREACH);
|
||||
#endif
|
||||
#ifdef EIDRM
|
||||
ERRNO_CASE(EIDRM);
|
||||
#endif
|
||||
#ifdef EILSEQ
|
||||
ERRNO_CASE(EILSEQ);
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
ERRNO_CASE(EINPROGRESS);
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
ERRNO_CASE(EINTR);
|
||||
#endif
|
||||
#ifdef EINVAL
|
||||
ERRNO_CASE(EINVAL);
|
||||
#endif
|
||||
#ifdef EIO
|
||||
ERRNO_CASE(EIO);
|
||||
#endif
|
||||
#ifdef EISCONN
|
||||
ERRNO_CASE(EISCONN);
|
||||
#endif
|
||||
#ifdef EISDIR
|
||||
ERRNO_CASE(EISDIR);
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
ERRNO_CASE(ELOOP);
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
ERRNO_CASE(EMFILE);
|
||||
#endif
|
||||
#ifdef EMLINK
|
||||
ERRNO_CASE(EMLINK);
|
||||
#endif
|
||||
#ifdef EMSGSIZE
|
||||
ERRNO_CASE(EMSGSIZE);
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
ERRNO_CASE(EMULTIHOP);
|
||||
#endif
|
||||
#ifdef ENAMETOOLONG
|
||||
ERRNO_CASE(ENAMETOOLONG);
|
||||
#endif
|
||||
#ifdef ENETDOWN
|
||||
ERRNO_CASE(ENETDOWN);
|
||||
#endif
|
||||
#ifdef ENETRESET
|
||||
ERRNO_CASE(ENETRESET);
|
||||
#endif
|
||||
#ifdef ENETUNREACH
|
||||
ERRNO_CASE(ENETUNREACH);
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
ERRNO_CASE(ENFILE);
|
||||
#endif
|
||||
#ifdef ENOBUFS
|
||||
ERRNO_CASE(ENOBUFS);
|
||||
#endif
|
||||
#ifdef ENODATA
|
||||
ERRNO_CASE(ENODATA);
|
||||
#endif
|
||||
#ifdef ENODEV
|
||||
ERRNO_CASE(ENODEV);
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
ERRNO_CASE(ENOENT);
|
||||
#endif
|
||||
#ifdef ENOEXEC
|
||||
ERRNO_CASE(ENOEXEC);
|
||||
#endif
|
||||
#ifdef ENOLINK
|
||||
ERRNO_CASE(ENOLINK);
|
||||
#endif
|
||||
#ifdef ENOLCK
|
||||
#if ENOLINK != ENOLCK
|
||||
ERRNO_CASE(ENOLCK);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
ERRNO_CASE(ENOMEM);
|
||||
#endif
|
||||
#ifdef ENOMSG
|
||||
ERRNO_CASE(ENOMSG);
|
||||
#endif
|
||||
#ifdef ENOPROTOOPT
|
||||
ERRNO_CASE(ENOPROTOOPT);
|
||||
#endif
|
||||
#ifdef ENOSPC
|
||||
ERRNO_CASE(ENOSPC);
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
ERRNO_CASE(ENOSR);
|
||||
#endif
|
||||
#ifdef ENOSTR
|
||||
ERRNO_CASE(ENOSTR);
|
||||
#endif
|
||||
#ifdef ENOSYS
|
||||
ERRNO_CASE(ENOSYS);
|
||||
#endif
|
||||
#ifdef ENOTCONN
|
||||
ERRNO_CASE(ENOTCONN);
|
||||
#endif
|
||||
#ifdef ENOTDIR
|
||||
ERRNO_CASE(ENOTDIR);
|
||||
#endif
|
||||
#ifdef ENOTEMPTY
|
||||
#if ENOTEMPTY != EEXIST
|
||||
ERRNO_CASE(ENOTEMPTY);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOTSOCK
|
||||
ERRNO_CASE(ENOTSOCK);
|
||||
#endif
|
||||
#ifdef ENOTSUP
|
||||
ERRNO_CASE(ENOTSUP);
|
||||
#else
|
||||
#ifdef EOPNOTSUPP
|
||||
ERRNO_CASE(EOPNOTSUPP);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef ENOTTY
|
||||
ERRNO_CASE(ENOTTY);
|
||||
#endif
|
||||
#ifdef ENXIO
|
||||
ERRNO_CASE(ENXIO);
|
||||
#endif
|
||||
#ifdef EOVERFLOW
|
||||
ERRNO_CASE(EOVERFLOW);
|
||||
#endif
|
||||
#ifdef EPERM
|
||||
ERRNO_CASE(EPERM);
|
||||
#endif
|
||||
#ifdef EPIPE
|
||||
ERRNO_CASE(EPIPE);
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
ERRNO_CASE(EPROTO);
|
||||
#endif
|
||||
#ifdef EPROTONOSUPPORT
|
||||
ERRNO_CASE(EPROTONOSUPPORT);
|
||||
#endif
|
||||
#ifdef EPROTOTYPE
|
||||
ERRNO_CASE(EPROTOTYPE);
|
||||
#endif
|
||||
#ifdef ERANGE
|
||||
ERRNO_CASE(ERANGE);
|
||||
#endif
|
||||
#ifdef EROFS
|
||||
ERRNO_CASE(EROFS);
|
||||
#endif
|
||||
#ifdef ESPIPE
|
||||
ERRNO_CASE(ESPIPE);
|
||||
#endif
|
||||
#ifdef ESRCH
|
||||
ERRNO_CASE(ESRCH);
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
ERRNO_CASE(ESTALE);
|
||||
#endif
|
||||
#ifdef ETIME
|
||||
ERRNO_CASE(ETIME);
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
ERRNO_CASE(ETIMEDOUT);
|
||||
#endif
|
||||
#ifdef ETXTBSY
|
||||
ERRNO_CASE(ETXTBSY);
|
||||
#endif
|
||||
#ifdef EXDEV
|
||||
ERRNO_CASE(EXDEV);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral message, ASCIILiteral syscall, int err)
|
||||
{
|
||||
@@ -15,11 +269,12 @@ JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral message
|
||||
|
||||
JSC::JSValue createSystemError(JSC::JSGlobalObject* global, ASCIILiteral syscall, int err)
|
||||
{
|
||||
auto* instance = JSC::createError(global, makeString(String(syscall), "() failed"_s));
|
||||
auto* instance = JSC::createError(global, makeString(String(syscall), "() failed: "_s, String::fromLatin1(strerror(err))));
|
||||
auto& vm = global->vm();
|
||||
auto& builtinNames = WebCore::builtinNames(vm);
|
||||
instance->putDirect(vm, builtinNames.syscallPublicName(), jsString(vm, String(syscall)), 0);
|
||||
instance->putDirect(vm, builtinNames.errnoPublicName(), JSC::jsNumber(err), 0);
|
||||
instance->putDirect(vm, vm.propertyNames->name, jsString(vm, String("SystemError"_s)), JSC::PropertyAttribute::DontEnum | 0);
|
||||
instance->putDirect(vm, builtinNames.codePublicName(), jsString(vm, String::fromLatin1(errno_string(err))));
|
||||
return instance;
|
||||
}
|
||||
|
||||
118
test/js/node/test/parallel/process-uid-gid.test.js
Normal file
118
test/js/node/test/parallel/process-uid-gid.test.js
Normal file
@@ -0,0 +1,118 @@
|
||||
//#FILE: test-process-uid-gid.js
|
||||
//#SHA1: fdd637ef2fcf3bcada2c86f574494e32e5c03780
|
||||
//-----------------
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
"use strict";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
const isMainThread = !process.env.NODE_WORKER_ID;
|
||||
|
||||
if (isWindows) {
|
||||
test("uid/gid functions are POSIX only", () => {
|
||||
// uid/gid functions are POSIX only.
|
||||
expect(process.getuid).toBeUndefined();
|
||||
expect(process.getgid).toBeUndefined();
|
||||
expect(process.setuid).toBeUndefined();
|
||||
expect(process.setgid).toBeUndefined();
|
||||
});
|
||||
} else if (isMainThread) {
|
||||
test("setuid with invalid arguments", () => {
|
||||
expect(() => process.setuid({})).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
message: expect.stringContaining('The "id" argument must be of type number or string'),
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => process.setuid("fhqwhgadshgnsdhjsdbkhsdabkfabkveyb")).toThrow(
|
||||
expect.objectContaining({
|
||||
code: "ERR_UNKNOWN_CREDENTIAL",
|
||||
message: "User identifier does not exist: fhqwhgadshgnsdhjsdbkhsdabkfabkveyb",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("edge cases for uid/gid functions", () => {
|
||||
// Passing -0 shouldn't crash the process
|
||||
// Refs: https://github.com/nodejs/node/issues/32750
|
||||
// And neither should values exceeding 2 ** 31 - 1.
|
||||
const ids = [-0, 2 ** 31, 2 ** 32 - 1];
|
||||
const fns = [process.setuid, process.setuid, process.setgid, process.setegid];
|
||||
|
||||
for (const id of ids) {
|
||||
for (const fn of fns) {
|
||||
expect(() => {
|
||||
try {
|
||||
fn(id);
|
||||
} catch {
|
||||
// Continue regardless of error.
|
||||
}
|
||||
}).not.toThrow();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (process.getuid() !== 0) {
|
||||
test("non-root user permissions", () => {
|
||||
// Should not throw.
|
||||
expect(() => process.getgid()).not.toThrow();
|
||||
expect(() => process.getuid()).not.toThrow();
|
||||
|
||||
expect(() => process.setgid("nobody")).toThrow(
|
||||
expect.objectContaining({
|
||||
syscall: "setgid",
|
||||
code: "EPERM",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(() => process.setuid("nobody")).toThrow(
|
||||
expect.objectContaining({
|
||||
syscall: "setuid",
|
||||
code: "EPERM",
|
||||
}),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
test("root user permissions", async () => {
|
||||
const oldgid = process.getgid();
|
||||
try {
|
||||
process.setgid("nobody");
|
||||
} catch (err) {
|
||||
if (err.code !== "ERR_UNKNOWN_CREDENTIAL") {
|
||||
throw err;
|
||||
}
|
||||
process.setgid("nogroup");
|
||||
}
|
||||
|
||||
const newgid = process.getgid();
|
||||
expect(newgid).not.toBe(oldgid);
|
||||
|
||||
const olduid = process.getuid();
|
||||
process.setuid("nobody");
|
||||
const newuid = process.getuid();
|
||||
expect(newuid).not.toBe(olduid);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//<#END_FILE: test-process-uid-gid.js
|
||||
Reference in New Issue
Block a user