From patchwork Tue Oct 8 10:15:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sabyrzhan Tasbolatov X-Patchwork-Id: 13826166 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 13D65CEF148 for ; Tue, 8 Oct 2024 10:14:44 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8C5DA6B007B; Tue, 8 Oct 2024 06:14:43 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 8769E6B0083; Tue, 8 Oct 2024 06:14:43 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 717016B0085; Tue, 8 Oct 2024 06:14:43 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 537076B007B for ; Tue, 8 Oct 2024 06:14:43 -0400 (EDT) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id C66D5A127B for ; Tue, 8 Oct 2024 10:14:40 +0000 (UTC) X-FDA: 82650026004.09.B8C1972 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) by imf17.hostedemail.com (Postfix) with ESMTP id D4BD940009 for ; Tue, 8 Oct 2024 10:14:40 +0000 (UTC) Authentication-Results: imf17.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=aXOQhPW1; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf17.hostedemail.com: domain of snovitoll@gmail.com designates 209.85.128.51 as permitted sender) smtp.mailfrom=snovitoll@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1728382438; a=rsa-sha256; cv=none; b=bKaYEWJlBPhxNdYLzGT96lLQTtewvsJjfNbliJHzsv0QRX23rhFm5vqmOXT/Y2KbEdT+en ZLaokCNNXcP9hpI1sIzMEdYEh48PJzxXnN3N4Fm5isv2NCt5/mHyhgijbtCMgigSVEanu3 pIqjWTQMvyk8YYh+vnmzRE70EWbHW/E= ARC-Authentication-Results: i=1; imf17.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=aXOQhPW1; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf17.hostedemail.com: domain of snovitoll@gmail.com designates 209.85.128.51 as permitted sender) smtp.mailfrom=snovitoll@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1728382438; 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-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Imn45k5J9wM19h9i9/RuyLoAF2diDSxFA12TsgI6H5w=; b=RL5/62XKDP9hLRZYjrlZKauFVodFuPf23cah0vt8Lbk+gehd4Mi4PQgbFxjAHZPq2K6gRr xPGBn9VupWSfxM+O8ThjyDbTj9TEFipI5A4UNaKf53mK7Qz4jd5HRNxGrJzTjVb0PxaR8i CJt8kFFLpjmeMnF+FPYDRxQRlpD+wiY= Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-42cb2191107so48573435e9.1 for ; Tue, 08 Oct 2024 03:14:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728382479; x=1728987279; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Imn45k5J9wM19h9i9/RuyLoAF2diDSxFA12TsgI6H5w=; b=aXOQhPW1dgFZiE/hgAY+N0DX18G/dnPBKvly5mxlbN4NpavdWsrf+7Nyt0ve09caNJ TgL1nimIgyMnzAUVH5YDyzipYUViXOB4Fubo8IGQ3BdWDbZj11rwgQB4vx6zaJvrIqWm AEK1jjhKORpo+WJwX9fyNkdOJ7QzPirQl54lz7ypDU2D35fffyQkcGvHFlyjt0QZozjU B4B25KxZB5CzNAx5kd6EvRiOUkzKux+Y99Tx+u559Evr7oS5nRssJlBTw/Y3MGg2s5lO 2t1LIUeY5nONH2G9CrjrCYDYFp/ScByYgIxhLEqtQ50aWxfqIn08/BU72g5KYKPxHcsm Briw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728382479; x=1728987279; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Imn45k5J9wM19h9i9/RuyLoAF2diDSxFA12TsgI6H5w=; b=oPp/rynbDxaCoXhosJFz6gAnxYE/EaVQ1ob42gbs2gzmRfQOhtCQhmpAjP9s0L/gRH ClUeAWGg/0vrSjoIFmiCntlDNo1zG7mUnhFA44LCaHmzh70JiYL7+E44EDbRe+t5auhE pxDFabwJK1Qg1ZCDexVXfvS3sr89RcDlW1gdj29A4HX5A5hpOSYTlgWZVzQnFIG/H6T4 eY04Z3JpLbYn5TKFT5jvcBOOdRklNCdR6dVBdsbegRLeFM4F/J/hOf2USzMgP+MDdgah 4EClVIAmAAUUYY5F46Z5+e+JVCgP02reSEOtKouEVfgR6zCA1HwpaXQ0Y0UKuCXRMYAW fFSQ== X-Forwarded-Encrypted: i=1; AJvYcCW5mP+mJvUS++g/Sbbct8xEbRjF54i6YS+x4Jc4tz+Y8iN8wyzOO9d9QFmTrNOdRb2wUMeT1DRFvw==@kvack.org X-Gm-Message-State: AOJu0YyWSQT8ofpwKSw/aezo97EvjKSn+tkU5prhAYr5nl46MMlIzv+8 i5W+zwfntH/RF6ZaLwOhKuHBfcJIh4Iz5zewWX7U0+XyGmvpKfxP X-Google-Smtp-Source: AGHT+IFUHFdsSTKRxb8639sVgXceTyFTrRE4SGLmq/ZsJV2CO1ZElzEx8lFPPP5n/dq949hi8/BBKA== X-Received: by 2002:a05:600c:4f14:b0:42b:a88f:f872 with SMTP id 5b1f17b1804b1-42f85af5387mr96155965e9.32.1728382479035; Tue, 08 Oct 2024 03:14:39 -0700 (PDT) Received: from work.. ([94.200.20.179]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-42f89e89624sm103790585e9.12.2024.10.08.03.14.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Oct 2024 03:14:38 -0700 (PDT) From: Sabyrzhan Tasbolatov To: elver@google.com, akpm@linux-foundation.org Cc: andreyknvl@gmail.com, bpf@vger.kernel.org, dvyukov@google.com, glider@google.com, kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org, ryabinin.a.a@gmail.com, snovitoll@gmail.com, syzbot+61123a5daeb9f7454599@syzkaller.appspotmail.com, vincenzo.frascino@arm.com Subject: [PATCH v3] mm, kasan, kmsan: copy_from/to_kernel_nofault Date: Tue, 8 Oct 2024 15:15:26 +0500 Message-Id: <20241008101526.2591147-1-snovitoll@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Queue-Id: D4BD940009 X-Rspamd-Server: rspam01 X-Stat-Signature: js8euturpnwkz8ecytw849baumytpkr6 X-HE-Tag: 1728382480-999160 X-HE-Meta: U2FsdGVkX19isMf/CdrIDmf58/BdcsEhF7MRhOHqA32wMffHqAdFEw+0LkiIBT+qMlvUvSlPij2VpEc9aK5XF/NMZOtcGnsvVADHJHvIbcEUO8r73nWFboz7NJ93DHA9aFmt4p3DaVy3LHUiBFQ2kersUWtc8VZnpRUYdQherlMxq2gzZU7aoI/TcCcl9I7hnRgaTyf+ivfUvw7L6g5F2A9AcAK28jFPcwHqsecg74pCXkItfs8ZzxQWqzITVv6peVwNLxnOyp7+65ecqNIDNB/rUY7ruYFkP2KORiJr42biRBy/qBE1UxXkghoZSCxeEqaIQ1MSM/honc+QccjyYW2qQQbtnbaBIm+kzI3FTLcVj/ckBOLcFkKVeRSsZu+08tL2Nr8DgEO/wg1qrvrUa29FTlDdWb6XnRqKlRQbrgjU99autL6kpsAmek6Z0z/ez+rYUdbolTpNGLp2V2k5CSL5N33xS+yjoGyFYIPgBldSb/mzCofFy4lYlq7X2K52h/6tk6KOfAwBEDF4Mw+PR5BApsp53zzKcKM2uCAWoqJBMLq8IGywhR6di4eGEtn3naDagcJrDkkhb2LGz7XBBuxDuGn6zXJTfQKNo1ps3qMo2GK8dtQPiyb/iIcUMFdvCUpI6j77EiIgeor6GViw7JDBnjmk7G7kOm2TSODmWDPMNV2yfxqVbDA7uutghw/CCz8HmSfL1Iqwyf1UPnWW5LFAcqF0DNTApVgVDXFQ6zW0dUMjKarLfDveFfzP/I9C9T0VIdNwVVfCvCjqgjejv/L5QtvpuxSG7kbq5cn/K1/oy9VT2ZuZpF3q1DbOPa0E6uj1eGjzwa6ikQOB27pgwgW+cRiGMiNzxyED1ru+vQe8ImBjuNHweLm7wVRkntgUC3uqGTFJk2bK5fnnP05Bq1QGg0hlmjWieldvQEXpo9hvGURvATrHe0q6Ey20tIpo74vxgZ8N1kzwznoUWLe LE1pbY3i S5h3ZCNF85Fn+g0sHSJZV7jcc+y9Utj/2GimZWl1bKeUj8OyBHnll1mOytJk5dvJlNDhhxC42Qj5SD+yolz+pF8UOOzU3ddjg6bwRtJkLB6GVD9UcmKx8NqtNoXpyyF9fpqXjAX1Ddb+fSFk/kziAs++i72rOu4TTRTIzQ5qJc0aZUtnH234vo8QQziB/1zB4IQcW3Nq2x7LVYuDoHJj67sjexrnawbPAYBTvCK+1stAkHYjudDpAtqzgaqdBrRfqg2zZyBxr5Cvmr/J/ODl4g60qnqw2TikfR9ciC/W+LVS9oDQvW17hLIz9piNvesNCf3aAF64/on/J4N1iJyyj09y6/pcLQxBOeQbI9ikhp0gbr0Ia0Rr7lNjTThjINBwHtpjQgLEZF9JTotMrU98XX1mpRBj0wqqvymIKIK2PhczLT/NxJ7D3rZfmmnodHBLziVjlahvFmThrYSPqf1SJGdWop5QWIB4mGa4kB3sTo+NbfCRMRyqYEp2rbPNZO731PIO6Z4JYgcwHJj/4PF4nOAgjeEgbQv8sDy51o/Y6PER+MwOR7/FyMLnpi3/mialsc4jlahinPLh7NBoRZcc21K5yDZyPCcI0JuysPVGjBe++wwQaIsL34c1WjSTH8MJwu9OVqel3//5K5FcBxV5UYqLhEKZaDD56XRexunc4ppESrZG9hWYvt/3OxA== 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: Instrument copy_from_kernel_nofault() with KMSAN for uninitialized kernel memory check and copy_to_kernel_nofault() with KASAN, KCSAN to detect the memory corruption. syzbot reported that bpf_probe_read_kernel() kernel helper triggered KASAN report via kasan_check_range() which is not the expected behaviour as copy_from_kernel_nofault() is meant to be a non-faulting helper. Solution is, suggested by Marco Elver, to replace KASAN, KCSAN check in copy_from_kernel_nofault() with KMSAN detection of copying uninitilaized kernel memory. In copy_to_kernel_nofault() we can retain instrument_write() explicitly for the memory corruption instrumentation. copy_to_kernel_nofault() is tested on x86_64 and arm64 with CONFIG_KASAN_SW_TAGS. On arm64 with CONFIG_KASAN_HW_TAGS, kunit test currently fails. Need more clarification on it - currently, disabled in kunit test. Link: https://lore.kernel.org/linux-mm/CANpmjNMAVFzqnCZhEity9cjiqQ9CVN1X7qeeeAp_6yKjwKo8iw@mail.gmail.com/ Suggested-by: Marco Elver Reported-by: syzbot+61123a5daeb9f7454599@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=61123a5daeb9f7454599 Reported-by: Andrey Konovalov Closes: https://bugzilla.kernel.org/show_bug.cgi?id=210505 Signed-off-by: Sabyrzhan Tasbolatov Reviewed-by: Marco Elver --- v2: - squashed previous submitted in -mm tree 2 patches based on Linus tree v3: - moved checks to *_nofault_loop macros per Marco's comments - edited the commit message --- mm/kasan/kasan_test_c.c | 27 +++++++++++++++++++++++++++ mm/kmsan/kmsan_test.c | 17 +++++++++++++++++ mm/maccess.c | 10 ++++++++-- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c index a181e4780d9d..5cff90f831db 100644 --- a/mm/kasan/kasan_test_c.c +++ b/mm/kasan/kasan_test_c.c @@ -1954,6 +1954,32 @@ static void rust_uaf(struct kunit *test) KUNIT_EXPECT_KASAN_FAIL(test, kasan_test_rust_uaf()); } +static void copy_to_kernel_nofault_oob(struct kunit *test) +{ + char *ptr; + char buf[128]; + size_t size = sizeof(buf); + + /* Not detecting fails currently with HW_TAGS */ + KASAN_TEST_NEEDS_CONFIG_OFF(test, CONFIG_KASAN_HW_TAGS); + + ptr = kmalloc(size - KASAN_GRANULE_SIZE, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); + OPTIMIZER_HIDE_VAR(ptr); + + if (IS_ENABLED(CONFIG_KASAN_SW_TAGS)) { + /* Check that the returned pointer is tagged. */ + KUNIT_EXPECT_GE(test, (u8)get_tag(ptr), (u8)KASAN_TAG_MIN); + KUNIT_EXPECT_LT(test, (u8)get_tag(ptr), (u8)KASAN_TAG_KERNEL); + } + + KUNIT_EXPECT_KASAN_FAIL(test, + copy_to_kernel_nofault(&buf[0], ptr, size)); + KUNIT_EXPECT_KASAN_FAIL(test, + copy_to_kernel_nofault(ptr, &buf[0], size)); + kfree(ptr); +} + static struct kunit_case kasan_kunit_test_cases[] = { KUNIT_CASE(kmalloc_oob_right), KUNIT_CASE(kmalloc_oob_left), @@ -2027,6 +2053,7 @@ static struct kunit_case kasan_kunit_test_cases[] = { KUNIT_CASE(match_all_not_assigned), KUNIT_CASE(match_all_ptr_tag), KUNIT_CASE(match_all_mem_tag), + KUNIT_CASE(copy_to_kernel_nofault_oob), KUNIT_CASE(rust_uaf), {} }; diff --git a/mm/kmsan/kmsan_test.c b/mm/kmsan/kmsan_test.c index 13236d579eba..9733a22c46c1 100644 --- a/mm/kmsan/kmsan_test.c +++ b/mm/kmsan/kmsan_test.c @@ -640,6 +640,22 @@ static void test_unpoison_memory(struct kunit *test) KUNIT_EXPECT_TRUE(test, report_matches(&expect)); } +static void test_copy_from_kernel_nofault(struct kunit *test) +{ + long ret; + char buf[4], src[4]; + size_t size = sizeof(buf); + + EXPECTATION_UNINIT_VALUE_FN(expect, "copy_from_kernel_nofault"); + kunit_info( + test, + "testing copy_from_kernel_nofault with uninitialized memory\n"); + + ret = copy_from_kernel_nofault((char *)&buf[0], (char *)&src[0], size); + USE(ret); + KUNIT_EXPECT_TRUE(test, report_matches(&expect)); +} + static struct kunit_case kmsan_test_cases[] = { KUNIT_CASE(test_uninit_kmalloc), KUNIT_CASE(test_init_kmalloc), @@ -664,6 +680,7 @@ static struct kunit_case kmsan_test_cases[] = { KUNIT_CASE(test_long_origin_chain), KUNIT_CASE(test_stackdepot_roundtrip), KUNIT_CASE(test_unpoison_memory), + KUNIT_CASE(test_copy_from_kernel_nofault), {}, }; diff --git a/mm/maccess.c b/mm/maccess.c index 518a25667323..3ca55ec63a6a 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -13,9 +13,14 @@ bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, return true; } +/* + * The below only uses kmsan_check_memory() to ensure uninitialized kernel + * memory isn't leaked. + */ #define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \ while (len >= sizeof(type)) { \ - __get_kernel_nofault(dst, src, type, err_label); \ + __get_kernel_nofault(dst, src, type, err_label); \ + kmsan_check_memory(src, sizeof(type)); \ dst += sizeof(type); \ src += sizeof(type); \ len -= sizeof(type); \ @@ -49,7 +54,8 @@ EXPORT_SYMBOL_GPL(copy_from_kernel_nofault); #define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \ while (len >= sizeof(type)) { \ - __put_kernel_nofault(dst, src, type, err_label); \ + __put_kernel_nofault(dst, src, type, err_label); \ + instrument_write(dst, sizeof(type)); \ dst += sizeof(type); \ src += sizeof(type); \ len -= sizeof(type); \