Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Bevenius <daniel.bevenius@gmail.com>2021-03-17 15:48:51 +0300
committerDaniel Bevenius <daniel.bevenius@gmail.com>2021-09-24 06:56:43 +0300
commit3f619407fe1e597657b598383d0b5003a064311b (patch)
treea49211a6c3e8ebbc63a6f712a1da30fcc7d12597 /src/node_credentials.cc
parent8e84d566eababe9585864678e729c735a19e0085 (diff)
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: https://github.com/nodejs/node/pull/37727 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com>
Diffstat (limited to 'src/node_credentials.cc')
-rw-r--r--src/node_credentials.cc37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/node_credentials.cc b/src/node_credentials.cc
index fa3dfa48a3c..de0ba3c8be2 100644
--- a/src/node_credentials.cc
+++ b/src/node_credentials.cc
@@ -11,6 +11,10 @@
#if !defined(_MSC_VER)
#include <unistd.h> // setuid, getuid
#endif
+#ifdef __linux__
+#include <linux/capability.h>
+#include <sys/syscall.h>
+#endif // __linux__
namespace node {
@@ -33,11 +37,42 @@ bool linux_at_secure = false;
namespace credentials {
-// Look up environment variable unless running as setuid root.
+#if defined(__linux__)
+// Returns true if the current process only has the passed-in capability.
+bool HasOnly(int capability) {
+ DCHECK(cap_valid(capability));
+
+ struct __user_cap_data_struct cap_data[2];
+ struct __user_cap_header_struct cap_header_data = {
+ _LINUX_CAPABILITY_VERSION_3,
+ getpid()};
+
+
+ if (syscall(SYS_capget, &cap_header_data, &cap_data) != 0) {
+ return false;
+ }
+ if (capability < 32) {
+ return cap_data[0].permitted ==
+ static_cast<unsigned int>(CAP_TO_MASK(capability));
+ }
+ return cap_data[1].permitted ==
+ static_cast<unsigned int>(CAP_TO_MASK(capability));
+}
+#endif
+
+// Look up the environment variable and allow the lookup if the current
+// process only 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 defined(__linux__)
+ if ((!HasOnly(CAP_NET_BIND_SERVICE) && per_process::linux_at_secure) ||
+ getuid() != geteuid() || getgid() != getegid())
+#else
if (per_process::linux_at_secure || getuid() != geteuid() ||
getgid() != getegid())
+#endif
goto fail;
#endif