Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

process.setuid results in an abort #32750

Closed
zyscoder opened this issue Apr 10, 2020 · 13 comments
Closed

process.setuid results in an abort #32750

zyscoder opened this issue Apr 10, 2020 · 13 comments
Labels
confirmed-bug Issues with confirmed bugs.

Comments

@zyscoder
Copy link

  • Version: v12.16.0
  • Platform: Linux vul337 4.15.0-91-generic new design of error handling #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
  • Subsystem: process

What steps will reproduce the bug?

Directly run the following code snippet using node:

require('process').setuid(-0)

How often does it reproduce? Is there a required condition?

No. This potential bug can always be reproduced.

What is the expected behavior?

The argument to 'process.setuid' should be a Uint32 or string value, but we passed a -0 into it. The function should throw an exception or other similar error-reporting stuff rather than crash the whole nodejs process.

What do you see instead?

This is the stack dump produced during abort:

./node[37487]: ../src/node_credentials.cc:247:void node::credentials::SetUid(const FunctionCallbackInfo<v8::Value> &): Assertion `args[0]->IsUint32() || args[0]->IsString()' failed.
 1: 0x13f9b30 node::Abort() [./node]
 2: 0x13f9709  [./node]
 3: 0x13ea56b  [./node]
 4: 0x17b379c v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) [./node]
 5: 0x17b23d5  [./node]
 6: 0x17b1092  [./node]
 7: 0x2717a59  [./node]
[2]    37487 abort      ./node

Additional information

@gireeshpunathil
Copy link
Member

I can recreate this on master, v10.x prints a proper error message, so looks like a regression to me

@gireeshpunathil
Copy link
Member

definition of unsigned int seem to have diverged between JS and C++? looks like the check passed in the former, but failed later?

const validateUint32 = hideStackFrames((value, name, positive) => {

CHECK(args[0]->IsUint32() || args[0]->IsString());

@gireeshpunathil
Copy link
Member

gireeshpunathil commented Apr 10, 2020

failed later -> failed * in * later

@gireeshpunathil
Copy link
Member

node --expose-internals -e 'require("internal/validators").validateInt32(-0)'

does not throw, implies this method (validateInt32) does not consider IsMinusZero which IsUint32 of v8 does.

@gireeshpunathil
Copy link
Member

validateInt32 hasn't changed between (passing and failing) versions:

const validateInt32 = hideStackFrames(

does this imply IsUint32 has changed its meaning in V8? that doesn't sound logical!

@zyscoder zyscoder reopened this Apr 10, 2020
@zyscoder
Copy link
Author

My team is trying to find bugs and vulnerabilities at the interface between js and c++, and we think this problem of inconsistency is an interesting study case for us. Can you give us a confirmation for this bug? As proof for us to make a discussion in our work.

@gireeshpunathil gireeshpunathil added the confirmed-bug Issues with confirmed bugs. label Apr 10, 2020
@gireeshpunathil
Copy link
Member

@zyscoder - that is an interesting area to research, good luck! I tagged it as bug

/cc @nodejs/v8 in case if there is an obvious explanation.

@himself65

This comment has been minimized.

@gireeshpunathil
Copy link
Member

bisecting now.

@gireeshpunathil
Copy link
Member

bisect is pointing to the commit(s) in #19973 /cc @targos

@targos
Copy link
Member

targos commented Apr 10, 2020

Interesting! That problem is not only present in process.setuid. The following also fails on Node.js 10:

> node -e "require('fs').chownSync('test', -0, -0)"    
src\node_file.cc:2029: Assertion `args[1]->IsUint32()' failed.

V8 always returns false (and it's not new) for IsInt32 and IsUint32 methods.

I see two things that we can do:

  • Throw in our int32/uint32 validators if -0 is passed (potentially breaking change)
  • Make sure we coerce -0 to 0 either in the validator itself or before passing the value to C++

Thoughts?

@gireeshpunathil
Copy link
Member

technically -0 is signed, so throwing from uint32 validator makes sense to me!

@bnoordhuis
Copy link
Member

The counterargument is that 0 and -0 are indistinguishable (i.e., 0 === -0) except when checking with Object.is(). Coercion to positive 0 seems like the principle of least surprise to me.

HarshithaKP added a commit to HarshithaKP/node that referenced this issue Apr 14, 2020
jasnell added a commit to jasnell/node that referenced this issue Jan 4, 2021
Fixes: nodejs#32750
Signed-off-by: James M Snell <jasnell@gmail.com>
@jasnell jasnell closed this as completed in 421279b Jan 9, 2021
danielleadams pushed a commit that referenced this issue Jan 12, 2021
Fixes: #32750
Signed-off-by: James M Snell <jasnell@gmail.com>

PR-URL: #36786
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Harshitha K P <harshitha014@gmail.com>
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
targos pushed a commit that referenced this issue May 1, 2021
Fixes: #32750
Signed-off-by: James M Snell <jasnell@gmail.com>

PR-URL: #36786
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Harshitha K P <harshitha014@gmail.com>
Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs.
Projects
None yet
5 participants