From patchwork Tue Aug 1 12:48:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 13336683 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 E2136C001DF for ; Tue, 1 Aug 2023 12:49:35 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 86CCA940019; Tue, 1 Aug 2023 08:49:35 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 81AAB940010; Tue, 1 Aug 2023 08:49:35 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6E2CB940019; Tue, 1 Aug 2023 08:49:35 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 5E95D940010 for ; Tue, 1 Aug 2023 08:49:35 -0400 (EDT) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 2E6B5C0CB2 for ; Tue, 1 Aug 2023 12:49:35 +0000 (UTC) X-FDA: 81075517110.28.ED8F956 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf09.hostedemail.com (Postfix) with ESMTP id 176C7140017 for ; Tue, 1 Aug 2023 12:49:32 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ZidO4QKX; spf=pass (imf09.hostedemail.com: domain of david@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=david@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1690894173; 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=hi/J18RARw6/Qxc4oFoZIMtkW25pVX+KOdV/ft2I3Ss=; b=8lJybzHMuazwsMI3eeW6HI2AMLlOmpOVU7YALR+ZPkgkdQMNH0OxKTrGo/6a7xx6atb548 FoZRiUaY234aKyPkgPxFcKEE9aHQZHzAAhXF6tjuPDPrJzamFP33hckEqWfCf+EdCGO8TT RB+6SVub+FCN+ob+ntR8fOczxanG9KU= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1690894173; a=rsa-sha256; cv=none; b=NLNpdL/JyEnwGioqI+iRLXVF1ehrzRSS7306zSQKMDyUKBc1LGCtTWO5QPNKrFbRFpBUzd nGIyZuogCfKNiyEttp/TNzZ4huJ17P/fusWPRyYOgx/JDyP7IHjOaWtcFaqMf+ZSkUxVwO rlwEW2enyePEaiyL/ZlYl91e1NSIbAA= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=ZidO4QKX; spf=pass (imf09.hostedemail.com: domain of david@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=david@redhat.com; dmarc=pass (policy=none) header.from=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1690894172; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hi/J18RARw6/Qxc4oFoZIMtkW25pVX+KOdV/ft2I3Ss=; b=ZidO4QKXdBxWkwb+DXCyX462fJjJpaxR3Oa8WlARuCX4DtPsVC7njU/rQAzSp5aK2ZiTjJ S1JnAvSJL3sLdUnRkqFQ7uLrr7tOYJhrVC43K4D5PvJpy8Om0EdjFsDcYpFeveWlGemEIZ UFATr5+VWIuepMWy0EjgKIexxZZK6vI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-284-oN0NdSRGOK6hQjSuybYWtw-1; Tue, 01 Aug 2023 08:49:27 -0400 X-MC-Unique: oN0NdSRGOK6hQjSuybYWtw-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 73D17805C10; Tue, 1 Aug 2023 12:49:26 +0000 (UTC) Received: from t14s.fritz.box (unknown [10.39.193.232]) by smtp.corp.redhat.com (Postfix) with ESMTP id 75021C585A0; Tue, 1 Aug 2023 12:49:23 +0000 (UTC) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org, linux-fsdevel@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, David Hildenbrand , Andrew Morton , Linus Torvalds , liubo , Peter Xu , Matthew Wilcox , Hugh Dickins , Jason Gunthorpe , John Hubbard , Mel Gorman , Shuah Khan , Paolo Bonzini Subject: [PATCH v2 8/8] selftest/mm: ksm_functional_tests: Add PROT_NONE test Date: Tue, 1 Aug 2023 14:48:44 +0200 Message-ID: <20230801124844.278698-9-david@redhat.com> In-Reply-To: <20230801124844.278698-1-david@redhat.com> References: <20230801124844.278698-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Stat-Signature: dzm1bktdde7sb49dj1qy84c9wjdkb7aa X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 176C7140017 X-Rspam-User: X-HE-Tag: 1690894172-204512 X-HE-Meta: U2FsdGVkX1+yfHQPY7ejQRfNyY+AGdM/NgMwJ4zwjz7Ay2Ef9AdXj1NsZxXA6EUzVdVOQbV/2gkeSuZIWSHyy0droYcB6V6YKGNQSu+gS4X+E/NlhiOlgiAy3FhZ2T/o8P+R3D+R+HPGOuRC0ECimkY/c3r5U+Bz+lIB8tfQ2AjW40jLxJy38X0wSvYtUQuOu1skwyCcOH99n/4kSNjdKrXVH7odLAXTrkWwE1Qkd7lG0dAOnoz2M8MLFkFImzNgxFPfL1NfLStlh96OZNiI64BHfD73o2uFbJmL/7cpZ6MekguZwsvYyJCg5Y/XhHQfrJM31kG9y9r3/w45RkgbMaRFE1yvkGq6y4XXyfol+QOn9psh5dUknrQpTas+TS3crXIKOAM4W/0lM7Pjimjluyibwoupm6xrevugjbk039xUpEKgOyn3xLp7mL3CA4mhy70d/sASF/D4kI+1+hWiSPHSwIhhYJWpARVoPQbogIK9vurnpXpJU06yneOicC3htYaPRWKHIQkRPk0WpjbipuPXwjpr1REwEBjzshGaW2dcXEzV6EfEYl1p/cWJT+JBZ/QAezWqQC50izDW7fp1O98M901Hws2FIO/X+KPPU/cvKi+KrZrXbEocJVNum0ozBePXxH9XDXYm6x4rv4YxBeJeP7JUJDDYVMH7xnL4mdcKvtSogXJTKvsbKc2JAUbt9bYib0jd2CJvjofIOpv/Z5yPbSEKJiEnQwglS7JZI6uyddER9UmThqOqtf/aGb7AwfKFgV92ZguMz88wkpQFsWi8NGFHBEQs4+0+yZfOfm0jQNl/42TI7XRKmPFd/8W4EwWaW7Y2g+X6HBCzjI4UcEilHx0bwcCwkzx9wfY1tZoKVgePNqi6/hjBekV0Tln5cHXckF5Hxzmr6YtLATJxueWKdRz5dylbaueD0qftwd/qtE4xpu7EvSN7dhw27WVkCqbpgEOY1qg7Ykhb2K/ msP4uYSX ALHcPwE1/GflCZ7j0iyJNssWvOWRON4QZNUT/Szp6kqpqN7iOI/e6wyHN01GB3C0lFcTyr7iP2oFO75/7FHgH3ONX5FXu6jkWKZq4pl4M4DjktBoZ3Feq6RIe2BN2aPHBubg6gSUbvWhCqwj8PhD+ycAy+dI9MWK7/0aX4hYoWzxlOS1pDcI8CLBE7dpsDz7e9+XorSNtShMRk9QXCTEu4SR3hYghxLK87kbH 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: Let's test whether merging and unmerging in PROT_NONE areas works as expected. Pass a page protection to mmap_and_merge_range(), which will trigger an mprotect() after writing to the pages, but before enabling merging. Make sure that unsharing works as expected, by performing a ptrace write (using /proc/self/mem) and by setting MADV_UNMERGEABLE. Note that this implicitly tests that ptrace writes in an inaccessible (PROT_NONE) mapping work as expected. Signed-off-by: David Hildenbrand --- .../selftests/mm/ksm_functional_tests.c | 59 ++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/tools/testing/selftests/mm/ksm_functional_tests.c b/tools/testing/selftests/mm/ksm_functional_tests.c index cb63b600cb4f..8fa4889ab4f3 100644 --- a/tools/testing/selftests/mm/ksm_functional_tests.c +++ b/tools/testing/selftests/mm/ksm_functional_tests.c @@ -27,6 +27,7 @@ #define KiB 1024u #define MiB (1024 * KiB) +static int mem_fd; static int ksm_fd; static int ksm_full_scans_fd; static int proc_self_ksm_stat_fd; @@ -144,7 +145,8 @@ static int ksm_unmerge(void) return 0; } -static char *mmap_and_merge_range(char val, unsigned long size, bool use_prctl) +static char *mmap_and_merge_range(char val, unsigned long size, int prot, + bool use_prctl) { char *map; int ret; @@ -176,6 +178,11 @@ static char *mmap_and_merge_range(char val, unsigned long size, bool use_prctl) /* Make sure each page contains the same values to merge them. */ memset(map, val, size); + if (mprotect(map, size, prot)) { + ksft_test_result_skip("mprotect() failed\n"); + goto unmap; + } + if (use_prctl) { ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0); if (ret < 0 && errno == EINVAL) { @@ -218,7 +225,7 @@ static void test_unmerge(void) ksft_print_msg("[RUN] %s\n", __func__); - map = mmap_and_merge_range(0xcf, size, false); + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, false); if (map == MAP_FAILED) return; @@ -256,7 +263,7 @@ static void test_unmerge_zero_pages(void) } /* Let KSM deduplicate zero pages. */ - map = mmap_and_merge_range(0x00, size, false); + map = mmap_and_merge_range(0x00, size, PROT_READ | PROT_WRITE, false); if (map == MAP_FAILED) return; @@ -304,7 +311,7 @@ static void test_unmerge_discarded(void) ksft_print_msg("[RUN] %s\n", __func__); - map = mmap_and_merge_range(0xcf, size, false); + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, false); if (map == MAP_FAILED) return; @@ -336,7 +343,7 @@ static void test_unmerge_uffd_wp(void) ksft_print_msg("[RUN] %s\n", __func__); - map = mmap_and_merge_range(0xcf, size, false); + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, false); if (map == MAP_FAILED) return; @@ -479,7 +486,7 @@ static void test_prctl_unmerge(void) ksft_print_msg("[RUN] %s\n", __func__); - map = mmap_and_merge_range(0xcf, size, true); + map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, true); if (map == MAP_FAILED) return; @@ -494,9 +501,42 @@ static void test_prctl_unmerge(void) munmap(map, size); } +static void test_prot_none(void) +{ + const unsigned int size = 2 * MiB; + char *map; + int i; + + ksft_print_msg("[RUN] %s\n", __func__); + + map = mmap_and_merge_range(0x11, size, PROT_NONE, false); + if (map == MAP_FAILED) + goto unmap; + + /* Store a unique value in each page on one half using ptrace */ + for (i = 0; i < size / 2; i += pagesize) { + lseek(mem_fd, (uintptr_t) map + i, SEEK_SET); + if (write(mem_fd, &i, sizeof(size)) != sizeof(size)) { + ksft_test_result_fail("ptrace write failed\n"); + goto unmap; + } + } + + /* Trigger unsharing on the other half. */ + if (madvise(map + size / 2, size / 2, MADV_UNMERGEABLE)) { + ksft_test_result_fail("MADV_UNMERGEABLE failed\n"); + goto unmap; + } + + ksft_test_result(!range_maps_duplicates(map, size), + "Pages were unmerged\n"); +unmap: + munmap(map, size); +} + int main(int argc, char **argv) { - unsigned int tests = 6; + unsigned int tests = 7; int err; #ifdef __NR_userfaultfd @@ -508,6 +548,9 @@ int main(int argc, char **argv) pagesize = getpagesize(); + mem_fd = open("/proc/self/mem", O_RDWR); + if (mem_fd < 0) + ksft_exit_fail_msg("opening /proc/self/mem failed\n"); ksm_fd = open("/sys/kernel/mm/ksm/run", O_RDWR); if (ksm_fd < 0) ksft_exit_skip("open(\"/sys/kernel/mm/ksm/run\") failed\n"); @@ -529,6 +572,8 @@ int main(int argc, char **argv) test_unmerge_uffd_wp(); #endif + test_prot_none(); + test_prctl(); test_prctl_fork(); test_prctl_unmerge();