[2/2] Fix gdb.base/attach-deleted-exec.exp with sudo-allow-ptrace.sh
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Testing passed
|
Commit Message
When running test-case gdb.base/attach-deleted-exec.exp with script
gdb/contrib/sudo-allow-ptrace.sh, we run into:
...
(gdb) attach 2804069^M
Attaching to process 2804069^M
No executable file now.^M
warning: Could not load vsyscall page because no executable was specified^M
0x0000ffff79cd83c8 in ?? ()^M
(gdb) FAIL: gdb.base/attach-deleted-exec.exp: \
attach to process with deleted executable
...
The script sudo-allow-ptrace.sh was introduced to work around
kernel.yama.ptrace_scope being set to 1 or 2, but this fail also happens for
kernel.yama.ptrace_scope=0.
The root cause for the fail is the failing "access (name, R_OK) == 0" check in
linux_proc_pid_to_exec_file:
...
/* Use /proc/PID/exe if the actual file can't be read, but /proc/PID/exe
can be. */
if (access (buf, R_OK) != 0 && access (name, R_OK) == 0)
strcpy (buf, name);
...
In other words, the system says there's no read permission for /proc/PID/exe.
Confusingly though, reading /proc/PID/exe works fine, so there seems to be a
contradiction here.
This behaviour can be minimally reproduced using:
...
$ cat try.sh
kill -9 $(pidof mysleep) 2> /dev/null
cp /usr/bin/sleep mysleep
md5sum mysleep
./mysleep 10000 &
(
sleep 1
pid=$(pidof mysleep)
echo "PID: $pid"
test -r /proc/$pid/exe
echo $?
md5sum /proc/$pid/exe
kill -9 $(pidof mysleep) 2> /dev/null
)
...
and:
...
$ cat ./try2.sh
sudo \
-E \
capsh \
--caps="cap_setpcap,cap_setuid,cap_setgid+ep cap_sys_ptrace+eip" \
--keep=1 \
--user=$USER \
--addamb="cap_sys_ptrace" \
--shell=./try.sh --
...
which shows:
...
$ ./try2.sh
[sudo] password for root:
6a85b2e53dce34ce2c35129b5b20c50b mysleep
PID: 4536
1
6a85b2e53dce34ce2c35129b5b20c50b /proc/4536/exe
...
where:
- according to test -r, we cannot read /proc/$pid/exe
- but according to md5sum, we can read /proc/$pid/exe
This was filed as a potential kernel PR here (
https://bugzilla.suse.com/show_bug.cgi?id=1221867 ).
As for gdb, fix or workaround this by dropping the "access (name, R_OK) == 0"
check.
While reading about /proc/PID/exe I came across:
- https://bugzilla.suse.com/show_bug.cgi?id=1216352
- https://bugzilla.kernel.org/show_bug.cgi?id=211593
which advise avoiding using readlink on /proc/PID/exec before reading.
I've looked briefly into fixing this, but found that it's not trivial, so
for now I've added a FIXME comment in linux_proc_pid_to_exec_file.
PR gdb/31528
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31528
---
gdb/nat/linux-procfs.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
@@ -345,6 +345,23 @@ linux_proc_pid_to_exec_file (int pid)
char name[PATH_MAX];
ssize_t len;
+ /* FIXME: calling readlink to determine the file to read symbols from is
+ problematic. Consider the scenario where:
+ - we run an application /foo/bar,
+ - we use gdb to attach to the running application,
+ - gdb calls linux_proc_pid_to_exec_file to the get the filename to read
+ the symbols from,
+ - linux_proc_pid_to_exec_file calls readlink on /proc/PID/exe, and
+ returns /foo/bar,
+ - we remove /foo/bar, and
+ - gdb tries to read the symbols from /foo/bar, and fails.
+ At this point we can still read the symbols from /proc/PID/exe.
+
+ See also:
+ - https://bugzilla.suse.com/show_bug.cgi?id=1216352
+ - https://bugzilla.kernel.org/show_bug.cgi?id=211593
+ */
+
xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid);
len = readlink (name, buf, PATH_MAX - 1);
if (len <= 0)
@@ -352,9 +369,11 @@ linux_proc_pid_to_exec_file (int pid)
else
buf[len] = '\0';
- /* Use /proc/PID/exe if the actual file can't be read, but /proc/PID/exe
- can be. */
- if (access (buf, R_OK) != 0 && access (name, R_OK) == 0)
+ /* Use /proc/PID/exe if the actual file can't be read. Note that we don't
+ check for "access ("/proc/PID/exe", R_OK) == 0". It possible that this
+ check will fail while we can actually read /proc/PID/exe (
+ https://bugzilla.suse.com/show_bug.cgi?id=1221867 ). */
+ if (access (buf, R_OK) != 0)
strcpy (buf, name);
return buf;