Skip to content
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

LLDB should skip disabling ASLR when permissions do not allow it to #61899

Open
am11 opened this issue Apr 2, 2023 · 7 comments
Open

LLDB should skip disabling ASLR when permissions do not allow it to #61899

am11 opened this issue Apr 2, 2023 · 7 comments
Labels

Comments

@am11
Copy link

am11 commented Apr 2, 2023

Running application under lldb in a docker container gives an unfriendly error:

# tested in the following docker containers:
#     Ubuntu 22.04 -> apt install lldb
#     Alpine 3.17 -> apk add lldb

(lldb) r
'A' packet returned an error: 8
# that's all; it gives up (no indication, whatsoever, that it is failing because of the environment constraint)
(lldb)

Workaround is to manually enable ASLR by setting disable-aslr to false: settings set target.disable-aslr false

gdb, on the other hand, makes its best effort by tolerating the case when disabling ASLR fails; with a warning:

(gdb) r
Starting program: app
warning: Error disabling address space randomization: Operation not permitted
# and continues running the app

Expected behavior

Warn but still continue with ASLR
Adapt to the environment constraints in a similar manner as gdb.

(lldb) r
- 'A' packet returned an error: 8
+ Warning! Disabling address space randomization failed with 'Operation not permitted'. Continuing..

Issue a friendly error and stop
Alternatively, a better (searchable) error message would be appreciated:

(lldb) r
- 'A' packet returned an error: 8
+ Error! Disabling address space randomization failed with 'Operation not permitted'. Stopping..
(lldb)
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 2, 2023

@llvm/issue-subscribers-lldb

@SonicStark
Copy link

@am11 FYI: With lldb-16 from apt.llvm.org, the error becomes sth more related since error msg output by ExitWithError in child process is captured then.

error: Cannot launch '/tmp/a.out': personality set failed: Operation not permitted

Still not friendly enough, IMO😕

@DavidSpickett DavidSpickett changed the title LLDB to skip disabling ASLR in constrained environments LLDB should skip enabling ASLR when permissions do not allow it to Feb 5, 2024
@DavidSpickett
Copy link
Collaborator

Another report via the forums https://discourse.llvm.org/t/running-lldb-in-a-container/76801.

@mstorsjo
Copy link
Member

mstorsjo commented Feb 6, 2024

@DavidSpickett I think the change of subject that you did yesterday seems incorrect, while the original subject was correct - ASLR is enabled by default by the OS, and when running in a debugger, the debugger wants to disable ASLR. But we should allow skipping the disabling. I.e. s/enabling/disabling/ in the subject should fix it.

@DavidSpickett DavidSpickett changed the title LLDB should skip enabling ASLR when permissions do not allow it to LLDB should skip disabling ASLR when permissions do not allow it to Feb 6, 2024
@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Feb 6, 2024

Reproduced this on the official Ubuntu docker image, just docker run without any extra capabilities or using privileged mode.

GDB's warning:

# gdb /tmp/test.o
<...>
(gdb) run
Starting program: /tmp/test.o
warning: Error disabling address space randomization: Operation not permitted

lldb:

root@3f85fd99aab7:/build-llvm# ./bin/lldb /tmp/test.o -o run
(lldb) target create "/tmp/test.o"
Current executable set to '/tmp/test.o' (aarch64).
(lldb) run
error: Cannot launch '/tmp/test.o': personality set failed: Operation not permitted

Workaround is to opt out of disabling ALSR before running the program:

# ./bin/lldb /tmp/test.o -o "settings set target.disable-aslr false" -o run
Process 72446 launched: '/tmp/test.o' (aarch64)
Process 72446 exited with status = 0 (0x00000000)

The way this works is we send a packet to set the option to disable ALSR:

lldb             <  21> send packet: $QSetDisableASLR:1#ce
lldb             <   6> read packet: $OK#9a

The setting isn't applied until we launch. ProcessLauncherPosixFork.cpp::DisableASLR is the function used on Linux, and it runs in lldb-server. lldb sends a run packet then lldb-server starts a process:

lldb             <  31> send packet: $vRun;2f746d702f746573742e6f#60
lldb             < 102> read packet: $Eff;706572736f6e616c69747920736574206661696c65643a204f7065726174696f6e206e6f74207065726d6974746564#be
error: Cannot launch '/tmp/test.o': personality set failed: Operation not permitted

That giant hex number is the error message personality set failed: Operation not permitted which is generated by ExitWithError.

This hack ignores the failure and allows you to debug, but it's a hack because there's no way to know from lldb that something failed:

diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
index 0a832ebad13a..1a24270b69d4 100644
--- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -64,9 +64,8 @@ static void DisableASLR(int error_fd) {
   if (value == -1)
     ExitWithError(error_fd, "personality get");

-  value = personality(ADDR_NO_RANDOMIZE | value);
-  if (value == -1)
-    ExitWithError(error_fd, "personality set");
+  // If we don't have permissions, just let it fail.
+  personality(ADDR_NO_RANDOMIZE | value);
 #endif
 }

I see some reports online that GDB in this scenario has trouble with breakpoints. Haven't tested that myself but it means we definitely need to warn users.

The good news is that given we already send errors back to lldb, there is a stream we could write a warning too. Bad news is that stream is only used if the run fails. So I'll have to find some way to send that info back to lldb, perhaps we can already attach strings to "OK" responses, or there is an async messaging thing we can use.

I looked at how gdb does it. The warning comes from gdbserver, or the "in process" version of gdbserver that runs inside gdb when you're running stuff locally. This means they aren't using any remote protocol packets to send that warning to gdb.

# gdbserver :1234 /tmp/test.o
gdbserver: Error disabling address space randomization: Operation not permitted
Process /tmp/test.o created; pid = 73668
Listening on port 1234

@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Feb 6, 2024

With lldb-16 from apt.llvm.org, the error becomes sth more related since error msg output by ExitWithError in child process is captured then.

Done by 681d0d9 / 8d1de7b.

@labath
Copy link
Collaborator

labath commented May 13, 2024

lldb             <  21> send packet: $QSetDisableASLR:1#ce
lldb             <   6> read packet: $OK#9a

The setting isn't applied until we launch.

We could change that. If we figure out a way to check that disabling the ASLR will fail (worst case: fork a child and let it try disabling it?), we could return an error here. The client could print it, and resume launching.

That said, I don't think having this warning is a prerequisite for making the aslr errors non-fatal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants