From patchwork Sat May 15 00:27:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 440069 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable 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 90E43C433B4 for ; Sat, 15 May 2021 00:27:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 771E061453 for ; Sat, 15 May 2021 00:27:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234507AbhEOA2S (ORCPT ); Fri, 14 May 2021 20:28:18 -0400 Received: from mail.kernel.org ([198.145.29.99]:43270 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234494AbhEOA2Q (ORCPT ); Fri, 14 May 2021 20:28:16 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 9BE8B61440; Sat, 15 May 2021 00:27:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038424; bh=ZqllgKLgs6frxWMNLzQsofnOMBDx0n2L3PKXy7dlwPw=; h=Date:From:To:Subject:In-Reply-To:From; b=K3M0vHgjEAqvW8tdpDpvC+aIT53nvf0cE+9p4XmtsLFrPsKmAdGP8t0JHZJxnEhPC Kkh2KzaOx73kAbLFTmWSlHSlsIE2Blv4437O0DrUA6/O2QOb1mtkZMVp7R03QzDLIj sFugycUc63ezQi3lmhqWC154pin2Cm5GT2UXsRfo= Date: Fri, 14 May 2021 17:27:04 -0700 From: Andrew Morton To: akpm@linux-foundation.org, hughd@google.com, joel@joelfernandes.org, linux-mm@kvack.org, mike.kravetz@oracle.com, mm-commits@vger.kernel.org, peterx@redhat.com, stable@vger.kernel.org, torvalds@linux-foundation.org Subject: [patch 01/13] mm/hugetlb: fix F_SEAL_FUTURE_WRITE Message-ID: <20210515002704.WGRdZnbbV%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Peter Xu Subject: mm/hugetlb: fix F_SEAL_FUTURE_WRITE Patch series "mm/hugetlb: Fix issues on file sealing and fork", v2. Hugh reported issue with F_SEAL_FUTURE_WRITE not applied correctly to hugetlbfs, which I can easily verify using the memfd_test program, which seems that the program is hardly run with hugetlbfs pages (as by default shmem). Meanwhile I found another probably even more severe issue on that hugetlb fork won't wr-protect child cow pages, so child can potentially write to parent private pages. Patch 2 addresses that. After this series applied, "memfd_test hugetlbfs" should start to pass. This patch (of 2): F_SEAL_FUTURE_WRITE is missing for hugetlb starting from the first day. There is a test program for that and it fails constantly. $ ./memfd_test hugetlbfs memfd-hugetlb: CREATE memfd-hugetlb: BASIC memfd-hugetlb: SEAL-WRITE memfd-hugetlb: SEAL-FUTURE-WRITE mmap() didn't fail as expected Aborted (core dumped) I think it's probably because no one is really running the hugetlbfs test. Fix it by checking FUTURE_WRITE also in hugetlbfs_file_mmap() as what we do in shmem_mmap(). Generalize a helper for that. Link: https://lkml.kernel.org/r/20210503234356.9097-1-peterx@redhat.com Link: https://lkml.kernel.org/r/20210503234356.9097-2-peterx@redhat.com Fixes: ab3948f58ff84 ("mm/memfd: add an F_SEAL_FUTURE_WRITE seal to memfd") Signed-off-by: Peter Xu Reported-by: Hugh Dickins Reviewed-by: Mike Kravetz Cc: Joel Fernandes (Google) Cc: Signed-off-by: Andrew Morton --- fs/hugetlbfs/inode.c | 5 +++++ include/linux/mm.h | 32 ++++++++++++++++++++++++++++++++ mm/shmem.c | 22 ++++------------------ 3 files changed, 41 insertions(+), 18 deletions(-) --- a/fs/hugetlbfs/inode.c~mm-hugetlb-fix-f_seal_future_write +++ a/fs/hugetlbfs/inode.c @@ -131,6 +131,7 @@ static void huge_pagevec_release(struct static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file_inode(file); + struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode); loff_t len, vma_len; int ret; struct hstate *h = hstate_file(file); @@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct fi vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND; vma->vm_ops = &hugetlb_vm_ops; + ret = seal_check_future_write(info->seals, vma); + if (ret) + return ret; + /* * page based offset in vm_pgoff could be sufficiently large to * overflow a loff_t when converted to byte offset. This can --- a/include/linux/mm.h~mm-hugetlb-fix-f_seal_future_write +++ a/include/linux/mm.h @@ -3216,5 +3216,37 @@ void mem_dump_obj(void *object); static inline void mem_dump_obj(void *object) {} #endif +/** + * seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it + * @seals: the seals to check + * @vma: the vma to operate on + * + * Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on + * the vma flags. Return 0 if check pass, or <0 for errors. + */ +static inline int seal_check_future_write(int seals, struct vm_area_struct *vma) +{ + if (seals & F_SEAL_FUTURE_WRITE) { + /* + * New PROT_WRITE and MAP_SHARED mmaps are not allowed when + * "future write" seal active. + */ + if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE)) + return -EPERM; + + /* + * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as + * MAP_SHARED and read-only, take care to not allow mprotect to + * revert protections on such mappings. Do this only for shared + * mappings. For private mappings, don't need to mask + * VM_MAYWRITE as we still want them to be COW-writable. + */ + if (vma->vm_flags & VM_SHARED) + vma->vm_flags &= ~(VM_MAYWRITE); + } + + return 0; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ --- a/mm/shmem.c~mm-hugetlb-fix-f_seal_future_write +++ a/mm/shmem.c @@ -2258,25 +2258,11 @@ out_nomem: static int shmem_mmap(struct file *file, struct vm_area_struct *vma) { struct shmem_inode_info *info = SHMEM_I(file_inode(file)); + int ret; - if (info->seals & F_SEAL_FUTURE_WRITE) { - /* - * New PROT_WRITE and MAP_SHARED mmaps are not allowed when - * "future write" seal active. - */ - if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE)) - return -EPERM; - - /* - * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as - * MAP_SHARED and read-only, take care to not allow mprotect to - * revert protections on such mappings. Do this only for shared - * mappings. For private mappings, don't need to mask - * VM_MAYWRITE as we still want them to be COW-writable. - */ - if (vma->vm_flags & VM_SHARED) - vma->vm_flags &= ~(VM_MAYWRITE); - } + ret = seal_check_future_write(info->seals, vma); + if (ret) + return ret; /* arm64 - allow memory tagging on RAM-based files */ vma->vm_flags |= VM_MTE_ALLOWED; From patchwork Sat May 15 00:27:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 439825 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable 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 DBA26C433ED for ; Sat, 15 May 2021 00:27:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BC3D961453 for ; Sat, 15 May 2021 00:27:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234494AbhEOA2V (ORCPT ); Fri, 14 May 2021 20:28:21 -0400 Received: from mail.kernel.org ([198.145.29.99]:43356 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA2U (ORCPT ); Fri, 14 May 2021 20:28:20 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8E39761446; Sat, 15 May 2021 00:27:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038427; bh=DhcuA4EivNVuq4ZDGwN7CQQyCFo4+IQDgT/eQDfSkv0=; h=Date:From:To:Subject:In-Reply-To:From; b=JMINWsinS52HeYjlwDq8yMhjBF0cbxD7jFVNFNpG1Iz1N/FHJEjV7BaDYX9fEGONs EK7J9ybW6td7va0FIYtO2zFxH0k2cyznoovlTObu24/0qxUFzbt67e61oS7C5U6qEc 7kCtsmsoXC2OJK2fos1neoFa4HfjwXtKw8XtkwZw= Date: Fri, 14 May 2021 17:27:07 -0700 From: Andrew Morton To: akpm@linux-foundation.org, hughd@google.com, joel@joelfernandes.org, linux-mm@kvack.org, mike.kravetz@oracle.com, mm-commits@vger.kernel.org, peterx@redhat.com, stable@vger.kernel.org, torvalds@linux-foundation.org Subject: [patch 02/13] mm/hugetlb: fix cow where page writtable in child Message-ID: <20210515002707.LZb1SqAkO%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Peter Xu Subject: mm/hugetlb: fix cow where page writtable in child When rework early cow of pinned hugetlb pages, we moved huge_ptep_get() upper but overlooked a side effect that the huge_ptep_get() will fetch the pte after wr-protection. After moving it upwards, we need explicit wr-protect of child pte or we will keep the write bit set in the child process, which could cause data corrution where the child can write to the original page directly. This issue can also be exposed by "memfd_test hugetlbfs" kselftest. Link: https://lkml.kernel.org/r/20210503234356.9097-3-peterx@redhat.com Fixes: 4eae4efa2c299 ("hugetlb: do early cow when page pinned on src mm") Signed-off-by: Peter Xu Reviewed-by: Mike Kravetz Cc: Hugh Dickins Cc: Joel Fernandes (Google) Cc: Signed-off-by: Andrew Morton --- mm/hugetlb.c | 1 + 1 file changed, 1 insertion(+) --- a/mm/hugetlb.c~mm-hugetlb-fix-cow-where-page-writtable-in-child +++ a/mm/hugetlb.c @@ -4056,6 +4056,7 @@ again: * See Documentation/vm/mmu_notifier.rst */ huge_ptep_set_wrprotect(src, addr, src_pte); + entry = huge_pte_wrprotect(entry); } page_dup_rmap(ptepage, true); From patchwork Sat May 15 00:27:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 440068 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable 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 2BFB5C433B4 for ; Sat, 15 May 2021 00:27:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0BC5561176 for ; Sat, 15 May 2021 00:27:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234513AbhEOA23 (ORCPT ); Fri, 14 May 2021 20:28:29 -0400 Received: from mail.kernel.org ([198.145.29.99]:43616 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA22 (ORCPT ); Fri, 14 May 2021 20:28:28 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id A2B6C61440; Sat, 15 May 2021 00:27:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038436; bh=q9VfCXkCafejL6EKzUf8WpxrHYOGYl3QKNbY6MS0ZwE=; h=Date:From:To:Subject:In-Reply-To:From; b=IZoHGCudut9IE1aBxKhz8YzLZukXQiHZUJbLvARVBgPG2jb5/W/ge6KpzQlRpFybw oC53iud82uz/59+6qcF6gk3k1HQjXdzbc69WYoq9XE7XwHdJG5cm2YcwvxJAnyJV3v FOmiX8taKo0WbVrAquX9sL65ta+OwJfyL2xKmKPE= Date: Fri, 14 May 2021 17:27:16 -0700 From: Andrew Morton To: akpm@linux-foundation.org, linux-mm@kvack.org, mm-commits@vger.kernel.org, phillip@squashfs.org.uk, stable@vger.kernel.org, syzbot+7b98870d4fec9447b951@syzkaller.appspotmail.com, syzbot+e8f781243ce16ac2f962@syzkaller.appspotmail.com, torvalds@linux-foundation.org Subject: [patch 05/13] squashfs: fix divide error in calculate_skip() Message-ID: <20210515002716.xFCvUKslt%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Phillip Lougher Subject: squashfs: fix divide error in calculate_skip() Sysbot has reported a "divide error" which has been identified as being caused by a corrupted file_size value within the file inode. This value has been corrupted to a much larger value than expected. Calculate_skip() is passed i_size_read(inode) >> msblk->block_log. Due to the file_size value corruption this overflows the int argument/variable in that function, leading to the divide error. This patch changes the function to use u64. This will accommodate any unexpectedly large values due to corruption. The value returned from calculate_skip() is clamped to be never more than SQUASHFS_CACHED_BLKS - 1, or 7. So file_size corruption does not lead to an unexpectedly large return result here. Link: https://lkml.kernel.org/r/20210507152618.9447-1-phillip@squashfs.org.uk Signed-off-by: Phillip Lougher Reported-by: Reported-by: Cc: Signed-off-by: Andrew Morton --- fs/squashfs/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- a/fs/squashfs/file.c~squashfs-fix-divide-error-in-calculate_skip +++ a/fs/squashfs/file.c @@ -211,11 +211,11 @@ failure: * If the skip factor is limited in this way then the file will use multiple * slots. */ -static inline int calculate_skip(int blocks) +static inline int calculate_skip(u64 blocks) { - int skip = blocks / ((SQUASHFS_META_ENTRIES + 1) + u64 skip = blocks / ((SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); - return min(SQUASHFS_CACHED_BLKS - 1, skip + 1); + return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1); } From patchwork Sat May 15 00:27:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 439824 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, 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 4A648C433B4 for ; Sat, 15 May 2021 00:27:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2F80661457 for ; Sat, 15 May 2021 00:27:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234517AbhEOA2c (ORCPT ); Fri, 14 May 2021 20:28:32 -0400 Received: from mail.kernel.org ([198.145.29.99]:43708 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA2b (ORCPT ); Fri, 14 May 2021 20:28:31 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8BAEC61176; Sat, 15 May 2021 00:27:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038439; bh=KsHlOjWWpiWbhUWj38CsS3aihRqJiw43myh9AH5dSng=; h=Date:From:To:Subject:In-Reply-To:From; b=t3f/TrCCXtal0pbeCTx/WmCrpSeCvvAIlJ/5ZFjnQ2enlcBkDGHY8Uk8Bdy/L1BCo NFVxEpjU3kDwmS//F12UAe/HwkXeAK9oC5D2J2sG/MsW6d9W6O/SXf1dqwj+QXeFmE RlOeO5JXkDJZnXYfaY1FzVXiQx5yBE+HpzdWLfz8= Date: Fri, 14 May 2021 17:27:19 -0700 From: Andrew Morton To: akpm@linux-foundation.org, axelrasmussen@google.com, hughd@google.com, linux-mm@kvack.org, mm-commits@vger.kernel.org, peterx@redhat.com, stable@vger.kernel.org, torvalds@linux-foundation.org Subject: [patch 06/13] userfaultfd: release page in error path to avoid BUG_ON Message-ID: <20210515002719.QX9ZRXcYB%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Axel Rasmussen Subject: userfaultfd: release page in error path to avoid BUG_ON Consider the following sequence of events: 1. Userspace issues a UFFD ioctl, which ends up calling into shmem_mfill_atomic_pte(). We successfully account the blocks, we shmem_alloc_page(), but then the copy_from_user() fails. We return -ENOENT. We don't release the page we allocated. 2. Our caller detects this error code, tries the copy_from_user() after dropping the mmap_lock, and retries, calling back into shmem_mfill_atomic_pte(). 3. Meanwhile, let's say another process filled up the tmpfs being used. 4. So shmem_mfill_atomic_pte() fails to account blocks this time, and immediately returns - without releasing the page. This triggers a BUG_ON in our caller, which asserts that the page should always be consumed, unless -ENOENT is returned. To fix this, detect if we have such a "dangling" page when accounting fails, and if so, release it before returning. Link: https://lkml.kernel.org/r/20210428230858.348400-1-axelrasmussen@google.com Fixes: cb658a453b93 ("userfaultfd: shmem: avoid leaking blocks and used blocks in UFFDIO_COPY") Signed-off-by: Axel Rasmussen Reported-by: Hugh Dickins Acked-by: Hugh Dickins Reviewed-by: Peter Xu Cc: Signed-off-by: Andrew Morton --- mm/shmem.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) --- a/mm/shmem.c~userfaultfd-release-page-in-error-path-to-avoid-bug_on +++ a/mm/shmem.c @@ -2361,8 +2361,18 @@ static int shmem_mfill_atomic_pte(struct pgoff_t offset, max_off; ret = -ENOMEM; - if (!shmem_inode_acct_block(inode, 1)) + if (!shmem_inode_acct_block(inode, 1)) { + /* + * We may have got a page, returned -ENOENT triggering a retry, + * and now we find ourselves with -ENOMEM. Release the page, to + * avoid a BUG_ON in our caller. + */ + if (unlikely(*pagep)) { + put_page(*pagep); + *pagep = NULL; + } goto out; + } if (!*pagep) { page = shmem_alloc_page(gfp, info, pgoff); From patchwork Sat May 15 00:27:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 440067 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, 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 9AB9BC43460 for ; Sat, 15 May 2021 00:27:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7DF2D61176 for ; Sat, 15 May 2021 00:27:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234502AbhEOA2i (ORCPT ); Fri, 14 May 2021 20:28:38 -0400 Received: from mail.kernel.org ([198.145.29.99]:43852 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA2i (ORCPT ); Fri, 14 May 2021 20:28:38 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3EC0361440; Sat, 15 May 2021 00:27:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038445; bh=SgpnbkSZHTi4AWM+dQwq9Re1kiGetDCBWeaMldKCkCE=; h=Date:From:To:Subject:In-Reply-To:From; b=eJ6c/FM/b94SZUvBfznpgNhbI63k1+kxTq2SVrBtMlVwJ8u2lG4n2JqZlGzs2fIgQ UfU/+gojbSka0Re0Za1qDDEGgPW94yxG6KCJrnO0Yc15YuBAqLHbgxWbCNTLhYl+Oz NL1/pI/tVeU/MJC/212EzmtqxvZK2YxE0+P45Y34= Date: Fri, 14 May 2021 17:27:24 -0700 From: Andrew Morton To: akpm@linux-foundation.org, brouer@redhat.com, ilias.apalodimas@linaro.org, linux-mm@kvack.org, mcroce@linux.microsoft.com, mm-commits@vger.kernel.org, stable@vger.kernel.org, torvalds@linux-foundation.org, vbabka@suse.cz, willy@infradead.org Subject: [patch 08/13] mm: fix struct page layout on 32-bit systems Message-ID: <20210515002724.4C8uJfcjY%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: "Matthew Wilcox (Oracle)" Subject: mm: fix struct page layout on 32-bit systems 32-bit architectures which expect 8-byte alignment for 8-byte integers and need 64-bit DMA addresses (arm, mips, ppc) had their struct page inadvertently expanded in 2019. When the dma_addr_t was added, it forced the alignment of the union to 8 bytes, which inserted a 4 byte gap between 'flags' and the union. Fix this by storing the dma_addr_t in one or two adjacent unsigned longs. This restores the alignment to that of an unsigned long. We always store the low bits in the first word to prevent the PageTail bit from being inadvertently set on a big endian platform. If that happened, get_user_pages_fast() racing against a page which was freed and reallocated to the page_pool could dereference a bogus compound_head(), which would be hard to trace back to this cause. Link: https://lkml.kernel.org/r/20210510153211.1504886-1-willy@infradead.org Fixes: c25fff7171be ("mm: add dma_addr_t to struct page") Signed-off-by: Matthew Wilcox (Oracle) Acked-by: Ilias Apalodimas Acked-by: Jesper Dangaard Brouer Acked-by: Vlastimil Babka Tested-by: Matteo Croce Cc: Signed-off-by: Andrew Morton --- include/linux/mm_types.h | 4 ++-- include/net/page_pool.h | 12 +++++++++++- net/core/page_pool.c | 12 +++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) --- a/include/linux/mm_types.h~mm-fix-struct-page-layout-on-32-bit-systems +++ a/include/linux/mm_types.h @@ -97,10 +97,10 @@ struct page { }; struct { /* page_pool used by netstack */ /** - * @dma_addr: might require a 64-bit value even on + * @dma_addr: might require a 64-bit value on * 32-bit architectures. */ - dma_addr_t dma_addr; + unsigned long dma_addr[2]; }; struct { /* slab, slob and slub */ union { --- a/include/net/page_pool.h~mm-fix-struct-page-layout-on-32-bit-systems +++ a/include/net/page_pool.h @@ -198,7 +198,17 @@ static inline void page_pool_recycle_dir static inline dma_addr_t page_pool_get_dma_addr(struct page *page) { - return page->dma_addr; + dma_addr_t ret = page->dma_addr[0]; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16; + return ret; +} + +static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr) +{ + page->dma_addr[0] = addr; + if (sizeof(dma_addr_t) > sizeof(unsigned long)) + page->dma_addr[1] = upper_32_bits(addr); } static inline bool is_page_pool_compiled_in(void) --- a/net/core/page_pool.c~mm-fix-struct-page-layout-on-32-bit-systems +++ a/net/core/page_pool.c @@ -174,8 +174,10 @@ static void page_pool_dma_sync_for_devic struct page *page, unsigned int dma_sync_size) { + dma_addr_t dma_addr = page_pool_get_dma_addr(page); + dma_sync_size = min(dma_sync_size, pool->p.max_len); - dma_sync_single_range_for_device(pool->p.dev, page->dma_addr, + dma_sync_single_range_for_device(pool->p.dev, dma_addr, pool->p.offset, dma_sync_size, pool->p.dma_dir); } @@ -195,7 +197,7 @@ static bool page_pool_dma_map(struct pag if (dma_mapping_error(pool->p.dev, dma)) return false; - page->dma_addr = dma; + page_pool_set_dma_addr(page, dma); if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV) page_pool_dma_sync_for_device(pool, page, pool->p.max_len); @@ -331,13 +333,13 @@ void page_pool_release_page(struct page_ */ goto skip_dma_unmap; - dma = page->dma_addr; + dma = page_pool_get_dma_addr(page); - /* When page is unmapped, it cannot be returned our pool */ + /* When page is unmapped, it cannot be returned to our pool */ dma_unmap_page_attrs(pool->p.dev, dma, PAGE_SIZE << pool->p.order, pool->p.dma_dir, DMA_ATTR_SKIP_CPU_SYNC); - page->dma_addr = 0; + page_pool_set_dma_addr(page, 0); skip_dma_unmap: /* This may be the last page returned, releasing the pool, so * it is not safe to reference pool afterwards. From patchwork Sat May 15 00:27:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 439823 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable 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 77143C43460 for ; Sat, 15 May 2021 00:27:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5CA1F61457 for ; Sat, 15 May 2021 00:27:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234521AbhEOA2l (ORCPT ); Fri, 14 May 2021 20:28:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:43912 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA2k (ORCPT ); Fri, 14 May 2021 20:28:40 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2E13261176; Sat, 15 May 2021 00:27:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038448; bh=bSGxouT3kOSPsbFK7LM4HYQDu0TSOgVamWpI66joQqU=; h=Date:From:To:Subject:In-Reply-To:From; b=MVhk/ftv2XEmif8cs8Sat4o7zjUpCR2ILVcYrfeKc9E5br/mhkRUUZpXBxMu5D4zU BveyxaXhEoGZNwcoX5/IZiSgReUdTw3vMeCoDT6yNvG4pRnf+mUZidT/kGqJwZ3z2+ xeMR1v+hQqRTj40aFyi8qRLjZrXsDKFkgz1x++qg= Date: Fri, 14 May 2021 17:27:27 -0700 From: Andrew Morton To: akpm@linux-foundation.org, andreyknvl@gmail.com, eugenis@google.com, georgepope@android.com, glider@google.com, lenaptr@google.com, linux-mm@kvack.org, mm-commits@vger.kernel.org, pcc@google.com, stable@vger.kernel.org, torvalds@linux-foundation.org Subject: [patch 09/13] kasan: fix unit tests with CONFIG_UBSAN_LOCAL_BOUNDS enabled Message-ID: <20210515002727.2LmnD7uG3%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Peter Collingbourne Subject: kasan: fix unit tests with CONFIG_UBSAN_LOCAL_BOUNDS enabled These tests deliberately access these arrays out of bounds, which will cause the dynamic local bounds checks inserted by CONFIG_UBSAN_LOCAL_BOUNDS to fail and panic the kernel. To avoid this problem, access the arrays via volatile pointers, which will prevent the compiler from being able to determine the array bounds. These accesses use volatile pointers to char (char *volatile) rather than the more conventional pointers to volatile char (volatile char *) because we want to prevent the compiler from making inferences about the pointer itself (i.e. its array bounds), not the data that it refers to. Link: https://lkml.kernel.org/r/20210507025915.1464056-1-pcc@google.com Link: https://linux-review.googlesource.com/id/I90b1713fbfa1bf68ff895aef099ea77b98a7c3b9 Signed-off-by: Peter Collingbourne Tested-by: Alexander Potapenko Reviewed-by: Andrey Konovalov Cc: Peter Collingbourne Cc: George Popescu Cc: Elena Petrova Cc: Evgenii Stepanov Cc: Signed-off-by: Andrew Morton --- lib/test_kasan.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) --- a/lib/test_kasan.c~kasan-fix-unit-tests-with-config_ubsan_local_bounds-enabled +++ a/lib/test_kasan.c @@ -654,8 +654,20 @@ static char global_array[10]; static void kasan_global_oob(struct kunit *test) { - volatile int i = 3; - char *p = &global_array[ARRAY_SIZE(global_array) + i]; + /* + * Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS + * from failing here and panicing the kernel, access the array via a + * volatile pointer, which will prevent the compiler from being able to + * determine the array bounds. + * + * This access uses a volatile pointer to char (char *volatile) rather + * than the more conventional pointer to volatile char (volatile char *) + * because we want to prevent the compiler from making inferences about + * the pointer itself (i.e. its array bounds), not the data that it + * refers to. + */ + char *volatile array = global_array; + char *p = &array[ARRAY_SIZE(global_array) + 3]; /* Only generic mode instruments globals. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); @@ -703,8 +715,9 @@ static void ksize_uaf(struct kunit *test static void kasan_stack_oob(struct kunit *test) { char stack_array[10]; - volatile int i = OOB_TAG_OFF; - char *p = &stack_array[ARRAY_SIZE(stack_array) + i]; + /* See comment in kasan_global_oob. */ + char *volatile array = stack_array; + char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF]; KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_STACK); @@ -715,7 +728,9 @@ static void kasan_alloca_oob_left(struct { volatile int i = 10; char alloca_array[i]; - char *p = alloca_array - 1; + /* See comment in kasan_global_oob. */ + char *volatile array = alloca_array; + char *p = array - 1; /* Only generic mode instruments dynamic allocas. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); @@ -728,7 +743,9 @@ static void kasan_alloca_oob_right(struc { volatile int i = 10; char alloca_array[i]; - char *p = alloca_array + i; + /* See comment in kasan_global_oob. */ + char *volatile array = alloca_array; + char *p = array + i; /* Only generic mode instruments dynamic allocas. */ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC); From patchwork Sat May 15 00:27:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Morton X-Patchwork-Id: 440066 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable 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 A44F0C43461 for ; Sat, 15 May 2021 00:27:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 89E076145A for ; Sat, 15 May 2021 00:27:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234524AbhEOA2q (ORCPT ); Fri, 14 May 2021 20:28:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:44072 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230022AbhEOA2q (ORCPT ); Fri, 14 May 2021 20:28:46 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0705B61440; Sat, 15 May 2021 00:27:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1621038454; bh=5TKQccw0MfrPcBro+UF6pP1bAi79nl8XEtlMz/Eb7KU=; h=Date:From:To:Subject:In-Reply-To:From; b=Wwg+CCI4p7eGLnxLqkFKQUdnEXuHkZwRP2dl1wKHREtypRr95DIexmQbg7hPrjZUV SpYdNMFhJ99nsJdfYVoa78q8dTFFZGAchrbLNCwAwZMlVLg+4lm6yV43OKQqtiQNhd Xz0zdjaa2dcAfo7/BwyRlgw9YtOEy9SyP71wqHjQ= Date: Fri, 14 May 2021 17:27:33 -0700 From: Andrew Morton To: akpm@linux-foundation.org, anatoly.trosinenko@gmail.com, anton@tuxera.com, jouni.roivas@tuxera.com, linux-mm@kvack.org, mm-commits@vger.kernel.org, slava@dubeyko.com, stable@vger.kernel.org, torvalds@linux-foundation.org Subject: [patch 11/13] hfsplus: prevent corruption in shrinking truncate Message-ID: <20210515002733.KxUyvD09_%akpm@linux-foundation.org> In-Reply-To: <20210514172634.9018621171d5334ceee97e95@linux-foundation.org> User-Agent: s-nail v14.8.16 Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Jouni Roivas Subject: hfsplus: prevent corruption in shrinking truncate I believe there are some issues introduced by commit 31651c607151 ("hfsplus: avoid deadlock on file truncation") HFS+ has extent records which always contains 8 extents. In case the first extent record in catalog file gets full, new ones are allocated from extents overflow file. In case shrinking truncate happens to middle of an extent record which locates in extents overflow file, the logic in hfsplus_file_truncate() was changed so that call to hfs_brec_remove() is not guarded any more. Right action would be just freeing the extents that exceed the new size inside extent record by calling hfsplus_free_extents(), and then check if the whole extent record should be removed. However since the guard (blk_cnt > start) is now after the call to hfs_brec_remove(), this has unfortunate effect that the last matching extent record is removed unconditionally. To reproduce this issue, create a file which has at least 10 extents, and then perform shrinking truncate into middle of the last extent record, so that the number of remaining extents is not under or divisible by 8. This causes the last extent record (8 extents) to be removed totally instead of truncating into middle of it. Thus this causes corruption, and lost data. Fix for this is simply checking if the new truncated end is below the start of this extent record, making it safe to remove the full extent record. However call to hfs_brec_remove() can't be moved to it's previous place since we're dropping ->tree_lock and it can cause a race condition and the cached info being invalidated possibly corrupting the node data. Another issue is related to this one. When entering into the block (blk_cnt > start) we are not holding the ->tree_lock. We break out from the loop not holding the lock, but hfs_find_exit() does unlock it. Not sure if it's possible for someone else to take the lock under our feet, but it can cause hard to debug errors and premature unlocking. Even if there's no real risk of it, the locking should still always be kept in balance. Thus taking the lock now just before the check. Link: https://lkml.kernel.org/r/20210429165139.3082828-1-jouni.roivas@tuxera.com Fixes: 31651c607151f ("hfsplus: avoid deadlock on file truncation") Signed-off-by: Jouni Roivas Reviewed-by: Anton Altaparmakov Cc: Anatoly Trosinenko Cc: Viacheslav Dubeyko Cc: Signed-off-by: Andrew Morton --- fs/hfsplus/extents.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) --- a/fs/hfsplus/extents.c~hfsplus-prevent-corruption-in-shrinking-truncate +++ a/fs/hfsplus/extents.c @@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt); if (res) break; - hfs_brec_remove(&fd); - mutex_unlock(&fd.tree->tree_lock); start = hip->cached_start; + if (blk_cnt <= start) + hfs_brec_remove(&fd); + mutex_unlock(&fd.tree->tree_lock); hfsplus_free_extents(sb, hip->cached_extents, alloc_cnt - start, alloc_cnt - blk_cnt); hfsplus_dump_extent(hip->cached_extents); + mutex_lock(&fd.tree->tree_lock); if (blk_cnt > start) { hip->extent_state |= HFSPLUS_EXT_DIRTY; break; @@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode alloc_cnt = start; hip->cached_start = hip->cached_blocks = 0; hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); - mutex_lock(&fd.tree->tree_lock); } hfs_find_exit(&fd);