Re: [PATCH resend v3 2/2] exec: Broadly lock nascent mm until setup_arg_pages()

From: Jann Horn
Date: Mon Nov 02 2020 - 22:53:59 EST


On Tue, Oct 20, 2020 at 9:15 PM Jason Gunthorpe <jgg@xxxxxxxxxx> wrote:
> On Sat, Oct 17, 2020 at 12:57:13AM +0200, Jann Horn wrote:
> > @@ -1545,6 +1532,18 @@ void setup_new_exec(struct linux_binprm * bprm)
> > me->mm->task_size = TASK_SIZE;
> > mutex_unlock(&me->signal->exec_update_mutex);
> > mutex_unlock(&me->signal->cred_guard_mutex);
> > +
> > + if (!IS_ENABLED(CONFIG_MMU)) {
> > + /*
> > + * On MMU, setup_arg_pages() wants to access bprm->vma after
> > + * this point, so we can't drop the mmap lock yet.
> > + * On !MMU, we have neither setup_arg_pages() nor bprm->vma,
> > + * so we should drop the lock here.
> > + */
> > + mmap_write_unlock(bprm->mm);
> > + mmput(bprm->mm);
> > + bprm->mm = NULL;
> > + }
>
> The only thing I dislike about this is how tricky the lock lifetime
> is, it all looks correct, but expecting the setup_arg_pages() or
> setup_new_exec() to unlock (depending!) is quite tricky.
>
> It feels like it would be clearer to have an explicit function to do
> this, like 'release_brp_mm()' indicating that current->mm is now the
> only way to get the mm and it must be locked.

That was a good suggestion; I tried to amend my patch as suggested,
and while trying to do that, noticed that under CONFIG_MMU,
binfmt_flat first does setup_new_exec(), then vm_mmap(), and then
later on setup_arg_pages()...

So your suggestion indeed helped make it clear that my patch was
wrong. Guess I'll have to go figure out how to rearrange the pieces in
binfmt_flat to make this work...