1*6aacab30SLorenzo Stoakes // SPDX-License-Identifier: GPL-2.0-or-later
2*6aacab30SLorenzo Stoakes
3*6aacab30SLorenzo Stoakes /* Helper function which provides a wrapper around a merge new VMA operation. */
merge_new(struct vma_merge_struct * vmg)4*6aacab30SLorenzo Stoakes static struct vm_area_struct *merge_new(struct vma_merge_struct *vmg)
5*6aacab30SLorenzo Stoakes {
6*6aacab30SLorenzo Stoakes struct vm_area_struct *vma;
7*6aacab30SLorenzo Stoakes /*
8*6aacab30SLorenzo Stoakes * For convenience, get prev and next VMAs. Which the new VMA operation
9*6aacab30SLorenzo Stoakes * requires.
10*6aacab30SLorenzo Stoakes */
11*6aacab30SLorenzo Stoakes vmg->next = vma_next(vmg->vmi);
12*6aacab30SLorenzo Stoakes vmg->prev = vma_prev(vmg->vmi);
13*6aacab30SLorenzo Stoakes vma_iter_next_range(vmg->vmi);
14*6aacab30SLorenzo Stoakes
15*6aacab30SLorenzo Stoakes vma = vma_merge_new_range(vmg);
16*6aacab30SLorenzo Stoakes if (vma)
17*6aacab30SLorenzo Stoakes vma_assert_attached(vma);
18*6aacab30SLorenzo Stoakes
19*6aacab30SLorenzo Stoakes return vma;
20*6aacab30SLorenzo Stoakes }
21*6aacab30SLorenzo Stoakes
22*6aacab30SLorenzo Stoakes /*
23*6aacab30SLorenzo Stoakes * Helper function which provides a wrapper around the expansion of an existing
24*6aacab30SLorenzo Stoakes * VMA.
25*6aacab30SLorenzo Stoakes */
expand_existing(struct vma_merge_struct * vmg)26*6aacab30SLorenzo Stoakes static int expand_existing(struct vma_merge_struct *vmg)
27*6aacab30SLorenzo Stoakes {
28*6aacab30SLorenzo Stoakes return vma_expand(vmg);
29*6aacab30SLorenzo Stoakes }
30*6aacab30SLorenzo Stoakes
31*6aacab30SLorenzo Stoakes /*
32*6aacab30SLorenzo Stoakes * Helper function to reset merge state the associated VMA iterator to a
33*6aacab30SLorenzo Stoakes * specified new range.
34*6aacab30SLorenzo Stoakes */
vmg_set_range(struct vma_merge_struct * vmg,unsigned long start,unsigned long end,pgoff_t pgoff,vm_flags_t vm_flags)35*6aacab30SLorenzo Stoakes void vmg_set_range(struct vma_merge_struct *vmg, unsigned long start,
36*6aacab30SLorenzo Stoakes unsigned long end, pgoff_t pgoff, vm_flags_t vm_flags)
37*6aacab30SLorenzo Stoakes {
38*6aacab30SLorenzo Stoakes vma_iter_set(vmg->vmi, start);
39*6aacab30SLorenzo Stoakes
40*6aacab30SLorenzo Stoakes vmg->prev = NULL;
41*6aacab30SLorenzo Stoakes vmg->middle = NULL;
42*6aacab30SLorenzo Stoakes vmg->next = NULL;
43*6aacab30SLorenzo Stoakes vmg->target = NULL;
44*6aacab30SLorenzo Stoakes
45*6aacab30SLorenzo Stoakes vmg->start = start;
46*6aacab30SLorenzo Stoakes vmg->end = end;
47*6aacab30SLorenzo Stoakes vmg->pgoff = pgoff;
48*6aacab30SLorenzo Stoakes vmg->vm_flags = vm_flags;
49*6aacab30SLorenzo Stoakes
50*6aacab30SLorenzo Stoakes vmg->just_expand = false;
51*6aacab30SLorenzo Stoakes vmg->__remove_middle = false;
52*6aacab30SLorenzo Stoakes vmg->__remove_next = false;
53*6aacab30SLorenzo Stoakes vmg->__adjust_middle_start = false;
54*6aacab30SLorenzo Stoakes vmg->__adjust_next_start = false;
55*6aacab30SLorenzo Stoakes }
56*6aacab30SLorenzo Stoakes
57*6aacab30SLorenzo Stoakes /* Helper function to set both the VMG range and its anon_vma. */
vmg_set_range_anon_vma(struct vma_merge_struct * vmg,unsigned long start,unsigned long end,pgoff_t pgoff,vm_flags_t vm_flags,struct anon_vma * anon_vma)58*6aacab30SLorenzo Stoakes static void vmg_set_range_anon_vma(struct vma_merge_struct *vmg, unsigned long start,
59*6aacab30SLorenzo Stoakes unsigned long end, pgoff_t pgoff, vm_flags_t vm_flags,
60*6aacab30SLorenzo Stoakes struct anon_vma *anon_vma)
61*6aacab30SLorenzo Stoakes {
62*6aacab30SLorenzo Stoakes vmg_set_range(vmg, start, end, pgoff, vm_flags);
63*6aacab30SLorenzo Stoakes vmg->anon_vma = anon_vma;
64*6aacab30SLorenzo Stoakes }
65*6aacab30SLorenzo Stoakes
66*6aacab30SLorenzo Stoakes /*
67*6aacab30SLorenzo Stoakes * Helper function to try to merge a new VMA.
68*6aacab30SLorenzo Stoakes *
69*6aacab30SLorenzo Stoakes * Update vmg and the iterator for it and try to merge, otherwise allocate a new
70*6aacab30SLorenzo Stoakes * VMA, link it to the maple tree and return it.
71*6aacab30SLorenzo Stoakes */
try_merge_new_vma(struct mm_struct * mm,struct vma_merge_struct * vmg,unsigned long start,unsigned long end,pgoff_t pgoff,vm_flags_t vm_flags,bool * was_merged)72*6aacab30SLorenzo Stoakes static struct vm_area_struct *try_merge_new_vma(struct mm_struct *mm,
73*6aacab30SLorenzo Stoakes struct vma_merge_struct *vmg, unsigned long start,
74*6aacab30SLorenzo Stoakes unsigned long end, pgoff_t pgoff, vm_flags_t vm_flags,
75*6aacab30SLorenzo Stoakes bool *was_merged)
76*6aacab30SLorenzo Stoakes {
77*6aacab30SLorenzo Stoakes struct vm_area_struct *merged;
78*6aacab30SLorenzo Stoakes
79*6aacab30SLorenzo Stoakes vmg_set_range(vmg, start, end, pgoff, vm_flags);
80*6aacab30SLorenzo Stoakes
81*6aacab30SLorenzo Stoakes merged = merge_new(vmg);
82*6aacab30SLorenzo Stoakes if (merged) {
83*6aacab30SLorenzo Stoakes *was_merged = true;
84*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg->state, VMA_MERGE_SUCCESS);
85*6aacab30SLorenzo Stoakes return merged;
86*6aacab30SLorenzo Stoakes }
87*6aacab30SLorenzo Stoakes
88*6aacab30SLorenzo Stoakes *was_merged = false;
89*6aacab30SLorenzo Stoakes
90*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg->state, VMA_MERGE_NOMERGE);
91*6aacab30SLorenzo Stoakes
92*6aacab30SLorenzo Stoakes return alloc_and_link_vma(mm, start, end, pgoff, vm_flags);
93*6aacab30SLorenzo Stoakes }
94*6aacab30SLorenzo Stoakes
test_simple_merge(void)95*6aacab30SLorenzo Stoakes static bool test_simple_merge(void)
96*6aacab30SLorenzo Stoakes {
97*6aacab30SLorenzo Stoakes struct vm_area_struct *vma;
98*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
99*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
100*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_left = alloc_vma(&mm, 0, 0x1000, 0, vm_flags);
101*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_right = alloc_vma(&mm, 0x2000, 0x3000, 2, vm_flags);
102*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0x1000);
103*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
104*6aacab30SLorenzo Stoakes .mm = &mm,
105*6aacab30SLorenzo Stoakes .vmi = &vmi,
106*6aacab30SLorenzo Stoakes .start = 0x1000,
107*6aacab30SLorenzo Stoakes .end = 0x2000,
108*6aacab30SLorenzo Stoakes .vm_flags = vm_flags,
109*6aacab30SLorenzo Stoakes .pgoff = 1,
110*6aacab30SLorenzo Stoakes };
111*6aacab30SLorenzo Stoakes
112*6aacab30SLorenzo Stoakes ASSERT_FALSE(attach_vma(&mm, vma_left));
113*6aacab30SLorenzo Stoakes ASSERT_FALSE(attach_vma(&mm, vma_right));
114*6aacab30SLorenzo Stoakes
115*6aacab30SLorenzo Stoakes vma = merge_new(&vmg);
116*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
117*6aacab30SLorenzo Stoakes
118*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
119*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x3000);
120*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
121*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_flags, vm_flags);
122*6aacab30SLorenzo Stoakes
123*6aacab30SLorenzo Stoakes detach_free_vma(vma);
124*6aacab30SLorenzo Stoakes mtree_destroy(&mm.mm_mt);
125*6aacab30SLorenzo Stoakes
126*6aacab30SLorenzo Stoakes return true;
127*6aacab30SLorenzo Stoakes }
128*6aacab30SLorenzo Stoakes
test_simple_modify(void)129*6aacab30SLorenzo Stoakes static bool test_simple_modify(void)
130*6aacab30SLorenzo Stoakes {
131*6aacab30SLorenzo Stoakes struct vm_area_struct *vma;
132*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
133*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
134*6aacab30SLorenzo Stoakes struct vm_area_struct *init_vma = alloc_vma(&mm, 0, 0x3000, 0, vm_flags);
135*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0x1000);
136*6aacab30SLorenzo Stoakes vm_flags_t flags = VM_READ | VM_MAYREAD;
137*6aacab30SLorenzo Stoakes
138*6aacab30SLorenzo Stoakes ASSERT_FALSE(attach_vma(&mm, init_vma));
139*6aacab30SLorenzo Stoakes
140*6aacab30SLorenzo Stoakes /*
141*6aacab30SLorenzo Stoakes * The flags will not be changed, the vma_modify_flags() function
142*6aacab30SLorenzo Stoakes * performs the merge/split only.
143*6aacab30SLorenzo Stoakes */
144*6aacab30SLorenzo Stoakes vma = vma_modify_flags(&vmi, init_vma, init_vma,
145*6aacab30SLorenzo Stoakes 0x1000, 0x2000, &flags);
146*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
147*6aacab30SLorenzo Stoakes /* We modify the provided VMA, and on split allocate new VMAs. */
148*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, init_vma);
149*6aacab30SLorenzo Stoakes
150*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x1000);
151*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x2000);
152*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 1);
153*6aacab30SLorenzo Stoakes
154*6aacab30SLorenzo Stoakes /*
155*6aacab30SLorenzo Stoakes * Now walk through the three split VMAs and make sure they are as
156*6aacab30SLorenzo Stoakes * expected.
157*6aacab30SLorenzo Stoakes */
158*6aacab30SLorenzo Stoakes
159*6aacab30SLorenzo Stoakes vma_iter_set(&vmi, 0);
160*6aacab30SLorenzo Stoakes vma = vma_iter_load(&vmi);
161*6aacab30SLorenzo Stoakes
162*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
163*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x1000);
164*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
165*6aacab30SLorenzo Stoakes
166*6aacab30SLorenzo Stoakes detach_free_vma(vma);
167*6aacab30SLorenzo Stoakes vma_iter_clear(&vmi);
168*6aacab30SLorenzo Stoakes
169*6aacab30SLorenzo Stoakes vma = vma_next(&vmi);
170*6aacab30SLorenzo Stoakes
171*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x1000);
172*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x2000);
173*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 1);
174*6aacab30SLorenzo Stoakes
175*6aacab30SLorenzo Stoakes detach_free_vma(vma);
176*6aacab30SLorenzo Stoakes vma_iter_clear(&vmi);
177*6aacab30SLorenzo Stoakes
178*6aacab30SLorenzo Stoakes vma = vma_next(&vmi);
179*6aacab30SLorenzo Stoakes
180*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x2000);
181*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x3000);
182*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 2);
183*6aacab30SLorenzo Stoakes
184*6aacab30SLorenzo Stoakes detach_free_vma(vma);
185*6aacab30SLorenzo Stoakes mtree_destroy(&mm.mm_mt);
186*6aacab30SLorenzo Stoakes
187*6aacab30SLorenzo Stoakes return true;
188*6aacab30SLorenzo Stoakes }
189*6aacab30SLorenzo Stoakes
test_simple_expand(void)190*6aacab30SLorenzo Stoakes static bool test_simple_expand(void)
191*6aacab30SLorenzo Stoakes {
192*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
193*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
194*6aacab30SLorenzo Stoakes struct vm_area_struct *vma = alloc_vma(&mm, 0, 0x1000, 0, vm_flags);
195*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
196*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
197*6aacab30SLorenzo Stoakes .vmi = &vmi,
198*6aacab30SLorenzo Stoakes .target = vma,
199*6aacab30SLorenzo Stoakes .start = 0,
200*6aacab30SLorenzo Stoakes .end = 0x3000,
201*6aacab30SLorenzo Stoakes .pgoff = 0,
202*6aacab30SLorenzo Stoakes };
203*6aacab30SLorenzo Stoakes
204*6aacab30SLorenzo Stoakes ASSERT_FALSE(attach_vma(&mm, vma));
205*6aacab30SLorenzo Stoakes
206*6aacab30SLorenzo Stoakes ASSERT_FALSE(expand_existing(&vmg));
207*6aacab30SLorenzo Stoakes
208*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
209*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x3000);
210*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
211*6aacab30SLorenzo Stoakes
212*6aacab30SLorenzo Stoakes detach_free_vma(vma);
213*6aacab30SLorenzo Stoakes mtree_destroy(&mm.mm_mt);
214*6aacab30SLorenzo Stoakes
215*6aacab30SLorenzo Stoakes return true;
216*6aacab30SLorenzo Stoakes }
217*6aacab30SLorenzo Stoakes
test_simple_shrink(void)218*6aacab30SLorenzo Stoakes static bool test_simple_shrink(void)
219*6aacab30SLorenzo Stoakes {
220*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
221*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
222*6aacab30SLorenzo Stoakes struct vm_area_struct *vma = alloc_vma(&mm, 0, 0x3000, 0, vm_flags);
223*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
224*6aacab30SLorenzo Stoakes
225*6aacab30SLorenzo Stoakes ASSERT_FALSE(attach_vma(&mm, vma));
226*6aacab30SLorenzo Stoakes
227*6aacab30SLorenzo Stoakes ASSERT_FALSE(vma_shrink(&vmi, vma, 0, 0x1000, 0));
228*6aacab30SLorenzo Stoakes
229*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
230*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x1000);
231*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
232*6aacab30SLorenzo Stoakes
233*6aacab30SLorenzo Stoakes detach_free_vma(vma);
234*6aacab30SLorenzo Stoakes mtree_destroy(&mm.mm_mt);
235*6aacab30SLorenzo Stoakes
236*6aacab30SLorenzo Stoakes return true;
237*6aacab30SLorenzo Stoakes }
238*6aacab30SLorenzo Stoakes
__test_merge_new(bool is_sticky,bool a_is_sticky,bool b_is_sticky,bool c_is_sticky)239*6aacab30SLorenzo Stoakes static bool __test_merge_new(bool is_sticky, bool a_is_sticky, bool b_is_sticky, bool c_is_sticky)
240*6aacab30SLorenzo Stoakes {
241*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
242*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
243*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
244*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
245*6aacab30SLorenzo Stoakes .mm = &mm,
246*6aacab30SLorenzo Stoakes .vmi = &vmi,
247*6aacab30SLorenzo Stoakes };
248*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_a = {
249*6aacab30SLorenzo Stoakes .anon_vma = &dummy_anon_vma,
250*6aacab30SLorenzo Stoakes };
251*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_b = {
252*6aacab30SLorenzo Stoakes .anon_vma = &dummy_anon_vma,
253*6aacab30SLorenzo Stoakes };
254*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_c = {
255*6aacab30SLorenzo Stoakes .anon_vma = &dummy_anon_vma,
256*6aacab30SLorenzo Stoakes };
257*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_d = {
258*6aacab30SLorenzo Stoakes .anon_vma = &dummy_anon_vma,
259*6aacab30SLorenzo Stoakes };
260*6aacab30SLorenzo Stoakes const struct vm_operations_struct vm_ops = {
261*6aacab30SLorenzo Stoakes .close = dummy_close,
262*6aacab30SLorenzo Stoakes };
263*6aacab30SLorenzo Stoakes int count;
264*6aacab30SLorenzo Stoakes struct vm_area_struct *vma, *vma_a, *vma_b, *vma_c, *vma_d;
265*6aacab30SLorenzo Stoakes bool merged;
266*6aacab30SLorenzo Stoakes
267*6aacab30SLorenzo Stoakes if (is_sticky)
268*6aacab30SLorenzo Stoakes vm_flags |= VM_STICKY;
269*6aacab30SLorenzo Stoakes
270*6aacab30SLorenzo Stoakes /*
271*6aacab30SLorenzo Stoakes * 0123456789abc
272*6aacab30SLorenzo Stoakes * AA B CC
273*6aacab30SLorenzo Stoakes */
274*6aacab30SLorenzo Stoakes vma_a = alloc_and_link_vma(&mm, 0, 0x2000, 0, vm_flags);
275*6aacab30SLorenzo Stoakes ASSERT_NE(vma_a, NULL);
276*6aacab30SLorenzo Stoakes if (a_is_sticky)
277*6aacab30SLorenzo Stoakes vm_flags_set(vma_a, VM_STICKY);
278*6aacab30SLorenzo Stoakes /* We give each VMA a single avc so we can test anon_vma duplication. */
279*6aacab30SLorenzo Stoakes INIT_LIST_HEAD(&vma_a->anon_vma_chain);
280*6aacab30SLorenzo Stoakes list_add(&dummy_anon_vma_chain_a.same_vma, &vma_a->anon_vma_chain);
281*6aacab30SLorenzo Stoakes
282*6aacab30SLorenzo Stoakes vma_b = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, vm_flags);
283*6aacab30SLorenzo Stoakes ASSERT_NE(vma_b, NULL);
284*6aacab30SLorenzo Stoakes if (b_is_sticky)
285*6aacab30SLorenzo Stoakes vm_flags_set(vma_b, VM_STICKY);
286*6aacab30SLorenzo Stoakes INIT_LIST_HEAD(&vma_b->anon_vma_chain);
287*6aacab30SLorenzo Stoakes list_add(&dummy_anon_vma_chain_b.same_vma, &vma_b->anon_vma_chain);
288*6aacab30SLorenzo Stoakes
289*6aacab30SLorenzo Stoakes vma_c = alloc_and_link_vma(&mm, 0xb000, 0xc000, 0xb, vm_flags);
290*6aacab30SLorenzo Stoakes ASSERT_NE(vma_c, NULL);
291*6aacab30SLorenzo Stoakes if (c_is_sticky)
292*6aacab30SLorenzo Stoakes vm_flags_set(vma_c, VM_STICKY);
293*6aacab30SLorenzo Stoakes INIT_LIST_HEAD(&vma_c->anon_vma_chain);
294*6aacab30SLorenzo Stoakes list_add(&dummy_anon_vma_chain_c.same_vma, &vma_c->anon_vma_chain);
295*6aacab30SLorenzo Stoakes
296*6aacab30SLorenzo Stoakes /*
297*6aacab30SLorenzo Stoakes * NO merge.
298*6aacab30SLorenzo Stoakes *
299*6aacab30SLorenzo Stoakes * 0123456789abc
300*6aacab30SLorenzo Stoakes * AA B ** CC
301*6aacab30SLorenzo Stoakes */
302*6aacab30SLorenzo Stoakes vma_d = try_merge_new_vma(&mm, &vmg, 0x7000, 0x9000, 7, vm_flags, &merged);
303*6aacab30SLorenzo Stoakes ASSERT_NE(vma_d, NULL);
304*6aacab30SLorenzo Stoakes INIT_LIST_HEAD(&vma_d->anon_vma_chain);
305*6aacab30SLorenzo Stoakes list_add(&dummy_anon_vma_chain_d.same_vma, &vma_d->anon_vma_chain);
306*6aacab30SLorenzo Stoakes ASSERT_FALSE(merged);
307*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 4);
308*6aacab30SLorenzo Stoakes
309*6aacab30SLorenzo Stoakes /*
310*6aacab30SLorenzo Stoakes * Merge BOTH sides.
311*6aacab30SLorenzo Stoakes *
312*6aacab30SLorenzo Stoakes * 0123456789abc
313*6aacab30SLorenzo Stoakes * AA*B DD CC
314*6aacab30SLorenzo Stoakes */
315*6aacab30SLorenzo Stoakes vma_a->vm_ops = &vm_ops; /* This should have no impact. */
316*6aacab30SLorenzo Stoakes vma_b->anon_vma = &dummy_anon_vma;
317*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0x2000, 0x3000, 2, vm_flags, &merged);
318*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_a);
319*6aacab30SLorenzo Stoakes /* Merge with A, delete B. */
320*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
321*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
322*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x4000);
323*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
324*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
325*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
326*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 3);
327*6aacab30SLorenzo Stoakes if (is_sticky || a_is_sticky || b_is_sticky)
328*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
329*6aacab30SLorenzo Stoakes
330*6aacab30SLorenzo Stoakes /*
331*6aacab30SLorenzo Stoakes * Merge to PREVIOUS VMA.
332*6aacab30SLorenzo Stoakes *
333*6aacab30SLorenzo Stoakes * 0123456789abc
334*6aacab30SLorenzo Stoakes * AAAA* DD CC
335*6aacab30SLorenzo Stoakes */
336*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0x4000, 0x5000, 4, vm_flags, &merged);
337*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_a);
338*6aacab30SLorenzo Stoakes /* Extend A. */
339*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
340*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
341*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x5000);
342*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
343*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
344*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
345*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 3);
346*6aacab30SLorenzo Stoakes if (is_sticky || a_is_sticky)
347*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
348*6aacab30SLorenzo Stoakes
349*6aacab30SLorenzo Stoakes /*
350*6aacab30SLorenzo Stoakes * Merge to NEXT VMA.
351*6aacab30SLorenzo Stoakes *
352*6aacab30SLorenzo Stoakes * 0123456789abc
353*6aacab30SLorenzo Stoakes * AAAAA *DD CC
354*6aacab30SLorenzo Stoakes */
355*6aacab30SLorenzo Stoakes vma_d->anon_vma = &dummy_anon_vma;
356*6aacab30SLorenzo Stoakes vma_d->vm_ops = &vm_ops; /* This should have no impact. */
357*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0x6000, 0x7000, 6, vm_flags, &merged);
358*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_d);
359*6aacab30SLorenzo Stoakes /* Prepend. */
360*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
361*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x6000);
362*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x9000);
363*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 6);
364*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
365*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
366*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 3);
367*6aacab30SLorenzo Stoakes if (is_sticky) /* D uses is_sticky. */
368*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
369*6aacab30SLorenzo Stoakes
370*6aacab30SLorenzo Stoakes /*
371*6aacab30SLorenzo Stoakes * Merge BOTH sides.
372*6aacab30SLorenzo Stoakes *
373*6aacab30SLorenzo Stoakes * 0123456789abc
374*6aacab30SLorenzo Stoakes * AAAAA*DDD CC
375*6aacab30SLorenzo Stoakes */
376*6aacab30SLorenzo Stoakes vma_d->vm_ops = NULL; /* This would otherwise degrade the merge. */
377*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0x5000, 0x6000, 5, vm_flags, &merged);
378*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_a);
379*6aacab30SLorenzo Stoakes /* Merge with A, delete D. */
380*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
381*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
382*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x9000);
383*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
384*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
385*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
386*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 2);
387*6aacab30SLorenzo Stoakes if (is_sticky || a_is_sticky)
388*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
389*6aacab30SLorenzo Stoakes
390*6aacab30SLorenzo Stoakes /*
391*6aacab30SLorenzo Stoakes * Merge to NEXT VMA.
392*6aacab30SLorenzo Stoakes *
393*6aacab30SLorenzo Stoakes * 0123456789abc
394*6aacab30SLorenzo Stoakes * AAAAAAAAA *CC
395*6aacab30SLorenzo Stoakes */
396*6aacab30SLorenzo Stoakes vma_c->anon_vma = &dummy_anon_vma;
397*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0xa000, 0xb000, 0xa, vm_flags, &merged);
398*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_c);
399*6aacab30SLorenzo Stoakes /* Prepend C. */
400*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
401*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0xa000);
402*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0xc000);
403*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0xa);
404*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
405*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
406*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 2);
407*6aacab30SLorenzo Stoakes if (is_sticky || c_is_sticky)
408*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
409*6aacab30SLorenzo Stoakes
410*6aacab30SLorenzo Stoakes /*
411*6aacab30SLorenzo Stoakes * Merge BOTH sides.
412*6aacab30SLorenzo Stoakes *
413*6aacab30SLorenzo Stoakes * 0123456789abc
414*6aacab30SLorenzo Stoakes * AAAAAAAAA*CCC
415*6aacab30SLorenzo Stoakes */
416*6aacab30SLorenzo Stoakes vma = try_merge_new_vma(&mm, &vmg, 0x9000, 0xa000, 0x9, vm_flags, &merged);
417*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_a);
418*6aacab30SLorenzo Stoakes /* Extend A and delete C. */
419*6aacab30SLorenzo Stoakes ASSERT_TRUE(merged);
420*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
421*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0xc000);
422*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
423*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
424*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
425*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 1);
426*6aacab30SLorenzo Stoakes if (is_sticky || a_is_sticky || c_is_sticky)
427*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma->vm_flags, VM_STICKY));
428*6aacab30SLorenzo Stoakes
429*6aacab30SLorenzo Stoakes /*
430*6aacab30SLorenzo Stoakes * Final state.
431*6aacab30SLorenzo Stoakes *
432*6aacab30SLorenzo Stoakes * 0123456789abc
433*6aacab30SLorenzo Stoakes * AAAAAAAAAAAAA
434*6aacab30SLorenzo Stoakes */
435*6aacab30SLorenzo Stoakes
436*6aacab30SLorenzo Stoakes count = 0;
437*6aacab30SLorenzo Stoakes vma_iter_set(&vmi, 0);
438*6aacab30SLorenzo Stoakes for_each_vma(vmi, vma) {
439*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
440*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
441*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0xc000);
442*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
443*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);
444*6aacab30SLorenzo Stoakes
445*6aacab30SLorenzo Stoakes detach_free_vma(vma);
446*6aacab30SLorenzo Stoakes count++;
447*6aacab30SLorenzo Stoakes }
448*6aacab30SLorenzo Stoakes
449*6aacab30SLorenzo Stoakes /* Should only have one VMA left (though freed) after all is done.*/
450*6aacab30SLorenzo Stoakes ASSERT_EQ(count, 1);
451*6aacab30SLorenzo Stoakes
452*6aacab30SLorenzo Stoakes mtree_destroy(&mm.mm_mt);
453*6aacab30SLorenzo Stoakes return true;
454*6aacab30SLorenzo Stoakes }
455*6aacab30SLorenzo Stoakes
test_merge_new(void)456*6aacab30SLorenzo Stoakes static bool test_merge_new(void)
457*6aacab30SLorenzo Stoakes {
458*6aacab30SLorenzo Stoakes int i, j, k, l;
459*6aacab30SLorenzo Stoakes
460*6aacab30SLorenzo Stoakes /* Generate every possible permutation of sticky flags. */
461*6aacab30SLorenzo Stoakes for (i = 0; i < 2; i++)
462*6aacab30SLorenzo Stoakes for (j = 0; j < 2; j++)
463*6aacab30SLorenzo Stoakes for (k = 0; k < 2; k++)
464*6aacab30SLorenzo Stoakes for (l = 0; l < 2; l++)
465*6aacab30SLorenzo Stoakes ASSERT_TRUE(__test_merge_new(i, j, k, l));
466*6aacab30SLorenzo Stoakes
467*6aacab30SLorenzo Stoakes return true;
468*6aacab30SLorenzo Stoakes }
469*6aacab30SLorenzo Stoakes
test_vma_merge_special_flags(void)470*6aacab30SLorenzo Stoakes static bool test_vma_merge_special_flags(void)
471*6aacab30SLorenzo Stoakes {
472*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
473*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
474*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
475*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
476*6aacab30SLorenzo Stoakes .mm = &mm,
477*6aacab30SLorenzo Stoakes .vmi = &vmi,
478*6aacab30SLorenzo Stoakes };
479*6aacab30SLorenzo Stoakes vm_flags_t special_flags[] = { VM_IO, VM_DONTEXPAND, VM_PFNMAP, VM_MIXEDMAP };
480*6aacab30SLorenzo Stoakes vm_flags_t all_special_flags = 0;
481*6aacab30SLorenzo Stoakes int i;
482*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_left, *vma;
483*6aacab30SLorenzo Stoakes
484*6aacab30SLorenzo Stoakes /* Make sure there aren't new VM_SPECIAL flags. */
485*6aacab30SLorenzo Stoakes for (i = 0; i < ARRAY_SIZE(special_flags); i++) {
486*6aacab30SLorenzo Stoakes all_special_flags |= special_flags[i];
487*6aacab30SLorenzo Stoakes }
488*6aacab30SLorenzo Stoakes ASSERT_EQ(all_special_flags, VM_SPECIAL);
489*6aacab30SLorenzo Stoakes
490*6aacab30SLorenzo Stoakes /*
491*6aacab30SLorenzo Stoakes * 01234
492*6aacab30SLorenzo Stoakes * AAA
493*6aacab30SLorenzo Stoakes */
494*6aacab30SLorenzo Stoakes vma_left = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
495*6aacab30SLorenzo Stoakes ASSERT_NE(vma_left, NULL);
496*6aacab30SLorenzo Stoakes
497*6aacab30SLorenzo Stoakes /* 1. Set up new VMA with special flag that would otherwise merge. */
498*6aacab30SLorenzo Stoakes
499*6aacab30SLorenzo Stoakes /*
500*6aacab30SLorenzo Stoakes * 01234
501*6aacab30SLorenzo Stoakes * AAA*
502*6aacab30SLorenzo Stoakes *
503*6aacab30SLorenzo Stoakes * This should merge if not for the VM_SPECIAL flag.
504*6aacab30SLorenzo Stoakes */
505*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x4000, 3, vm_flags);
506*6aacab30SLorenzo Stoakes for (i = 0; i < ARRAY_SIZE(special_flags); i++) {
507*6aacab30SLorenzo Stoakes vm_flags_t special_flag = special_flags[i];
508*6aacab30SLorenzo Stoakes
509*6aacab30SLorenzo Stoakes vm_flags_reset(vma_left, vm_flags | special_flag);
510*6aacab30SLorenzo Stoakes vmg.vm_flags = vm_flags | special_flag;
511*6aacab30SLorenzo Stoakes vma = merge_new(&vmg);
512*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, NULL);
513*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
514*6aacab30SLorenzo Stoakes }
515*6aacab30SLorenzo Stoakes
516*6aacab30SLorenzo Stoakes /* 2. Modify VMA with special flag that would otherwise merge. */
517*6aacab30SLorenzo Stoakes
518*6aacab30SLorenzo Stoakes /*
519*6aacab30SLorenzo Stoakes * 01234
520*6aacab30SLorenzo Stoakes * AAAB
521*6aacab30SLorenzo Stoakes *
522*6aacab30SLorenzo Stoakes * Create a VMA to modify.
523*6aacab30SLorenzo Stoakes */
524*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, vm_flags);
525*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
526*6aacab30SLorenzo Stoakes vmg.middle = vma;
527*6aacab30SLorenzo Stoakes
528*6aacab30SLorenzo Stoakes for (i = 0; i < ARRAY_SIZE(special_flags); i++) {
529*6aacab30SLorenzo Stoakes vm_flags_t special_flag = special_flags[i];
530*6aacab30SLorenzo Stoakes
531*6aacab30SLorenzo Stoakes vm_flags_reset(vma_left, vm_flags | special_flag);
532*6aacab30SLorenzo Stoakes vmg.vm_flags = vm_flags | special_flag;
533*6aacab30SLorenzo Stoakes vma = merge_existing(&vmg);
534*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, NULL);
535*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
536*6aacab30SLorenzo Stoakes }
537*6aacab30SLorenzo Stoakes
538*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
539*6aacab30SLorenzo Stoakes return true;
540*6aacab30SLorenzo Stoakes }
541*6aacab30SLorenzo Stoakes
test_vma_merge_with_close(void)542*6aacab30SLorenzo Stoakes static bool test_vma_merge_with_close(void)
543*6aacab30SLorenzo Stoakes {
544*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
545*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
546*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
547*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
548*6aacab30SLorenzo Stoakes .mm = &mm,
549*6aacab30SLorenzo Stoakes .vmi = &vmi,
550*6aacab30SLorenzo Stoakes };
551*6aacab30SLorenzo Stoakes const struct vm_operations_struct vm_ops = {
552*6aacab30SLorenzo Stoakes .close = dummy_close,
553*6aacab30SLorenzo Stoakes };
554*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_prev, *vma_next, *vma;
555*6aacab30SLorenzo Stoakes
556*6aacab30SLorenzo Stoakes /*
557*6aacab30SLorenzo Stoakes * When merging VMAs we are not permitted to remove any VMA that has a
558*6aacab30SLorenzo Stoakes * vm_ops->close() hook.
559*6aacab30SLorenzo Stoakes *
560*6aacab30SLorenzo Stoakes * Considering the two possible adjacent VMAs to which a VMA can be
561*6aacab30SLorenzo Stoakes * merged:
562*6aacab30SLorenzo Stoakes *
563*6aacab30SLorenzo Stoakes * [ prev ][ vma ][ next ]
564*6aacab30SLorenzo Stoakes *
565*6aacab30SLorenzo Stoakes * In no case will we need to delete prev. If the operation is
566*6aacab30SLorenzo Stoakes * mergeable, then prev will be extended with one or both of vma and
567*6aacab30SLorenzo Stoakes * next deleted.
568*6aacab30SLorenzo Stoakes *
569*6aacab30SLorenzo Stoakes * As a result, during initial mergeability checks, only
570*6aacab30SLorenzo Stoakes * can_vma_merge_before() (which implies the VMA being merged with is
571*6aacab30SLorenzo Stoakes * 'next' as shown above) bothers to check to see whether the next VMA
572*6aacab30SLorenzo Stoakes * has a vm_ops->close() callback that will need to be called when
573*6aacab30SLorenzo Stoakes * removed.
574*6aacab30SLorenzo Stoakes *
575*6aacab30SLorenzo Stoakes * If it does, then we cannot merge as the resources that the close()
576*6aacab30SLorenzo Stoakes * operation potentially clears down are tied only to the existing VMA
577*6aacab30SLorenzo Stoakes * range and we have no way of extending those to the nearly merged one.
578*6aacab30SLorenzo Stoakes *
579*6aacab30SLorenzo Stoakes * We must consider two scenarios:
580*6aacab30SLorenzo Stoakes *
581*6aacab30SLorenzo Stoakes * A.
582*6aacab30SLorenzo Stoakes *
583*6aacab30SLorenzo Stoakes * vm_ops->close: - - !NULL
584*6aacab30SLorenzo Stoakes * [ prev ][ vma ][ next ]
585*6aacab30SLorenzo Stoakes *
586*6aacab30SLorenzo Stoakes * Where prev may or may not be present/mergeable.
587*6aacab30SLorenzo Stoakes *
588*6aacab30SLorenzo Stoakes * This is picked up by a specific check in can_vma_merge_before().
589*6aacab30SLorenzo Stoakes *
590*6aacab30SLorenzo Stoakes * B.
591*6aacab30SLorenzo Stoakes *
592*6aacab30SLorenzo Stoakes * vm_ops->close: - !NULL
593*6aacab30SLorenzo Stoakes * [ prev ][ vma ]
594*6aacab30SLorenzo Stoakes *
595*6aacab30SLorenzo Stoakes * Where prev and vma are present and mergeable.
596*6aacab30SLorenzo Stoakes *
597*6aacab30SLorenzo Stoakes * This is picked up by a specific check in the modified VMA merge.
598*6aacab30SLorenzo Stoakes *
599*6aacab30SLorenzo Stoakes * IMPORTANT NOTE: We make the assumption that the following case:
600*6aacab30SLorenzo Stoakes *
601*6aacab30SLorenzo Stoakes * - !NULL NULL
602*6aacab30SLorenzo Stoakes * [ prev ][ vma ][ next ]
603*6aacab30SLorenzo Stoakes *
604*6aacab30SLorenzo Stoakes * Cannot occur, because vma->vm_ops being the same implies the same
605*6aacab30SLorenzo Stoakes * vma->vm_file, and therefore this would mean that next->vm_ops->close
606*6aacab30SLorenzo Stoakes * would be set too, and thus scenario A would pick this up.
607*6aacab30SLorenzo Stoakes */
608*6aacab30SLorenzo Stoakes
609*6aacab30SLorenzo Stoakes /*
610*6aacab30SLorenzo Stoakes * The only case of a new VMA merge that results in a VMA being deleted
611*6aacab30SLorenzo Stoakes * is one where both the previous and next VMAs are merged - in this
612*6aacab30SLorenzo Stoakes * instance the next VMA is deleted, and the previous VMA is extended.
613*6aacab30SLorenzo Stoakes *
614*6aacab30SLorenzo Stoakes * If we are unable to do so, we reduce the operation to simply
615*6aacab30SLorenzo Stoakes * extending the prev VMA and not merging next.
616*6aacab30SLorenzo Stoakes *
617*6aacab30SLorenzo Stoakes * 0123456789
618*6aacab30SLorenzo Stoakes * PPP**NNNN
619*6aacab30SLorenzo Stoakes * ->
620*6aacab30SLorenzo Stoakes * 0123456789
621*6aacab30SLorenzo Stoakes * PPPPPPNNN
622*6aacab30SLorenzo Stoakes */
623*6aacab30SLorenzo Stoakes
624*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
625*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, vm_flags);
626*6aacab30SLorenzo Stoakes vma_next->vm_ops = &vm_ops;
627*6aacab30SLorenzo Stoakes
628*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
629*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_new(&vmg), vma_prev);
630*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
631*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
632*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x5000);
633*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
634*6aacab30SLorenzo Stoakes
635*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
636*6aacab30SLorenzo Stoakes
637*6aacab30SLorenzo Stoakes /*
638*6aacab30SLorenzo Stoakes * When modifying an existing VMA there are further cases where we
639*6aacab30SLorenzo Stoakes * delete VMAs.
640*6aacab30SLorenzo Stoakes *
641*6aacab30SLorenzo Stoakes * <>
642*6aacab30SLorenzo Stoakes * 0123456789
643*6aacab30SLorenzo Stoakes * PPPVV
644*6aacab30SLorenzo Stoakes *
645*6aacab30SLorenzo Stoakes * In this instance, if vma has a close hook, the merge simply cannot
646*6aacab30SLorenzo Stoakes * proceed.
647*6aacab30SLorenzo Stoakes */
648*6aacab30SLorenzo Stoakes
649*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
650*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
651*6aacab30SLorenzo Stoakes vma->vm_ops = &vm_ops;
652*6aacab30SLorenzo Stoakes
653*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
654*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
655*6aacab30SLorenzo Stoakes vmg.middle = vma;
656*6aacab30SLorenzo Stoakes
657*6aacab30SLorenzo Stoakes /*
658*6aacab30SLorenzo Stoakes * The VMA being modified in a way that would otherwise merge should
659*6aacab30SLorenzo Stoakes * also fail.
660*6aacab30SLorenzo Stoakes */
661*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
662*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
663*6aacab30SLorenzo Stoakes
664*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
665*6aacab30SLorenzo Stoakes
666*6aacab30SLorenzo Stoakes /*
667*6aacab30SLorenzo Stoakes * This case is mirrored if merging with next.
668*6aacab30SLorenzo Stoakes *
669*6aacab30SLorenzo Stoakes * <>
670*6aacab30SLorenzo Stoakes * 0123456789
671*6aacab30SLorenzo Stoakes * VVNNNN
672*6aacab30SLorenzo Stoakes *
673*6aacab30SLorenzo Stoakes * In this instance, if vma has a close hook, the merge simply cannot
674*6aacab30SLorenzo Stoakes * proceed.
675*6aacab30SLorenzo Stoakes */
676*6aacab30SLorenzo Stoakes
677*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
678*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, vm_flags);
679*6aacab30SLorenzo Stoakes vma->vm_ops = &vm_ops;
680*6aacab30SLorenzo Stoakes
681*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
682*6aacab30SLorenzo Stoakes vmg.middle = vma;
683*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
684*6aacab30SLorenzo Stoakes /*
685*6aacab30SLorenzo Stoakes * Initially this is misapprehended as an out of memory report, as the
686*6aacab30SLorenzo Stoakes * close() check is handled in the same way as anon_vma duplication
687*6aacab30SLorenzo Stoakes * failures, however a subsequent patch resolves this.
688*6aacab30SLorenzo Stoakes */
689*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
690*6aacab30SLorenzo Stoakes
691*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
692*6aacab30SLorenzo Stoakes
693*6aacab30SLorenzo Stoakes /*
694*6aacab30SLorenzo Stoakes * Finally, we consider two variants of the case where we modify a VMA
695*6aacab30SLorenzo Stoakes * to merge with both the previous and next VMAs.
696*6aacab30SLorenzo Stoakes *
697*6aacab30SLorenzo Stoakes * The first variant is where vma has a close hook. In this instance, no
698*6aacab30SLorenzo Stoakes * merge can proceed.
699*6aacab30SLorenzo Stoakes *
700*6aacab30SLorenzo Stoakes * <>
701*6aacab30SLorenzo Stoakes * 0123456789
702*6aacab30SLorenzo Stoakes * PPPVVNNNN
703*6aacab30SLorenzo Stoakes */
704*6aacab30SLorenzo Stoakes
705*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
706*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
707*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, vm_flags);
708*6aacab30SLorenzo Stoakes vma->vm_ops = &vm_ops;
709*6aacab30SLorenzo Stoakes
710*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
711*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
712*6aacab30SLorenzo Stoakes vmg.middle = vma;
713*6aacab30SLorenzo Stoakes
714*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
715*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
716*6aacab30SLorenzo Stoakes
717*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 3);
718*6aacab30SLorenzo Stoakes
719*6aacab30SLorenzo Stoakes /*
720*6aacab30SLorenzo Stoakes * The second variant is where next has a close hook. In this instance,
721*6aacab30SLorenzo Stoakes * we reduce the operation to a merge between prev and vma.
722*6aacab30SLorenzo Stoakes *
723*6aacab30SLorenzo Stoakes * <>
724*6aacab30SLorenzo Stoakes * 0123456789
725*6aacab30SLorenzo Stoakes * PPPVVNNNN
726*6aacab30SLorenzo Stoakes * ->
727*6aacab30SLorenzo Stoakes * 0123456789
728*6aacab30SLorenzo Stoakes * PPPPPNNNN
729*6aacab30SLorenzo Stoakes */
730*6aacab30SLorenzo Stoakes
731*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
732*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
733*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, vm_flags);
734*6aacab30SLorenzo Stoakes vma_next->vm_ops = &vm_ops;
735*6aacab30SLorenzo Stoakes
736*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
737*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
738*6aacab30SLorenzo Stoakes vmg.middle = vma;
739*6aacab30SLorenzo Stoakes
740*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
741*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
742*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
743*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x5000);
744*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
745*6aacab30SLorenzo Stoakes
746*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
747*6aacab30SLorenzo Stoakes
748*6aacab30SLorenzo Stoakes return true;
749*6aacab30SLorenzo Stoakes }
750*6aacab30SLorenzo Stoakes
test_vma_merge_new_with_close(void)751*6aacab30SLorenzo Stoakes static bool test_vma_merge_new_with_close(void)
752*6aacab30SLorenzo Stoakes {
753*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
754*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
755*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
756*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
757*6aacab30SLorenzo Stoakes .mm = &mm,
758*6aacab30SLorenzo Stoakes .vmi = &vmi,
759*6aacab30SLorenzo Stoakes };
760*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_prev = alloc_and_link_vma(&mm, 0, 0x2000, 0, vm_flags);
761*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_next = alloc_and_link_vma(&mm, 0x5000, 0x7000, 5, vm_flags);
762*6aacab30SLorenzo Stoakes const struct vm_operations_struct vm_ops = {
763*6aacab30SLorenzo Stoakes .close = dummy_close,
764*6aacab30SLorenzo Stoakes };
765*6aacab30SLorenzo Stoakes struct vm_area_struct *vma;
766*6aacab30SLorenzo Stoakes
767*6aacab30SLorenzo Stoakes /*
768*6aacab30SLorenzo Stoakes * We should allow the partial merge of a proposed new VMA if the
769*6aacab30SLorenzo Stoakes * surrounding VMAs have vm_ops->close() hooks (but are otherwise
770*6aacab30SLorenzo Stoakes * compatible), e.g.:
771*6aacab30SLorenzo Stoakes *
772*6aacab30SLorenzo Stoakes * New VMA
773*6aacab30SLorenzo Stoakes * A v-------v B
774*6aacab30SLorenzo Stoakes * |-----| |-----|
775*6aacab30SLorenzo Stoakes * close close
776*6aacab30SLorenzo Stoakes *
777*6aacab30SLorenzo Stoakes * Since the rule is to not DELETE a VMA with a close operation, this
778*6aacab30SLorenzo Stoakes * should be permitted, only rather than expanding A and deleting B, we
779*6aacab30SLorenzo Stoakes * should simply expand A and leave B intact, e.g.:
780*6aacab30SLorenzo Stoakes *
781*6aacab30SLorenzo Stoakes * New VMA
782*6aacab30SLorenzo Stoakes * A B
783*6aacab30SLorenzo Stoakes * |------------||-----|
784*6aacab30SLorenzo Stoakes * close close
785*6aacab30SLorenzo Stoakes */
786*6aacab30SLorenzo Stoakes
787*6aacab30SLorenzo Stoakes /* Have prev and next have a vm_ops->close() hook. */
788*6aacab30SLorenzo Stoakes vma_prev->vm_ops = &vm_ops;
789*6aacab30SLorenzo Stoakes vma_next->vm_ops = &vm_ops;
790*6aacab30SLorenzo Stoakes
791*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x2000, 0x5000, 2, vm_flags);
792*6aacab30SLorenzo Stoakes vma = merge_new(&vmg);
793*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
794*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
795*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
796*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x5000);
797*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
798*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_ops, &vm_ops);
799*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
800*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 2);
801*6aacab30SLorenzo Stoakes
802*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
803*6aacab30SLorenzo Stoakes return true;
804*6aacab30SLorenzo Stoakes }
805*6aacab30SLorenzo Stoakes
__test_merge_existing(bool prev_is_sticky,bool middle_is_sticky,bool next_is_sticky)806*6aacab30SLorenzo Stoakes static bool __test_merge_existing(bool prev_is_sticky, bool middle_is_sticky, bool next_is_sticky)
807*6aacab30SLorenzo Stoakes {
808*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
809*6aacab30SLorenzo Stoakes vm_flags_t prev_flags = vm_flags;
810*6aacab30SLorenzo Stoakes vm_flags_t next_flags = vm_flags;
811*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
812*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
813*6aacab30SLorenzo Stoakes struct vm_area_struct *vma, *vma_prev, *vma_next;
814*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
815*6aacab30SLorenzo Stoakes .mm = &mm,
816*6aacab30SLorenzo Stoakes .vmi = &vmi,
817*6aacab30SLorenzo Stoakes };
818*6aacab30SLorenzo Stoakes const struct vm_operations_struct vm_ops = {
819*6aacab30SLorenzo Stoakes .close = dummy_close,
820*6aacab30SLorenzo Stoakes };
821*6aacab30SLorenzo Stoakes struct anon_vma_chain avc = {};
822*6aacab30SLorenzo Stoakes
823*6aacab30SLorenzo Stoakes if (prev_is_sticky)
824*6aacab30SLorenzo Stoakes prev_flags |= VM_STICKY;
825*6aacab30SLorenzo Stoakes if (middle_is_sticky)
826*6aacab30SLorenzo Stoakes vm_flags |= VM_STICKY;
827*6aacab30SLorenzo Stoakes if (next_is_sticky)
828*6aacab30SLorenzo Stoakes next_flags |= VM_STICKY;
829*6aacab30SLorenzo Stoakes
830*6aacab30SLorenzo Stoakes /*
831*6aacab30SLorenzo Stoakes * Merge right case - partial span.
832*6aacab30SLorenzo Stoakes *
833*6aacab30SLorenzo Stoakes * <->
834*6aacab30SLorenzo Stoakes * 0123456789
835*6aacab30SLorenzo Stoakes * VVVVNNN
836*6aacab30SLorenzo Stoakes * ->
837*6aacab30SLorenzo Stoakes * 0123456789
838*6aacab30SLorenzo Stoakes * VNNNNNN
839*6aacab30SLorenzo Stoakes */
840*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, vm_flags);
841*6aacab30SLorenzo Stoakes vma->vm_ops = &vm_ops; /* This should have no impact. */
842*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, next_flags);
843*6aacab30SLorenzo Stoakes vma_next->vm_ops = &vm_ops; /* This should have no impact. */
844*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x6000, 3, vm_flags, &dummy_anon_vma);
845*6aacab30SLorenzo Stoakes vmg.middle = vma;
846*6aacab30SLorenzo Stoakes vmg.prev = vma;
847*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
848*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_next);
849*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
850*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_start, 0x3000);
851*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_end, 0x9000);
852*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_pgoff, 3);
853*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);
854*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x2000);
855*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x3000);
856*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 2);
857*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
858*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_next));
859*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 2);
860*6aacab30SLorenzo Stoakes if (middle_is_sticky || next_is_sticky)
861*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma_next->vm_flags, VM_STICKY));
862*6aacab30SLorenzo Stoakes
863*6aacab30SLorenzo Stoakes /* Clear down and reset. */
864*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
865*6aacab30SLorenzo Stoakes
866*6aacab30SLorenzo Stoakes /*
867*6aacab30SLorenzo Stoakes * Merge right case - full span.
868*6aacab30SLorenzo Stoakes *
869*6aacab30SLorenzo Stoakes * <-->
870*6aacab30SLorenzo Stoakes * 0123456789
871*6aacab30SLorenzo Stoakes * VVVVNNN
872*6aacab30SLorenzo Stoakes * ->
873*6aacab30SLorenzo Stoakes * 0123456789
874*6aacab30SLorenzo Stoakes * NNNNNNN
875*6aacab30SLorenzo Stoakes */
876*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, vm_flags);
877*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, next_flags);
878*6aacab30SLorenzo Stoakes vma_next->vm_ops = &vm_ops; /* This should have no impact. */
879*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x2000, 0x6000, 2, vm_flags, &dummy_anon_vma);
880*6aacab30SLorenzo Stoakes vmg.middle = vma;
881*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
882*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_next);
883*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
884*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_start, 0x2000);
885*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_end, 0x9000);
886*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_pgoff, 2);
887*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);
888*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_next));
889*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 1);
890*6aacab30SLorenzo Stoakes if (middle_is_sticky || next_is_sticky)
891*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma_next->vm_flags, VM_STICKY));
892*6aacab30SLorenzo Stoakes
893*6aacab30SLorenzo Stoakes /* Clear down and reset. We should have deleted vma. */
894*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);
895*6aacab30SLorenzo Stoakes
896*6aacab30SLorenzo Stoakes /*
897*6aacab30SLorenzo Stoakes * Merge left case - partial span.
898*6aacab30SLorenzo Stoakes *
899*6aacab30SLorenzo Stoakes * <->
900*6aacab30SLorenzo Stoakes * 0123456789
901*6aacab30SLorenzo Stoakes * PPPVVVV
902*6aacab30SLorenzo Stoakes * ->
903*6aacab30SLorenzo Stoakes * 0123456789
904*6aacab30SLorenzo Stoakes * PPPPPPV
905*6aacab30SLorenzo Stoakes */
906*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags);
907*6aacab30SLorenzo Stoakes vma_prev->vm_ops = &vm_ops; /* This should have no impact. */
908*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags);
909*6aacab30SLorenzo Stoakes vma->vm_ops = &vm_ops; /* This should have no impact. */
910*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x6000, 3, vm_flags, &dummy_anon_vma);
911*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
912*6aacab30SLorenzo Stoakes vmg.middle = vma;
913*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
914*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
915*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
916*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
917*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x6000);
918*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
919*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
920*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x6000);
921*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x7000);
922*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 6);
923*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_prev));
924*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
925*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 2);
926*6aacab30SLorenzo Stoakes if (prev_is_sticky || middle_is_sticky)
927*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY));
928*6aacab30SLorenzo Stoakes
929*6aacab30SLorenzo Stoakes /* Clear down and reset. */
930*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
931*6aacab30SLorenzo Stoakes
932*6aacab30SLorenzo Stoakes /*
933*6aacab30SLorenzo Stoakes * Merge left case - full span.
934*6aacab30SLorenzo Stoakes *
935*6aacab30SLorenzo Stoakes * <-->
936*6aacab30SLorenzo Stoakes * 0123456789
937*6aacab30SLorenzo Stoakes * PPPVVVV
938*6aacab30SLorenzo Stoakes * ->
939*6aacab30SLorenzo Stoakes * 0123456789
940*6aacab30SLorenzo Stoakes * PPPPPPP
941*6aacab30SLorenzo Stoakes */
942*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags);
943*6aacab30SLorenzo Stoakes vma_prev->vm_ops = &vm_ops; /* This should have no impact. */
944*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags);
945*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, &dummy_anon_vma);
946*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
947*6aacab30SLorenzo Stoakes vmg.middle = vma;
948*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
949*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
950*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
951*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
952*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x7000);
953*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
954*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
955*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_prev));
956*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 1);
957*6aacab30SLorenzo Stoakes if (prev_is_sticky || middle_is_sticky)
958*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY));
959*6aacab30SLorenzo Stoakes
960*6aacab30SLorenzo Stoakes /* Clear down and reset. We should have deleted vma. */
961*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);
962*6aacab30SLorenzo Stoakes
963*6aacab30SLorenzo Stoakes /*
964*6aacab30SLorenzo Stoakes * Merge both case.
965*6aacab30SLorenzo Stoakes *
966*6aacab30SLorenzo Stoakes * <-->
967*6aacab30SLorenzo Stoakes * 0123456789
968*6aacab30SLorenzo Stoakes * PPPVVVVNNN
969*6aacab30SLorenzo Stoakes * ->
970*6aacab30SLorenzo Stoakes * 0123456789
971*6aacab30SLorenzo Stoakes * PPPPPPPPPP
972*6aacab30SLorenzo Stoakes */
973*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags);
974*6aacab30SLorenzo Stoakes vma_prev->vm_ops = &vm_ops; /* This should have no impact. */
975*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags);
976*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, next_flags);
977*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, &dummy_anon_vma);
978*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
979*6aacab30SLorenzo Stoakes vmg.middle = vma;
980*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
981*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
982*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
983*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
984*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x9000);
985*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
986*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
987*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_prev));
988*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 1);
989*6aacab30SLorenzo Stoakes if (prev_is_sticky || middle_is_sticky || next_is_sticky)
990*6aacab30SLorenzo Stoakes ASSERT_TRUE(IS_SET(vma_prev->vm_flags, VM_STICKY));
991*6aacab30SLorenzo Stoakes
992*6aacab30SLorenzo Stoakes /* Clear down and reset. We should have deleted prev and next. */
993*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);
994*6aacab30SLorenzo Stoakes
995*6aacab30SLorenzo Stoakes /*
996*6aacab30SLorenzo Stoakes * Non-merge ranges. the modified VMA merge operation assumes that the
997*6aacab30SLorenzo Stoakes * caller always specifies ranges within the input VMA so we need only
998*6aacab30SLorenzo Stoakes * examine these cases.
999*6aacab30SLorenzo Stoakes *
1000*6aacab30SLorenzo Stoakes * -
1001*6aacab30SLorenzo Stoakes * -
1002*6aacab30SLorenzo Stoakes * -
1003*6aacab30SLorenzo Stoakes * <->
1004*6aacab30SLorenzo Stoakes * <>
1005*6aacab30SLorenzo Stoakes * <>
1006*6aacab30SLorenzo Stoakes * 0123456789a
1007*6aacab30SLorenzo Stoakes * PPPVVVVVNNN
1008*6aacab30SLorenzo Stoakes */
1009*6aacab30SLorenzo Stoakes
1010*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, prev_flags);
1011*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x8000, 3, vm_flags);
1012*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x8000, 0xa000, 8, next_flags);
1013*6aacab30SLorenzo Stoakes
1014*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x4000, 0x5000, 4, vm_flags);
1015*6aacab30SLorenzo Stoakes vmg.prev = vma;
1016*6aacab30SLorenzo Stoakes vmg.middle = vma;
1017*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1018*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1019*6aacab30SLorenzo Stoakes
1020*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x5000, 0x6000, 5, vm_flags);
1021*6aacab30SLorenzo Stoakes vmg.prev = vma;
1022*6aacab30SLorenzo Stoakes vmg.middle = vma;
1023*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1024*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1025*6aacab30SLorenzo Stoakes
1026*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x6000, 0x7000, 6, vm_flags);
1027*6aacab30SLorenzo Stoakes vmg.prev = vma;
1028*6aacab30SLorenzo Stoakes vmg.middle = vma;
1029*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1030*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1031*6aacab30SLorenzo Stoakes
1032*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x4000, 0x7000, 4, vm_flags);
1033*6aacab30SLorenzo Stoakes vmg.prev = vma;
1034*6aacab30SLorenzo Stoakes vmg.middle = vma;
1035*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1036*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1037*6aacab30SLorenzo Stoakes
1038*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x4000, 0x6000, 4, vm_flags);
1039*6aacab30SLorenzo Stoakes vmg.prev = vma;
1040*6aacab30SLorenzo Stoakes vmg.middle = vma;
1041*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1042*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1043*6aacab30SLorenzo Stoakes
1044*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x5000, 0x6000, 5, vm_flags);
1045*6aacab30SLorenzo Stoakes vmg.prev = vma;
1046*6aacab30SLorenzo Stoakes vmg.middle = vma;
1047*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1048*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);
1049*6aacab30SLorenzo Stoakes
1050*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 3);
1051*6aacab30SLorenzo Stoakes
1052*6aacab30SLorenzo Stoakes return true;
1053*6aacab30SLorenzo Stoakes }
1054*6aacab30SLorenzo Stoakes
test_merge_existing(void)1055*6aacab30SLorenzo Stoakes static bool test_merge_existing(void)
1056*6aacab30SLorenzo Stoakes {
1057*6aacab30SLorenzo Stoakes int i, j, k;
1058*6aacab30SLorenzo Stoakes
1059*6aacab30SLorenzo Stoakes /* Generate every possible permutation of sticky flags. */
1060*6aacab30SLorenzo Stoakes for (i = 0; i < 2; i++)
1061*6aacab30SLorenzo Stoakes for (j = 0; j < 2; j++)
1062*6aacab30SLorenzo Stoakes for (k = 0; k < 2; k++)
1063*6aacab30SLorenzo Stoakes ASSERT_TRUE(__test_merge_existing(i, j, k));
1064*6aacab30SLorenzo Stoakes
1065*6aacab30SLorenzo Stoakes return true;
1066*6aacab30SLorenzo Stoakes }
1067*6aacab30SLorenzo Stoakes
test_anon_vma_non_mergeable(void)1068*6aacab30SLorenzo Stoakes static bool test_anon_vma_non_mergeable(void)
1069*6aacab30SLorenzo Stoakes {
1070*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
1071*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
1072*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
1073*6aacab30SLorenzo Stoakes struct vm_area_struct *vma, *vma_prev, *vma_next;
1074*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
1075*6aacab30SLorenzo Stoakes .mm = &mm,
1076*6aacab30SLorenzo Stoakes .vmi = &vmi,
1077*6aacab30SLorenzo Stoakes };
1078*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_1 = {};
1079*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain_2 = {};
1080*6aacab30SLorenzo Stoakes struct anon_vma dummy_anon_vma_2;
1081*6aacab30SLorenzo Stoakes
1082*6aacab30SLorenzo Stoakes /*
1083*6aacab30SLorenzo Stoakes * In the case of modified VMA merge, merging both left and right VMAs
1084*6aacab30SLorenzo Stoakes * but where prev and next have incompatible anon_vma objects, we revert
1085*6aacab30SLorenzo Stoakes * to a merge of prev and VMA:
1086*6aacab30SLorenzo Stoakes *
1087*6aacab30SLorenzo Stoakes * <-->
1088*6aacab30SLorenzo Stoakes * 0123456789
1089*6aacab30SLorenzo Stoakes * PPPVVVVNNN
1090*6aacab30SLorenzo Stoakes * ->
1091*6aacab30SLorenzo Stoakes * 0123456789
1092*6aacab30SLorenzo Stoakes * PPPPPPPNNN
1093*6aacab30SLorenzo Stoakes */
1094*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1095*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, vm_flags);
1096*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, vm_flags);
1097*6aacab30SLorenzo Stoakes
1098*6aacab30SLorenzo Stoakes /*
1099*6aacab30SLorenzo Stoakes * Give both prev and next single anon_vma_chain fields, so they will
1100*6aacab30SLorenzo Stoakes * merge with the NULL vmg->anon_vma.
1101*6aacab30SLorenzo Stoakes *
1102*6aacab30SLorenzo Stoakes * However, when prev is compared to next, the merge should fail.
1103*6aacab30SLorenzo Stoakes */
1104*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, NULL);
1105*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1106*6aacab30SLorenzo Stoakes vmg.middle = vma;
1107*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma_prev, &dummy_anon_vma_chain_1);
1108*6aacab30SLorenzo Stoakes __vma_set_dummy_anon_vma(vma_next, &dummy_anon_vma_chain_2, &dummy_anon_vma_2);
1109*6aacab30SLorenzo Stoakes
1110*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
1111*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1112*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
1113*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x7000);
1114*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
1115*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_prev));
1116*6aacab30SLorenzo Stoakes ASSERT_FALSE(vma_write_started(vma_next));
1117*6aacab30SLorenzo Stoakes
1118*6aacab30SLorenzo Stoakes /* Clear down and reset. */
1119*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
1120*6aacab30SLorenzo Stoakes
1121*6aacab30SLorenzo Stoakes /*
1122*6aacab30SLorenzo Stoakes * Now consider the new VMA case. This is equivalent, only adding a new
1123*6aacab30SLorenzo Stoakes * VMA in a gap between prev and next.
1124*6aacab30SLorenzo Stoakes *
1125*6aacab30SLorenzo Stoakes * <-->
1126*6aacab30SLorenzo Stoakes * 0123456789
1127*6aacab30SLorenzo Stoakes * PPP****NNN
1128*6aacab30SLorenzo Stoakes * ->
1129*6aacab30SLorenzo Stoakes * 0123456789
1130*6aacab30SLorenzo Stoakes * PPPPPPPNNN
1131*6aacab30SLorenzo Stoakes */
1132*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1133*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, vm_flags);
1134*6aacab30SLorenzo Stoakes
1135*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x7000, 3, vm_flags, NULL);
1136*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1137*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma_prev, &dummy_anon_vma_chain_1);
1138*6aacab30SLorenzo Stoakes __vma_set_dummy_anon_vma(vma_next, &dummy_anon_vma_chain_2, &dummy_anon_vma_2);
1139*6aacab30SLorenzo Stoakes
1140*6aacab30SLorenzo Stoakes vmg.anon_vma = NULL;
1141*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_new(&vmg), vma_prev);
1142*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1143*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
1144*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x7000);
1145*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_pgoff, 0);
1146*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma_prev));
1147*6aacab30SLorenzo Stoakes ASSERT_FALSE(vma_write_started(vma_next));
1148*6aacab30SLorenzo Stoakes
1149*6aacab30SLorenzo Stoakes /* Final cleanup. */
1150*6aacab30SLorenzo Stoakes ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);
1151*6aacab30SLorenzo Stoakes
1152*6aacab30SLorenzo Stoakes return true;
1153*6aacab30SLorenzo Stoakes }
1154*6aacab30SLorenzo Stoakes
test_dup_anon_vma(void)1155*6aacab30SLorenzo Stoakes static bool test_dup_anon_vma(void)
1156*6aacab30SLorenzo Stoakes {
1157*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
1158*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
1159*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
1160*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
1161*6aacab30SLorenzo Stoakes .mm = &mm,
1162*6aacab30SLorenzo Stoakes .vmi = &vmi,
1163*6aacab30SLorenzo Stoakes };
1164*6aacab30SLorenzo Stoakes struct anon_vma_chain dummy_anon_vma_chain = {
1165*6aacab30SLorenzo Stoakes .anon_vma = &dummy_anon_vma,
1166*6aacab30SLorenzo Stoakes };
1167*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_prev, *vma_next, *vma;
1168*6aacab30SLorenzo Stoakes
1169*6aacab30SLorenzo Stoakes reset_dummy_anon_vma();
1170*6aacab30SLorenzo Stoakes
1171*6aacab30SLorenzo Stoakes /*
1172*6aacab30SLorenzo Stoakes * Expanding a VMA delete the next one duplicates next's anon_vma and
1173*6aacab30SLorenzo Stoakes * assigns it to the expanded VMA.
1174*6aacab30SLorenzo Stoakes *
1175*6aacab30SLorenzo Stoakes * This covers new VMA merging, as these operations amount to a VMA
1176*6aacab30SLorenzo Stoakes * expand.
1177*6aacab30SLorenzo Stoakes */
1178*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1179*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1180*6aacab30SLorenzo Stoakes vma_next->anon_vma = &dummy_anon_vma;
1181*6aacab30SLorenzo Stoakes
1182*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0, 0x5000, 0, vm_flags);
1183*6aacab30SLorenzo Stoakes vmg.target = vma_prev;
1184*6aacab30SLorenzo Stoakes vmg.next = vma_next;
1185*6aacab30SLorenzo Stoakes
1186*6aacab30SLorenzo Stoakes ASSERT_EQ(expand_existing(&vmg), 0);
1187*6aacab30SLorenzo Stoakes
1188*6aacab30SLorenzo Stoakes /* Will have been cloned. */
1189*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1190*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_prev->anon_vma->was_cloned);
1191*6aacab30SLorenzo Stoakes
1192*6aacab30SLorenzo Stoakes /* Cleanup ready for next run. */
1193*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1194*6aacab30SLorenzo Stoakes
1195*6aacab30SLorenzo Stoakes /*
1196*6aacab30SLorenzo Stoakes * next has anon_vma, we assign to prev.
1197*6aacab30SLorenzo Stoakes *
1198*6aacab30SLorenzo Stoakes * |<----->|
1199*6aacab30SLorenzo Stoakes * |-------*********-------|
1200*6aacab30SLorenzo Stoakes * prev vma next
1201*6aacab30SLorenzo Stoakes * extend delete delete
1202*6aacab30SLorenzo Stoakes */
1203*6aacab30SLorenzo Stoakes
1204*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1205*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1206*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, vm_flags);
1207*6aacab30SLorenzo Stoakes
1208*6aacab30SLorenzo Stoakes /* Initialise avc so mergeability check passes. */
1209*6aacab30SLorenzo Stoakes INIT_LIST_HEAD(&vma_next->anon_vma_chain);
1210*6aacab30SLorenzo Stoakes list_add(&dummy_anon_vma_chain.same_vma, &vma_next->anon_vma_chain);
1211*6aacab30SLorenzo Stoakes
1212*6aacab30SLorenzo Stoakes vma_next->anon_vma = &dummy_anon_vma;
1213*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
1214*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1215*6aacab30SLorenzo Stoakes vmg.middle = vma;
1216*6aacab30SLorenzo Stoakes
1217*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
1218*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1219*6aacab30SLorenzo Stoakes
1220*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
1221*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x8000);
1222*6aacab30SLorenzo Stoakes
1223*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1224*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_prev->anon_vma->was_cloned);
1225*6aacab30SLorenzo Stoakes
1226*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1227*6aacab30SLorenzo Stoakes
1228*6aacab30SLorenzo Stoakes /*
1229*6aacab30SLorenzo Stoakes * vma has anon_vma, we assign to prev.
1230*6aacab30SLorenzo Stoakes *
1231*6aacab30SLorenzo Stoakes * |<----->|
1232*6aacab30SLorenzo Stoakes * |-------*********-------|
1233*6aacab30SLorenzo Stoakes * prev vma next
1234*6aacab30SLorenzo Stoakes * extend delete delete
1235*6aacab30SLorenzo Stoakes */
1236*6aacab30SLorenzo Stoakes
1237*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1238*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1239*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, vm_flags);
1240*6aacab30SLorenzo Stoakes vmg.anon_vma = &dummy_anon_vma;
1241*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &dummy_anon_vma_chain);
1242*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
1243*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1244*6aacab30SLorenzo Stoakes vmg.middle = vma;
1245*6aacab30SLorenzo Stoakes
1246*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
1247*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1248*6aacab30SLorenzo Stoakes
1249*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
1250*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x8000);
1251*6aacab30SLorenzo Stoakes
1252*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1253*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_prev->anon_vma->was_cloned);
1254*6aacab30SLorenzo Stoakes
1255*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1256*6aacab30SLorenzo Stoakes
1257*6aacab30SLorenzo Stoakes /*
1258*6aacab30SLorenzo Stoakes * vma has anon_vma, we assign to prev.
1259*6aacab30SLorenzo Stoakes *
1260*6aacab30SLorenzo Stoakes * |<----->|
1261*6aacab30SLorenzo Stoakes * |-------*************
1262*6aacab30SLorenzo Stoakes * prev vma
1263*6aacab30SLorenzo Stoakes * extend shrink/delete
1264*6aacab30SLorenzo Stoakes */
1265*6aacab30SLorenzo Stoakes
1266*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1267*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x8000, 3, vm_flags);
1268*6aacab30SLorenzo Stoakes
1269*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &dummy_anon_vma_chain);
1270*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
1271*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1272*6aacab30SLorenzo Stoakes vmg.middle = vma;
1273*6aacab30SLorenzo Stoakes
1274*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_prev);
1275*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1276*6aacab30SLorenzo Stoakes
1277*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_start, 0);
1278*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->vm_end, 0x5000);
1279*6aacab30SLorenzo Stoakes
1280*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1281*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_prev->anon_vma->was_cloned);
1282*6aacab30SLorenzo Stoakes
1283*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1284*6aacab30SLorenzo Stoakes
1285*6aacab30SLorenzo Stoakes /*
1286*6aacab30SLorenzo Stoakes * vma has anon_vma, we assign to next.
1287*6aacab30SLorenzo Stoakes *
1288*6aacab30SLorenzo Stoakes * |<----->|
1289*6aacab30SLorenzo Stoakes * *************-------|
1290*6aacab30SLorenzo Stoakes * vma next
1291*6aacab30SLorenzo Stoakes * shrink/delete extend
1292*6aacab30SLorenzo Stoakes */
1293*6aacab30SLorenzo Stoakes
1294*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0, 0x5000, 0, vm_flags);
1295*6aacab30SLorenzo Stoakes vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, vm_flags);
1296*6aacab30SLorenzo Stoakes
1297*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &dummy_anon_vma_chain);
1298*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0x3000, 0x5000, 3, vm_flags);
1299*6aacab30SLorenzo Stoakes vmg.prev = vma;
1300*6aacab30SLorenzo Stoakes vmg.middle = vma;
1301*6aacab30SLorenzo Stoakes
1302*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), vma_next);
1303*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1304*6aacab30SLorenzo Stoakes
1305*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_start, 0x3000);
1306*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->vm_end, 0x8000);
1307*6aacab30SLorenzo Stoakes
1308*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);
1309*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_next->anon_vma->was_cloned);
1310*6aacab30SLorenzo Stoakes
1311*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1312*6aacab30SLorenzo Stoakes return true;
1313*6aacab30SLorenzo Stoakes }
1314*6aacab30SLorenzo Stoakes
test_vmi_prealloc_fail(void)1315*6aacab30SLorenzo Stoakes static bool test_vmi_prealloc_fail(void)
1316*6aacab30SLorenzo Stoakes {
1317*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
1318*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
1319*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
1320*6aacab30SLorenzo Stoakes struct vma_merge_struct vmg = {
1321*6aacab30SLorenzo Stoakes .mm = &mm,
1322*6aacab30SLorenzo Stoakes .vmi = &vmi,
1323*6aacab30SLorenzo Stoakes };
1324*6aacab30SLorenzo Stoakes struct anon_vma_chain avc = {};
1325*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_prev, *vma;
1326*6aacab30SLorenzo Stoakes
1327*6aacab30SLorenzo Stoakes /*
1328*6aacab30SLorenzo Stoakes * We are merging vma into prev, with vma possessing an anon_vma, which
1329*6aacab30SLorenzo Stoakes * will be duplicated. We cause the vmi preallocation to fail and assert
1330*6aacab30SLorenzo Stoakes * the duplicated anon_vma is unlinked.
1331*6aacab30SLorenzo Stoakes */
1332*6aacab30SLorenzo Stoakes
1333*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1334*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1335*6aacab30SLorenzo Stoakes vma->anon_vma = &dummy_anon_vma;
1336*6aacab30SLorenzo Stoakes
1337*6aacab30SLorenzo Stoakes vmg_set_range_anon_vma(&vmg, 0x3000, 0x5000, 3, vm_flags, &dummy_anon_vma);
1338*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1339*6aacab30SLorenzo Stoakes vmg.middle = vma;
1340*6aacab30SLorenzo Stoakes vma_set_dummy_anon_vma(vma, &avc);
1341*6aacab30SLorenzo Stoakes
1342*6aacab30SLorenzo Stoakes fail_prealloc = true;
1343*6aacab30SLorenzo Stoakes
1344*6aacab30SLorenzo Stoakes /* This will cause the merge to fail. */
1345*6aacab30SLorenzo Stoakes ASSERT_EQ(merge_existing(&vmg), NULL);
1346*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_ERROR_NOMEM);
1347*6aacab30SLorenzo Stoakes /* We will already have assigned the anon_vma. */
1348*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1349*6aacab30SLorenzo Stoakes /* And it was both cloned and unlinked. */
1350*6aacab30SLorenzo Stoakes ASSERT_TRUE(dummy_anon_vma.was_cloned);
1351*6aacab30SLorenzo Stoakes ASSERT_TRUE(dummy_anon_vma.was_unlinked);
1352*6aacab30SLorenzo Stoakes
1353*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi); /* Resets fail_prealloc too. */
1354*6aacab30SLorenzo Stoakes
1355*6aacab30SLorenzo Stoakes /*
1356*6aacab30SLorenzo Stoakes * We repeat the same operation for expanding a VMA, which is what new
1357*6aacab30SLorenzo Stoakes * VMA merging ultimately uses too. This asserts that unlinking is
1358*6aacab30SLorenzo Stoakes * performed in this case too.
1359*6aacab30SLorenzo Stoakes */
1360*6aacab30SLorenzo Stoakes
1361*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, vm_flags);
1362*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1363*6aacab30SLorenzo Stoakes vma->anon_vma = &dummy_anon_vma;
1364*6aacab30SLorenzo Stoakes
1365*6aacab30SLorenzo Stoakes vmg_set_range(&vmg, 0, 0x5000, 3, vm_flags);
1366*6aacab30SLorenzo Stoakes vmg.target = vma_prev;
1367*6aacab30SLorenzo Stoakes vmg.next = vma;
1368*6aacab30SLorenzo Stoakes
1369*6aacab30SLorenzo Stoakes fail_prealloc = true;
1370*6aacab30SLorenzo Stoakes ASSERT_EQ(expand_existing(&vmg), -ENOMEM);
1371*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_ERROR_NOMEM);
1372*6aacab30SLorenzo Stoakes
1373*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);
1374*6aacab30SLorenzo Stoakes ASSERT_TRUE(dummy_anon_vma.was_cloned);
1375*6aacab30SLorenzo Stoakes ASSERT_TRUE(dummy_anon_vma.was_unlinked);
1376*6aacab30SLorenzo Stoakes
1377*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1378*6aacab30SLorenzo Stoakes return true;
1379*6aacab30SLorenzo Stoakes }
1380*6aacab30SLorenzo Stoakes
test_merge_extend(void)1381*6aacab30SLorenzo Stoakes static bool test_merge_extend(void)
1382*6aacab30SLorenzo Stoakes {
1383*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
1384*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
1385*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0x1000);
1386*6aacab30SLorenzo Stoakes struct vm_area_struct *vma;
1387*6aacab30SLorenzo Stoakes
1388*6aacab30SLorenzo Stoakes vma = alloc_and_link_vma(&mm, 0, 0x1000, 0, vm_flags);
1389*6aacab30SLorenzo Stoakes alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, vm_flags);
1390*6aacab30SLorenzo Stoakes
1391*6aacab30SLorenzo Stoakes /*
1392*6aacab30SLorenzo Stoakes * Extend a VMA into the gap between itself and the following VMA.
1393*6aacab30SLorenzo Stoakes * This should result in a merge.
1394*6aacab30SLorenzo Stoakes *
1395*6aacab30SLorenzo Stoakes * <->
1396*6aacab30SLorenzo Stoakes * * *
1397*6aacab30SLorenzo Stoakes *
1398*6aacab30SLorenzo Stoakes */
1399*6aacab30SLorenzo Stoakes
1400*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_merge_extend(&vmi, vma, 0x2000), vma);
1401*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0);
1402*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x4000);
1403*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 0);
1404*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
1405*6aacab30SLorenzo Stoakes ASSERT_EQ(mm.map_count, 1);
1406*6aacab30SLorenzo Stoakes
1407*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1408*6aacab30SLorenzo Stoakes return true;
1409*6aacab30SLorenzo Stoakes }
1410*6aacab30SLorenzo Stoakes
test_expand_only_mode(void)1411*6aacab30SLorenzo Stoakes static bool test_expand_only_mode(void)
1412*6aacab30SLorenzo Stoakes {
1413*6aacab30SLorenzo Stoakes vm_flags_t vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;
1414*6aacab30SLorenzo Stoakes struct mm_struct mm = {};
1415*6aacab30SLorenzo Stoakes VMA_ITERATOR(vmi, &mm, 0);
1416*6aacab30SLorenzo Stoakes struct vm_area_struct *vma_prev, *vma;
1417*6aacab30SLorenzo Stoakes VMG_STATE(vmg, &mm, &vmi, 0x5000, 0x9000, vm_flags, 5);
1418*6aacab30SLorenzo Stoakes
1419*6aacab30SLorenzo Stoakes /*
1420*6aacab30SLorenzo Stoakes * Place a VMA prior to the one we're expanding so we assert that we do
1421*6aacab30SLorenzo Stoakes * not erroneously try to traverse to the previous VMA even though we
1422*6aacab30SLorenzo Stoakes * have, through the use of the just_expand flag, indicated we do not
1423*6aacab30SLorenzo Stoakes * need to do so.
1424*6aacab30SLorenzo Stoakes */
1425*6aacab30SLorenzo Stoakes alloc_and_link_vma(&mm, 0, 0x2000, 0, vm_flags);
1426*6aacab30SLorenzo Stoakes
1427*6aacab30SLorenzo Stoakes /*
1428*6aacab30SLorenzo Stoakes * We will be positioned at the prev VMA, but looking to expand to
1429*6aacab30SLorenzo Stoakes * 0x9000.
1430*6aacab30SLorenzo Stoakes */
1431*6aacab30SLorenzo Stoakes vma_iter_set(&vmi, 0x3000);
1432*6aacab30SLorenzo Stoakes vma_prev = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, vm_flags);
1433*6aacab30SLorenzo Stoakes vmg.prev = vma_prev;
1434*6aacab30SLorenzo Stoakes vmg.just_expand = true;
1435*6aacab30SLorenzo Stoakes
1436*6aacab30SLorenzo Stoakes vma = vma_merge_new_range(&vmg);
1437*6aacab30SLorenzo Stoakes ASSERT_NE(vma, NULL);
1438*6aacab30SLorenzo Stoakes ASSERT_EQ(vma, vma_prev);
1439*6aacab30SLorenzo Stoakes ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);
1440*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_start, 0x3000);
1441*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_end, 0x9000);
1442*6aacab30SLorenzo Stoakes ASSERT_EQ(vma->vm_pgoff, 3);
1443*6aacab30SLorenzo Stoakes ASSERT_TRUE(vma_write_started(vma));
1444*6aacab30SLorenzo Stoakes ASSERT_EQ(vma_iter_addr(&vmi), 0x3000);
1445*6aacab30SLorenzo Stoakes vma_assert_attached(vma);
1446*6aacab30SLorenzo Stoakes
1447*6aacab30SLorenzo Stoakes cleanup_mm(&mm, &vmi);
1448*6aacab30SLorenzo Stoakes return true;
1449*6aacab30SLorenzo Stoakes }
1450*6aacab30SLorenzo Stoakes
run_merge_tests(int * num_tests,int * num_fail)1451*6aacab30SLorenzo Stoakes static void run_merge_tests(int *num_tests, int *num_fail)
1452*6aacab30SLorenzo Stoakes {
1453*6aacab30SLorenzo Stoakes /* Very simple tests to kick the tyres. */
1454*6aacab30SLorenzo Stoakes TEST(simple_merge);
1455*6aacab30SLorenzo Stoakes TEST(simple_modify);
1456*6aacab30SLorenzo Stoakes TEST(simple_expand);
1457*6aacab30SLorenzo Stoakes TEST(simple_shrink);
1458*6aacab30SLorenzo Stoakes
1459*6aacab30SLorenzo Stoakes TEST(merge_new);
1460*6aacab30SLorenzo Stoakes TEST(vma_merge_special_flags);
1461*6aacab30SLorenzo Stoakes TEST(vma_merge_with_close);
1462*6aacab30SLorenzo Stoakes TEST(vma_merge_new_with_close);
1463*6aacab30SLorenzo Stoakes TEST(merge_existing);
1464*6aacab30SLorenzo Stoakes TEST(anon_vma_non_mergeable);
1465*6aacab30SLorenzo Stoakes TEST(dup_anon_vma);
1466*6aacab30SLorenzo Stoakes TEST(vmi_prealloc_fail);
1467*6aacab30SLorenzo Stoakes TEST(merge_extend);
1468*6aacab30SLorenzo Stoakes TEST(expand_only_mode);
1469*6aacab30SLorenzo Stoakes }
1470