From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49187C4320A for ; Thu, 12 Aug 2021 09:18:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2CFBA6103A for ; Thu, 12 Aug 2021 09:18:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235505AbhHLJSY (ORCPT ); Thu, 12 Aug 2021 05:18:24 -0400 Received: from mail.kernel.org ([198.145.29.99]:57912 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235317AbhHLJSX (ORCPT ); Thu, 12 Aug 2021 05:18:23 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0C8256056B; Thu, 12 Aug 2021 09:17:44 +0000 (UTC) Date: Thu, 12 Aug 2021 11:17:42 +0200 From: Christian Brauner To: David Hildenbrand Cc: linux-kernel@vger.kernel.org, Linus Torvalds , Andrew Morton , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , Alexander Viro , Alexey Dobriyan , Steven Rostedt , Peter Zijlstra , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Petr Mladek , Sergey Senozhatsky , Andy Shevchenko , Rasmus Villemoes , Kees Cook , "Eric W. Biederman" , Greg Ungerer , Geert Uytterhoeven , Mike Rapoport , Vlastimil Babka , Vincenzo Frascino , Chinwen Chang , Michel Lespinasse , Catalin Marinas , "Matthew Wilcox (Oracle)" , Huang Ying , Jann Horn , Feng Tang , Kevin Brodsky , Michael Ellerman , Shawn Anastasio , Steven Price , Nicholas Piggin , Jens Axboe , Gabriel Krisman Bertazi , Peter Xu , Suren Baghdasaryan , Shakeel Butt , Marco Elver , Daniel Jordan , Nicolas Viennot , Thomas Cedeno , Collin Fijalkovich , Michal Hocko , Miklos Szeredi , Chengguang Xu , Christian =?utf-8?B?S8O2bmln?= , linux-unionfs@vger.kernel.org, linux-api@vger.kernel.org, x86@kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Subject: Re: [PATCH v1 2/7] kernel/fork: factor out atomcially replacing the current MM exe_file Message-ID: <20210812091742.nbnmsa37adaqkxwd@wittgenstein> References: <20210812084348.6521-1-david@redhat.com> <20210812084348.6521-3-david@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20210812084348.6521-3-david@redhat.com> Precedence: bulk List-ID: X-Mailing-List: linux-unionfs@vger.kernel.org On Thu, Aug 12, 2021 at 10:43:43AM +0200, David Hildenbrand wrote: > Let's factor the main logic out into atomic_set_mm_exe_file(), such that > all mm->exe_file logic is contained in kernel/fork.c. > > While at it, perform some simple cleanups that are possible now that > we're simplifying the individual functions. > > Signed-off-by: David Hildenbrand > --- Looks good. Acked-by: Christian Brauner > include/linux/mm.h | 2 ++ > kernel/fork.c | 35 +++++++++++++++++++++++++++++++++-- > kernel/sys.c | 33 +-------------------------------- > 3 files changed, 36 insertions(+), 34 deletions(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 7ca22e6e694a..197505324b74 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2581,6 +2581,8 @@ extern int mm_take_all_locks(struct mm_struct *mm); > extern void mm_drop_all_locks(struct mm_struct *mm); > > extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file); > +extern int atomic_set_mm_exe_file(struct mm_struct *mm, > + struct file *new_exe_file); > extern struct file *get_mm_exe_file(struct mm_struct *mm); > extern struct file *get_task_exe_file(struct task_struct *task); > > diff --git a/kernel/fork.c b/kernel/fork.c > index bc94b2cc5995..6bd2e52bcdfb 100644 > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -1149,8 +1149,8 @@ void mmput_async(struct mm_struct *mm) > * Main users are mmput() and sys_execve(). Callers prevent concurrent > * invocations: in mmput() nobody alive left, in execve task is single > * threaded. sys_prctl(PR_SET_MM_MAP/EXE_FILE) also needs to set the > - * mm->exe_file, but does so without using set_mm_exe_file() in order > - * to avoid the need for any locks. > + * mm->exe_file, but uses atomic_set_mm_exe_file(), avoiding the need > + * for any locks. > */ > void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) > { > @@ -1170,6 +1170,37 @@ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) > fput(old_exe_file); > } > > +int atomic_set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) > +{ > + struct vm_area_struct *vma; > + struct file *old_exe_file; > + int ret = 0; > + > + /* Forbid mm->exe_file change if old file still mapped. */ > + old_exe_file = get_mm_exe_file(mm); > + if (old_exe_file) { > + mmap_read_lock(mm); > + for (vma = mm->mmap; vma && !ret; vma = vma->vm_next) { > + if (!vma->vm_file) > + continue; > + if (path_equal(&vma->vm_file->f_path, > + &old_exe_file->f_path)) > + ret = -EBUSY; > + } > + mmap_read_unlock(mm); > + fput(old_exe_file); > + if (ret) > + return ret; > + } > + > + /* set the new file, lockless */ > + get_file(new_exe_file); > + old_exe_file = xchg(&mm->exe_file, new_exe_file); > + if (old_exe_file) > + fput(old_exe_file); > + return 0; > +} > + > /** > * get_mm_exe_file - acquire a reference to the mm's executable file > * > diff --git a/kernel/sys.c b/kernel/sys.c > index ef1a78f5d71c..40551b411fda 100644 > --- a/kernel/sys.c > +++ b/kernel/sys.c > @@ -1846,7 +1846,6 @@ SYSCALL_DEFINE1(umask, int, mask) > static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) > { > struct fd exe; > - struct file *old_exe, *exe_file; > struct inode *inode; > int err; > > @@ -1869,40 +1868,10 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) > if (err) > goto exit; > > - /* > - * Forbid mm->exe_file change if old file still mapped. > - */ > - exe_file = get_mm_exe_file(mm); > - err = -EBUSY; > - if (exe_file) { > - struct vm_area_struct *vma; > - > - mmap_read_lock(mm); > - for (vma = mm->mmap; vma; vma = vma->vm_next) { > - if (!vma->vm_file) > - continue; > - if (path_equal(&vma->vm_file->f_path, > - &exe_file->f_path)) > - goto exit_err; > - } > - > - mmap_read_unlock(mm); > - fput(exe_file); > - } > - > - err = 0; > - /* set the new file, lockless */ > - get_file(exe.file); > - old_exe = xchg(&mm->exe_file, exe.file); > - if (old_exe) > - fput(old_exe); > + err = atomic_set_mm_exe_file(mm, exe.file); > exit: > fdput(exe); > return err; > -exit_err: > - mmap_read_unlock(mm); > - fput(exe_file); > - goto exit; > } > > /* > -- > 2.31.1 >