-
Notifications
You must be signed in to change notification settings - Fork 16.3k
fix: fix launch crash when null device is disabled on Windows #44882
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
fix: fix launch crash when null device is disabled on Windows #44882
Conversation
💖 Thanks for opening this pull request! 💖 Semantic PR titlesWe use semantic commit messages to streamline the release process. Before your pull request can be merged, you should update your pull request title to start with a semantic prefix. Examples of commit messages with semantic prefixes:
Commit signingThis repo enforces commit signatures for all incoming PRs. PR tipsThings that will help get your PR across the finish line:
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can. |
1619402
to
ecf4d8a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change looks like it does what the summary says, but I'm not familiar with the null device crash. @yangllu could you add a explanation to the description about why adding kNoStdioInitialization
fixes this?
Also, would setting it on all three platforms, instead of just on Windows, cause any potential problems?
@ckerr As explained in this issue #44881 , null device can be disabled on windows. Node doesn't handle this situation and invokes crash when trying to initialize stdio using nul device, which makes all electron apps crash definitely when nul device is disabled on user's machine. As far as I know, nul device is part of the posix standand and will casue the os to run abnormally if disabled on macos and linux. Also, not like windows gui apps, where stdio is not associated with an underlying stream, on macos and linux, stdio usually has a valid fd and the code to initialize stdio in node will usually not be called. So I think it's both ok to use or not to use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember this PR being raised before but it is no longer available when I search, rewriting some comments I had from there.
-
What are the side effects of using
kNoStdioInitialization
specifically related to handle inheritance for child process when we attach to console via https://source.chromium.org/chromium/chromium/src/+/main:base/process/launch_win.cc;l=167-234, with the flag we will now miss this call https://github.com/nodejs/node/blob/5ef498517574e1534041cdd25c920f8d0b2cf845/src/node.cc#L819-L823 -
We also use nul device to support the ignore option on child_process and utilityProcess.fork api. When the device is not available the child process may not be created and the applications functionality will be broken, should we still continue execution in these cases ?
|
What's your motive for disabling the null device? Honestly you should expect disabling basic drivers would break the system in unexpected ways. |
@brjsp In my personal view, I really don’t want the null device to be disabled. However, according to our statistics, around 0.1% windows machines have disabled null device. Without this issue fixed we will lose 0.1% users when upgrading electron to the new version. This is indeed a serious number. I have tested adequately that the null device service can be safely disabled and the windows system will not break. I am also really confused about why Microsoft has implemented such a feature. |
“If i delete ntoskrnl.exe, the system won't boot. I'm confused about why Microsoft has implemented such feature!” sorry but this PR seems to be a bad-faith effort to disable security features in an effort to make the code “compatible” with intentionally broken installations. |
I think disabling null devices is different from deleting core system files. As mentioned in the Issue, #44881 we can disable null devices through a registry setting - this is really a Windows feature. After disabling null devices, most software can still run normally. However, if system core files are deleted, the system cannot run. Since this condition is so simple, malicious attackers could potentially crash all Electron applications with just one registry command - this is practically a vulnerability. If there is a security application built with Electron, an attacker will be able to crash this security app by setting this registry key, then the attacker can do everything he wants. Additionally, as mentioned above, some users have indeed configured this registry setting. Although we don't know why they chose to do so, but the user set this register is so many. Just like what was mentioned above, about 0.1% of the Windows machines among our users are affected. Although this data was only collected during one of our upgrades and it might be a bit high. I think it's better to add some compatibility to allow more users to enjoy Electron applications. |
If you want to limit yourself to disabling services, then disable
Even if it's a compatibility/usability issue, what it's definitely not is a vulnerability. Malicious attackers cannot write anything under HKLM\System. If you can modify services configuration, you could just add a new service that runs the code you want to run. |
I don't think it is appropriate compare the nul device to core components that can cause the windows system to fail to boot. I have disabled nul deivce on my windows computer and used it for servel days. The windows system has been functioning normally, and I haven't found any other application that crashes except for electron. I think the nul device service is only an optional sercive that can be disabled safely on windows, although we have not fully figured out in which specific scenarios the nul device service will be disabled (I haven't found much official material describing windows nul device, and I hope anyone can find and share some authoritative information). |
I think that what we should executly discuss here is what is the best way to solve this issue. To be honest, I do not agree that my code is elegant to fix it by adding I have found this relevant code segment in the chromium project. When failing to open a nul device, maybe it would be ok to just ignore the error to avoid crashes ? FuzzerUtilWindows.cpp DiscardOutput
|
Sorry for the delay, based on your testing given the application does break when either utilityprocess or childprocess attempts to use the nul device, ignoring the early exit from Node.js in these cases doesn't help much. But again not all use cases of the child process api require the nul device, so it cannot made into a startup check as well. In my mind, this situation runs similar to how the application will fail to start when sandbox cannot be used on linux. But only in this case, we don't have enough feedback from the application to let users know why the application failed to launch and maybe provide an opt-out mechanism. Can this PR try the following,
|
@deepak1556 Great! I will revise my PR based on your suggestions. |
add node flag node::ProcessInitializationFlags::kNoStdioInitialization
ecf4d8a
to
4e280d9
Compare
@deepak1556 I have added the feature flag Also, I added
|
Sorry for the delay here, I missed the notification on this PR. I will review it by Monday. |
@deepak1556 Hi, do you have any new opinions about my code? |
if (command_line->HasSwitch(switches::kNoStdioInit)) { | ||
process_flags |= node::ProcessInitializationFlags::kNoStdioInitialization; | ||
// remove the option to avoid node error "bad option: --no-stdio-init" | ||
std::string option = std::string("--") + switches::kNoStdioInit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @yangllu , thanks for your work. I've tried this patch once, here is what I found:
it seems that in a windows machine without NUL device, the main process works normally, but the nodejs integrated with renderer processes still don't work, though --no-stdio-init
is provided from command line. maybe the reason is that the command line flag is erased here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, very likely need to pass the flag in
if (process_type == ::switches::kRendererProcess) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay in reviewing this change, couple more comments.
if (fd < 0) { | ||
ret = false; | ||
} else { | ||
ret = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ret = true; |
LOG(FATAL) << "Fail to open nul device and node initialization may " | ||
"crash! Try using --" | ||
<< switches::kNoStdioInit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG(FATAL) << "Fail to open nul device and node initialization may " | |
"crash! Try using --" | |
<< switches::kNoStdioInit; | |
LOG(FATAL) << "Unable to open nul device needed for initialization, aborting startup. As a workaround, try starting with --" | |
<< switches::kNoStdioInit; |
LOG(FATAL) << "Fail to open nul device and node initialization may " | ||
"crash! Try using --" | ||
<< switches::kNoStdioInit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG(FATAL) << "Fail to open nul device and node initialization may " | |
"crash! Try using --" | |
<< switches::kNoStdioInit; | |
LOG(FATAL) << "Unable to open nul device needed for initialization, aborting startup. As a workaround, try starting with --" | |
<< switches::kNoStdioInit; |
if (command_line->HasSwitch(switches::kNoStdioInit)) { | ||
process_flags |= node::ProcessInitializationFlags::kNoStdioInitialization; | ||
// remove the option to avoid node error "bad option: --no-stdio-init" | ||
std::string option = std::string("--") + switches::kNoStdioInit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, very likely need to pass the flag in
if (process_type == ::switches::kRendererProcess) { |
Hi @deepak1556 |
Closing in favor of #47870 |
add node flag node::ProcessInitializationFlags::kNoStdioInitialization
Fixes #44881
Description of Change
Checklist
npm test
passesRelease Notes
Notes: