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...