Open ghost opened 7 years ago
The simplest way to pass ASAN_OPTIONS to the application with capabilities is to disable security measure mentioned above (all /proc/self items are owned by root for the application with capabilities) by doing:
echo "1" > /proc/sys/fs/suid_dumpable
With this option set sanitizer can access /proc/self/environ even if the application has some capabilities assigned.
This option was initially designed to decide if suid application can write core dumps or not (and if yes who should be the owner of the core dump file). Core dump of the privileged application may leak some data to the unprivileged user and sysadmin needs to be able to choose what to do with these core dumps. Procfs simply re-uses the same configuration option because it tries to solve the same issue (prevent privileged data leakage through /proc/self/mem, /proc/self/environ and so on).
[!] You shouldn't use this option on production machines because it implies a security risk.
We had the same problem on android, and it was fixed with the cherry-pick of https://lkml.org/lkml/2016/5/3/705. Looking at it now, I don't understand how it could have helped. It might have been fixed by some other kernel change.
This sounds like a kernel bug. How can reading one's own /proc/self/environ be a data leak?
I agree that a warning would be nice.
On Fri, Mar 17, 2017 at 7:12 AM, Oleg Strikov notifications@github.com wrote:
The simplest way to pass ASAN_OPTIONS to the application with capabilities is to disable security measure mentioned above (all /proc/self items are owned by root for the application with capabilities) by doing:
echo "1" > /proc/sys/fs/suid_dumpable
With this option set sanitizer can access /proc/self/environ even if the application has some permissions assigned.
This option was initially designed to decide if suid application can write core dumps or not (and if yes who should be the owner of the core dump file). Core dump of the privileged application may leak some data to the unprivileged user and sysadmin needs to be able to choose what to do with these core dumps. Procfs simply re-uses the same configuration option because it tries to solve the same issue (prevent privileged data leak through /proc/self/mem, /proc/self/environ and so on).
[!] You shouldn't use this option on production machines because it implies a security risk.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/google/sanitizers/issues/784#issuecomment-287364210, or mute the thread https://github.com/notifications/unsubscribe-auth/AAZuSn5L0_8YiwRuMeFUOYLKmoVwMi52ks5rmpS1gaJpZM4MgnKB .
Thanks for reply, @eugenis
We had the same problem on android, and it was fixed with the cherry-pick of https://lkml.org/lkml/2016/5/3/705 Looking at it now, I don't understand how it could have helped.
I agree that this patch is not capable of fixing the issue we observe. It makes a loophole to access /proc/$pid>/task/$tid/comm not /proc/$pid/environ. This patch is quite useful though because it demonstrates how to make such a loophole. It can be easily modified to fix our issue if someone from linux-fsdevel@ would accept it. Thanks for mentioning it. I'm not a huge fan of such loopholes though, because they create leaky abstractions. From the userspace, there is no way to figure out that someone else than root can access the file. But in reality some non-root processes can do this due to a loophole. I just sent an email to linux-fsdevel@ to see what they think about the issue.
This sounds like a kernel bug. How can reading one's own /proc/self/environ be a data leak?
My point was that all the items inside /proc/self are owned by root (for applications with capabilities) to prevent data leaks, not specifically /proc/self/environ. All the items probably get the same owner for simplicity. While /proc/{$pid,self}/environ is not a fruitful target for data leaks, some other items (/proc/$pid/{mem,stack,syscall}) are. Imagine that unprivileged user starts some privileged application (with suid or capabilities which are partial-suid). Privileged application accesses some privileged data using its privileges and stores it in memory. If /proc/{self,$pid}/mem is owned by the user who started the application, unprivileged user may read it and get access to some privileged information. Same approach applies to /proc/$pid/{stack,syscall}. I initially thought that /proc/self/environ may be also used to leak some data if privileged application updates its environment with some privileged data. But, hopefully, that's not the case because /proc/self/environ contains initial environment of the process, any future updates (via setenv) are not available through /proc/self/environ. So it indeed seems to be data-leak-free. It can be easily fixed in the kernel if linux-fsdevel@ approves it.
Any progress on the kernel side?
this is still an issue
Not sure if I'm running into the exact same issue or not, but I've set detect_leaks=0 and it is silently ignored:
mitch@mitch-kubuntu:~/dev/qt-dev/qtbase/tests/auto/testlib/selftests$ echo $ASAN_OPTIONS
detect_leaks=0,new_delete_type_mismatch=0
mitch@mitch-kubuntu:~/dev/qt-dev/qtbase/tests/auto/testlib/selftests$ (cd ~/dev/qt-dev-debug/qtbase && ninja cmptest && tests/auto/testlib/selftests/cmptest/cmptest compareQPalettes)
ninja: no work to do.
********* Start testing of tst_Cmptest *********
Config: Using QtTest library 6.7.0, Qt 6.7.0 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 11.4.0), ubuntu 22.04
PASS : tst_Cmptest::initTestCase()
FAIL! : tst_Cmptest::compareQPalettes(one role set in actual) Compared values are not the same
Actual (actualPalette) : QPalette(resolve=0x800004000020000,"Accent:[Active:#ffff0000,Disabled:#ffff0000,Inactive:#ffff0000]")
Expected (expectedPalette): QPalette(resolve=0x0)
Loc: [/home/mitch/dev/qt-dev/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(690)]
FAIL! : tst_Cmptest::compareQPalettes(all roles set in actual) Compared values are not the same
Actual (actualPalette) : QPalette(resolve=0x7fffffffffffffff,"WindowText:[Active:#ff000000,Disabled:#ff000000,Inactive:#ff000000],Button:[Active:#ff000001,Disabled:#ff000001,Inactive:#ff000001],Light:[Active:#ff000002,Disabled:#ff000002,Inactive:#ff000002],Midlight:[Active:#ff000003,Disabled:#ff000003,Inactive:#ff000003],Dark:[Active:#ff000004,Disabled:#ff000004,Inactive:#ff000004],Mid:[Active:#ff000005,Disabled:#ff000005,Inactive:#ff000005],Text:[Active:#ff000006,Disabled:#ff000006,Inactive:#ff000006],BrightText:[Active:#ff000007,Disabled:#ff000007,Inactive:#ff000007],ButtonText:[Active:#ff000008,Disabled:#ff000008,Inactive:#ff000008],Base:[Active:#ff000009,Disabled:#ff000009,Inactive:#ff000009],Window:[Active:#ff00000a,Disabled:#ff00000a,Inactive:#ff00000a],Shadow:[Active:#ff00000b,Disabled:#ff00000b,Inactive:#ff00000b],Highlight:[Active:#ff00000c,Disabled:#ff00000c,Inactive:#ff00000c],HighlightedText:[Active:#ff00000d,Disabled:#ff00000d,Inactive:#ff00000d],Link:[Active:#ff00000e,Disabled:#ff00000e,Inactive:#ff00000e],LinkVisited:[Active:#ff00000f,Disabled:#ff00000f,Inactive:#ff00000f],AlternateBase:[Active:#ff000010,Disabled:#ff000010,Inactive:#ff000010],ToolTipBase:[Active:#ff000012,Disabled:#ff000012,Inactive:#ff000012],ToolTipText:[Active:#ff000013,Disabled:#ff000013,Inactive:#ff000013],PlaceholderText:[Active:#ff000014,Disabled:#ff000014,Inactive:#ff000014],Accent:[Active:#ff000015,Disabled:#ff000015,Inactive:#ff000015]")
Expected (expectedPalette): QPalette(resolve=0x0)
Loc: [/home/mitch/dev/qt-dev/qtbase/tests/auto/testlib/selftests/cmptest/tst_cmptest.cpp(690)]
PASS : tst_Cmptest::compareQPalettes(all roles set in both)
PASS : tst_Cmptest::cleanupTestCase()
Totals: 3 passed, 2 failed, 0 skipped, 0 blacklisted, 1ms
********* Finished testing of tst_Cmptest *********
=================================================================
==10128==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 520 byte(s) in 13 object(s) allocated from:
#0 0x7f9ddd4b4887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x7f9dd36cc045 (/home/mitch/dev/qt-dev-debug/qtbase/tests/auto/testlib/selftests/cmptest/cmptest+0x24c045)
[...]
Has the kernel fixed this problem?
Has the kernel fixed this problem?
Still an issue, I'm afraid
How to reproduce the issue:
This happens because /proc/self/environ (and other items in the folder) is owned by root for any application with capabilities set. This was done to prevent data leakage from privileged (user < capabilities < root) process to unprivileged user. Application's euid is still user (not root) hence it can't access the file with 400 permissions owned by root:
Address sanitizer tries to open /proc/self/environ, fails (permission denied) and silently moves on. The same issue can be reproduced with simple cat utility:
It's an open question if we want to fix this issue by switching from /proc/self/environ to some other way of fetching the environment. It's probably enough to display a warning if sanitizer can't get access to /proc/self/environ. But we shouldn't ignore ASAN_OPTIONS silently.