[PATCH wayland 2/2 v2] tests: Fix FAIL in sanity-test (*timeout*) when Yama LSM enabled
Bryce Harrington
bryce at osg.samsung.com
Wed Jan 7 12:34:54 PST 2015
This fixes a regression in the testsuite since c3653f7f, where four of
the timeout tests fail with "Timeouts suppressed" messages.
The timeouts are being suppressed because the testsuite is erroneously
detecting that a debugger is attached. This detection mechanism
(adopted from libinput) uses ptrace to test if there is a debugger
parent process that can be attached. Unfortunately, this is an
unreliable test: Kernel security policies exist to restrict the scope of
ptrace to prevent processes from snooping on one another.[1] This
security policy is set as the default on Ubuntu, and potentially other
Linux distributions.[2]
The Yama documentation suggests, "For software that has defined
application-specific relationships between a debugging process and its
inferior (crash handlers, etc), prctl(PR_SET_PTRACER, pid, ...) can be
used. An inferior can declare which other process (and its descendents)
are allowed to call PTRACE_ATTACH against it."
The child needs to be synchronized to the client to prevent a race
condition where the child might try to operate before the parent has
finished its prctl call. This synchronization is done via pipes.
1: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2d514487faf188938a4ee4fb3464eeecfbdcf8eb
2: https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace_Protection
Signed-off-by: Bryce Harrington <bryce at osg.samsung.com>
---
tests/test-runner.c | 35 ++++++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/tests/test-runner.c b/tests/test-runner.c
index b813b69..11d064e 100644
--- a/tests/test-runner.c
+++ b/tests/test-runner.c
@@ -34,6 +34,7 @@
#include <errno.h>
#include <limits.h>
#include <sys/ptrace.h>
+#include <linux/prctl.h>
#include "test-runner.h"
@@ -255,13 +256,33 @@ is_debugger_attached(void)
{
int status;
int rc;
- pid_t pid = fork();
+ pid_t pid;
+ int pipefd[2];
- if (pid == -1)
+ if (pipe(pipefd) == -1) {
+ perror("pipe");
return 0;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ perror("fork");
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return 0;
+ }
if (pid == 0) {
- pid_t ppid = getppid();
+ char buf;
+ pid_t ppid;
+
+ /* Wait until parent is ready */
+ close(pipefd[1]); /* Close unused write end */
+ while (read(pipefd[0], &buf, 1) > 0);
+ close(pipefd[0]);
+
+ /* Attempt to ptrace the parent */
+ ppid = getppid();
rc = ptrace(PTRACE_ATTACH, ppid, NULL, NULL);
if (rc == 0) {
waitpid(ppid, NULL, 0);
@@ -273,6 +294,14 @@ is_debugger_attached(void)
}
_exit(rc);
} else {
+ close(pipefd[0]);
+
+ /* Enable child to ptrace the parent process */
+ prctl(PR_SET_PTRACER, pid);
+
+ /* Signal to client that parent is ready */
+ close(pipefd[1]);
+
waitpid(pid, &status, 0);
rc = WEXITSTATUS(status);
}
--
1.9.1
More information about the wayland-devel
mailing list