Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1250971 > unrolled thread
| Started by | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| First post | 2015-10-19 20:00 +0200 |
| Last post | 2015-10-20 13:00 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
Unkillable processes due to PTRACE_TRACEME Dmitry Vyukov <dvyukov@google.com> - 2015-10-19 20:00 +0200
Re: Unkillable processes due to PTRACE_TRACEME Oleg Nesterov <oleg@redhat.com> - 2015-10-19 22:00 +0200
Re: Unkillable processes due to PTRACE_TRACEME Dmitry Vyukov <dvyukov@google.com> - 2015-10-19 22:20 +0200
Re: Unkillable processes due to PTRACE_TRACEME Dmitry Vyukov <dvyukov@google.com> - 2015-10-20 10:40 +0200
Re: Unkillable processes due to PTRACE_TRACEME Dmitry Vyukov <dvyukov@google.com> - 2015-10-20 10:50 +0200
Re: Unkillable processes due to PTRACE_TRACEME Oleg Nesterov <oleg@redhat.com> - 2015-10-20 13:00 +0200
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2015-10-19 20:00 +0200 |
| Subject | Unkillable processes due to PTRACE_TRACEME |
| Message-ID | <qlmSZ-3hP-1@gated-at.bofh.it> |
Hello,
The following program hangs in some interesting state and is not
killable (started by a normal user, not root):
// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <pthread.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <stdio.h>
#include <signal.h>
void *thr(void *arg) {
ptrace(PTRACE_TRACEME, 0, 0, 0);
sleep(3);
kill(getpid(), SIGCHLD);
return 0;
}
int main() {
if (fork() == 0) {
sleep(1);
pthread_t th;
pthread_create(&th, 0, thr, 0);
sleep(1);
}
return 0;
}
The child process attaches as tracee to init process and then hangs in
a state that I don't understand. When I did a similar thing but
attached it to a normal parent process (shell), I still was able to
get rid of it by killing parent (shell). But definitely you don't want
to kill init.
I am not sure who is guilty here, but an unkillable process started by
a normal user looks like an issue in itself.
I am not sure whether it makes sense to allow to attach as tracee to
init. But I've been told that it can make sense in some security
setups where init traces everything.
Also, what is that state that the process hangs in? It looks like a
usual un-waited process, but when I just do ptrace(PTRACE_TRACEME) in
main, the process does not hang. The additional thread somehow makes a
difference.
I am on commit f9fbf6b72ffaaca8612979116c872c9d5d9cc1f5 (Sep 24).
Found with syzkaller system call fuzzer.
Thank you
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Oleg Nesterov <oleg@redhat.com> |
|---|---|
| Date | 2015-10-19 22:00 +0200 |
| Message-ID | <qloL8-64d-25@gated-at.bofh.it> |
| In reply to | #1250971 |
On 10/19, Dmitry Vyukov wrote:
>
> The following program hangs in some interesting state and is not
> killable (started by a normal user, not root):
Thanks.
> #include <pthread.h>
> #include <unistd.h>
> #include <sys/ptrace.h>
> #include <stdio.h>
> #include <signal.h>
>
> void *thr(void *arg) {
> ptrace(PTRACE_TRACEME, 0, 0, 0);
> sleep(3);
> kill(getpid(), SIGCHLD);
> return 0;
> }
>
> int main() {
> if (fork() == 0) {
> sleep(1);
> pthread_t th;
> pthread_create(&th, 0, thr, 0);
> sleep(1);
> }
> return 0;
> }
>
>
> The child process attaches as tracee to init process
Yes, although in a racy manner, the parent can exit after
PTRACE_TRACEME in this case the kernel will untrace the task
before reparenting. Not that this matters.
> and then hangs in
> a state that I don't understand. When I did a similar thing but
> attached it to a normal parent process (shell), I still was able to
> get rid of it by killing parent (shell).
See above.
So I bet the problem is that your /sbin/init doesn't use __WALL,
so wait() doesn't reap the traced zombie sub-thread, and thus it
can't release the non-empty thread group.
Could you please verify? Just do "strace -p1" and send SIGCHLD to
init.
perhaps eligible_child() should assume WALL if ptrace && ZOMBIE...
Oleg.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2015-10-19 22:20 +0200 |
| Message-ID | <qlp4t-6It-1@gated-at.bofh.it> |
| In reply to | #1251041 |
On Mon, Oct 19, 2015 at 9:49 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> On 10/19, Dmitry Vyukov wrote:
>>
>> The following program hangs in some interesting state and is not
>> killable (started by a normal user, not root):
>
> Thanks.
>
>> #include <pthread.h>
>> #include <unistd.h>
>> #include <sys/ptrace.h>
>> #include <stdio.h>
>> #include <signal.h>
>>
>> void *thr(void *arg) {
>> ptrace(PTRACE_TRACEME, 0, 0, 0);
>> sleep(3);
>> kill(getpid(), SIGCHLD);
>> return 0;
>> }
>>
>> int main() {
>> if (fork() == 0) {
>> sleep(1);
>> pthread_t th;
>> pthread_create(&th, 0, thr, 0);
>> sleep(1);
>> }
>> return 0;
>> }
>>
>>
>> The child process attaches as tracee to init process
>
> Yes, although in a racy manner, the parent can exit after
> PTRACE_TRACEME in this case the kernel will untrace the task
> before reparenting. Not that this matters.
>
>> and then hangs in
>> a state that I don't understand. When I did a similar thing but
>> attached it to a normal parent process (shell), I still was able to
>> get rid of it by killing parent (shell).
>
> See above.
>
> So I bet the problem is that your /sbin/init doesn't use __WALL,
> so wait() doesn't reap the traced zombie sub-thread, and thus it
> can't release the non-empty thread group.
>
> Could you please verify? Just do "strace -p1" and send SIGCHLD to
> init.
>
> perhaps eligible_child() should assume WALL if ptrace && ZOMBIE...
I am using Ubuntu.
Here strace output from init:
waitid(P_ALL, 0, {}, WNOHANG|WEXITED|WSTOPPED|WCONTINUED, NULL) = 0
So what should be fixed here? Kernel of distro init?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2015-10-20 10:40 +0200 |
| Message-ID | <qlACB-6KM-1@gated-at.bofh.it> |
| In reply to | #1251046 |
On Mon, Oct 19, 2015 at 10:17 PM, Dmitry Vyukov <dvyukov@google.com> wrote:
> On Mon, Oct 19, 2015 at 9:49 PM, Oleg Nesterov <oleg@redhat.com> wrote:
>> On 10/19, Dmitry Vyukov wrote:
>>>
>>> The following program hangs in some interesting state and is not
>>> killable (started by a normal user, not root):
>>
>> Thanks.
>>
>>> #include <pthread.h>
>>> #include <unistd.h>
>>> #include <sys/ptrace.h>
>>> #include <stdio.h>
>>> #include <signal.h>
>>>
>>> void *thr(void *arg) {
>>> ptrace(PTRACE_TRACEME, 0, 0, 0);
>>> sleep(3);
>>> kill(getpid(), SIGCHLD);
>>> return 0;
>>> }
>>>
>>> int main() {
>>> if (fork() == 0) {
>>> sleep(1);
>>> pthread_t th;
>>> pthread_create(&th, 0, thr, 0);
>>> sleep(1);
>>> }
>>> return 0;
>>> }
>>>
>>>
>>> The child process attaches as tracee to init process
>>
>> Yes, although in a racy manner, the parent can exit after
>> PTRACE_TRACEME in this case the kernel will untrace the task
>> before reparenting. Not that this matters.
>>
>>> and then hangs in
>>> a state that I don't understand. When I did a similar thing but
>>> attached it to a normal parent process (shell), I still was able to
>>> get rid of it by killing parent (shell).
>>
>> See above.
>>
>> So I bet the problem is that your /sbin/init doesn't use __WALL,
>> so wait() doesn't reap the traced zombie sub-thread, and thus it
>> can't release the non-empty thread group.
>>
>> Could you please verify? Just do "strace -p1" and send SIGCHLD to
>> init.
>>
>> perhaps eligible_child() should assume WALL if ptrace && ZOMBIE...
>
>
> I am using Ubuntu.
> Here strace output from init:
>
> waitid(P_ALL, 0, {}, WNOHANG|WEXITED|WSTOPPED|WCONTINUED, NULL) = 0
>
> So what should be fixed here? Kernel of distro init?
waitpid(__WALL) indeed joins these processes.
But __WALL can't be used with waitid and Ubuntu init uses waitid...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2015-10-20 10:50 +0200 |
| Message-ID | <qlAMi-6Wk-33@gated-at.bofh.it> |
| In reply to | #1251437 |
On Tue, Oct 20, 2015 at 10:34 AM, Dmitry Vyukov <dvyukov@google.com> wrote:
> On Mon, Oct 19, 2015 at 10:17 PM, Dmitry Vyukov <dvyukov@google.com> wrote:
>> On Mon, Oct 19, 2015 at 9:49 PM, Oleg Nesterov <oleg@redhat.com> wrote:
>>> On 10/19, Dmitry Vyukov wrote:
>>>>
>>>> The following program hangs in some interesting state and is not
>>>> killable (started by a normal user, not root):
>>>
>>> Thanks.
>>>
>>>> #include <pthread.h>
>>>> #include <unistd.h>
>>>> #include <sys/ptrace.h>
>>>> #include <stdio.h>
>>>> #include <signal.h>
>>>>
>>>> void *thr(void *arg) {
>>>> ptrace(PTRACE_TRACEME, 0, 0, 0);
>>>> sleep(3);
>>>> kill(getpid(), SIGCHLD);
>>>> return 0;
>>>> }
>>>>
>>>> int main() {
>>>> if (fork() == 0) {
>>>> sleep(1);
>>>> pthread_t th;
>>>> pthread_create(&th, 0, thr, 0);
>>>> sleep(1);
>>>> }
>>>> return 0;
>>>> }
>>>>
>>>>
>>>> The child process attaches as tracee to init process
>>>
>>> Yes, although in a racy manner, the parent can exit after
>>> PTRACE_TRACEME in this case the kernel will untrace the task
>>> before reparenting. Not that this matters.
>>>
>>>> and then hangs in
>>>> a state that I don't understand. When I did a similar thing but
>>>> attached it to a normal parent process (shell), I still was able to
>>>> get rid of it by killing parent (shell).
>>>
>>> See above.
>>>
>>> So I bet the problem is that your /sbin/init doesn't use __WALL,
>>> so wait() doesn't reap the traced zombie sub-thread, and thus it
>>> can't release the non-empty thread group.
>>>
>>> Could you please verify? Just do "strace -p1" and send SIGCHLD to
>>> init.
>>>
>>> perhaps eligible_child() should assume WALL if ptrace && ZOMBIE...
>>
>>
>> I am using Ubuntu.
>> Here strace output from init:
>>
>> waitid(P_ALL, 0, {}, WNOHANG|WEXITED|WSTOPPED|WCONTINUED, NULL) = 0
>>
>> So what should be fixed here? Kernel of distro init?
>
> waitpid(__WALL) indeed joins these processes.
> But __WALL can't be used with waitid and Ubuntu init uses waitid...
I am thinking how to workaround this issue.
The following program joins both child processes:
#include <pthread.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void *thr(void *arg) {
ptrace(PTRACE_TRACEME, 0, 0, 0);
return 0;
}
int main() {
int pid = fork();
if (pid == 0) {
pthread_t th;
pthread_create(&th, 0, thr, 0);
sleep(1);
return 0;
}
siginfo_t info = {};
int status = 0;
int res = waitpid(-1, &status, __WALL);
printf("pid=%d res=%d errno=%d\n", pid, res, errno);
res = waitpid(-1, &status, __WALL);
printf("pid=%d res=%d errno=%d\n", pid, res, errno);
return 0;
}
However, I need to wait for a particular child and if I change the
first waitpid to:
int res = waitpid(pid, &status, __WALL);
then it does not terminate.
So how can I wait for such child process?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Oleg Nesterov <oleg@redhat.com> |
|---|---|
| Date | 2015-10-20 13:00 +0200 |
| Message-ID | <qlCO7-1qN-25@gated-at.bofh.it> |
| In reply to | #1251452 |
On 10/20, Dmitry Vyukov wrote:
>
> On Tue, Oct 20, 2015 at 10:34 AM, Dmitry Vyukov <dvyukov@google.com> wrote:
> > On Mon, Oct 19, 2015 at 10:17 PM, Dmitry Vyukov <dvyukov@google.com> wrote:
> >> On Mon, Oct 19, 2015 at 9:49 PM, Oleg Nesterov <oleg@redhat.com> wrote:
> >>>
> >>> So I bet the problem is that your /sbin/init doesn't use __WALL,
> >>> so wait() doesn't reap the traced zombie sub-thread, and thus it
> >>> can't release the non-empty thread group.
> >>>
> >>> Could you please verify? Just do "strace -p1" and send SIGCHLD to
> >>> init.
> >>>
> >>> perhaps eligible_child() should assume WALL if ptrace && ZOMBIE...
> >>
> >>
> >> I am using Ubuntu.
> >> Here strace output from init:
> >>
> >> waitid(P_ALL, 0, {}, WNOHANG|WEXITED|WSTOPPED|WCONTINUED, NULL) = 0
> >>
> >> So what should be fixed here? Kernel of distro init?
> >
> > waitpid(__WALL) indeed joins these processes.
Thanks. And I just checked Fedora 22, it doesn't use __WALL too.
So I think we should change the kernel even if this is not a bug...
I'll send the patch.
> > But __WALL can't be used with waitid and Ubuntu init uses waitid...
Yes, and I never understood why. Perhaps we should change this too.
> #include <pthread.h>
> #include <unistd.h>
> #include <sys/ptrace.h>
> #include <stdio.h>
> #include <errno.h>
> #include <signal.h>
> #include <sys/types.h>
> #include <sys/wait.h>
>
> void *thr(void *arg) {
> ptrace(PTRACE_TRACEME, 0, 0, 0);
> return 0;
> }
>
> int main() {
> int pid = fork();
> if (pid == 0) {
> pthread_t th;
> pthread_create(&th, 0, thr, 0);
> sleep(1);
> return 0;
> }
> siginfo_t info = {};
> int status = 0;
> int res = waitpid(-1, &status, __WALL);
> printf("pid=%d res=%d errno=%d\n", pid, res, errno);
> res = waitpid(-1, &status, __WALL);
> printf("pid=%d res=%d errno=%d\n", pid, res, errno);
> return 0;
> }
>
>
> However, I need to wait for a particular child and if I change the
> first waitpid to:
>
> int res = waitpid(pid, &status, __WALL);
>
> then it does not terminate.
> So how can I wait for such child process?
You can't. This is one of historical oddities. You need to reap the
traced sub-thread first. And PTRACE_DETACH doesn't work.
Oleg.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web