From patchwork Tue Aug 18 06:12:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 11720035 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2CBDD138C for ; Tue, 18 Aug 2020 06:12:53 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id EC2FD2075B for ; Tue, 18 Aug 2020 06:12:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hvkd25vZ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EC2FD2075B Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id E7F116B0005; Tue, 18 Aug 2020 02:12:51 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id E31838D0001; Tue, 18 Aug 2020 02:12:51 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D476D6B0007; Tue, 18 Aug 2020 02:12:51 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0048.hostedemail.com [216.40.44.48]) by kanga.kvack.org (Postfix) with ESMTP id BFAC86B0005 for ; Tue, 18 Aug 2020 02:12:51 -0400 (EDT) Received: from smtpin06.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 7FA9B180AD822 for ; Tue, 18 Aug 2020 06:12:51 +0000 (UTC) X-FDA: 77162670942.06.dogs55_2000f592701d Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin06.hostedemail.com (Postfix) with ESMTP id 4C5D910040346 for ; Tue, 18 Aug 2020 06:12:51 +0000 (UTC) X-Spam-Summary: 1,0,0,41ef0cbf7291edcc,d41d8cd98f00b204,3yxe7xwukcdixobbvuccuzs.qcazwbil-aayjoqy.cfu@flex--jannh.bounces.google.com,,RULES_HIT:41:69:152:355:379:541:800:960:966:973:981:988:989:1260:1277:1313:1314:1345:1359:1437:1516:1518:1535:1544:1593:1594:1711:1730:1747:1777:1792:2196:2199:2393:2559:2562:2693:2898:2899:3138:3139:3140:3141:3142:3152:3355:3865:3866:3867:3868:3870:3871:3872:3874:4118:4250:4321:4385:4605:5007:6261:6653:7875:7903:7974:8660:9592:9969:10004:11026:11473:11658:11914:12043:12291:12296:12297:12438:12555:12683:12895:12986:13148:13230:13255:14096:14097:14181:14394:14659:14721:21080:21444:21627:21795:21939:21990:30003:30012:30051:30054:30070,0,RBL:209.85.160.201:@flex--jannh.bounces.google.com:.lbl8.mailshell.net-62.18.0.100 66.100.201.100;04yrcehur5n36i87gmw3p3kqsez41ycajtgnhbk1et9oqi3fx69o4cidohh1qb3.qhzg55yuhbcwhanpd8fetck9kb1oiy17czxrtfofawddm8xfw5jrb94k4q3a4rt.g-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,Domai nCache:0 X-HE-Tag: dogs55_2000f592701d X-Filterd-Recvd-Size: 7186 Received: from mail-qt1-f201.google.com (mail-qt1-f201.google.com [209.85.160.201]) by imf04.hostedemail.com (Postfix) with ESMTP for ; Tue, 18 Aug 2020 06:12:50 +0000 (UTC) Received: by mail-qt1-f201.google.com with SMTP id e11so4181829qth.21 for ; Mon, 17 Aug 2020 23:12:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=fmtjrw2NiRGUWmA+xNP8VLGlgPN22hDvuJd6RREZ1Uk=; b=hvkd25vZfBDuvPo6q33UmkfPOceVCVVmb65CH18K1GUDLyKlQ15oUB6XrL0MtXnusD JA7S6ecr6aTA9/jpVWkI4nsjHMnxUEnuZub7SALSoC/PwiQRAi1vHP3dBwQWdN3Q8LGj u3aQMJNkdFjRXPJl5yoikLOsLuqNkQMNBrZy/33KVY2fKCnPudfJYWMr/GnzFc/7McLP HBQ6jRmZiu7NXkCofQeTIm0cirWJR66MLsOcNpcqlDli1/f9c1c257d0Psfg8wEyQdbC QCH7vc9Urt48UXscwfp4cSibk4sLYdpp5F+orh6o0aENePXWjMde353uftORuYZovKFn TlVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=fmtjrw2NiRGUWmA+xNP8VLGlgPN22hDvuJd6RREZ1Uk=; b=inctJD6UX1sXfTp5b1BykufzJrRWEjboo/O+txmqlJsBRYtPDsOqM/IdTeXYHzIMsC FbDGeXSO7mpedgh9zgf48gFgxNJDnQi6+FrFlnLI1Ldg5NnZyguSbg8l8R9oi7DC/m78 YWd29HfL7fh42XsjqkiUQIXVKoTWq4n/XzGgklsCMgUMT5t36JhXa7aerhW55ZVF1ZZL WqMJ0CZRsW9Dl0t5l/YIluzEIRaiqJ5g+tcwTGMt2S7ptmSqJZ1SZaESYXfIfHoK4AmR UwFgQruYqabEFDlCyzLCcny75lCuNQy5bTMuoOpYAGLXgogiO+Ds6sA+2ml4hBNReZX4 msfA== X-Gm-Message-State: AOAM532HqA/SeRm26wIQeZU6BMiL3o9LygcxnmSLSPfSafTPuU4KXN88 AFPhyqnasA3EJS6jqsNqH5yJ676Jew== X-Google-Smtp-Source: ABdhPJwO+ELc+8ooufEtScS6e9Hlf7aAhZms+rK0szynExIR0CufYA7M7iBCYg4m4ltCXb6qLigMMsz8rA== X-Received: by 2002:a0c:b681:: with SMTP id u1mr17324890qvd.189.1597731169792; Mon, 17 Aug 2020 23:12:49 -0700 (PDT) Date: Tue, 18 Aug 2020 08:12:35 +0200 In-Reply-To: <20200818061239.29091-1-jannh@google.com> Message-Id: <20200818061239.29091-2-jannh@google.com> Mime-Version: 1.0 References: <20200818061239.29091-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.220.ged08abb693-goog Subject: [PATCH v3 1/5] binfmt_elf_fdpic: Stop using dump_emit() on user pointers on !MMU From: Jann Horn To: Andrew Morton Cc: Linus Torvalds , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, Alexander Viro , "Eric W . Biederman" , Oleg Nesterov X-Rspamd-Queue-Id: 4C5D910040346 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam04 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: dump_emit() is for kernel pointers, and VMAs describe userspace memory. Let's be tidy here and avoid accessing userspace pointers under KERNEL_DS, even if it probably doesn't matter much on !MMU systems - especially given that it looks like we can just use the same get_dump_page() as on MMU if we move it out of the CONFIG_MMU block. One small change we have to make in get_dump_page() is to use __get_user_pages_locked() instead of __get_user_pages(), since the latter doesn't exist on nommu. On mmu builds, __get_user_pages_locked() will just call __get_user_pages() for us. Signed-off-by: Jann Horn --- fs/binfmt_elf_fdpic.c | 8 ------ mm/gup.c | 57 +++++++++++++++++++++---------------------- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 50f845702b92..a53f83830986 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1529,14 +1529,11 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) struct vm_area_struct *vma; for (vma = current->mm->mmap; vma; vma = vma->vm_next) { -#ifdef CONFIG_MMU unsigned long addr; -#endif if (!maydump(vma, cprm->mm_flags)) continue; -#ifdef CONFIG_MMU for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) { bool res; @@ -1552,11 +1549,6 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) if (!res) return false; } -#else - if (!dump_emit(cprm, (void *) vma->vm_start, - vma->vm_end - vma->vm_start)) - return false; -#endif } return true; } diff --git a/mm/gup.c b/mm/gup.c index ae096ea7583f..92519e5a44b3 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1495,35 +1495,6 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors) mmap_read_unlock(mm); return ret; /* 0 or negative error code */ } - -/** - * get_dump_page() - pin user page in memory while writing it to core dump - * @addr: user address - * - * Returns struct page pointer of user page pinned for dump, - * to be freed afterwards by put_page(). - * - * Returns NULL on any kind of failure - a hole must then be inserted into - * the corefile, to preserve alignment with its headers; and also returns - * NULL wherever the ZERO_PAGE, or an anonymous pte_none, has been found - - * allowing a hole to be left in the corefile to save diskspace. - * - * Called without mmap_lock, but after all other threads have been killed. - */ -#ifdef CONFIG_ELF_CORE -struct page *get_dump_page(unsigned long addr) -{ - struct vm_area_struct *vma; - struct page *page; - - if (__get_user_pages(current->mm, addr, 1, - FOLL_FORCE | FOLL_DUMP | FOLL_GET, &page, &vma, - NULL) < 1) - return NULL; - flush_cache_page(vma, addr, page_to_pfn(page)); - return page; -} -#endif /* CONFIG_ELF_CORE */ #else /* CONFIG_MMU */ static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start, unsigned long nr_pages, struct page **pages, @@ -1569,6 +1540,34 @@ static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start, } #endif /* !CONFIG_MMU */ +/** + * get_dump_page() - pin user page in memory while writing it to core dump + * @addr: user address + * + * Returns struct page pointer of user page pinned for dump, + * to be freed afterwards by put_page(). + * + * Returns NULL on any kind of failure - a hole must then be inserted into + * the corefile, to preserve alignment with its headers; and also returns + * NULL wherever the ZERO_PAGE, or an anonymous pte_none, has been found - + * allowing a hole to be left in the corefile to save diskspace. + * + * Called without mmap_lock, but after all other threads have been killed. + */ +#ifdef CONFIG_ELF_CORE +struct page *get_dump_page(unsigned long addr) +{ + struct vm_area_struct *vma; + struct page *page; + + if (__get_user_pages_locked(current->mm, addr, 1, &page, &vma, NULL, + FOLL_FORCE | FOLL_DUMP | FOLL_GET) < 1) + return NULL; + flush_cache_page(vma, addr, page_to_pfn(page)); + return page; +} +#endif /* CONFIG_ELF_CORE */ + #if defined(CONFIG_FS_DAX) || defined (CONFIG_CMA) static bool check_dax_vmas(struct vm_area_struct **vmas, long nr_pages) { From patchwork Tue Aug 18 06:12:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 11720039 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1D645138C for ; Tue, 18 Aug 2020 06:12:57 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id D513E2075E for ; Tue, 18 Aug 2020 06:12:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="mJkEz75f" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D513E2075E Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id E59798D0003; Tue, 18 Aug 2020 02:12:55 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id E30778D0001; Tue, 18 Aug 2020 02:12:55 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D46498D0003; Tue, 18 Aug 2020 02:12:55 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0123.hostedemail.com [216.40.44.123]) by kanga.kvack.org (Postfix) with ESMTP id BEE5A8D0001 for ; Tue, 18 Aug 2020 02:12:55 -0400 (EDT) Received: from smtpin07.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 845988245571 for ; Tue, 18 Aug 2020 06:12:55 +0000 (UTC) X-FDA: 77162671110.07.blow79_1d0e52d2701d Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin07.hostedemail.com (Postfix) with ESMTP id 4EF821803F9A7 for ; Tue, 18 Aug 2020 06:12:55 +0000 (UTC) X-Spam-Summary: 1,0,0,35721025cc9e2728,d41d8cd98f00b204,3zxe7xwukcdybsffzyggydw.ugedafmp-eecnsuc.gjy@flex--jannh.bounces.google.com,,RULES_HIT:41:69:152:355:379:541:800:960:973:988:989:1260:1277:1313:1314:1345:1359:1437:1516:1518:1534:1541:1593:1594:1711:1730:1747:1777:1792:2393:2559:2562:3138:3139:3140:3141:3142:3152:3352:3865:3867:3868:3872:3874:4321:5007:6261:6653:7903:9969:10004:10400:11658:11914:12043:12296:12297:12555:12895:13069:13311:13357:14096:14097:14181:14394:14659:14721:21080:21444:21627:21990:30054,0,RBL:209.85.218.74:@flex--jannh.bounces.google.com:.lbl8.mailshell.net-62.18.0.100 66.100.201.100;04ygc8rjfbgjsqiuwgeqma17j9quhopmh9stjrzsgx6no5der1j4eaxgo3aoeom.wgjyyf9s81oicmxw3kn9basdjncwmu8fpwonkqsknjxejhfx8ox3xijqbbx891k.w-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:25,LUA_SUMMARY:none X-HE-Tag: blow79_1d0e52d2701d X-Filterd-Recvd-Size: 4003 Received: from mail-ej1-f74.google.com (mail-ej1-f74.google.com [209.85.218.74]) by imf48.hostedemail.com (Postfix) with ESMTP for ; Tue, 18 Aug 2020 06:12:54 +0000 (UTC) Received: by mail-ej1-f74.google.com with SMTP id e22so6386502ejx.18 for ; Mon, 17 Aug 2020 23:12:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=GSVoeZY4VtJncRCsBDOJV6iGFCXNH029JG2AgbxMzIw=; b=mJkEz75fkVHT8du8gdQBjaw6pE2ldFlA4jAPMSL2QbrZWXnfCVbN0C+c08ERHBXu6g C2fnjAZnH5RpJUIy5bISJjpd5WjqtYLOVKzqSpZEUfB9oMJdSN28QzPbF9Nlo8946/Fj oMh5GZo83yuAfd3Li5R2BToVuUri/UWMuEmqmPuoHlnAFltI6gltdTVRb4pk9SMR8r3s VxGDiC/Qdhttg9SXgox69qIlULfK8Md8HEGzpeXVfTvQr/JMHA9T5dT2KQ+7AwF2YMXd KtyAFJ/QUHW796NNlto8dQliaZ6uR4Jj68ysPjJBEx1Nd/tzEky2FMVHrzXQJZ+L4CxF tGAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=GSVoeZY4VtJncRCsBDOJV6iGFCXNH029JG2AgbxMzIw=; b=tUsHxWYAW2Buk97diN0R6oQsJfM9tTnrduC4RJGTkJrpu4qzppn/xMuZ5i7QP3VQsK o9iB3g2PrbTom6q8wnAawyeAXo+zlQmUR9zzZxWD+AhI3eTg4UHVx0HzwiE++8M2orG3 3mrphvdO9+MS5F9XOUkYwCzbJksQrNnpFQOXa12S5KWfjcUQpLFY5yYhUhXgdkBf4JnS TZx19bOH/RlwANcAI4LiAbFtMk/P2AhPgDN9+4cGDR125cK2gWHeymwuXkcDPbhmBu0s Tq8xozZetFkjyN9LUpADH4YLT1gz/CEHdPf4XN2kJf9eURR2WSP5JSL5LQtx7sPyJRVj 4Dew== X-Gm-Message-State: AOAM533RDUgOGTRTPJRETBirh9vyV1VyMaLmZx9yLmvEqwx/qvTZ1tv9 AQSqRpPtQj/Oi8ZLC/dQaqLqSxMXRw== X-Google-Smtp-Source: ABdhPJw8kbNtK89Z+bGnNpE12khmVpUyK5YNskcMYl1yh5qw2UP1aNNDhMVoCYncY9CyFubOVCb/FD841g== X-Received: by 2002:a50:d2c7:: with SMTP id q7mr17620488edg.61.1597731173685; Mon, 17 Aug 2020 23:12:53 -0700 (PDT) Date: Tue, 18 Aug 2020 08:12:36 +0200 In-Reply-To: <20200818061239.29091-1-jannh@google.com> Message-Id: <20200818061239.29091-3-jannh@google.com> Mime-Version: 1.0 References: <20200818061239.29091-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.220.ged08abb693-goog Subject: [PATCH v3 2/5] coredump: Let dump_emit() bail out on short writes From: Jann Horn To: Andrew Morton Cc: Linus Torvalds , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, Alexander Viro , "Eric W . Biederman" , Oleg Nesterov X-Rspamd-Queue-Id: 4EF821803F9A7 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam03 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: dump_emit() has a retry loop, but there seems to be no way for that retry logic to actually be used; and it was also buggy, writing the same data repeatedly after a short write. Let's just bail out on a short write. Suggested-by: Linus Torvalds Signed-off-by: Jann Horn --- fs/coredump.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/fs/coredump.c b/fs/coredump.c index 76e7c10edfc0..5e24c06092c9 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -840,17 +840,17 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr) ssize_t n; if (cprm->written + nr > cprm->limit) return 0; - while (nr) { - if (dump_interrupted()) - return 0; - n = __kernel_write(file, addr, nr, &pos); - if (n <= 0) - return 0; - file->f_pos = pos; - cprm->written += n; - cprm->pos += n; - nr -= n; - } + + + if (dump_interrupted()) + return 0; + n = __kernel_write(file, addr, nr, &pos); + if (n != nr) + return 0; + file->f_pos = pos; + cprm->written += n; + cprm->pos += n; + return 1; } EXPORT_SYMBOL(dump_emit); From patchwork Tue Aug 18 06:12:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 11720045 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 34A84739 for ; Tue, 18 Aug 2020 06:13:00 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 0264D2075B for ; Tue, 18 Aug 2020 06:13:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ScWCp387" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0264D2075B Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 0A1148D0005; Tue, 18 Aug 2020 02:12:59 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 027EC8D0001; Tue, 18 Aug 2020 02:12:58 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id E0C248D0005; Tue, 18 Aug 2020 02:12:58 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0135.hostedemail.com [216.40.44.135]) by kanga.kvack.org (Postfix) with ESMTP id CBE128D0001 for ; Tue, 18 Aug 2020 02:12:58 -0400 (EDT) Received: from smtpin08.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 94248362D for ; Tue, 18 Aug 2020 06:12:58 +0000 (UTC) X-FDA: 77162671236.08.eyes15_09011d22701d Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin08.hostedemail.com (Postfix) with ESMTP id 6945A1819E772 for ; Tue, 18 Aug 2020 06:12:58 +0000 (UTC) X-Spam-Summary: 1,0,0,8c0f2fcc02926f03,d41d8cd98f00b204,3axe7xwukcdofwjjdckkcha.ykihejqt-iigrwyg.knc@flex--jannh.bounces.google.com,,RULES_HIT:41:69:152:355:379:541:800:960:973:988:989:1260:1277:1313:1314:1345:1359:1437:1516:1518:1535:1544:1593:1594:1711:1730:1747:1777:1792:2393:2559:2562:2898:3138:3139:3140:3141:3142:3152:3354:3865:3866:3867:3868:3872:3874:4117:4321:4605:5007:6261:6653:7974:9592:9969:10004:11026:11473:11658:11914:12043:12291:12294:12296:12297:12438:12555:12683:12895:12986:14096:14097:14110:14181:14394:14659:14721:21080:21444:21627:21990:30003:30054:30070,0,RBL:209.85.160.201:@flex--jannh.bounces.google.com:.lbl8.mailshell.net-66.100.201.100 62.18.0.100;04y86df1bx84tugp1ao9c5gry6q5toc394ch9k9ts5ufg9zkbfmmf9aq39er6kc.bqzm16sqznfpncbbqayeeusx9eqrkanjz7bbnzxfabe1b9cuydeebhyia3thfcp.4-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:23,LUA_SUMMARY:no ne X-HE-Tag: eyes15_09011d22701d X-Filterd-Recvd-Size: 6914 Received: from mail-qt1-f201.google.com (mail-qt1-f201.google.com [209.85.160.201]) by imf19.hostedemail.com (Postfix) with ESMTP for ; Tue, 18 Aug 2020 06:12:57 +0000 (UTC) Received: by mail-qt1-f201.google.com with SMTP id g10so13711194qtr.19 for ; Mon, 17 Aug 2020 23:12:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=BQ6deNARx/tr049/coZN1ctnBsmm6qw6/g2K/OuqjPA=; b=ScWCp387mFONX1TRBXREQ33OJC79OiceR3AT7pe+fbYNruJ/cF79js7PVNcKdsqPDZ BTp7uhi1083v5EBt6Uppic6CT6DkZCElwoMRkhSSYggi6vKf9l4WpEIlB6RERBTJMNdM fZiO3/eIHW3UfOorwOBSFG5F2PsfxLoTtZ87LvIKmkzN27a8Xuwr7Y31057R2GF+aJHX 93E/1L9ITCo5UiEqejSGzxniroi3FHAYidFVlj72bQrHMtWuBkFNxUEW9YMRz2enbLSV G8/0r/4ylw5EbaG706fv6kMwkKApmrMMjh8P8HRffVbxfy0gyZcd1IpInr1gQGk7qJS5 vjoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=BQ6deNARx/tr049/coZN1ctnBsmm6qw6/g2K/OuqjPA=; b=efmHU92ns6jPtUqONQ/gg4MwfE0JamLB2rW3sbRiHGzxg54oGqGcsyc0HFBfZGF/lW npNX21F2vWf2dFgN133JfcA5wDzWTyX6aMPhT0Awq3PVJiwjIGIdpZELxiN3ZtR5LAKI LV8Xhr17jrQ6iu2D/VLUzQvSRY0Dt+5FWxkyX+EmOH1L+VQM+Qtl1MgSNHoLCVIIB33u 0EG6XMYcFUWVU4hXM9f6dIZn10UtttvuybdFCOzJyYr+vNccOuPGBZDh4NaaTQkAlJUD fVoa58Ftzphru6mS/zcdrY2dBH2RL7CBTEWOjuQgOpHz364v1aOGM1iho52Jb+s6EXr/ 8Pkw== X-Gm-Message-State: AOAM530POsWRJJEeDlrkz2PJuIPyO5CiOobSR8R9thMshJ0K0YiI3179 HyfosEv4NDyeMMlRTuCckeF10nad2Q== X-Google-Smtp-Source: ABdhPJyh/6VtzjvXkSvgr3+1RQjgt+P+1s2URdDDGUndrNNa2/EOYOf/bFUg8TykIbv7qlhxxhrVQHJBzA== X-Received: by 2002:ad4:4c0a:: with SMTP id bz10mr17004710qvb.78.1597731177252; Mon, 17 Aug 2020 23:12:57 -0700 (PDT) Date: Tue, 18 Aug 2020 08:12:37 +0200 In-Reply-To: <20200818061239.29091-1-jannh@google.com> Message-Id: <20200818061239.29091-4-jannh@google.com> Mime-Version: 1.0 References: <20200818061239.29091-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.220.ged08abb693-goog Subject: [PATCH v3 3/5] coredump: Refactor page range dumping into common helper From: Jann Horn To: Andrew Morton Cc: Linus Torvalds , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, Alexander Viro , "Eric W . Biederman" , Oleg Nesterov X-Rspamd-Queue-Id: 6945A1819E772 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam02 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Both fs/binfmt_elf.c and fs/binfmt_elf_fdpic.c need to dump ranges of pages into the coredump file. Extract that logic into a common helper. Signed-off-by: Jann Horn --- fs/binfmt_elf.c | 22 ++-------------------- fs/binfmt_elf_fdpic.c | 18 +++--------------- fs/coredump.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/coredump.h | 2 ++ 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 13d053982dd7..5fd11a25d320 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -2419,26 +2419,8 @@ static int elf_core_dump(struct coredump_params *cprm) for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; vma = next_vma(vma, gate_vma)) { - unsigned long addr; - unsigned long end; - - end = vma->vm_start + vma_filesz[i++]; - - for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { - struct page *page; - int stop; - - page = get_dump_page(addr); - if (page) { - void *kaddr = kmap(page); - stop = !dump_emit(cprm, kaddr, PAGE_SIZE); - kunmap(page); - put_page(page); - } else - stop = !dump_skip(cprm, PAGE_SIZE); - if (stop) - goto end_coredump; - } + if (!dump_user_range(cprm, vma->vm_start, vma_filesz[i++])) + goto end_coredump; } dump_truncate(cprm); diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index a53f83830986..76e8c0defdc8 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1534,21 +1534,9 @@ static bool elf_fdpic_dump_segments(struct coredump_params *cprm) if (!maydump(vma, cprm->mm_flags)) continue; - for (addr = vma->vm_start; addr < vma->vm_end; - addr += PAGE_SIZE) { - bool res; - struct page *page = get_dump_page(addr); - if (page) { - void *kaddr = kmap(page); - res = dump_emit(cprm, kaddr, PAGE_SIZE); - kunmap(page); - put_page(page); - } else { - res = dump_skip(cprm, PAGE_SIZE); - } - if (!res) - return false; - } + if (!dump_user_range(cprm, vma->vm_start, + vma->vma_end - vma->vm_start)) + return false; } return true; } diff --git a/fs/coredump.c b/fs/coredump.c index 5e24c06092c9..6042d15acd51 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -876,6 +876,40 @@ int dump_skip(struct coredump_params *cprm, size_t nr) } EXPORT_SYMBOL(dump_skip); +#ifdef CONFIG_ELF_CORE +int dump_user_range(struct coredump_params *cprm, unsigned long start, + unsigned long len) +{ + unsigned long addr; + + for (addr = start; addr < start + len; addr += PAGE_SIZE) { + struct page *page; + int stop; + + /* + * To avoid having to allocate page tables for virtual address + * ranges that have never been used yet, and also to make it + * easy to generate sparse core files, use a helper that returns + * NULL when encountering an empty page table entry that would + * otherwise have been filled with the zero page. + */ + page = get_dump_page(addr); + if (page) { + void *kaddr = kmap(page); + + stop = !dump_emit(cprm, kaddr, PAGE_SIZE); + kunmap(page); + put_page(page); + } else { + stop = !dump_skip(cprm, PAGE_SIZE); + } + if (stop) + return 0; + } + return 1; +} +#endif + int dump_align(struct coredump_params *cprm, int align) { unsigned mod = cprm->pos & (align - 1); diff --git a/include/linux/coredump.h b/include/linux/coredump.h index 7a899e83835d..f0b71a74d0bc 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -16,6 +16,8 @@ extern int dump_skip(struct coredump_params *cprm, size_t nr); extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); extern int dump_align(struct coredump_params *cprm, int align); extern void dump_truncate(struct coredump_params *cprm); +int dump_user_range(struct coredump_params *cprm, unsigned long start, + unsigned long len); #ifdef CONFIG_COREDUMP extern void do_coredump(const kernel_siginfo_t *siginfo); #else From patchwork Tue Aug 18 06:12:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 11720047 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0AA88138C for ; Tue, 18 Aug 2020 06:13:05 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id A4F572075B for ; Tue, 18 Aug 2020 06:13:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ol15Y1gP" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A4F572075B Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id BE73C8D0006; Tue, 18 Aug 2020 02:13:03 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id B9C8C8D0001; Tue, 18 Aug 2020 02:13:03 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id AB1358D0006; Tue, 18 Aug 2020 02:13:03 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0253.hostedemail.com [216.40.44.253]) by kanga.kvack.org (Postfix) with ESMTP id 923498D0001 for ; Tue, 18 Aug 2020 02:13:03 -0400 (EDT) Received: from smtpin29.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay02.hostedemail.com (Postfix) with ESMTP id 54854362D for ; Tue, 18 Aug 2020 06:13:03 +0000 (UTC) X-FDA: 77162671446.29.match14_040dceb2701d Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin29.hostedemail.com (Postfix) with ESMTP id 2A0D618086CC2 for ; Tue, 18 Aug 2020 06:13:03 +0000 (UTC) X-Spam-Summary: 1,0,0,bcb8f7dfead98b88,d41d8cd98f00b204,3bxe7xwukcd4ofssmlttlqj.htrqnsz2-rrp0fhp.twl@flex--jannh.bounces.google.com,,RULES_HIT:41:69:152:327:355:379:541:800:960:966:973:988:989:1260:1277:1313:1314:1345:1359:1431:1437:1516:1518:1593:1594:1605:1730:1747:1777:1792:2196:2198:2199:2200:2393:2553:2559:2562:2693:2892:2898:3138:3139:3140:3141:3142:3152:3865:3866:3867:3868:3870:3871:3872:3873:3874:4250:4321:4385:4605:5007:6119:6261:6653:7875:7903:7974:8603:9010:9012:9592:9969:10004:10226:10954:11026:11232:11473:11658:11914:12043:12294:12296:12297:12438:12555:12663:12683:12895:12986:13149:13230:13869:13972:14096:14097:14394:14659:21080:21220:21222:21324:21325:21433:21444:21450:21451:21627:21740:21939:21983:21987:21990:30005:30012:30034:30045:30051:30054:30070:30075:30090,0,RBL:209.85.208.74:@flex--jannh.bounces.google.com:.lbl8.mailshell.net-62.18.84.100 66.100.201.100;04yrrqx1yhtz5185zc1p7e7hsmfhjocdspsi5kk8b7ki6qasigo9eif1xgjxcqt.ia75kj35eahdoxw3pj4p8izcboihm3f9u41nim 9xgwzcur X-HE-Tag: match14_040dceb2701d X-Filterd-Recvd-Size: 22680 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.74]) by imf35.hostedemail.com (Postfix) with ESMTP for ; Tue, 18 Aug 2020 06:13:02 +0000 (UTC) Received: by mail-ed1-f74.google.com with SMTP id b11so7367442edy.17 for ; Mon, 17 Aug 2020 23:13:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=pYiZwcWeMz44ELBzcaK4rfrQj2l/TC9LD4qXY23V9zc=; b=ol15Y1gPEu6jshFw3dZcjIcrA/HgDsJlPZ3ryMcXexY7BWS86JStwF9tWm+dCA33of 6OciP+QOqijS3HC7puY0JE4fvfK1Cb6LzBh/JN8W5stoHHjLl/uELMzx7EUD/qN0PR/k xNVWwrZ1CXUnl0acWTYLaW9ehc2jB5kKQ+df0uQBu0EDu1JTe6VE56v0s7LyjF3EAoPv FnbC/NWuXWtx/VMBlrPBLkFqAFdOGfYichRJD5BdFTIgO1keE73rQTZBCkbhFKbWUo9z XKttviCO6j/KDVHPs7YK6fbPyRRt8cHBiGZfTEFKptqcDRHnu7J23ufv6VCZUyIXQbaH 4rKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=pYiZwcWeMz44ELBzcaK4rfrQj2l/TC9LD4qXY23V9zc=; b=bfrnr+WLar2eVZM8NxigiB1+n9d6uegtf/qTbljS6GrvOqZzLk3TmTpXHD5StddCCt o6LixM0ZCuW706Yf1nrkanAOiZcUMrOKGGehAKHZ/HM/pAPfW0SXfJOA6+ChbJiQvS68 vbbjmXqfm7RwYE+/8ToLvhD0jr42KBpFNCCR9/IPZFFuTerYCatoxqW51h+Qwuwr3l1R q4b29aNqbx/o3lxEWBSL98mV/U/U8T8wwL+Oq4dtklTWMiwKsQKJkzGJ/Bdis8R6nwMW Ro/037aZ5X9gnCdoDo2jCX2GroYpqgFYadvHF4P4CdlBvuLnF/vbuY6zAl3Hf8v8+j3L ljNA== X-Gm-Message-State: AOAM530P81mCxrPvELI904Ue9tBzz/sN8oguIVgASMGRXqhjDkZYWEWl 9vENCcjV1NeCwaQONFaa1PK0p4VePA== X-Google-Smtp-Source: ABdhPJwDEQp/gLR2K5vFDVNObgVui1XL8Z3wzGkzBYOIT7RNngti4bpH1ilcjWqRp61Uu9I83ncjTFQ0iA== X-Received: by 2002:a05:6402:1c88:: with SMTP id cy8mr18905326edb.24.1597731181085; Mon, 17 Aug 2020 23:13:01 -0700 (PDT) Date: Tue, 18 Aug 2020 08:12:38 +0200 In-Reply-To: <20200818061239.29091-1-jannh@google.com> Message-Id: <20200818061239.29091-5-jannh@google.com> Mime-Version: 1.0 References: <20200818061239.29091-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.220.ged08abb693-goog Subject: [PATCH v3 4/5] binfmt_elf, binfmt_elf_fdpic: Use a VMA list snapshot From: Jann Horn To: Andrew Morton Cc: Linus Torvalds , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, Alexander Viro , "Eric W . Biederman" , Oleg Nesterov X-Rspamd-Queue-Id: 2A0D618086CC2 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam01 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: In both binfmt_elf and binfmt_elf_fdpic, use a new helper dump_vma_snapshot() to take a snapshot of the VMA list (including the gate VMA, if we have one) while protected by the mmap_lock, and then use that snapshot instead of walking the VMA list without locking. An alternative approach would be to keep the mmap_lock held across the entire core dumping operation; however, keeping the mmap_lock locked while we may be blocked for an unbounded amount of time (e.g. because we're dumping to a FUSE filesystem or so) isn't really optimal; the mmap_lock blocks things like the ->release handler of userfaultfd, and we don't really want critical system daemons to grind to a halt just because someone "gifted" them SCM_RIGHTS to an eternally-locked userfaultfd, or something like that. Since both the normal ELF code and the FDPIC ELF code need this functionality (and if any other binfmt wants to add coredump support in the future, they'd probably need it, too), implement this with a common helper in fs/coredump.c. A downside of this approach is that we now need a bigger amount of kernel memory per userspace VMA in the normal ELF case, and that we need O(n) kernel memory in the FDPIC ELF case at all; but 40 bytes per VMA shouldn't be terribly bad. Signed-off-by: Jann Horn --- fs/binfmt_elf.c | 166 ++++++++++++++++----------------------- fs/binfmt_elf_fdpic.c | 86 ++++++++++---------- fs/coredump.c | 69 ++++++++++++++++ include/linux/coredump.h | 9 +++ 4 files changed, 186 insertions(+), 144 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 5fd11a25d320..519c38dc9097 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1420,8 +1420,12 @@ static bool always_dump_vma(struct vm_area_struct *vma) return false; } +#define DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER 1 + /* * Decide what to dump of a segment, part, all or none. + * The result must be fixed up via vma_dump_size_fixup() once we're in a context + * that doesn't hold mmap_lock. */ static unsigned long vma_dump_size(struct vm_area_struct *vma, unsigned long mm_flags) @@ -1476,30 +1480,15 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, /* * If this looks like the beginning of a DSO or executable mapping, - * check for an ELF header. If we find one, dump the first page to - * aid in determining what was mapped here. + * we'll check for an ELF header. If we find one, we'll dump the first + * page to aid in determining what was mapped here. + * However, we shouldn't sleep on userspace reads while holding the + * mmap_lock, so we just return a placeholder for now that will be fixed + * up later in vma_dump_size_fixup(). */ if (FILTER(ELF_HEADERS) && - vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) { - u32 __user *header = (u32 __user *) vma->vm_start; - u32 word; - /* - * Doing it this way gets the constant folded by GCC. - */ - union { - u32 cmp; - char elfmag[SELFMAG]; - } magic; - BUILD_BUG_ON(SELFMAG != sizeof word); - magic.elfmag[EI_MAG0] = ELFMAG0; - magic.elfmag[EI_MAG1] = ELFMAG1; - magic.elfmag[EI_MAG2] = ELFMAG2; - magic.elfmag[EI_MAG3] = ELFMAG3; - if (unlikely(get_user(word, header))) - word = 0; - if (word == magic.cmp) - return PAGE_SIZE; - } + vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) + return DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER; #undef FILTER @@ -1509,6 +1498,22 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, return vma->vm_end - vma->vm_start; } +/* + * Fix up vma_dump_size()'s result based on whether this VMA has an ELF header. + * The caller must *not* hold mmap_lock. + * See vma_dump_size() for context. + */ +static void vma_dump_size_fixup(struct core_vma_metadata *meta) +{ + char elfmag[SELFMAG]; + + if (copy_from_user(elfmag, (void __user *)meta->start, SELFMAG) || + memcmp(elfmag, ELFMAG, SELFMAG) != 0) + meta->dump_size = 0; + else + meta->dump_size = PAGE_SIZE; +} + /* An ELF note in memory */ struct memelfnote { @@ -2220,32 +2225,6 @@ static void free_note_info(struct elf_note_info *info) #endif -static struct vm_area_struct *first_vma(struct task_struct *tsk, - struct vm_area_struct *gate_vma) -{ - struct vm_area_struct *ret = tsk->mm->mmap; - - if (ret) - return ret; - return gate_vma; -} -/* - * Helper function for iterating across a vma list. It ensures that the caller - * will visit `gate_vma' prior to terminating the search. - */ -static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma, - struct vm_area_struct *gate_vma) -{ - struct vm_area_struct *ret; - - ret = this_vma->vm_next; - if (ret) - return ret; - if (this_vma == gate_vma) - return NULL; - return gate_vma; -} - static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, elf_addr_t e_shoff, int segs) { @@ -2272,9 +2251,8 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, static int elf_core_dump(struct coredump_params *cprm) { int has_dumped = 0; - int segs, i; + int vma_count, segs, i; size_t vma_data_size = 0; - struct vm_area_struct *vma, *gate_vma; struct elfhdr elf; loff_t offset = 0, dataoff; struct elf_note_info info = { }; @@ -2282,30 +2260,35 @@ static int elf_core_dump(struct coredump_params *cprm) struct elf_shdr *shdr4extnum = NULL; Elf_Half e_phnum; elf_addr_t e_shoff; - elf_addr_t *vma_filesz = NULL; + struct core_vma_metadata *vma_meta; + + if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, vma_dump_size)) + return 0; + + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; + + if (meta->dump_size == DUMP_SIZE_MAYBE_ELFHDR_PLACEHOLDER) { + /* + * We want to select ->dump_size based on whether the + * VMA starts with an ELF header, but that uses + * copy_from_user(), which doesn't work from the + * dump_vma_snapshot() callback because the mmap_lock + * is held there. + * So instead, fix it up here, where we're not holding + * any locks. + */ + vma_dump_size_fixup(meta); + } + + vma_data_size += meta->dump_size; + } - /* - * We no longer stop all VM operations. - * - * This is because those proceses that could possibly change map_count - * or the mmap / vma pages are now blocked in do_exit on current - * finishing this core dump. - * - * Only ptrace can touch these memory addresses, but it doesn't change - * the map_count or the pages allocated. So no possibility of crashing - * exists while dumping the mm->vm_next areas to the core file. - */ - /* * The number of segs are recored into ELF header as 16bit value. * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. */ - segs = current->mm->map_count; - segs += elf_core_extra_phdrs(); - - gate_vma = get_gate_vma(current->mm); - if (gate_vma != NULL) - segs++; + segs = vma_count + elf_core_extra_phdrs(); /* for notes section */ segs++; @@ -2343,24 +2326,6 @@ static int elf_core_dump(struct coredump_params *cprm) dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); - /* - * Zero vma process will get ZERO_SIZE_PTR here. - * Let coredump continue for register state at least. - */ - vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)), - GFP_KERNEL); - if (!vma_filesz) - goto end_coredump; - - for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; - vma = next_vma(vma, gate_vma)) { - unsigned long dump_size; - - dump_size = vma_dump_size(vma, cprm->mm_flags); - vma_filesz[i++] = dump_size; - vma_data_size += dump_size; - } - offset += vma_data_size; offset += elf_core_extra_data_size(); e_shoff = offset; @@ -2381,21 +2346,23 @@ static int elf_core_dump(struct coredump_params *cprm) goto end_coredump; /* Write program headers for segments dump */ - for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; - vma = next_vma(vma, gate_vma)) { + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; struct elf_phdr phdr; phdr.p_type = PT_LOAD; phdr.p_offset = offset; - phdr.p_vaddr = vma->vm_start; + phdr.p_vaddr = meta->start; phdr.p_paddr = 0; - phdr.p_filesz = vma_filesz[i++]; - phdr.p_memsz = vma->vm_end - vma->vm_start; + phdr.p_filesz = meta->dump_size; + phdr.p_memsz = meta->end - meta->start; offset += phdr.p_filesz; - phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; - if (vma->vm_flags & VM_WRITE) + phdr.p_flags = 0; + if (meta->flags & VM_READ) + phdr.p_flags |= PF_R; + if (meta->flags & VM_WRITE) phdr.p_flags |= PF_W; - if (vma->vm_flags & VM_EXEC) + if (meta->flags & VM_EXEC) phdr.p_flags |= PF_X; phdr.p_align = ELF_EXEC_PAGESIZE; @@ -2417,9 +2384,10 @@ static int elf_core_dump(struct coredump_params *cprm) if (!dump_skip(cprm, dataoff - cprm->pos)) goto end_coredump; - for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; - vma = next_vma(vma, gate_vma)) { - if (!dump_user_range(cprm, vma->vm_start, vma_filesz[i++])) + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; + + if (!dump_user_range(cprm, meta->start, meta->dump_size)) goto end_coredump; } dump_truncate(cprm); @@ -2435,7 +2403,7 @@ static int elf_core_dump(struct coredump_params *cprm) end_coredump: free_note_info(&info); kfree(shdr4extnum); - kvfree(vma_filesz); + kvfree(vma_meta); kfree(phdr4note); return has_dumped; } diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 76e8c0defdc8..f9d35bc9f0af 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -1222,7 +1222,8 @@ struct elf_prstatus_fdpic * * I think we should skip something. But I am not sure how. H.J. */ -static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) +static unsigned long vma_dump_size(struct vm_area_struct *vma, + unsigned long mm_flags) { int dump_ok; @@ -1251,7 +1252,7 @@ static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) kdcore("%08lx: %08lx: %s (DAX private)", vma->vm_start, vma->vm_flags, dump_ok ? "yes" : "no"); } - return dump_ok; + goto out; } /* By default, dump shared memory if mapped from an anonymous file. */ @@ -1260,13 +1261,13 @@ static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) dump_ok = test_bit(MMF_DUMP_ANON_SHARED, &mm_flags); kdcore("%08lx: %08lx: %s (share)", vma->vm_start, vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; + goto out; } dump_ok = test_bit(MMF_DUMP_MAPPED_SHARED, &mm_flags); kdcore("%08lx: %08lx: %s (share)", vma->vm_start, vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; + goto out; } #ifdef CONFIG_MMU @@ -1275,14 +1276,16 @@ static int maydump(struct vm_area_struct *vma, unsigned long mm_flags) dump_ok = test_bit(MMF_DUMP_MAPPED_PRIVATE, &mm_flags); kdcore("%08lx: %08lx: %s (!anon)", vma->vm_start, vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; + goto out; } #endif dump_ok = test_bit(MMF_DUMP_ANON_PRIVATE, &mm_flags); kdcore("%08lx: %08lx: %s", vma->vm_start, vma->vm_flags, dump_ok ? "yes" : "no"); - return dump_ok; + +out: + return dump_ok ? vma->vm_end - vma->vm_start : 0; } /* An ELF note in memory */ @@ -1524,31 +1527,30 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, /* * dump the segments for an MMU process */ -static bool elf_fdpic_dump_segments(struct coredump_params *cprm) +static bool elf_fdpic_dump_segments(struct coredump_params *cprm, + struct core_vma_metadata *vma_meta, + int vma_count) { - struct vm_area_struct *vma; + int i; - for (vma = current->mm->mmap; vma; vma = vma->vm_next) { - unsigned long addr; + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; - if (!maydump(vma, cprm->mm_flags)) - continue; - - if (!dump_user_range(cprm, vma->vm_start, - vma->vma_end - vma->vm_start)) + if (!dump_user_range(cprm, meta->start, meta->dump_size)) return false; } return true; } -static size_t elf_core_vma_data_size(unsigned long mm_flags) +static size_t elf_core_vma_data_size(unsigned long mm_flags, + struct core_vma_metadata *vma_meta, + int vma_count) { - struct vm_area_struct *vma; size_t size = 0; + int i; - for (vma = current->mm->mmap; vma; vma = vma->vm_next) - if (maydump(vma, mm_flags)) - size += vma->vm_end - vma->vm_start; + for (i = 0; i < vma_count; i++) + size += vma_meta[i].dump_size; return size; } @@ -1562,9 +1564,8 @@ static size_t elf_core_vma_data_size(unsigned long mm_flags) static int elf_fdpic_core_dump(struct coredump_params *cprm) { int has_dumped = 0; - int segs; + int vma_count, segs; int i; - struct vm_area_struct *vma; struct elfhdr *elf = NULL; loff_t offset = 0, dataoff; struct memelfnote psinfo_note, auxv_note; @@ -1578,18 +1579,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) elf_addr_t e_shoff; struct core_thread *ct; struct elf_thread_status *tmp; - - /* - * We no longer stop all VM operations. - * - * This is because those proceses that could possibly change map_count - * or the mmap / vma pages are now blocked in do_exit on current - * finishing this core dump. - * - * Only ptrace can touch these memory addresses, but it doesn't change - * the map_count or the pages allocated. So no possibility of crashing - * exists while dumping the mm->vm_next areas to the core file. - */ + struct core_vma_metadata *vma_meta = NULL; /* alloc memory for large data structures: too large to be on stack */ elf = kmalloc(sizeof(*elf), GFP_KERNEL); @@ -1599,6 +1589,9 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) if (!psinfo) goto end_coredump; + if (dump_vma_snapshot(cprm, &vma_count, &vma_meta, vma_dump_size)) + goto end_coredump; + for (ct = current->mm->core_state->dumper.next; ct; ct = ct->next) { tmp = elf_dump_thread_status(cprm->siginfo->si_signo, @@ -1618,8 +1611,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) tmp->next = thread_list; thread_list = tmp; - segs = current->mm->map_count; - segs += elf_core_extra_phdrs(); + segs = vma_count + elf_core_extra_phdrs(); /* for notes section */ segs++; @@ -1664,7 +1656,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) /* Page-align dumped data */ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); - offset += elf_core_vma_data_size(cprm->mm_flags); + offset += elf_core_vma_data_size(cprm->mm_flags, vma_meta, vma_count); offset += elf_core_extra_data_size(); e_shoff = offset; @@ -1684,23 +1676,26 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) goto end_coredump; /* write program headers for segments dump */ - for (vma = current->mm->mmap; vma; vma = vma->vm_next) { + for (i = 0; i < vma_count; i++) { + struct core_vma_metadata *meta = vma_meta + i; struct elf_phdr phdr; size_t sz; - sz = vma->vm_end - vma->vm_start; + sz = meta->end - meta->start; phdr.p_type = PT_LOAD; phdr.p_offset = offset; - phdr.p_vaddr = vma->vm_start; + phdr.p_vaddr = meta->start; phdr.p_paddr = 0; - phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0; + phdr.p_filesz = meta->dump_size; phdr.p_memsz = sz; offset += phdr.p_filesz; - phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; - if (vma->vm_flags & VM_WRITE) + phdr.p_flags = 0; + if (meta->flags & VM_READ) + phdr.p_flags |= PF_R; + if (meta->flags & VM_WRITE) phdr.p_flags |= PF_W; - if (vma->vm_flags & VM_EXEC) + if (meta->flags & VM_EXEC) phdr.p_flags |= PF_X; phdr.p_align = ELF_EXEC_PAGESIZE; @@ -1732,7 +1727,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) if (!dump_skip(cprm, dataoff - cprm->pos)) goto end_coredump; - if (!elf_fdpic_dump_segments(cprm)) + if (!elf_fdpic_dump_segments(cprm, vma_meta, vma_count)) goto end_coredump; if (!elf_core_write_extra_data(cprm)) @@ -1756,6 +1751,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) thread_list = thread_list->next; kfree(tmp); } + kvfree(vma_meta); kfree(phdr4note); kfree(elf); kfree(psinfo); diff --git a/fs/coredump.c b/fs/coredump.c index 6042d15acd51..7b4486b701bb 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -936,3 +936,72 @@ void dump_truncate(struct coredump_params *cprm) } } EXPORT_SYMBOL(dump_truncate); + +static struct vm_area_struct *first_vma(struct task_struct *tsk, + struct vm_area_struct *gate_vma) +{ + struct vm_area_struct *ret = tsk->mm->mmap; + + if (ret) + return ret; + return gate_vma; +} + +/* + * Helper function for iterating across a vma list. It ensures that the caller + * will visit `gate_vma' prior to terminating the search. + */ +static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma, + struct vm_area_struct *gate_vma) +{ + struct vm_area_struct *ret; + + ret = this_vma->vm_next; + if (ret) + return ret; + if (this_vma == gate_vma) + return NULL; + return gate_vma; +} + +/* + * Under the mmap_lock, take a snapshot of relevant information about the task's + * VMAs. + */ +int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count, + struct core_vma_metadata **vma_meta, + unsigned long (*dump_size_cb)(struct vm_area_struct *, unsigned long)) +{ + struct vm_area_struct *vma, *gate_vma; + struct mm_struct *mm = current->mm; + int i; + + if (mmap_read_lock_killable(mm)) + return -EINTR; + + gate_vma = get_gate_vma(mm); + *vma_count = mm->map_count + (gate_vma ? 1 : 0); + + *vma_meta = kvmalloc_array(*vma_count, sizeof(**vma_meta), GFP_KERNEL); + if (!*vma_meta) { + mmap_read_unlock(mm); + return -ENOMEM; + } + + for (i = 0, vma = first_vma(current, gate_vma); vma != NULL; + vma = next_vma(vma, gate_vma), i++) { + struct core_vma_metadata *m = (*vma_meta) + i; + + m->start = vma->vm_start; + m->end = vma->vm_end; + m->flags = vma->vm_flags; + m->dump_size = dump_size_cb(vma, cprm->mm_flags); + } + + mmap_read_unlock(mm); + + if (WARN_ON(i != *vma_count)) + return -EFAULT; + + return 0; +} diff --git a/include/linux/coredump.h b/include/linux/coredump.h index f0b71a74d0bc..21bbef9bd8d6 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -7,6 +7,12 @@ #include #include +struct core_vma_metadata { + unsigned long start, end; + unsigned long flags; + unsigned long dump_size; +}; + /* * These are the only things you should do on a core-file: use only these * functions to write out all the necessary info. @@ -18,6 +24,9 @@ extern int dump_align(struct coredump_params *cprm, int align); extern void dump_truncate(struct coredump_params *cprm); int dump_user_range(struct coredump_params *cprm, unsigned long start, unsigned long len); +int dump_vma_snapshot(struct coredump_params *cprm, int *vma_count, + struct core_vma_metadata **vma_meta, + unsigned long (*dump_size_cb)(struct vm_area_struct *, unsigned long)); #ifdef CONFIG_COREDUMP extern void do_coredump(const kernel_siginfo_t *siginfo); #else From patchwork Tue Aug 18 06:12:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jann Horn X-Patchwork-Id: 11720049 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CF751739 for ; Tue, 18 Aug 2020 06:13:07 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 9DB482075B for ; Tue, 18 Aug 2020 06:13:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ZwNZMdOm" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9DB482075B Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 8192E8D0007; Tue, 18 Aug 2020 02:13:06 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 7A0718D0001; Tue, 18 Aug 2020 02:13:06 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6DCA78D0007; Tue, 18 Aug 2020 02:13:06 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0164.hostedemail.com [216.40.44.164]) by kanga.kvack.org (Postfix) with ESMTP id 580448D0001 for ; Tue, 18 Aug 2020 02:13:06 -0400 (EDT) Received: from smtpin17.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay05.hostedemail.com (Postfix) with ESMTP id 1F9E6181AEF1F for ; Tue, 18 Aug 2020 06:13:06 +0000 (UTC) X-FDA: 77162671572.17.wood06_350af932701d Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin17.hostedemail.com (Postfix) with ESMTP id E7654180D0181 for ; Tue, 18 Aug 2020 06:13:05 +0000 (UTC) X-Spam-Summary: 1,0,0,94ec74275918221c,d41d8cd98f00b204,3che7xwukceemdqqkjrrjoh.frpolqx0-ppnydfn.ruj@flex--jannh.bounces.google.com,,RULES_HIT:41:152:355:379:541:800:960:973:981:988:989:1260:1277:1313:1314:1345:1359:1437:1516:1518:1534:1541:1593:1594:1711:1730:1747:1777:1792:2393:2559:2562:2693:3138:3139:3140:3141:3142:3152:3353:3865:3867:3868:3870:3872:4250:4321:4605:5007:6261:6653:7903:9969:10004:10400:11026:11233:11473:11658:11914:12043:12296:12297:12438:12555:12895:13069:13311:13357:14096:14097:14181:14394:14659:14721:21080:21444:21627:21987:21990:30012:30054:30070,0,RBL:209.85.219.73:@flex--jannh.bounces.google.com:.lbl8.mailshell.net-66.100.201.100 62.18.0.100;04ygwysronab191uoywh8w6jxaopyyctzfmuur85an99ewp6frqgw8ojhxtwgig.qmo1sck9z4jb7ktm9z978knmg4xsh1sah4tmskjet5kc1obe58u6nw7i7ygcgap.c-lbl8.mailshell.net-223.238.255.100,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: wood06_350af932701d X-Filterd-Recvd-Size: 4445 Received: from mail-qv1-f73.google.com (mail-qv1-f73.google.com [209.85.219.73]) by imf26.hostedemail.com (Postfix) with ESMTP for ; Tue, 18 Aug 2020 06:13:05 +0000 (UTC) Received: by mail-qv1-f73.google.com with SMTP id d19so12516499qvm.23 for ; Mon, 17 Aug 2020 23:13:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=uEsosFURBjONd+/+zLGkVplNTPfQUMPsbnxJn8l+5vc=; b=ZwNZMdOmDrLPGKWoU7+xUPQWuT5oFIHuub4ejn1ekJsju5Wwy4BLyJBNVFY7s7BOld z3j7VbHfP0i4lVA1JENTx0vcSL03Ivy7dRS9ixIgK6o9EnEGMJMVSN27CQhbCwLUUGja g2kOE4ob+pHuuCV3lxWoW781kDluCgRGWDnAPhZxeaR/O94K6cNgRXgdK/AQ0tq08LM/ HTnNGkc2Hr1LW06qlLL1igs/cd0cIwr/k5am8Yq+ZUlq2W/bZqQPuN/yvos43bmZzKui vGmfTNebqL+H4H3PJeXssHpUinSJ181aWS1QvdMT+BzOZLkJTgY+MgaAplPmApsiySYe alww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=uEsosFURBjONd+/+zLGkVplNTPfQUMPsbnxJn8l+5vc=; b=aLgOtmMiODzyy19jcdF3QWjVqhoJpdgCLO8OHOOW6fnRb/NC44hKVIHVGlxAHX59Gg CFmdy1DlScz1U+gjV0/AxSs0HHROXo3wP0Ei/YGKn6VA8s+r18gLAG1hpz+LT2Qx34a7 fY+3cOcBzzykbWUEwgzKSbTYtxtRsB7kWZkkS1loxgn8kw2WZg9/M+dQAdiVh1tl1oCM n2IlGyzqYoeXqMYFjl1lJgCQo/DHQphj/ChOJsVwp63jyR+kw/ZqN2TbAP7CSrsfCu3t iAmb5V9Vozsxx652B//ZtC4nnbftPkJnqOX3qsV99Y3Zke6XdYOc6MOC7Q9RCzQS9Q3d w8jg== X-Gm-Message-State: AOAM533GULE3VIFKORu10AcVqPl9KUxkQ6c/PTJ/WTlowOk1/sOYxVmE a+q8Ag0fGcDoKj8yPhF9YEQihtaM+Q== X-Google-Smtp-Source: ABdhPJxP3VNaCKztfKGOZRUkeGpGigQsg+G3JDfTvOzuksmwqiQeamW72iYG3Jd8rw3YImyyUmlMeGtIjQ== X-Received: by 2002:ad4:40cb:: with SMTP id x11mr18084057qvp.176.1597731184753; Mon, 17 Aug 2020 23:13:04 -0700 (PDT) Date: Tue, 18 Aug 2020 08:12:39 +0200 In-Reply-To: <20200818061239.29091-1-jannh@google.com> Message-Id: <20200818061239.29091-6-jannh@google.com> Mime-Version: 1.0 References: <20200818061239.29091-1-jannh@google.com> X-Mailer: git-send-email 2.28.0.220.ged08abb693-goog Subject: [PATCH v3 5/5] mm/gup: Take mmap_lock in get_dump_page() From: Jann Horn To: Andrew Morton Cc: Linus Torvalds , Christoph Hellwig , linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, Alexander Viro , "Eric W . Biederman" , Oleg Nesterov X-Rspamd-Queue-Id: E7654180D0181 X-Spamd-Result: default: False [0.00 / 100.00] X-Rspamd-Server: rspam03 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000003, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Properly take the mmap_lock before calling into the GUP code from get_dump_page(); and play nice, allowing the GUP code to drop the mmap_lock if it has to sleep. As Linus pointed out, we don't actually need the VMA because __get_user_pages() will flush the dcache for us if necessary. Signed-off-by: Jann Horn --- mm/gup.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/mm/gup.c b/mm/gup.c index 92519e5a44b3..bd0f7311c5c6 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1552,19 +1552,23 @@ static long __get_user_pages_locked(struct mm_struct *mm, unsigned long start, * NULL wherever the ZERO_PAGE, or an anonymous pte_none, has been found - * allowing a hole to be left in the corefile to save diskspace. * - * Called without mmap_lock, but after all other threads have been killed. + * Called without mmap_lock (takes and releases the mmap_lock by itself). */ #ifdef CONFIG_ELF_CORE struct page *get_dump_page(unsigned long addr) { - struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; struct page *page; + int locked = 1; + int ret; - if (__get_user_pages_locked(current->mm, addr, 1, &page, &vma, NULL, - FOLL_FORCE | FOLL_DUMP | FOLL_GET) < 1) + if (mmap_read_lock_killable(mm)) return NULL; - flush_cache_page(vma, addr, page_to_pfn(page)); - return page; + ret = __get_user_pages_locked(mm, addr, 1, &page, NULL, &locked, + FOLL_FORCE | FOLL_DUMP | FOLL_GET); + if (locked) + mmap_read_unlock(mm); + return (ret == 1) ? page : NULL; } #endif /* CONFIG_ELF_CORE */