Received: by 2002:a05:6a10:1d13:0:0:0:0 with SMTP id pp19csp606497pxb; Mon, 16 Aug 2021 12:52:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwmC9qAzrGtVmf5Gc9PmAGHtkyB/6Bg4exIkpGZJ2th/wGY4edQx7r9IjKHbseDbgo5CiPM X-Received: by 2002:a17:906:4f97:: with SMTP id o23mr152899eju.418.1629143551205; Mon, 16 Aug 2021 12:52:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629143551; cv=none; d=google.com; s=arc-20160816; b=uzdH/V5EkP+CpU9cD8hKGBVULN52AdXjit/DNxcRB9kLKymlxEZjzvAJlA4FJtk7LJ RMcLdxW8pJ4jKztZykkSO5JxuOcvWMwLi2pQF2KhJ4yBDh5WGgXWrcwHeSbt6Hf4EDpP 4YXpFwWM5cdOgIdlABhdvjdDceDI9Z8Rhh9x22YcpiQwbAwnPXqYrBt4dJMMHsePHdoO C2od64rtwHhEHLSKPo7kj3RBFhHUy3syPEA9Rz6DuC7/ZP/OZKrO3s0bwwX88uaRJOYF oUW+FHVBS1WdGtiUxogKlGy/Q94pQ+GtQRxC+TEJt9oK1sTFbAUsDT17yzFvYQHRUodg pM7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=OaQssic/mSdAfbGEFpAxDDR1LNO8rKXcgan69fY/97k=; b=eNlZDmTKAlvYI3AEUW9Vy4ZVHg9pHjaHqDhDBT/yyIip8ioR2N1vHPwoks+L90SbgM PAk2/TneEL/hFfOCFtZyzrFW9L7ePaVNy9EM+i+3yghJhO4jtkziaZDak1J738wiL2WZ c/rN4Q0cLTWAf/TSYlUXuUewzk04f+JYwqHAdDDJVDOEXllwgMsfyRKGK7Ka5T+Ynj5c T0PTx5CnOQdKkGs8jWa59EB5FtRYz7fuEBtwNGP967xYPzwhPeGPz7GIib+4cu+u3xB9 yFt3lkKj8bz/o0QEad/ZGcmNUe3a7T7u2WOKtwtKlNkiUCk5MR6H1Ukv9Y7Mc9lYlfX+ XZlA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=PoNYDpvC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ch5si163546ejb.547.2021.08.16.12.52.08; Mon, 16 Aug 2021 12:52:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=PoNYDpvC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231545AbhHPTul (ORCPT + 99 others); Mon, 16 Aug 2021 15:50:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:53550 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231443AbhHPTui (ORCPT ); Mon, 16 Aug 2021 15:50:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629143406; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OaQssic/mSdAfbGEFpAxDDR1LNO8rKXcgan69fY/97k=; b=PoNYDpvCIS09HALrADqXk9rRQYC9228/o3kus6Uqgklo04mbNUeRvCcqiOdEQqCkSK8+BA 0WaWO0AkAAO/XvDneIdKk8ltaV0vzB0RpRME+OAA3Lbzo/QmQ5kAV3k8xIs8DlHoY71wKb Mvv3zXy8sGtOQcGyf6JR8OrwcKJ360k= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-591-J3jO7BELMNqN2SqR5wWAGg-1; Mon, 16 Aug 2021 15:50:02 -0400 X-MC-Unique: J3jO7BELMNqN2SqR5wWAGg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BD801190A7A1; Mon, 16 Aug 2021 19:50:00 +0000 (UTC) Received: from t480s.redhat.com (unknown [10.39.192.85]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1536118017; Mon, 16 Aug 2021 19:49:40 +0000 (UTC) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: David Hildenbrand , 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 , Catalin Marinas , "Matthew Wilcox (Oracle)" , Huang Ying , Jann Horn , Feng Tang , Kevin Brodsky , Michael Ellerman , Shawn Anastasio , Steven Price , Nicholas Piggin , Christian Brauner , Jens Axboe , Gabriel Krisman Bertazi , Peter Xu , Suren Baghdasaryan , Shakeel Butt , Marco Elver , Daniel Jordan , Nicolas Viennot , Thomas Cedeno , Michal Hocko , Miklos Szeredi , Chengguang Xu , =?UTF-8?q?Christian=20K=C3=B6nig?= , Florian Weimer , David Laight , linux-unionfs@vger.kernel.org, linux-api@vger.kernel.org, x86@kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v2 2/7] kernel/fork: factor out replacing the current MM exe_file Date: Mon, 16 Aug 2021 21:48:35 +0200 Message-Id: <20210816194840.42769-3-david@redhat.com> In-Reply-To: <20210816194840.42769-1-david@redhat.com> References: <20210816194840.42769-1-david@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Let's factor the main logic out into replace_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. Acked-by: Christian Brauner Acked-by: "Eric W. Biederman" Signed-off-by: David Hildenbrand --- include/linux/mm.h | 1 + kernel/fork.c | 44 +++++++++++++++++++++++++++++++++++++++++--- kernel/sys.c | 33 +-------------------------------- 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 7ca22e6e694a..48c6fa9ab792 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2581,6 +2581,7 @@ 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 replace_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..eedce5c77041 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1148,9 +1148,7 @@ 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. + * threaded. */ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) { @@ -1170,6 +1168,46 @@ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) fput(old_exe_file); } +/** + * replace_mm_exe_file - replace a reference to the mm's executable file + * + * This changes mm's executable file (shown as symlink /proc/[pid]/exe), + * dealing with concurrent invocation and without grabbing the mmap lock in + * write mode. + * + * Main user is sys_prctl(PR_SET_MM_MAP/EXE_FILE). + */ +int replace_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..30c12e54585a 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 = replace_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