Skip to content

Commit 8e8da88

Browse files
authored
[lldb] Fix SIGSEGV in GetPtraceScope() in Procfs.cpp (llvm#142224)
# Symptom We have seen SIGSEGV like this: ``` * thread #1, name = 'lldb-server', stop reason = SIGSEGV frame #0: 0x00007f39e529c993 libc.so.6`__pthread_kill_internal(signo=11, threadid=<unavailable>) at pthread_kill.c:46:37 ... * frame #5: 0x000056027c94fe48 lldb-server`lldb_private::process_linux::GetPtraceScope() + 72 frame #6: 0x000056027c92f94f lldb-server`lldb_private::process_linux::NativeProcessLinux::Attach(int) + 1087 ... ``` See [full stack trace](https://pastebin.com/X0d6QhYj). This happens on Linux where LLDB doesn't have access to `/proc/sys/kernel/yama/ptrace_scope`. A similar error (an unchecked `Error`) can be reproduced by running the newly added unit test without the fix. See the "Test" section below. # Root cause `GetPtraceScope()` ([code](https://github.com/llvm/llvm-project/blob/328f40f408c218f25695ea42c844e43bef38660b/lldb/source/Plugins/Process/Linux/Procfs.cpp#L77)) has the following `if` statement: ``` llvm::Expected<int> lldb_private::process_linux::GetPtraceScope() { ErrorOr<std::unique_ptr<MemoryBuffer>> ptrace_scope_file = getProcFile("sys/kernel/yama/ptrace_scope"); if (!*ptrace_scope_file) return errorCodeToError(ptrace_scope_file.getError()); ... } ``` The intention of the `if` statement is to check whether the `ptrace_scope_file` is an `Error` or not, and return the error if it is. However, the `operator*` of `ErrorOr` returns the value that is stored (which is a `std::unique_ptr<MemoryBuffer>`), so what the `if` condition actually do is to check if the unique pointer is non-null. Note that the method `ErrorOr::getStorage()` ([called by](https://github.com/llvm/llvm-project/blob/328f40f408c218f25695ea42c844e43bef38660b/llvm/include/llvm/Support/ErrorOr.h#L162-L164) `ErrorOr::operator *`) **does** assert on whether or not `HasError` has been set (see [ErrorOr.h](https://github.com/llvm/llvm-project/blob/328f40f408c218f25695ea42c844e43bef38660b/llvm/include/llvm/Support/ErrorOr.h#L235-L243)). However, it seems this wasn't executed, probably because the LLDB was a release build. # Fix The fix is simply remove the `*` in the said `if` statement.
1 parent 7642313 commit 8e8da88

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

lldb/source/Plugins/Process/Linux/Procfs.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ lldb_private::process_linux::GetAvailableLogicalCoreIDs() {
7474
llvm::Expected<int> lldb_private::process_linux::GetPtraceScope() {
7575
ErrorOr<std::unique_ptr<MemoryBuffer>> ptrace_scope_file =
7676
getProcFile("sys/kernel/yama/ptrace_scope");
77-
if (!*ptrace_scope_file)
77+
if (!ptrace_scope_file)
7878
return errorCodeToError(ptrace_scope_file.getError());
7979
// The contents should be something like "1\n". Trim it so we get "1".
8080
StringRef buffer = (*ptrace_scope_file)->getBuffer().trim();

lldb/unittests/Process/Linux/ProcfsTests.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ TEST(Perf, RealLogicalCoreIDs) {
104104
ASSERT_GT((int)cpu_ids->size(), 0) << "We must see at least one core";
105105
}
106106

107-
TEST(Perf, RealPtraceScope) {
107+
TEST(Perf, RealPtraceScopeWhenExist) {
108108
// We first check we can read /proc/sys/kernel/yama/ptrace_scope
109109
auto buffer_or_error =
110110
errorOrToExpected(getProcFile("sys/kernel/yama/ptrace_scope"));
@@ -120,6 +120,21 @@ TEST(Perf, RealPtraceScope) {
120120
<< "Sensible values of ptrace_scope are between 0 and 3";
121121
}
122122

123+
TEST(Perf, RealPtraceScopeWhenNotExist) {
124+
// We first check we can NOT read /proc/sys/kernel/yama/ptrace_scope
125+
auto buffer_or_error =
126+
errorOrToExpected(getProcFile("sys/kernel/yama/ptrace_scope"));
127+
if (buffer_or_error)
128+
GTEST_SKIP() << "In order for this test to run, "
129+
"/proc/sys/kernel/yama/ptrace_scope should not exist";
130+
consumeError(buffer_or_error.takeError());
131+
132+
// At this point we should fail parsing the ptrace_scope value.
133+
Expected<int> ptrace_scope = GetPtraceScope();
134+
ASSERT_FALSE((bool)ptrace_scope);
135+
consumeError(ptrace_scope.takeError());
136+
}
137+
123138
#ifdef LLVM_ENABLE_THREADING
124139
TEST(Support, getProcFile_Tid) {
125140
auto BufferOrError = getProcFile(getpid(), llvm::get_threadid(), "comm");

0 commit comments

Comments
 (0)