Re: [GIT PULL] Please pull proc and exec work for 5.7-rc1

From: Oleg Nesterov
Date: Sun Apr 12 2020 - 15:51:26 EST


On 04/11, Linus Torvalds wrote:
>
> On Sat, Apr 11, 2020 at 11:21 AM Oleg Nesterov <oleg@xxxxxxxxxx> wrote:
> >
> > On 04/09, Linus Torvalds wrote:
> > >
> > > (1) have execve() not wait for dead threads while holding the cred
> > > mutex
> >
> > This is what I tried to do 3 years ago, see
>
> Well, you did it differently - by moving the "wait for dead threads"
> logic to after releasing the lock.

Yes, please see below.

> My simpler patch was lazier

To be honest, I don't understand it... OK, suppose that the main thread
M execs and zap_other_threads() finds a single (and alive) sub-thread T,
sig->notify_count = 1.

If T is traced, then ->notify_count won't be decremented until the tracer
reaps this task, so we have the same problem.

This is fixeable, say, we can uglify exit_notify() like my patch does,
but:

> - just don't wait for dead threads at all,
> since they are dead and not interesting.

Well, I am not sure. Just for example, seccomp(SECCOMP_FILTER_FLAG_TSYNC)
can fail after mt-exec because seccomp_can_sync_threads() finds a zombe
thread. Sure, this too can can be fixed, but I think there should be no
other threads after exec.

And:

> You do say in that old patch that we can't just share the signal
> state, but I wonder how true that is.

We can share sighand_struct with TASK_ZOMBIE's. The problem is that
we can not unshare ->sighand until they go away, execing thread and
zombies must use the same sighand->siglock to serialize the access to
->thread_head/etc.

OK, we probably can if we complicate unshare_sighand(), we will need
to take tasklist_lock/oldsighand->siglock unconditionally to check
oldsighand->count > sig->nr_thread, then do

for_each_thread(current, t) {
t->sighand = newsighand;
__cleanup_sighand(oldsighand);
}

but see above, I don't think this makes any sense.

Oleg