Skip to content

Commit

Permalink
src: fix HasOnly(capability) in node::credentials
Browse files Browse the repository at this point in the history
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: nodejs-private/node-private#505
Reviewed-By: Rafael Gonzaga <[email protected]>
CVE-ID: CVE-2024-21892
  • Loading branch information
tniessen authored and marco-ippolito committed Feb 7, 2024
1 parent 7fa1551 commit e6b4c10
Showing 1 changed file with 6 additions and 7 deletions.
13 changes: 6 additions & 7 deletions src/node_credentials.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace credentials {
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()};
Expand All @@ -61,12 +61,11 @@ 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<unsigned int>(CAP_TO_MASK(capability));
}
return cap_data[1].permitted ==
static_cast<unsigned int>(CAP_TO_MASK(capability));

static_assert(arraysize(cap_data) == 2);
return cap_data[CAP_TO_INDEX(capability)].permitted ==
static_cast<unsigned int>(CAP_TO_MASK(capability)) &&
cap_data[1 - CAP_TO_INDEX(capability)].permitted == 0;
}
#endif

Expand Down

0 comments on commit e6b4c10

Please sign in to comment.