From 40ff37dfcc29c5b7d312b1bd2697c36ec6b6b609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Nie=C3=9Fen?= Date: Sat, 4 Nov 2023 00:39:57 +0000 Subject: [PATCH] src: fix HasOnly(capability) in node::credentials SYS_capget with _LINUX_CAPABILITY_VERSION_3 returns the process's permitted capabilities as two 32-bit values. To determine if the only permitted capability is indeed CAP_NET_BIND_SERVICE, it is necessary to check both of those values. Not doing so creates a vulnerability that potentially allows unprivileged users to inject code into a privileged Node.js process through environment variables such as NODE_OPTIONS. PR-URL: https://github.com/nodejs-private/node-private/pull/505 Reviewed-By: Rafael Gonzaga CVE-ID: CVE-2024-21892 --- src/node_credentials.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/node_credentials.cc b/src/node_credentials.cc index 76088144950e49..b9f469f9d340ce 100644 --- a/src/node_credentials.cc +++ b/src/node_credentials.cc @@ -52,7 +52,7 @@ namespace credentials { static bool HasOnly(int capability) { DCHECK(cap_valid(capability)); - struct __user_cap_data_struct cap_data[2]; + struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3]; struct __user_cap_header_struct cap_header_data = { _LINUX_CAPABILITY_VERSION_3, getpid()}; @@ -61,12 +61,11 @@ static bool HasOnly(int capability) { if (syscall(SYS_capget, &cap_header_data, &cap_data) != 0) { return false; } - if (capability < 32) { - return cap_data[0].permitted == - static_cast(CAP_TO_MASK(capability)); - } - return cap_data[1].permitted == - static_cast(CAP_TO_MASK(capability)); + + static_assert(arraysize(cap_data) == 2); + return cap_data[CAP_TO_INDEX(capability)].permitted == + static_cast(CAP_TO_MASK(capability)) && + cap_data[1 - CAP_TO_INDEX(capability)].permitted == 0; } #endif