From: Andrew Burgess Date: Wed, 10 Sep 2025 13:54:21 +0000 (+0100) Subject: gdb/linux: consider ptrace_scope when building attach error message X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b582f86bd7a6ece68f4a979c40faeffde9eec5e;p=thirdparty%2Fbinutils-gdb.git gdb/linux: consider ptrace_scope when building attach error message On GNU/Linux, if an attach fails, then we end up calling linux_ptrace_attach_fail_reason, which returns a string describing why the attach might have failed. This commit extends linux_ptrace_attach_fail_reason to check the current /proc/sys/kernel/yama/ptrace_scope setting. When this is set to a value greater than 0 attaching can be restricted in some cases. If I first set ptrace_scope to 1, like this: $ echo 1 | sudo tee /proc/sys/kernel/yama/ptrace_scope Then use current master GDB to attach to a process, I see this: (gdb) attach 2476518 Attaching to process 2476518 ptrace: Operation not permitted. (gdb) With this patch applied the output becomes: (gdb) attach 2476518 Attaching to process 2476518 warning: the /proc/sys/kernel/yama/ptrace_scope setting of 1 might prevent attaching, see 'man 2 ptrace' ptrace: Operation not permitted. (gdb) In my (limited) experience, not every user is familiar with the ptrace_scope setting. Finding that attach just doesn't work often leads users to believe that the only way to have GDB attach to another process is to run GDB as root. Though that is a solution to the problem, my hope is that, by giving the users more information, they can make a more informed choice about which solution is right for them (e.g. run as root, change the setting, start the inferior directly under GDB, etc). This change also works for gdbserver. For example: (gdb) target extended-remote :54321 Remote debugging using :54321 (gdb) attach 2475389 Attaching to process 2475389 Attaching to process 2475389 failed: Cannot attach to process 2475389: \ Operation not permitted (1), the /proc/sys/kernel/yama/ptrace_scope \ setting of 1 might prevent attaching, see 'man 2 ptrace' (gdb) There's no test for this as testing would require adjusting a system wide setting. I've linked to a semi-related bug. It is discussing the same issue at least. This patch doesn't try to "fix" anything that the bug is talking about, it just makes it (I think) slightly clearer when the issue does arise. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31520 Approved-By: Pedro Alves Reviewed-By: Guinevere Larsen --- diff --git a/gdb/nat/linux-ptrace.c b/gdb/nat/linux-ptrace.c index f73058be2eb..7df85c1c87f 100644 --- a/gdb/nat/linux-ptrace.c +++ b/gdb/nat/linux-ptrace.c @@ -24,12 +24,46 @@ #endif #include "gdbsupport/eintr.h" #include "gdbsupport/signals-state-save-restore.h" +#include "gdbsupport/gdb_file.h" /* Stores the ptrace options supported by the running kernel. A value of -1 means we did not check for features yet. A value of 0 means there are no supported features. */ static int supported_ptrace_options = -1; +/* The file from which the kernel.yama.ptrace_scope setting is read. */ + +static constexpr char ptrace_scope_filename[] + = "/proc/sys/kernel/yama/ptrace_scope"; + +/* Reads the yama ptrace_scope value from /proc. Returns the integer value + of ptrace_scope (0, 1, 2, or 3) or -1 if the file cannot be read (e.g., + yama is not enabled). */ + +static int +get_ptrace_scope () +{ + int ptrace_scope = -1; + + /* The /proc file that contains the system-wide ptrace scope setting. */ + gdb_file_up fp (fopen (ptrace_scope_filename, "r")); + if (fp != nullptr) + { + if (fscanf (fp.get (), "%d", &ptrace_scope) != 1) + { + /* If fscanf fails then we couldn't parse the number. But just + to be safe, set the scope back to -1 to indicate no value is + available. */ + ptrace_scope = -1; + } + } + + /* If fp is NULL, it's likely because the yama security module is not + active. In this case, we return -1 to indicate that the scope is + unknown or not applicable. */ + return ptrace_scope; +} + /* Find all possible reasons we could fail to attach PID and return these as a string. An empty string is returned if we didn't find any reason. */ @@ -44,6 +78,13 @@ linux_ptrace_attach_fail_reason (pid_t pid) _("process %d is already traced by process %d"), (int) pid, (int) tracerpid); + int ptrace_scope = get_ptrace_scope (); + if (ptrace_scope > 0) + string_appendf (result, + _("the %s setting of %d might prevent attaching, " + "see 'man 2 ptrace'"), + ptrace_scope_filename, ptrace_scope); + if (linux_proc_pid_is_zombie_nowarn (pid)) string_appendf (result, _("process %d is a zombie - the process has already "