From patchwork Thu Aug 3 14:32:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 13340201 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 F0B2CEB64DD for ; Thu, 3 Aug 2023 14:33:18 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8D71B28026C; Thu, 3 Aug 2023 10:33:18 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 85FC228022C; Thu, 3 Aug 2023 10:33:18 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7028828026C; Thu, 3 Aug 2023 10:33:18 -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 5B10F28022C for ; Thu, 3 Aug 2023 10:33:18 -0400 (EDT) Received: from smtpin09.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id F24D98080E for ; Thu, 3 Aug 2023 14:33:17 +0000 (UTC) X-FDA: 81083036034.09.5EB9400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf13.hostedemail.com (Postfix) with ESMTP id 77EA320064 for ; Thu, 3 Aug 2023 14:32:41 +0000 (UTC) Authentication-Results: imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=M0ZiWK+a; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf13.hostedemail.com: domain of david@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=david@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1691073161; 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=wSyuiLd0qpT2GA2Estawqg/xJHM5HjhNUFEKOxKI28GGH8jODToBBkyOsix+bTwNGS/T0d aId7rXgmHSjno0wao6K5iStnVs4sBaFdg5OZ/bPCCFTBu9RK0l4sKcQ7folHbdXdE+J6DF mKnwRmTaptTlgKlRrEjIHHU++IXEG/4= ARC-Authentication-Results: i=1; imf13.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=M0ZiWK+a; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf13.hostedemail.com: domain of david@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=david@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1691073161; a=rsa-sha256; cv=none; b=AM7gI4h/PiWC9Js17oOfcivsWh3LzzmRynbAg2lUdqElpfx1am15D7aU9TCAqQbqyyaCSX Un6RT073BzUdZC7BCJR/bxxsp89VPl/ZN4jIWMwjUAktsIb0T1hapj+3VDJL8OuQdnRL4z B1tinRfNbgGtiI4wmZYgWgj/f04HGUQ= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691073160; 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=M0ZiWK+ayIqeG5BHo+BNiwNZTdvVd0U61HvjTBkrQUgFmtY+3sG+YFttw70UpK7aiFKA24 P7xZQsXB3UHD8riFZRpy5/mxq/4ohStJJ/8wxnHnQmyKuDu5jG8WJT7SpgwzHUA9N+0c2V mjT+A3TP+JgRCRpZ/oRTstSIj/GhGIU= 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-650-PGKiOyclP_iO75_O7B9M2w-1; Thu, 03 Aug 2023 10:32:36 -0400 X-MC-Unique: PGKiOyclP_iO75_O7B9M2w-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 686CE8DC664; Thu, 3 Aug 2023 14:32:35 +0000 (UTC) Received: from t14s.fritz.box (unknown [10.39.193.129]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5569C201EE6E; Thu, 3 Aug 2023 14:32:32 +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 v3 7/7] selftest/mm: ksm_functional_tests: Add PROT_NONE test Date: Thu, 3 Aug 2023 16:32:08 +0200 Message-ID: <20230803143208.383663-8-david@redhat.com> In-Reply-To: <20230803143208.383663-1-david@redhat.com> References: <20230803143208.383663-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 77EA320064 X-Stat-Signature: iaun7mxeciu1n6xxi7f1c5e9b15h3qta X-HE-Tag: 1691073161-157529 X-HE-Meta: U2FsdGVkX1+d14kPEtArllS3p6SyGF9AbUgW3secSILQuXhCLnAXNiKCJ+48wwWPTxefKYpsQqC+Zq98rPIYn0/Ox2IUYlfAbV9a/nB1xF3MHUe1bYWtcK6rHFuV1TFh7Rh8yOZgUssa2cQecpLVq/OY0NZKbCE7vipIM1o8mtrKjLNleI6ICFj0kSjoPXw2O09QAWAENCvs9bDWiat+RtLOTSxeZyQRQVnzMxovrXp58HFFMFm4TSnZzcBNoLV08qMckQd9vwpbcp34qc1nl24BZWY5xH//scFyTiX9WoUIGCpw9th6hKTH8go/8d7wjf4JaOMsCvu33E/KIwxM1hNQyIOD4uCID5VcKqpv8zI8P6wOjuzJ0wbd03y6CjIzSOePr5iVHcpUts8YkEbwzHK+mv+0EdqPXRdUSNB5XRL3QqPRwlcCGwsKB5CAzV13vnWlybpag60AJWK/Gjbo8Xtja9j0C3JyqCJnwHBM/d0i3Mz51R6fvuMUxf/4aBDxwgFqV7sNBXVmfBT8XSfiiROXA9kzj/Qw/J3MEAvvEm71nBDvMdF3oMOrKcxS41LaJDSG/XN3ihuSkBoCPKH4wu0HlnNIn5mPCt6vyzbuQmrj2cS4wEmbYuUdPFYpklM65WrRoxDNq+DU2RsjPktDHhi0Og+mNo9NMusng9r5Txk+egzQj1ljC78xzJv43JukE8PRYfvNbL+Qbofz+KNz4U0LUwfMEWagyL20ZbSHXLYYPHICB+GTCR0hDi4kmx4zS4RsrHZeoZkeaAbIUarGuAQ9mSYhkKYwV7F+5GXBwuigueQNWyeakOfCB+jGHiMv6P94sG+V7fD/8jZay/AQYHfYuXtHSEqQBihdYeKMQZ8IJuzfHETo8RNmFyCvqKddFMWwtnoPdNGwDLvcmxApOAk/VSZtVn3UqMhYJHlvVLIQoXpdBSFe1zIZx2brZ86pUvFsDUXtCWtOReY+QMV GLsrmf1B 9OIqzXiY3Rv0L0eOKX+Vv+OmczZl/DgdwIZTN7RyBHrD9XoDVhRgo+H19237PAw292S+mE9BZo4Ctt0apNFNSp2BLJRLZCRuAJxBiuTym3w/V+B3vSs3BvkhHn1ldIqCET7LzSTjBjrgA6TJ36Id1Y6qZUFSBJ5nsnCIq7YJSaFQuxg3ug1t4ezrJyRPzU4G+MqnoF34pA4rZ7LcjLWif+n6pKe+FKP3r8Htl 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 Acked-by: Peter Xu 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();