1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 static bool test_mmap_region_basic(void) 4 { 5 const vma_flags_t vma_flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, 6 VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT); 7 struct mm_struct mm = {}; 8 unsigned long addr; 9 struct vm_area_struct *vma; 10 VMA_ITERATOR(vmi, &mm, 0); 11 12 current->mm = &mm; 13 14 /* Map at 0x300000, length 0x3000. */ 15 addr = __mmap_region(NULL, 0x300000, 0x3000, vma_flags, 0x300, NULL); 16 ASSERT_EQ(addr, 0x300000); 17 18 /* Map at 0x250000, length 0x3000. */ 19 addr = __mmap_region(NULL, 0x250000, 0x3000, vma_flags, 0x250, NULL); 20 ASSERT_EQ(addr, 0x250000); 21 22 /* Map at 0x303000, merging to 0x300000 of length 0x6000. */ 23 addr = __mmap_region(NULL, 0x303000, 0x3000, vma_flags, 0x303, NULL); 24 ASSERT_EQ(addr, 0x303000); 25 26 /* Map at 0x24d000, merging to 0x250000 of length 0x6000. */ 27 addr = __mmap_region(NULL, 0x24d000, 0x3000, vma_flags, 0x24d, NULL); 28 ASSERT_EQ(addr, 0x24d000); 29 30 ASSERT_EQ(mm.map_count, 2); 31 32 for_each_vma(vmi, vma) { 33 if (vma->vm_start == 0x300000) { 34 ASSERT_EQ(vma->vm_end, 0x306000); 35 ASSERT_EQ(vma->vm_pgoff, 0x300); 36 } else if (vma->vm_start == 0x24d000) { 37 ASSERT_EQ(vma->vm_end, 0x253000); 38 ASSERT_EQ(vma->vm_pgoff, 0x24d); 39 } else { 40 ASSERT_FALSE(true); 41 } 42 } 43 44 cleanup_mm(&mm, &vmi); 45 return true; 46 } 47 48 static bool mmap_region_fill_hole(bool merge) 49 { 50 const vma_flags_t vma_flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, 51 VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT, VMA_MAYEXEC_BIT); 52 vma_flags_t middle_flags = vma_flags; 53 struct mm_struct mm = {}; 54 struct vm_area_struct *vma; 55 unsigned long addr; 56 int count = 0; 57 VMA_ITERATOR(vmi, &mm, 0); 58 59 current->mm = &mm; 60 if (!merge) 61 vma_flags_set(&middle_flags, VMA_EXEC_BIT); 62 63 /* Map at 0x300000, length 0x3000. */ 64 addr = __mmap_region(NULL, 0x300000, 0x3000, vma_flags, 0x300, NULL); 65 ASSERT_EQ(addr, 0x300000); 66 67 /* Map at 0x306000, length 0x3000, leaving a hole. */ 68 addr = __mmap_region(NULL, 0x306000, 0x3000, vma_flags, 0x306, NULL); 69 ASSERT_EQ(addr, 0x306000); 70 ASSERT_EQ(mm.map_count, 2); 71 72 /* Map at 0x303000, length 0x3000, filling the hole. */ 73 addr = __mmap_region(NULL, 0x303000, 0x3000, middle_flags, 0x303, NULL); 74 ASSERT_EQ(addr, 0x303000); 75 ASSERT_EQ(mm.map_count, merge ? 1 : 3); 76 77 vma_iter_set(&vmi, 0); 78 for_each_vma(vmi, vma) { 79 const unsigned long start = 0x300000 + count * 0x3000; 80 const unsigned long end = merge ? 0x309000 : start + 0x3000; 81 /* Only the middle VMA in the non-merge case has VMA_EXEC. */ 82 const bool is_middle_vma = count == 1; 83 const bool expect_exec_vma = is_middle_vma && !merge; 84 85 ASSERT_EQ(vma->vm_start, start); 86 ASSERT_EQ(vma->vm_end, end); 87 ASSERT_EQ(vma_start_pgoff(vma), start >> PAGE_SHIFT); 88 ASSERT_EQ(vma_start_anon_pgoff(vma), start >> PAGE_SHIFT); 89 90 ASSERT_TRUE(vma_test_all(vma, VMA_READ_BIT, VMA_WRITE_BIT, 91 VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT, 92 VMA_MAYEXEC_BIT)); 93 ASSERT_EQ(vma_test(vma, VMA_EXEC_BIT), expect_exec_vma); 94 95 count++; 96 } 97 98 ASSERT_EQ(count, mm.map_count); 99 100 ASSERT_EQ(cleanup_mm(&mm, &vmi), count); 101 return true; 102 } 103 104 static bool test_mmap_region_fill_hole_merge(void) 105 { 106 return mmap_region_fill_hole(true); 107 } 108 109 static bool test_mmap_region_fill_hole_flags_mismatch(void) 110 { 111 return mmap_region_fill_hole(false); 112 } 113 114 static bool test_pure_anon_dev_zero(void) 115 { 116 const vma_flags_t vma_flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, 117 VMA_MAYREAD_BIT, VMA_MAYWRITE_BIT); 118 struct file file = { 119 .f_op = &zero_fops, 120 }; 121 struct mm_struct mm = {}; 122 struct vm_area_struct *vma; 123 unsigned long addr; 124 VMA_ITERATOR(vmi, &mm, 0); 125 126 current->mm = &mm; 127 128 /* 129 * Map a MAP_PRIVATE-/dev/zero mapping at address 0x300000 with a page 130 * offset of 0x10, which we expect to be reset to the anonymous page 131 * offset. 132 */ 133 addr = __mmap_region(&file, 0x300000, 0x3000, vma_flags, 0x10, NULL); 134 ASSERT_EQ(addr, 0x300000); 135 136 /* Assert that it truly is an anonymous mapping. */ 137 vma = vma_lookup(&mm, addr); 138 ASSERT_NE(vma, NULL); 139 ASSERT_TRUE(vma_is_anonymous(vma)); 140 ASSERT_EQ(vma->vm_file, NULL); 141 ASSERT_EQ(vma->vm_private_data, NULL); 142 /* Expect anonymous page offsets. */ 143 ASSERT_EQ(vma->vm_pgoff, 0x300); 144 ASSERT_EQ(vma_start_anon_pgoff(vma), 0x300); 145 146 cleanup_mm(&mm, &vmi); 147 return true; 148 } 149 150 static void run_mmap_tests(int *num_tests, int *num_fail) 151 { 152 TEST(mmap_region_basic); 153 TEST(mmap_region_fill_hole_merge); 154 TEST(mmap_region_fill_hole_flags_mismatch); 155 TEST(pure_anon_dev_zero); 156 } 157