Skip to content

Commit 3f61940

Browse files
committed
src: allow CAP_NET_BIND_SERVICE in SafeGetenv
This commit updates SafeGetenv to check if the current process has the effective capability cap_net_bind_service set, and if so allows environment variables to be read. The motivation for this change is a use-case where Node is run in a container, and the is a requirement to be able to listen to ports below 1024. This is done by setting the capability of cap_net_bind_service. In addition there is a need to set the environment variable `NODE_EXTRA_CA_CERTS`. But currently this environment variable will not be read when the capability has been set on the executable. PR-URL: #37727 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Richard Lau <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent 8e84d56 commit 3f61940

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

src/node_credentials.cc

+36-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
#if !defined(_MSC_VER)
1212
#include <unistd.h> // setuid, getuid
1313
#endif
14+
#ifdef __linux__
15+
#include <linux/capability.h>
16+
#include <sys/syscall.h>
17+
#endif // __linux__
1418

1519
namespace node {
1620

@@ -33,11 +37,42 @@ bool linux_at_secure = false;
3337

3438
namespace credentials {
3539

36-
// Look up environment variable unless running as setuid root.
40+
#if defined(__linux__)
41+
// Returns true if the current process only has the passed-in capability.
42+
bool HasOnly(int capability) {
43+
DCHECK(cap_valid(capability));
44+
45+
struct __user_cap_data_struct cap_data[2];
46+
struct __user_cap_header_struct cap_header_data = {
47+
_LINUX_CAPABILITY_VERSION_3,
48+
getpid()};
49+
50+
51+
if (syscall(SYS_capget, &cap_header_data, &cap_data) != 0) {
52+
return false;
53+
}
54+
if (capability < 32) {
55+
return cap_data[0].permitted ==
56+
static_cast<unsigned int>(CAP_TO_MASK(capability));
57+
}
58+
return cap_data[1].permitted ==
59+
static_cast<unsigned int>(CAP_TO_MASK(capability));
60+
}
61+
#endif
62+
63+
// Look up the environment variable and allow the lookup if the current
64+
// process only has the capability CAP_NET_BIND_SERVICE set. If the current
65+
// process does not have any capabilities set and the process is running as
66+
// setuid root then lookup will not be allowed.
3767
bool SafeGetenv(const char* key, std::string* text, Environment* env) {
3868
#if !defined(__CloudABI__) && !defined(_WIN32)
69+
#if defined(__linux__)
70+
if ((!HasOnly(CAP_NET_BIND_SERVICE) && per_process::linux_at_secure) ||
71+
getuid() != geteuid() || getgid() != getegid())
72+
#else
3973
if (per_process::linux_at_secure || getuid() != geteuid() ||
4074
getgid() != getegid())
75+
#endif
4176
goto fail;
4277
#endif
4378

0 commit comments

Comments
 (0)