Skip to content

[sanitizer] Fix running sanitizer_bad_report_path_test on Linux as root #97732

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

Merged
merged 1 commit into from
Jul 18, 2024

Conversation

iii-i
Copy link
Member

@iii-i iii-i commented Jul 4, 2024

Running tests as root is not the greatest idea, however, there is one
valid use case - running them in a container in order to verify LLVM on
different distros. There is no reason to configure unprivileged users
in a container, so one works as root.

sanitizer_bad_report_path_test assumes that creating a file in a
non-writable directory would fail, which is not the always case. For
example, when we are on Linux and CAP_DAC_OVERRIDE, which root has, is
in effect. Therefore, one solution is to drop it. However, that would
be Linux-specific.

Instead, use argv[0] as if it were a directory. mkdir() on top of a
file should be prohibited by all supported Posix operating systems.
Combine this with a partial revert of commit f4214e1469ad ("[sanitizer]
Skip test on Android where chmod is not working"), since we shouldn't
need to exclude Android anymore.

@llvmbot
Copy link
Member

llvmbot commented Jul 4, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Ilya Leoshkevich (iii-i)

Changes

Running tests as root is not the greatest idea, however, there is one valid use case - running them in a container in order to verify LLVM on different distros. There is no reason to configure unprivileged users in a container, so one works as root.

sanitizer_bad_report_path_test assumes that creating a file in a non-writable directory would fail, which is not the case if CAP_DAC_OVERRIDE, which root has, is in effect. So drop it.


Full diff: https://github.com/llvm/llvm-project/pull/97732.diff

1 Files Affected:

  • (modified) compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_bad_report_path_test.cpp (+23)
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_bad_report_path_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_bad_report_path_test.cpp
index fd4abf448b09d..a7312341b6f5c 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_bad_report_path_test.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_bad_report_path_test.cpp
@@ -13,9 +13,32 @@
 #include <stdio.h>
 #include <string.h>
 
+#if defined(__linux__)
+#include <linux/capability.h>
+
+/* Use capget() and capset() from glibc. */
+extern "C" int capget(cap_user_header_t header, cap_user_data_t data);
+extern "C" int capset(cap_user_header_t header, const cap_user_data_t data);
+
+static void try_drop_cap_dac_override(void) {
+  struct __user_cap_header_struct hdr = {
+    .version = _LINUX_CAPABILITY_VERSION_1,
+    .pid = 0,
+  };
+  struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_1];
+  if (!capget(&hdr, data)) {
+    data[CAP_DAC_OVERRIDE >> 5].effective &= ~(1 << (CAP_DAC_OVERRIDE & 31));
+    capset(&hdr, data);
+  }
+}
+#else
+static void try_drop_cap_dac_override(void) {}
+#endif
+
 volatile int *null = 0;
 
 int main(int argc, char **argv) {
+  try_drop_cap_dac_override();
   char buff[1000];
   sprintf(buff, "%s.report_path/report", argv[0]);
   __sanitizer_set_report_path(buff);

@iii-i iii-i requested a review from vitalybuka July 4, 2024 14:08
Copy link

github-actions bot commented Jul 4, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@iii-i iii-i force-pushed the sanitizer_bad_report_path_test-as-root branch from ad37d3b to 75895bd Compare July 4, 2024 14:15
@iii-i iii-i force-pushed the sanitizer_bad_report_path_test-as-root branch from 75895bd to a52001c Compare July 12, 2024 12:21
@iii-i iii-i changed the title [sanitizer] Fix running sanitizer_bad_report_path_test on Linux as root [sanitizer] Misc error message improvements Jul 12, 2024
Running tests as root is not the greatest idea, however, there is one
valid use case - running them in a container in order to verify LLVM on
different distros. There is no reason to configure unprivileged users
in a container, so one works as root.

sanitizer_bad_report_path_test assumes that creating a file in a
non-writable directory would fail, which is not the always case. For
example, when we are on Linux and CAP_DAC_OVERRIDE, which root has, is
in effect. Therefore, one solution is to drop it. However, that would
be Linux-specific.

Instead, use argv[0] as if it were a directory. mkdir() on top of a
file should be prohibited by all supported Posix operating systems.
Combine this with a partial revert of commit f4214e1 ("[sanitizer]
Skip test on Android where chmod is not working"), since we shouldn't
need to exclude Android anymore.
@iii-i iii-i force-pushed the sanitizer_bad_report_path_test-as-root branch from a52001c to 0cd70b7 Compare July 14, 2024 16:53
@iii-i iii-i changed the title [sanitizer] Misc error message improvements [sanitizer] Fix running sanitizer_bad_report_path_test on Linux as root Jul 14, 2024
Copy link
Collaborator

@vitalybuka vitalybuka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@iii-i iii-i merged commit 8afb395 into llvm:main Jul 18, 2024
6 checks passed
@iii-i
Copy link
Member Author

iii-i commented Jul 18, 2024

Unfortunately this is now causing a buildbot failure on Android:

/var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp:27:11: error: CHECK: expected string not found in input
// CHECK: ERROR: Can't create directory: {{.*}}Posix/Output/sanitizer_set_report_path_test.cpp.tmp
          ^
<stdin>:2:243: note: scanning from here
Path /data/local/tmp/Output/var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/compiler_rt_build_android_arm/test/sanitizer_common/asan-arm-Android/Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.27545
                                                                                                                                                                                                                                                  ^

Input file: <stdin>
Check file: /var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/llvm-project/compiler-rt/test/sanitizer_common/TestCases/Posix/sanitizer_set_report_path_test.cpp

-dump-input=help explains the following input dump.

Input was:
<<<<<<
          1: ERROR: Can't create directory: /data/local/tmp/Output/var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/compiler_rt_build_android_arm/test/sanitizer_common/asan-arm-Android/Posix/Output/sanitizer_set_report_path_test.cpp.tmp
          2: Path /data/local/tmp/Output/var/lib/buildbot/sanitizer-buildbot6/sanitizer-x86_64-linux-android/build/compiler_rt_build_android_arm/test/sanitizer_common/asan-arm-Android/Posix/Output/sanitizer_set_report_path_test.cpp.tmp.report_path/report.27545
check:27                                                                                                                                                                                                                                                       X~~~~~ error: no match found

The problem is that Path and ERROR: messages come in the wrong order. The first is fprintf()ed to stdout, the second is write()ten to stderr. The testcase merges the two file descriptors. But the interesting part is that the test calls fflush(stdout); in between.

I'm not sure how to investigate that fflush() ends up being a no-op on that builder. I propose to work around that by doing a write(kStderrFd) for the Path message. I will send a PR.

@iii-i
Copy link
Member Author

iii-i commented Jul 18, 2024

I've posted #99469.

yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…ot (#97732)

Summary:
Running tests as root is not the greatest idea, however, there is one
valid use case - running them in a container in order to verify LLVM on
different distros. There is no reason to configure unprivileged users
in a container, so one works as root.
    
sanitizer_bad_report_path_test assumes that creating a file in a
non-writable directory would fail, which is not the always case. For
example, when we are on Linux and CAP_DAC_OVERRIDE, which root has, is
in effect. Therefore, one solution is to drop it. However, that would
be Linux-specific.
    
Instead, use argv[0] as if it were a directory. mkdir() on top of a
file should be prohibited by all supported Posix operating systems.
Combine this with a partial revert of commit f4214e1 ("[sanitizer]
Skip test on Android where chmod is not working"), since we shouldn't
need to exclude Android anymore.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251653
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants