Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/mm: add more mseal traversal tests

Add more mseal traversal tests across VMAs, where we could possibly screw
up sealing checks. These test more across-vma traversal for mprotect,
munmap and madvise. Particularly, we test for the case where a regular
VMA is followed by a sealed VMA.

[akpm@linux-foundation.org: remove incorrect comment, per review]
[akpm@linux-foundation.org: remove the correct comment, per Pedro]
[pedro.falcato@gmail.com: fix mseal's length]
Link: https://lkml.kernel.org/r/vc4czyuemmu3kylqb4ctaga6y5yvondlyabimx6jvljlw2fkea@djawlllf45xa
Link: https://lkml.kernel.org/r/20240817-mseal-depessimize-v3-7-d8d2e037df30@gmail.com
Signed-off-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Jeff Xu <jeffxu@chromium.org>
Cc: Kees Cook <kees@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Pedro Falcato and committed by
Andrew Morton
f28bdd1b 5b3db2b8

+105 -1
+105 -1
tools/testing/selftests/mm/mseal_test.c
··· 777 777 REPORT_TEST_PASS(); 778 778 } 779 779 780 + static void test_seal_mprotect_partial_mprotect_tail(bool seal) 781 + { 782 + void *ptr; 783 + unsigned long page_size = getpagesize(); 784 + unsigned long size = 2 * page_size; 785 + int ret; 786 + int prot; 787 + 788 + /* 789 + * Check if a partial mseal (that results in two vmas) works correctly. 790 + * It might mprotect the first, but it'll never touch the second (msealed) vma. 791 + */ 792 + 793 + setup_single_address(size, &ptr); 794 + FAIL_TEST_IF_FALSE(ptr != (void *)-1); 795 + 796 + if (seal) { 797 + ret = sys_mseal(ptr + page_size, page_size); 798 + FAIL_TEST_IF_FALSE(!ret); 799 + } 800 + 801 + ret = sys_mprotect(ptr, size, PROT_EXEC); 802 + if (seal) 803 + FAIL_TEST_IF_FALSE(ret < 0); 804 + else 805 + FAIL_TEST_IF_FALSE(!ret); 806 + 807 + if (seal) { 808 + FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); 809 + FAIL_TEST_IF_FALSE(prot == 0x4); 810 + } 811 + 812 + REPORT_TEST_PASS(); 813 + } 814 + 815 + 780 816 static void test_seal_mprotect_two_vma_with_gap(bool seal) 781 817 { 782 818 void *ptr; ··· 1026 990 1027 991 ret = sys_munmap(ptr, size); 1028 992 FAIL_TEST_IF_FALSE(!ret); 993 + 994 + REPORT_TEST_PASS(); 995 + } 996 + 997 + static void test_seal_munmap_partial_across_vmas(bool seal) 998 + { 999 + void *ptr; 1000 + unsigned long page_size = getpagesize(); 1001 + unsigned long size = 2 * page_size; 1002 + int ret; 1003 + int prot; 1004 + 1005 + setup_single_address(size, &ptr); 1006 + FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1007 + 1008 + if (seal) { 1009 + ret = sys_mseal(ptr + page_size, page_size); 1010 + FAIL_TEST_IF_FALSE(!ret); 1011 + } 1012 + 1013 + ret = sys_munmap(ptr, size); 1014 + if (seal) 1015 + FAIL_TEST_IF_FALSE(ret < 0); 1016 + else 1017 + FAIL_TEST_IF_FALSE(!ret); 1018 + 1019 + if (seal) { 1020 + FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); 1021 + FAIL_TEST_IF_FALSE(prot == 0x4); 1022 + } 1029 1023 1030 1024 REPORT_TEST_PASS(); 1031 1025 } ··· 1812 1746 REPORT_TEST_PASS(); 1813 1747 } 1814 1748 1749 + static void test_seal_discard_across_vmas(bool seal) 1750 + { 1751 + void *ptr; 1752 + unsigned long page_size = getpagesize(); 1753 + unsigned long size = 2 * page_size; 1754 + int ret; 1755 + 1756 + setup_single_address(size, &ptr); 1757 + FAIL_TEST_IF_FALSE(ptr != (void *)-1); 1758 + 1759 + if (seal) { 1760 + ret = seal_single_address(ptr + page_size, page_size); 1761 + FAIL_TEST_IF_FALSE(!ret); 1762 + } 1763 + 1764 + ret = sys_madvise(ptr, size, MADV_DONTNEED); 1765 + if (seal) 1766 + FAIL_TEST_IF_FALSE(ret < 0); 1767 + else 1768 + FAIL_TEST_IF_FALSE(!ret); 1769 + 1770 + ret = sys_munmap(ptr, size); 1771 + if (seal) 1772 + FAIL_TEST_IF_FALSE(ret < 0); 1773 + else 1774 + FAIL_TEST_IF_FALSE(!ret); 1775 + 1776 + REPORT_TEST_PASS(); 1777 + } 1778 + 1779 + 1815 1780 static void test_seal_madvise_nodiscard(bool seal) 1816 1781 { 1817 1782 void *ptr; ··· 1887 1790 if (!pkey_supported()) 1888 1791 ksft_print_msg("PKEY not supported\n"); 1889 1792 1890 - ksft_set_plan(82); 1793 + ksft_set_plan(88); 1891 1794 1892 1795 test_seal_addseal(); 1893 1796 test_seal_unmapped_start(); ··· 1933 1836 test_seal_mprotect_split(false); 1934 1837 test_seal_mprotect_split(true); 1935 1838 1839 + test_seal_mprotect_partial_mprotect_tail(false); 1840 + test_seal_mprotect_partial_mprotect_tail(true); 1841 + 1936 1842 test_seal_munmap(false); 1937 1843 test_seal_munmap(true); 1938 1844 test_seal_munmap_two_vma(false); 1939 1845 test_seal_munmap_two_vma(true); 1940 1846 test_seal_munmap_vma_with_gap(false); 1941 1847 test_seal_munmap_vma_with_gap(true); 1848 + test_seal_munmap_partial_across_vmas(false); 1849 + test_seal_munmap_partial_across_vmas(true); 1942 1850 1943 1851 test_munmap_start_freed(false); 1944 1852 test_munmap_start_freed(true); ··· 1975 1873 test_seal_madvise_nodiscard(true); 1976 1874 test_seal_discard_ro_anon(false); 1977 1875 test_seal_discard_ro_anon(true); 1876 + test_seal_discard_across_vmas(false); 1877 + test_seal_discard_across_vmas(true); 1978 1878 test_seal_discard_ro_anon_on_rw(false); 1979 1879 test_seal_discard_ro_anon_on_rw(true); 1980 1880 test_seal_discard_ro_anon_on_shared(false);