-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
build: Add Data Relocation and Protection flags (-z relro -z now) to address potential security issue #20122
Comments
I think the problem with We could either:
(2) can be checked up to a point through citgm. |
Yes, based on the consideration, It seems option 1 that doesn't affect add-ons is better. |
We could do (1) first and (2) in a major release (say, Node.js 11) since people recompile their add-ons anyway after a major upgrade. |
I know some but still not quite clear about how I could figure out the following 2 cases causing missing symbols, and please let me know if I missed some others. Case 1: Make a shared library with a symbol labeled undefined in the symbol table. This could be done by the following code, and the typedef void (*FuncPtr)(); 0000000000000000 D UND 0000000000000000 UndefinedFunc When we dlopen the generated shared library, it results in an error saying Case 2: If a add-on was compiled against a new version library but runs with an old version library with less symbols. If lazy binding is used, the add-on may work well if those missing symbols are never called, But when Let’s summary it,
Is case 2 the issue you mentioned? Thanks. |
(1) and (2) both. A variation of (1) where the missing symbol is external weak instead of strong won't be rejected by the dynamic linker, it's resolved on first use. (Sometimes. It's complicated.) My hunch is that it's predominantly a problem with add-ons that link against shared libraries. |
I investigated the weak symbol, as I never used it before :) It seemed that the flag has no impact on weak symbol resolving? Here is my code:
The main.c code:
My compile commands:
The output:
When I ran The UndefinedFunc() in libmy.so is a external undefined weak symbol: |
In your example, |
Thank you for the note. Above was just a try on the impacts. It seems quite complex than I originally thought. And I also think option (1) is the better choice and will focus on that. I will prepare a PR. |
These flags could make some sections and the GOT entries of node process read only to avoid being modified after dynamic linking is done, thus the security could be enhanced. Fixes: nodejs#20122
I made a PR #20513 for this issue, PTAL, thanks. |
This issue is created separately to track the Data Relocation and Protection flag from the issue #18671 to make it independent and more clear to track as #18671 contains several compile flags.
The flag is for linker:
-z relro -z now
The RELRO flag was a mitigation technique to harden the data sections of an ELF binary/process and could prevent the modification of GOT entries of a process. Thus able to make node more secure.
I made some investigation and tests based on the flag, It passed the builtin functional tests and have no obvious performance impact on the builtin benchmark tests.
I also made a performance test by loading some native add-ons (all enabled the
-z relro -z now
flag), and the result shows that the time spend on loading add-ons only increased 0.54%. Below is my testing steps:cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz with 8 cores
memory: 32G
os: Ubuntu 16.04
-z relro -z now
on them. Opencv4nodejs and node-librealsense totally exported about 600 methods and total library size is about 4MB.time /path/to/relro/enabled/node -e "require('node-librealsense');require('node-glfw-3');require('opencv4nodejs');
time /path/to/relro/enabled/node -e "require('node-glfw-3')
time /path/to/default/node -e "require('node-librealsense');require('node-glfw-3');require('opencv4nodejs');
time /path/to/default/node -e "require('node-glfw-3')
TR1 (node-librealsense+opencv4nodejs+node-glfw-3): 140.23 ms
TR2 (node-glfw-3): 45.804 ms
TD1 (node-librealsense+opencv4nodejs+node-glfw-3): 139.331 ms
TD2 (node-glfw-3): 45.415 ms
So the time spent on loading node-librealsense+opencv4nodejs is:
when relro enabled: DR1 = TR1 - TR2 = 94.426 ms
when relro not enabled(default built): DD1 = TD1 - TD2 = 93.916 ms
Time increased rate for loading node-librealsense+opencv4nodejs is: (DR1 - DD1)/DD1 = 0.0054. It's 0.54%.
Besides, I compared the time of running:
time /path/to/node -e ""
. And result shows a 0.68% time increase.Based on the above result, it seems to me that adding '-z relro -z now' doesn't impact the performance a lot and we can get more security, what do you think guys?
The text was updated successfully, but these errors were encountered: