From patchwork Thu Jan 18 10:59:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Elver X-Patchwork-Id: 13522697 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2FD6AC4707B for ; Thu, 18 Jan 2024 11:00:39 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A71176B0074; Thu, 18 Jan 2024 06:00:38 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A21946B0075; Thu, 18 Jan 2024 06:00:38 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 911306B0078; Thu, 18 Jan 2024 06:00:38 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 830216B0074 for ; Thu, 18 Jan 2024 06:00:38 -0500 (EST) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 45A14A1A55 for ; Thu, 18 Jan 2024 11:00:38 +0000 (UTC) X-FDA: 81692138556.09.D95A07D Received: from mail-ej1-f73.google.com (mail-ej1-f73.google.com [209.85.218.73]) by imf20.hostedemail.com (Postfix) with ESMTP id 6AC741C0023 for ; Thu, 18 Jan 2024 11:00:35 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=4HnAXonf; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf20.hostedemail.com: domain of 30QSpZQUKCLIWdnWjYggYdW.Ugedafmp-eecnSUc.gjY@flex--elver.bounces.google.com designates 209.85.218.73 as permitted sender) smtp.mailfrom=30QSpZQUKCLIWdnWjYggYdW.Ugedafmp-eecnSUc.gjY@flex--elver.bounces.google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1705575635; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding:in-reply-to: references:dkim-signature; bh=6RrXGrowsStE9nemPJC0cN0IXJkwkJ+pwI0mRPXiexU=; b=fc6QtJ2AXO5/1lx+D/3rMFJiTHilCW1FXcBYAd4zr/HyCnMz2s+Z2VKefWwwpEJEqyx4iy CCI/cTOtFdN1+SP/OQsRMMayPj+ypVWnw+oeuhJ5dGMFx5ddyHYVTUwqPqWrPt8YZf5MC+ ozZ2sAPn/H0stERj1hyU4jHOvA0wwso= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=4HnAXonf; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf20.hostedemail.com: domain of 30QSpZQUKCLIWdnWjYggYdW.Ugedafmp-eecnSUc.gjY@flex--elver.bounces.google.com designates 209.85.218.73 as permitted sender) smtp.mailfrom=30QSpZQUKCLIWdnWjYggYdW.Ugedafmp-eecnSUc.gjY@flex--elver.bounces.google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1705575635; a=rsa-sha256; cv=none; b=hR6lqZCuYQBUjFKjSwySRnYzepU/fy+tSSuWZyGuMBYDfiBB/XNX3NUkZB4OofgaVmLrmy eq52p65nhkiiXCnbZdrYvZg8+HYXijYsGWZO5chF6SSVmTNQIGHE/zLdLTSmDZUQrbi6bV 8M1vHUww5WYk3EgxcC4AWrhu5dp34Rc= Received: by mail-ej1-f73.google.com with SMTP id a640c23a62f3a-a2e1630853eso162383766b.0 for ; Thu, 18 Jan 2024 03:00:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1705575634; x=1706180434; darn=kvack.org; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=6RrXGrowsStE9nemPJC0cN0IXJkwkJ+pwI0mRPXiexU=; b=4HnAXonf0OexiVSasfM3KPonbEK0LocH6DQiyhpi3SczCwgpNLanylXB77mi6218Rd eGxo1wz6+v7KCaB/H3w1fa7kc04BWzb6xv2ABo3ajodl7Avt6d6WYV9DkECmfsjj4I5X 3ToSFF6CZpD2901VCW1m7umuvruFWWU1AmEg8FYOmpVC2NA6jMTkEiv6UJD8BoZo+vpp n4Njv5T13WbgJwsaDrU+j+m7ikZRbA6bNT7JDA0Z4dBuVZ2Rcmb48yiC8WyLAI+3GaY/ vkLZ3d2AsI7MllJRcXvg10/T8i8zjX0uZI4DEsGomllFMQwwf6Mvm6jCj5rUI5N4sOJe TMzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1705575634; x=1706180434; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=6RrXGrowsStE9nemPJC0cN0IXJkwkJ+pwI0mRPXiexU=; b=lMTy6V4fD3IrbyXEqmNfuMjdVmjkTRNMUvJZg2SOipWrc1WIoHWyaOkU9ksH82kTkj CPSVyD/qj4D+jHvl+jHKnluwXpvh7Y1tTCsMmfpyBKgq24Tms4K1DNP5hVUknu4k8mSV 6QCHeKz7fUaY3QzP1p7wiSKgSiTIpEdhJ/B+KTqaJzIcJWUNnymc829CVFtZJr0xD9fN VBY6pCbKvXO9YQTUX0znGNYFiJhcqmt9pVhu2LlO6FZkqYD40i+A/7H5Fr3ONobsic4S I/F9fb7PM94pHG48DDGvqj4qgkcPv+FyRNsO3TSOwcsBE9d7nxfD4CeMVNwnCDoZnpVh m/5w== X-Gm-Message-State: AOJu0YwmtgqaOePaijBz+PbqayRkwosXchkHasq5gOvhCdtSLVOihKSA aPMQjcAUnoRY+53rM2jox6kiIvnmHv53+UoLnas4mKdY3CthQ6YmT5KghpL0oG7nfU/rSpjbhQ= = X-Google-Smtp-Source: AGHT+IFa7FQxY4lu1mD59CzjOMD/gCR8C9dFGiq1Jl93adEZmgb2tdPkH71clHTN05oD3miarDKNgZ6Y0A== X-Received: from elver.muc.corp.google.com ([2a00:79e0:9c:201:9d7e:25fb:9605:2bef]) (user=elver job=sendgmr) by 2002:a17:907:788f:b0:a2d:51d4:9ddc with SMTP id ku15-20020a170907788f00b00a2d51d49ddcmr1361ejc.14.1705575633222; Thu, 18 Jan 2024 03:00:33 -0800 (PST) Date: Thu, 18 Jan 2024 11:59:14 +0100 Mime-Version: 1.0 X-Mailer: git-send-email 2.43.0.381.gb435a96ce8-goog Message-ID: <20240118110022.2538350-1-elver@google.com> Subject: [PATCH] mm, kmsan: fix infinite recursion due to RCU critical section From: Marco Elver To: elver@google.com, Andrew Morton Cc: Alexander Potapenko , Dmitry Vyukov , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org, syzbot+93a9e8a3dea8d6085e12@syzkaller.appspotmail.com, Charan Teja Kalla X-Rspamd-Queue-Id: 6AC741C0023 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: a11iswzmif5ai3z3z1w6dyp16rr77onx X-HE-Tag: 1705575635-108589 X-HE-Meta: U2FsdGVkX192GrcufIwYKEMwzWcFiewG4Z+0O6eRa301TDsw2iH3e9eYDgU533/KqlmZRKgWMxLv/mYpYLK7j/cQ/8Lr2lMb2YNfWbTohNwzr/pYyHJS27UUqXwJQ3y39ZSrA++TsDQRr/dX1XH81G1CgN2ur8SYR6tYv9KCufSR7Xmqs1YYKYGEIypJdl4DR7t51teVy6F1MAMUMDWF5BLe9uMeQ2Ag6UF7Auvv7WNX+IrSsnc5BAeclZ0Z9wdyVua2ZUnYuVJEG54vu7dIfuytDnyiMjpFv71UEaXVhyfCeXOQg7Yqj2rKAfYCuNOdlXMCmR+HP4Vb+Gu45LcjhUeTBMNtVZpfsS1CKJTkBwFr3fg4527yQf8bHy3+obcaU+lcLK84+H2/U+icNlsnUQP87jpgaxASKOUo23xcbUqCZXjG0TFmli7+A4nbYiu5CXuF2QokVan2PlJHQzABMmx2GYi+wPGx/QlSE+RVkaT1dgTsKTJKA6dC2dD2ANTXsPI5ruq2SEb/isXvXiZ4nyXNtynGvcp0dJlS00rdYcysbY2w4p/CkyezgMLfCPorjP3Voet50a2XlPFPXI9qtL7zqTK665utKwMpAPVgTC1EiiTasZgmTL218ulxKYSaAU0lBOXmXwka4IadsI+MdtyTtzv5igAhjfhInV9RY9yfi0K3ZVmo8u04/+erOJj+VzE2VfSRVzPT5XMRwM8RbfOjykZmLDljxlDpnUNQyOpE9ivDx9+CVI32MxmcbJONXcvOGc6nmLoTnfDnhJjX+YAuisZbfqbLnpyh+/FjxvlpIIlfGU4Dd/H2vh3fQ8NEzLY6TwRCKIw/Y/2U0ym6Uq1bXd48NZclaVONnW9302b9vB1FuYjIdtofK/A7a7sb/7YX59xGn4AcItQknKA615M8ncY5m5F0du1h4RXliSuBgQ01rWTrmKcHr8QC9xOENGD0okGUFI2dyLjz9pl /y1B7uvf hG+5cF6sRk5aaagKr20A7dBEBmYTrOv1LJEOPje3QGysJ+aAI4SEQZnuWGBVMMnDnNoooqsmwgA3qmWWityA8vRCtso5TZ/sSsC3gJC0r27AwUbICopdzAotEGOe/lPFiqxp2TOlI2XaoMnkwNO+HXO1ZG0jeMYBNn+m3Vn4qE+S2qBVB5vwdrsgKCRPUnKOt2125qyeX1+i03l+snmTKh+Vu5uLBM6/4aK52EGCGK1My9SQOzMc4RpAKPtKPFpptUj0Dkc0CO0GQBpvvpOvjHkj0ExEFyE8za6O6qdJ921EAaaZLjBzbawGZhj5KvKX6NesmXneIxSJxf5kEwh9teIcDnqLqknf4wZaSaJbpXhY36WIEvUNehNH2REza+BFb/92614siZ/3wFgPtJrJYV08Q2Kje+CAeGqXSVdmixuvR+5NVnR59WBLgaLmtYbDoGj0TwPqkjmDXJigGsX5bNFgS74H0oOnG4Wk5ALTw59Y4lQl846tejSJmbFf0pJvSjf2Yc8bWuughRbrQUtJtvy1sSWcTY4b72YLerZNYaEv8GlwW0z19P2ubWTWgpQ5Umj7t7ogf28eGBfJ06dobOSFgc3vmSlzrHUDbpltbnE8dLmaZKtmHxufU1QHWaeXmaKcTz+R6q2p4i2atxyTLBPB4B1eS7oF9MyDcb6/eeq3OY00FHkvIerRf95DXYG4/VUKHtzZaO2tknBhs2XKkbbZd5qynf4FigEnvTaxd5OVavD+ax/vtqJd68I3DTHAVXvq6/+QH9ex7oUSejYYamAKfAg== 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: List-Subscribe: List-Unsubscribe: Alexander Potapenko writes in [1]: "For every memory access in the code instrumented by KMSAN we call kmsan_get_metadata() to obtain the metadata for the memory being accessed. For virtual memory the metadata pointers are stored in the corresponding `struct page`, therefore we need to call virt_to_page() to get them. According to the comment in arch/x86/include/asm/page.h, virt_to_page(kaddr) returns a valid pointer iff virt_addr_valid(kaddr) is true, so KMSAN needs to call virt_addr_valid() as well. To avoid recursion, kmsan_get_metadata() must not call instrumented code, therefore ./arch/x86/include/asm/kmsan.h forks parts of arch/x86/mm/physaddr.c to check whether a virtual address is valid or not. But the introduction of rcu_read_lock() to pfn_valid() added instrumented RCU API calls to virt_to_page_or_null(), which is called by kmsan_get_metadata(), so there is an infinite recursion now. I do not think it is correct to stop that recursion by doing kmsan_enter_runtime()/kmsan_exit_runtime() in kmsan_get_metadata(): that would prevent instrumented functions called from within the runtime from tracking the shadow values, which might introduce false positives." Fix the issue by switching pfn_valid() to the _sched() variant of rcu_read_lock/unlock(), which does not require calling into RCU. Given the critical section in pfn_valid() is very small, this is a reasonable trade-off (with preemptible RCU). KMSAN further needs to be careful to suppress calls into the scheduler, which would be another source of recursion. This can be done by wrapping the call to pfn_valid() into preempt_disable/enable_no_resched(). The downside is that this sacrifices breaking scheduling guarantees; however, a kernel compiled with KMSAN has already given up any performance guarantees due to being heavily instrumented. Note, KMSAN code already disables tracing via Makefile, and since mmzone.h is included, it is not necessary to use the notrace variant, which is generally preferred in all other cases. Link: https://lkml.kernel.org/r/20240115184430.2710652-1-glider@google.com [1] Reported-by: Alexander Potapenko Reported-by: syzbot+93a9e8a3dea8d6085e12@syzkaller.appspotmail.com Signed-off-by: Marco Elver Cc: Charan Teja Kalla Reviewed-by: Alexander Potapenko Tested-by: Alexander Potapenko --- arch/x86/include/asm/kmsan.h | 17 ++++++++++++++++- include/linux/mmzone.h | 6 +++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/kmsan.h b/arch/x86/include/asm/kmsan.h index 8fa6ac0e2d76..d91b37f5b4bb 100644 --- a/arch/x86/include/asm/kmsan.h +++ b/arch/x86/include/asm/kmsan.h @@ -64,6 +64,7 @@ static inline bool kmsan_virt_addr_valid(void *addr) { unsigned long x = (unsigned long)addr; unsigned long y = x - __START_KERNEL_map; + bool ret; /* use the carry flag to determine if x was < __START_KERNEL_map */ if (unlikely(x > y)) { @@ -79,7 +80,21 @@ static inline bool kmsan_virt_addr_valid(void *addr) return false; } - return pfn_valid(x >> PAGE_SHIFT); + /* + * pfn_valid() relies on RCU, and may call into the scheduler on exiting + * the critical section. However, this would result in recursion with + * KMSAN. Therefore, disable preemption here, and re-enable preemption + * below while suppressing reschedules to avoid recursion. + * + * Note, this sacrifices occasionally breaking scheduling guarantees. + * Although, a kernel compiled with KMSAN has already given up on any + * performance guarantees due to being heavily instrumented. + */ + preempt_disable(); + ret = pfn_valid(x >> PAGE_SHIFT); + preempt_enable_no_resched(); + + return ret; } #endif /* !MODULE */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 4ed33b127821..a497f189d988 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -2013,9 +2013,9 @@ static inline int pfn_valid(unsigned long pfn) if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) return 0; ms = __pfn_to_section(pfn); - rcu_read_lock(); + rcu_read_lock_sched(); if (!valid_section(ms)) { - rcu_read_unlock(); + rcu_read_unlock_sched(); return 0; } /* @@ -2023,7 +2023,7 @@ static inline int pfn_valid(unsigned long pfn) * the entire section-sized span. */ ret = early_section(ms) || pfn_section_valid(ms, pfn); - rcu_read_unlock(); + rcu_read_unlock_sched(); return ret; }