diff options
author | Yong He <chenglang.hy@antfin.com> | 2019-06-12 21:13:13 +0800 |
---|---|---|
committer | Yong He <chenglang.hy@antfin.com> | 2019-06-14 14:05:41 +0800 |
commit | 0dbdca349cd90fff4353650efcb0198b4ad6cb6d (patch) | |
tree | b7d08f170e32beadf11651ce9e066d450953951f /pkg | |
parent | df110ad4fe571721a7eb4a5a1f9ce92584ef7809 (diff) |
Skip tid allocation which is using
When leader of process group (session) exit, the process
group ID (session ID) is holding by other processes in
the process group, so the process group ID (session ID)
can not be reused.
If reusing the process group ID (seession ID) as new process
group ID for new process, this will cause session create
failed, and later runsc crash when access process group.
The fix skip the tid if it is using by a process group
(session) when allocating a new tid.
We could easily reproduce the runsc crash follow
these steps:
1. build test program, and run inside container
int main(int argc, char *argv[])
{
pid_t cpid, spid;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) {
pid_t sid = setsid();
printf("Start New Session %ld\n",sid);
printf("Child PID %ld / PPID %ld / PGID %ld / SID %ld\n",
getpid(),getppid(),getpgid(getpid()),getsid(getpid()));
spid = fork();
if (spid == 0) {
setpgid(getpid(), getpid());
printf("Set GrandSon as New Process Group\n");
printf("GrandSon PID %ld / PPID %ld / PGID %ld / SID %ld\n",
getpid(),getppid(),getpgid(getpid()),getsid(getpid()));
while(1) {
usleep(1);
}
}
sleep(3);
exit(0);
} else {
exit(0);
}
return 0;
}
2. build hello program
int main(int argc, char *argv[])
{
printf("Current PID is %ld\n", (long) getpid());
return 0;
}
3. run script on host which run hello inside container, you can
speed up the test with set TasksLimit as lower value.
for (( i=0; i<65535; i++ ))
do
docker exec <container id> /test/hello
done
4. when hello process reusing the process group of loop process,
runsc will crash.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x79f0c8]
goroutine 612475 [running]:
gvisor.googlesource.com/gvisor/pkg/sentry/kernel.(*ProcessGroup).decRefWithParent(0x0, 0x0)
pkg/sentry/kernel/sessions.go:160 +0x78
gvisor.googlesource.com/gvisor/pkg/sentry/kernel.(*Task).exitNotifyLocked(0xc000663500, 0x0)
pkg/sentry/kernel/task_exit.go:672 +0x2b7
gvisor.googlesource.com/gvisor/pkg/sentry/kernel.(*runExitNotify).execute(0x0, 0xc000663500, 0x0, 0x0)
pkg/sentry/kernel/task_exit.go:542 +0xc4
gvisor.googlesource.com/gvisor/pkg/sentry/kernel.(*Task).run(0xc000663500, 0xc)
pkg/sentry/kernel/task_run.go:91 +0x194
created by gvisor.googlesource.com/gvisor/pkg/sentry/kernel.(*Task).Start
pkg/sentry/kernel/task_start.go:286 +0xfe
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/kernel/task_start.go | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/pkg/sentry/kernel/task_start.go b/pkg/sentry/kernel/task_start.go index b42531e57..b67251d5b 100644 --- a/pkg/sentry/kernel/task_start.go +++ b/pkg/sentry/kernel/task_start.go @@ -249,8 +249,20 @@ func (ns *PIDNamespace) allocateTID() (ThreadID, error) { } // Is it available? - _, ok := ns.tasks[tid] - if !ok { + tidInUse := func() bool { + if _, ok := ns.tasks[tid]; ok { + return true + } + if _, ok := ns.processGroups[ProcessGroupID(tid)]; ok { + return true + } + if _, ok := ns.sessions[SessionID(tid)]; ok { + return true + } + return false + } () + + if !tidInUse { ns.last = tid return tid, nil } |