Skip to content

Commit

Permalink
src: allow CAP_NET_BIND_SERVICE in SafeGetenv
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
danbev committed Mar 23, 2021
1 parent 3bee6d8 commit 9e3b90e
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions src/node_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#if !defined(_MSC_VER)
#include <unistd.h> // setuid, getuid
#include <sys/capability.h>
#endif

namespace node {
Expand All @@ -33,11 +34,32 @@ bool linux_at_secure = false;

namespace credentials {

// Look up environment variable unless running as setuid root.
#if !defined(__CloudABI__) && !defined(_WIN32)
// Returns true if the current process has effective capabilities and the
// passed-in capability is in that set.
bool HasCapability(int capability) {
DCHECK(cap_valid(capability));
struct __user_cap_header_struct cap_header_data = {
_LINUX_CAPABILITY_VERSION_1, getpid()
};
struct __user_cap_data_struct cap_data;

if (capget(&cap_header_data, &cap_data) == -1) {
return false;
}

return cap_data.effective & CAP_TO_MASK(capability);
}
#endif

// Look up the environment variable and allow the lookup if the current
// process has the capability CAP_NET_BIND_SERVICE set. If the current process
// does not have any capabilities set and the process is running as setuid root
// then lookup will not be allowed.
bool SafeGetenv(const char* key, std::string* text, Environment* env) {
#if !defined(__CloudABI__) && !defined(_WIN32)
if (per_process::linux_at_secure || getuid() != geteuid() ||
getgid() != getegid())
if (!HasCapability(CAP_NET_BIND_SERVICE) && (per_process::linux_at_secure ||
getuid() != geteuid() || getgid() != getegid()))
goto fail;
#endif

Expand Down

0 comments on commit 9e3b90e

Please sign in to comment.