diff mbox series

[v3] syscalls/ptrace11: Add test for tracing init process

Message ID 1605233273-3784-1-git-send-email-xuyang2018.jy@cn.fujitsu.com
State Changes Requested
Headers show
Series [v3] syscalls/ptrace11: Add test for tracing init process | expand

Commit Message

Yang Xu Nov. 13, 2020, 2:07 a.m. UTC
Before kernel 2.6.26, ptrace can't trace init process and will get
EPERM error. Now, it should succeed when we have enough privileges.

Signed-off-by: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
---
 runtest/syscalls                            |  1 +
 testcases/kernel/syscalls/ptrace/.gitignore |  1 +
 testcases/kernel/syscalls/ptrace/ptrace11.c | 40 +++++++++++++++++++++
 3 files changed, 42 insertions(+)
 create mode 100644 testcases/kernel/syscalls/ptrace/ptrace11.c

Comments

Cyril Hrubis Nov. 13, 2020, 3:12 p.m. UTC | #1
Hi!
> +	/*
> +	 * Running attach/detach more times will trigger a ESRCH error because
> +	 * ptrace_check_attach function in kernel will report it if its process
> +	 * stats is not __TASK_TRACED.
> +	 */
> +	TST_RETRY_FUNC(ptrace(PTRACE_DETACH, 1, NULL, NULL), TST_RETVAL_EQ0);

Why do we have to retry the detach here?

Other than that the rest looks fine now.
Yang Xu Nov. 16, 2020, 10:51 a.m. UTC | #2
Hi Cyril
> Hi!
>> +	/*
>> +	 * Running attach/detach more times will trigger a ESRCH error because
>> +	 * ptrace_check_attach function in kernel will report it if its process
>> +	 * stats is not __TASK_TRACED.
>> +	 */
>> +	TST_RETRY_FUNC(ptrace(PTRACE_DETACH, 1, NULL, NULL), TST_RETVAL_EQ0);
>
> Why do we have to retry the detach here?

I add a retry here because running attach/detach serval times may make 
init process isn't traced status . Even we have do attach action, detach 
will get ESRCH error .

In kernel/ptrace.c code, it has the following calltrace
SYSCALL_DEFINE4(ptrace...
    =>ptrace_check_attach   //if we don't use PTRACE_ATTACH/PTRACE_SEIZE
      =>ptrace_freeze_traced

/* Ensure that nothing can wake it up, even SIGKILL */
static bool ptrace_freeze_traced(struct task_struct *task)
{
         bool ret = false;

         /* Lockless, nobody but us can set this flag */
         if (task->jobctl & JOBCTL_LISTENING)
                 return ret;
         spin_lock_irq(&task->sighand->siglock);
         if (task_is_traced(task) && !__fatal_signal_pending(task)) {
                 task->state = __TASK_TRACED;
                 ret = true;
         }
         spin_unlock_irq(&task->sighand->siglock);

         return ret;
}

ptrace_freeze_traced() may returns false when we run attach/detach 
serval times, so ptrace_check_attach returns ESRCH error .

To be honset, I don't figure out why task->stat is not task_traced 
status after attaching. I am looking into this.

Best Regards
Yang Xu
>
> Other than that the rest looks fine now.
>
Cyril Hrubis Nov. 19, 2020, 3:31 p.m. UTC | #3
Hi!
> >> +	/*
> >> +	 * Running attach/detach more times will trigger a ESRCH error because
> >> +	 * ptrace_check_attach function in kernel will report it if its process
> >> +	 * stats is not __TASK_TRACED.
> >> +	 */
> >> +	TST_RETRY_FUNC(ptrace(PTRACE_DETACH, 1, NULL, NULL), TST_RETVAL_EQ0);
> >
> > Why do we have to retry the detach here?
> 
> I add a retry here because running attach/detach serval times may make 
> init process isn't traced status . Even we have do attach action, detach 
> will get ESRCH error .

Looking at the manual page it says:

PTRACE_ATTACH

...
The tracee is sent a SIGSTOP, but will not necessarily have stopped by
the completion of this call; use waitpid(2) to wait for the tracee to
stop.
...

So my guess is that if we call PTRACE_ATTACH followed by the
PTRACE_DETACH we may end up in a state where the SIGSTOP for the traced
process haven't arrived yet and in this case we should get ESCRCH.

So the correct solution is waitpid() for the traced process before we
detach it.
Yang Xu Nov. 20, 2020, 2:30 a.m. UTC | #4
Hi Cyril
> Hi!
>>>> +	/*
>>>> +	 * Running attach/detach more times will trigger a ESRCH error because
>>>> +	 * ptrace_check_attach function in kernel will report it if its process
>>>> +	 * stats is not __TASK_TRACED.
>>>> +	 */
>>>> +	TST_RETRY_FUNC(ptrace(PTRACE_DETACH, 1, NULL, NULL), TST_RETVAL_EQ0);
>>>
>>> Why do we have to retry the detach here?
>>
>> I add a retry here because running attach/detach serval times may make
>> init process isn't traced status . Even we have do attach action, detach
>> will get ESRCH error .
>
> Looking at the manual page it says:
>
> PTRACE_ATTACH
>
> ...
> The tracee is sent a SIGSTOP, but will not necessarily have stopped by
> the completion of this call; use waitpid(2) to wait for the tracee to
> stop.
Oh, I ignored it. Sorry.
> ...
>
> So my guess is that if we call PTRACE_ATTACH followed by the
> PTRACE_DETACH we may end up in a state where the SIGSTOP for the traced
> process haven't arrived yet and in this case we should get ESCRCH.
>
> So the correct solution is waitpid() for the traced process before we
> detach it.
Yes, using waitpid() is ok. I Will send a v4 soon.
>
diff mbox series

Patch

diff --git a/runtest/syscalls b/runtest/syscalls
index aeacb8bc8..6b5908662 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1000,6 +1000,7 @@  ptrace07 ptrace07
 ptrace08 ptrace08
 ptrace09 ptrace09
 ptrace10 ptrace10
+ptrace11 ptrace11
 
 pwrite01 pwrite01
 pwrite02 pwrite02
diff --git a/testcases/kernel/syscalls/ptrace/.gitignore b/testcases/kernel/syscalls/ptrace/.gitignore
index 34be5148f..01cbc6072 100644
--- a/testcases/kernel/syscalls/ptrace/.gitignore
+++ b/testcases/kernel/syscalls/ptrace/.gitignore
@@ -7,3 +7,4 @@ 
 /ptrace08
 /ptrace09
 /ptrace10
+/ptrace11
diff --git a/testcases/kernel/syscalls/ptrace/ptrace11.c b/testcases/kernel/syscalls/ptrace/ptrace11.c
new file mode 100644
index 000000000..28a08f69d
--- /dev/null
+++ b/testcases/kernel/syscalls/ptrace/ptrace11.c
@@ -0,0 +1,40 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 FUJITSU LIMITED. All rights reserved.
+ * Author: Yang Xu <xuyang2018.jy@cn.fujitsu.com>
+ *
+ * Before kernel 2.6.26, we can't trace init(1) process and ptrace() will
+ * get EPERM error. This case just check whether we can trace init(1)
+ * process and doesn't trigger error.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <pwd.h>
+#include <config.h>
+#include <stdlib.h>
+#include "ptrace.h"
+#include "tst_test.h"
+
+static void verify_ptrace(void)
+{
+	TEST(ptrace(PTRACE_ATTACH, 1, NULL, NULL));
+	if (TST_RET == 0)
+		tst_res(TPASS, "ptrace() traces init process successfully");
+	else
+		tst_res(TFAIL | TTERRNO,
+			"ptrace() returns %ld, failed unexpectedly", TST_RET);
+
+	/*
+	 * Running attach/detach more times will trigger a ESRCH error because
+	 * ptrace_check_attach function in kernel will report it if its process
+	 * stats is not __TASK_TRACED.
+	 */
+	TST_RETRY_FUNC(ptrace(PTRACE_DETACH, 1, NULL, NULL), TST_RETVAL_EQ0);
+}
+
+static struct tst_test test = {
+	.test_all = verify_ptrace,
+	.needs_root = 1,
+};