brintos

brintos / linux-shallow public Read only

0
0
Text · 41.0 KiB · b33b473 Raw
1604 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 3#include <stdbool.h>4#include <stdio.h>5#include <stdlib.h>6 7#include "maple-shared.h"8#include "vma_internal.h"9 10/* Include so header guard set. */11#include "../../../mm/vma.h"12 13static bool fail_prealloc;14 15/* Then override vma_iter_prealloc() so we can choose to fail it. */16#define vma_iter_prealloc(vmi, vma)					\17	(fail_prealloc ? -ENOMEM : mas_preallocate(&(vmi)->mas, (vma), GFP_KERNEL))18 19/*20 * Directly import the VMA implementation here. Our vma_internal.h wrapper21 * provides userland-equivalent functionality for everything vma.c uses.22 */23#include "../../../mm/vma.c"24 25const struct vm_operations_struct vma_dummy_vm_ops;26static struct anon_vma dummy_anon_vma;27 28#define ASSERT_TRUE(_expr)						\29	do {								\30		if (!(_expr)) {						\31			fprintf(stderr,					\32				"Assert FAILED at %s:%d:%s(): %s is FALSE.\n", \33				__FILE__, __LINE__, __FUNCTION__, #_expr); \34			return false;					\35		}							\36	} while (0)37#define ASSERT_FALSE(_expr) ASSERT_TRUE(!(_expr))38#define ASSERT_EQ(_val1, _val2) ASSERT_TRUE((_val1) == (_val2))39#define ASSERT_NE(_val1, _val2) ASSERT_TRUE((_val1) != (_val2))40 41static struct task_struct __current;42 43struct task_struct *get_current(void)44{45	return &__current;46}47 48/* Helper function to simply allocate a VMA. */49static struct vm_area_struct *alloc_vma(struct mm_struct *mm,50					unsigned long start,51					unsigned long end,52					pgoff_t pgoff,53					vm_flags_t flags)54{55	struct vm_area_struct *ret = vm_area_alloc(mm);56 57	if (ret == NULL)58		return NULL;59 60	ret->vm_start = start;61	ret->vm_end = end;62	ret->vm_pgoff = pgoff;63	ret->__vm_flags = flags;64 65	return ret;66}67 68/* Helper function to allocate a VMA and link it to the tree. */69static struct vm_area_struct *alloc_and_link_vma(struct mm_struct *mm,70						 unsigned long start,71						 unsigned long end,72						 pgoff_t pgoff,73						 vm_flags_t flags)74{75	struct vm_area_struct *vma = alloc_vma(mm, start, end, pgoff, flags);76 77	if (vma == NULL)78		return NULL;79 80	if (vma_link(mm, vma)) {81		vm_area_free(vma);82		return NULL;83	}84 85	/*86	 * Reset this counter which we use to track whether writes have87	 * begun. Linking to the tree will have caused this to be incremented,88	 * which means we will get a false positive otherwise.89	 */90	vma->vm_lock_seq = -1;91 92	return vma;93}94 95/* Helper function which provides a wrapper around a merge new VMA operation. */96static struct vm_area_struct *merge_new(struct vma_merge_struct *vmg)97{98	/*99	 * For convenience, get prev and next VMAs. Which the new VMA operation100	 * requires.101	 */102	vmg->next = vma_next(vmg->vmi);103	vmg->prev = vma_prev(vmg->vmi);104	vma_iter_next_range(vmg->vmi);105 106	return vma_merge_new_range(vmg);107}108 109/*110 * Helper function which provides a wrapper around a merge existing VMA111 * operation.112 */113static struct vm_area_struct *merge_existing(struct vma_merge_struct *vmg)114{115	return vma_merge_existing_range(vmg);116}117 118/*119 * Helper function which provides a wrapper around the expansion of an existing120 * VMA.121 */122static int expand_existing(struct vma_merge_struct *vmg)123{124	return vma_expand(vmg);125}126 127/*128 * Helper function to reset merge state the associated VMA iterator to a129 * specified new range.130 */131static void vmg_set_range(struct vma_merge_struct *vmg, unsigned long start,132			  unsigned long end, pgoff_t pgoff, vm_flags_t flags)133{134	vma_iter_set(vmg->vmi, start);135 136	vmg->prev = NULL;137	vmg->next = NULL;138	vmg->vma = NULL;139 140	vmg->start = start;141	vmg->end = end;142	vmg->pgoff = pgoff;143	vmg->flags = flags;144}145 146/*147 * Helper function to try to merge a new VMA.148 *149 * Update vmg and the iterator for it and try to merge, otherwise allocate a new150 * VMA, link it to the maple tree and return it.151 */152static struct vm_area_struct *try_merge_new_vma(struct mm_struct *mm,153						struct vma_merge_struct *vmg,154						unsigned long start, unsigned long end,155						pgoff_t pgoff, vm_flags_t flags,156						bool *was_merged)157{158	struct vm_area_struct *merged;159 160	vmg_set_range(vmg, start, end, pgoff, flags);161 162	merged = merge_new(vmg);163	if (merged) {164		*was_merged = true;165		ASSERT_EQ(vmg->state, VMA_MERGE_SUCCESS);166		return merged;167	}168 169	*was_merged = false;170 171	ASSERT_EQ(vmg->state, VMA_MERGE_NOMERGE);172 173	return alloc_and_link_vma(mm, start, end, pgoff, flags);174}175 176/*177 * Helper function to reset the dummy anon_vma to indicate it has not been178 * duplicated.179 */180static void reset_dummy_anon_vma(void)181{182	dummy_anon_vma.was_cloned = false;183	dummy_anon_vma.was_unlinked = false;184}185 186/*187 * Helper function to remove all VMAs and destroy the maple tree associated with188 * a virtual address space. Returns a count of VMAs in the tree.189 */190static int cleanup_mm(struct mm_struct *mm, struct vma_iterator *vmi)191{192	struct vm_area_struct *vma;193	int count = 0;194 195	fail_prealloc = false;196	reset_dummy_anon_vma();197 198	vma_iter_set(vmi, 0);199	for_each_vma(*vmi, vma) {200		vm_area_free(vma);201		count++;202	}203 204	mtree_destroy(&mm->mm_mt);205	mm->map_count = 0;206	return count;207}208 209/* Helper function to determine if VMA has had vma_start_write() performed. */210static bool vma_write_started(struct vm_area_struct *vma)211{212	int seq = vma->vm_lock_seq;213 214	/* We reset after each check. */215	vma->vm_lock_seq = -1;216 217	/* The vma_start_write() stub simply increments this value. */218	return seq > -1;219}220 221/* Helper function providing a dummy vm_ops->close() method.*/222static void dummy_close(struct vm_area_struct *)223{224}225 226static bool test_simple_merge(void)227{228	struct vm_area_struct *vma;229	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;230	struct mm_struct mm = {};231	struct vm_area_struct *vma_left = alloc_vma(&mm, 0, 0x1000, 0, flags);232	struct vm_area_struct *vma_right = alloc_vma(&mm, 0x2000, 0x3000, 2, flags);233	VMA_ITERATOR(vmi, &mm, 0x1000);234	struct vma_merge_struct vmg = {235		.mm = &mm,236		.vmi = &vmi,237		.start = 0x1000,238		.end = 0x2000,239		.flags = flags,240		.pgoff = 1,241	};242 243	ASSERT_FALSE(vma_link(&mm, vma_left));244	ASSERT_FALSE(vma_link(&mm, vma_right));245 246	vma = merge_new(&vmg);247	ASSERT_NE(vma, NULL);248 249	ASSERT_EQ(vma->vm_start, 0);250	ASSERT_EQ(vma->vm_end, 0x3000);251	ASSERT_EQ(vma->vm_pgoff, 0);252	ASSERT_EQ(vma->vm_flags, flags);253 254	vm_area_free(vma);255	mtree_destroy(&mm.mm_mt);256 257	return true;258}259 260static bool test_simple_modify(void)261{262	struct vm_area_struct *vma;263	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;264	struct mm_struct mm = {};265	struct vm_area_struct *init_vma = alloc_vma(&mm, 0, 0x3000, 0, flags);266	VMA_ITERATOR(vmi, &mm, 0x1000);267 268	ASSERT_FALSE(vma_link(&mm, init_vma));269 270	/*271	 * The flags will not be changed, the vma_modify_flags() function272	 * performs the merge/split only.273	 */274	vma = vma_modify_flags(&vmi, init_vma, init_vma,275			       0x1000, 0x2000, VM_READ | VM_MAYREAD);276	ASSERT_NE(vma, NULL);277	/* We modify the provided VMA, and on split allocate new VMAs. */278	ASSERT_EQ(vma, init_vma);279 280	ASSERT_EQ(vma->vm_start, 0x1000);281	ASSERT_EQ(vma->vm_end, 0x2000);282	ASSERT_EQ(vma->vm_pgoff, 1);283 284	/*285	 * Now walk through the three split VMAs and make sure they are as286	 * expected.287	 */288 289	vma_iter_set(&vmi, 0);290	vma = vma_iter_load(&vmi);291 292	ASSERT_EQ(vma->vm_start, 0);293	ASSERT_EQ(vma->vm_end, 0x1000);294	ASSERT_EQ(vma->vm_pgoff, 0);295 296	vm_area_free(vma);297	vma_iter_clear(&vmi);298 299	vma = vma_next(&vmi);300 301	ASSERT_EQ(vma->vm_start, 0x1000);302	ASSERT_EQ(vma->vm_end, 0x2000);303	ASSERT_EQ(vma->vm_pgoff, 1);304 305	vm_area_free(vma);306	vma_iter_clear(&vmi);307 308	vma = vma_next(&vmi);309 310	ASSERT_EQ(vma->vm_start, 0x2000);311	ASSERT_EQ(vma->vm_end, 0x3000);312	ASSERT_EQ(vma->vm_pgoff, 2);313 314	vm_area_free(vma);315	mtree_destroy(&mm.mm_mt);316 317	return true;318}319 320static bool test_simple_expand(void)321{322	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;323	struct mm_struct mm = {};324	struct vm_area_struct *vma = alloc_vma(&mm, 0, 0x1000, 0, flags);325	VMA_ITERATOR(vmi, &mm, 0);326	struct vma_merge_struct vmg = {327		.vmi = &vmi,328		.vma = vma,329		.start = 0,330		.end = 0x3000,331		.pgoff = 0,332	};333 334	ASSERT_FALSE(vma_link(&mm, vma));335 336	ASSERT_FALSE(expand_existing(&vmg));337 338	ASSERT_EQ(vma->vm_start, 0);339	ASSERT_EQ(vma->vm_end, 0x3000);340	ASSERT_EQ(vma->vm_pgoff, 0);341 342	vm_area_free(vma);343	mtree_destroy(&mm.mm_mt);344 345	return true;346}347 348static bool test_simple_shrink(void)349{350	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;351	struct mm_struct mm = {};352	struct vm_area_struct *vma = alloc_vma(&mm, 0, 0x3000, 0, flags);353	VMA_ITERATOR(vmi, &mm, 0);354 355	ASSERT_FALSE(vma_link(&mm, vma));356 357	ASSERT_FALSE(vma_shrink(&vmi, vma, 0, 0x1000, 0));358 359	ASSERT_EQ(vma->vm_start, 0);360	ASSERT_EQ(vma->vm_end, 0x1000);361	ASSERT_EQ(vma->vm_pgoff, 0);362 363	vm_area_free(vma);364	mtree_destroy(&mm.mm_mt);365 366	return true;367}368 369static bool test_merge_new(void)370{371	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;372	struct mm_struct mm = {};373	VMA_ITERATOR(vmi, &mm, 0);374	struct vma_merge_struct vmg = {375		.mm = &mm,376		.vmi = &vmi,377	};378	struct anon_vma_chain dummy_anon_vma_chain_a = {379		.anon_vma = &dummy_anon_vma,380	};381	struct anon_vma_chain dummy_anon_vma_chain_b = {382		.anon_vma = &dummy_anon_vma,383	};384	struct anon_vma_chain dummy_anon_vma_chain_c = {385		.anon_vma = &dummy_anon_vma,386	};387	struct anon_vma_chain dummy_anon_vma_chain_d = {388		.anon_vma = &dummy_anon_vma,389	};390	const struct vm_operations_struct vm_ops = {391		.close = dummy_close,392	};393	int count;394	struct vm_area_struct *vma, *vma_a, *vma_b, *vma_c, *vma_d;395	bool merged;396 397	/*398	 * 0123456789abc399	 * AA B       CC400	 */401	vma_a = alloc_and_link_vma(&mm, 0, 0x2000, 0, flags);402	ASSERT_NE(vma_a, NULL);403	/* We give each VMA a single avc so we can test anon_vma duplication. */404	INIT_LIST_HEAD(&vma_a->anon_vma_chain);405	list_add(&dummy_anon_vma_chain_a.same_vma, &vma_a->anon_vma_chain);406 407	vma_b = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, flags);408	ASSERT_NE(vma_b, NULL);409	INIT_LIST_HEAD(&vma_b->anon_vma_chain);410	list_add(&dummy_anon_vma_chain_b.same_vma, &vma_b->anon_vma_chain);411 412	vma_c = alloc_and_link_vma(&mm, 0xb000, 0xc000, 0xb, flags);413	ASSERT_NE(vma_c, NULL);414	INIT_LIST_HEAD(&vma_c->anon_vma_chain);415	list_add(&dummy_anon_vma_chain_c.same_vma, &vma_c->anon_vma_chain);416 417	/*418	 * NO merge.419	 *420	 * 0123456789abc421	 * AA B   **  CC422	 */423	vma_d = try_merge_new_vma(&mm, &vmg, 0x7000, 0x9000, 7, flags, &merged);424	ASSERT_NE(vma_d, NULL);425	INIT_LIST_HEAD(&vma_d->anon_vma_chain);426	list_add(&dummy_anon_vma_chain_d.same_vma, &vma_d->anon_vma_chain);427	ASSERT_FALSE(merged);428	ASSERT_EQ(mm.map_count, 4);429 430	/*431	 * Merge BOTH sides.432	 *433	 * 0123456789abc434	 * AA*B   DD  CC435	 */436	vma_a->vm_ops = &vm_ops; /* This should have no impact. */437	vma_b->anon_vma = &dummy_anon_vma;438	vma = try_merge_new_vma(&mm, &vmg, 0x2000, 0x3000, 2, flags, &merged);439	ASSERT_EQ(vma, vma_a);440	/* Merge with A, delete B. */441	ASSERT_TRUE(merged);442	ASSERT_EQ(vma->vm_start, 0);443	ASSERT_EQ(vma->vm_end, 0x4000);444	ASSERT_EQ(vma->vm_pgoff, 0);445	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);446	ASSERT_TRUE(vma_write_started(vma));447	ASSERT_EQ(mm.map_count, 3);448 449	/*450	 * Merge to PREVIOUS VMA.451	 *452	 * 0123456789abc453	 * AAAA*  DD  CC454	 */455	vma = try_merge_new_vma(&mm, &vmg, 0x4000, 0x5000, 4, flags, &merged);456	ASSERT_EQ(vma, vma_a);457	/* Extend A. */458	ASSERT_TRUE(merged);459	ASSERT_EQ(vma->vm_start, 0);460	ASSERT_EQ(vma->vm_end, 0x5000);461	ASSERT_EQ(vma->vm_pgoff, 0);462	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);463	ASSERT_TRUE(vma_write_started(vma));464	ASSERT_EQ(mm.map_count, 3);465 466	/*467	 * Merge to NEXT VMA.468	 *469	 * 0123456789abc470	 * AAAAA *DD  CC471	 */472	vma_d->anon_vma = &dummy_anon_vma;473	vma_d->vm_ops = &vm_ops; /* This should have no impact. */474	vma = try_merge_new_vma(&mm, &vmg, 0x6000, 0x7000, 6, flags, &merged);475	ASSERT_EQ(vma, vma_d);476	/* Prepend. */477	ASSERT_TRUE(merged);478	ASSERT_EQ(vma->vm_start, 0x6000);479	ASSERT_EQ(vma->vm_end, 0x9000);480	ASSERT_EQ(vma->vm_pgoff, 6);481	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);482	ASSERT_TRUE(vma_write_started(vma));483	ASSERT_EQ(mm.map_count, 3);484 485	/*486	 * Merge BOTH sides.487	 *488	 * 0123456789abc489	 * AAAAA*DDD  CC490	 */491	vma_d->vm_ops = NULL; /* This would otherwise degrade the merge. */492	vma = try_merge_new_vma(&mm, &vmg, 0x5000, 0x6000, 5, flags, &merged);493	ASSERT_EQ(vma, vma_a);494	/* Merge with A, delete D. */495	ASSERT_TRUE(merged);496	ASSERT_EQ(vma->vm_start, 0);497	ASSERT_EQ(vma->vm_end, 0x9000);498	ASSERT_EQ(vma->vm_pgoff, 0);499	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);500	ASSERT_TRUE(vma_write_started(vma));501	ASSERT_EQ(mm.map_count, 2);502 503	/*504	 * Merge to NEXT VMA.505	 *506	 * 0123456789abc507	 * AAAAAAAAA *CC508	 */509	vma_c->anon_vma = &dummy_anon_vma;510	vma = try_merge_new_vma(&mm, &vmg, 0xa000, 0xb000, 0xa, flags, &merged);511	ASSERT_EQ(vma, vma_c);512	/* Prepend C. */513	ASSERT_TRUE(merged);514	ASSERT_EQ(vma->vm_start, 0xa000);515	ASSERT_EQ(vma->vm_end, 0xc000);516	ASSERT_EQ(vma->vm_pgoff, 0xa);517	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);518	ASSERT_TRUE(vma_write_started(vma));519	ASSERT_EQ(mm.map_count, 2);520 521	/*522	 * Merge BOTH sides.523	 *524	 * 0123456789abc525	 * AAAAAAAAA*CCC526	 */527	vma = try_merge_new_vma(&mm, &vmg, 0x9000, 0xa000, 0x9, flags, &merged);528	ASSERT_EQ(vma, vma_a);529	/* Extend A and delete C. */530	ASSERT_TRUE(merged);531	ASSERT_EQ(vma->vm_start, 0);532	ASSERT_EQ(vma->vm_end, 0xc000);533	ASSERT_EQ(vma->vm_pgoff, 0);534	ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);535	ASSERT_TRUE(vma_write_started(vma));536	ASSERT_EQ(mm.map_count, 1);537 538	/*539	 * Final state.540	 *541	 * 0123456789abc542	 * AAAAAAAAAAAAA543	 */544 545	count = 0;546	vma_iter_set(&vmi, 0);547	for_each_vma(vmi, vma) {548		ASSERT_NE(vma, NULL);549		ASSERT_EQ(vma->vm_start, 0);550		ASSERT_EQ(vma->vm_end, 0xc000);551		ASSERT_EQ(vma->vm_pgoff, 0);552		ASSERT_EQ(vma->anon_vma, &dummy_anon_vma);553 554		vm_area_free(vma);555		count++;556	}557 558	/* Should only have one VMA left (though freed) after all is done.*/559	ASSERT_EQ(count, 1);560 561	mtree_destroy(&mm.mm_mt);562	return true;563}564 565static bool test_vma_merge_special_flags(void)566{567	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;568	struct mm_struct mm = {};569	VMA_ITERATOR(vmi, &mm, 0);570	struct vma_merge_struct vmg = {571		.mm = &mm,572		.vmi = &vmi,573	};574	vm_flags_t special_flags[] = { VM_IO, VM_DONTEXPAND, VM_PFNMAP, VM_MIXEDMAP };575	vm_flags_t all_special_flags = 0;576	int i;577	struct vm_area_struct *vma_left, *vma;578 579	/* Make sure there aren't new VM_SPECIAL flags. */580	for (i = 0; i < ARRAY_SIZE(special_flags); i++) {581		all_special_flags |= special_flags[i];582	}583	ASSERT_EQ(all_special_flags, VM_SPECIAL);584 585	/*586	 * 01234587	 * AAA588	 */589	vma_left = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);590	ASSERT_NE(vma_left, NULL);591 592	/* 1. Set up new VMA with special flag that would otherwise merge. */593 594	/*595	 * 01234596	 * AAA*597	 *598	 * This should merge if not for the VM_SPECIAL flag.599	 */600	vmg_set_range(&vmg, 0x3000, 0x4000, 3, flags);601	for (i = 0; i < ARRAY_SIZE(special_flags); i++) {602		vm_flags_t special_flag = special_flags[i];603 604		vma_left->__vm_flags = flags | special_flag;605		vmg.flags = flags | special_flag;606		vma = merge_new(&vmg);607		ASSERT_EQ(vma, NULL);608		ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);609	}610 611	/* 2. Modify VMA with special flag that would otherwise merge. */612 613	/*614	 * 01234615	 * AAAB616	 *617	 * Create a VMA to modify.618	 */619	vma = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, flags);620	ASSERT_NE(vma, NULL);621	vmg.vma = vma;622 623	for (i = 0; i < ARRAY_SIZE(special_flags); i++) {624		vm_flags_t special_flag = special_flags[i];625 626		vma_left->__vm_flags = flags | special_flag;627		vmg.flags = flags | special_flag;628		vma = merge_existing(&vmg);629		ASSERT_EQ(vma, NULL);630		ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);631	}632 633	cleanup_mm(&mm, &vmi);634	return true;635}636 637static bool test_vma_merge_with_close(void)638{639	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;640	struct mm_struct mm = {};641	VMA_ITERATOR(vmi, &mm, 0);642	struct vma_merge_struct vmg = {643		.mm = &mm,644		.vmi = &vmi,645	};646	const struct vm_operations_struct vm_ops = {647		.close = dummy_close,648	};649	struct vm_area_struct *vma_prev, *vma_next, *vma;650 651	/*652	 * When merging VMAs we are not permitted to remove any VMA that has a653	 * vm_ops->close() hook.654	 *655	 * Considering the two possible adjacent VMAs to which a VMA can be656	 * merged:657	 *658	 * [ prev ][ vma ][ next ]659	 *660	 * In no case will we need to delete prev. If the operation is661	 * mergeable, then prev will be extended with one or both of vma and662	 * next deleted.663	 *664	 * As a result, during initial mergeability checks, only665	 * can_vma_merge_before() (which implies the VMA being merged with is666	 * 'next' as shown above) bothers to check to see whether the next VMA667	 * has a vm_ops->close() callback that will need to be called when668	 * removed.669	 *670	 * If it does, then we cannot merge as the resources that the close()671	 * operation potentially clears down are tied only to the existing VMA672	 * range and we have no way of extending those to the nearly merged one.673	 *674	 * We must consider two scenarios:675	 *676	 * A.677	 *678	 * vm_ops->close:     -       -    !NULL679	 *                 [ prev ][ vma ][ next ]680	 *681	 * Where prev may or may not be present/mergeable.682	 *683	 * This is picked up by a specific check in can_vma_merge_before().684	 *685	 * B.686	 *687	 * vm_ops->close:     -     !NULL688	 *                 [ prev ][ vma ]689	 *690	 * Where prev and vma are present and mergeable.691	 *692	 * This is picked up by a specific check in the modified VMA merge.693	 *694	 * IMPORTANT NOTE: We make the assumption that the following case:695	 *696	 *    -     !NULL   NULL697	 * [ prev ][ vma ][ next ]698	 *699	 * Cannot occur, because vma->vm_ops being the same implies the same700	 * vma->vm_file, and therefore this would mean that next->vm_ops->close701	 * would be set too, and thus scenario A would pick this up.702	 */703 704	/*705	 * The only case of a new VMA merge that results in a VMA being deleted706	 * is one where both the previous and next VMAs are merged - in this707	 * instance the next VMA is deleted, and the previous VMA is extended.708	 *709	 * If we are unable to do so, we reduce the operation to simply710	 * extending the prev VMA and not merging next.711	 *712	 * 0123456789713	 * PPP**NNNN714	 *             ->715	 * 0123456789716	 * PPPPPPNNN717	 */718 719	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);720	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, flags);721	vma_next->vm_ops = &vm_ops;722 723	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);724	ASSERT_EQ(merge_new(&vmg), vma_prev);725	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);726	ASSERT_EQ(vma_prev->vm_start, 0);727	ASSERT_EQ(vma_prev->vm_end, 0x5000);728	ASSERT_EQ(vma_prev->vm_pgoff, 0);729 730	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);731 732	/*733	 * When modifying an existing VMA there are further cases where we734	 * delete VMAs.735	 *736	 *    <>737	 * 0123456789738	 * PPPVV739	 *740	 * In this instance, if vma has a close hook, the merge simply cannot741	 * proceed.742	 */743 744	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);745	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);746	vma->vm_ops = &vm_ops;747 748	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);749	vmg.prev = vma_prev;750	vmg.vma = vma;751 752	/*753	 * The VMA being modified in a way that would otherwise merge should754	 * also fail.755	 */756	ASSERT_EQ(merge_existing(&vmg), NULL);757	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);758 759	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);760 761	/*762	 * This case is mirrored if merging with next.763	 *764	 *    <>765	 * 0123456789766	 *    VVNNNN767	 *768	 * In this instance, if vma has a close hook, the merge simply cannot769	 * proceed.770	 */771 772	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);773	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, flags);774	vma->vm_ops = &vm_ops;775 776	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);777	vmg.vma = vma;778	ASSERT_EQ(merge_existing(&vmg), NULL);779	/*780	 * Initially this is misapprehended as an out of memory report, as the781	 * close() check is handled in the same way as anon_vma duplication782	 * failures, however a subsequent patch resolves this.783	 */784	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);785 786	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);787 788	/*789	 * Finally, we consider two variants of the case where we modify a VMA790	 * to merge with both the previous and next VMAs.791	 *792	 * The first variant is where vma has a close hook. In this instance, no793	 * merge can proceed.794	 *795	 *    <>796	 * 0123456789797	 * PPPVVNNNN798	 */799 800	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);801	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);802	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, flags);803	vma->vm_ops = &vm_ops;804 805	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);806	vmg.prev = vma_prev;807	vmg.vma = vma;808 809	ASSERT_EQ(merge_existing(&vmg), NULL);810	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);811 812	ASSERT_EQ(cleanup_mm(&mm, &vmi), 3);813 814	/*815	 * The second variant is where next has a close hook. In this instance,816	 * we reduce the operation to a merge between prev and vma.817	 *818	 *    <>819	 * 0123456789820	 * PPPVVNNNN821	 *            ->822	 * 0123456789823	 * PPPPPNNNN824	 */825 826	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);827	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);828	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x9000, 5, flags);829	vma_next->vm_ops = &vm_ops;830 831	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);832	vmg.prev = vma_prev;833	vmg.vma = vma;834 835	ASSERT_EQ(merge_existing(&vmg), vma_prev);836	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);837	ASSERT_EQ(vma_prev->vm_start, 0);838	ASSERT_EQ(vma_prev->vm_end, 0x5000);839	ASSERT_EQ(vma_prev->vm_pgoff, 0);840 841	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);842 843	return true;844}845 846static bool test_vma_merge_new_with_close(void)847{848	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;849	struct mm_struct mm = {};850	VMA_ITERATOR(vmi, &mm, 0);851	struct vma_merge_struct vmg = {852		.mm = &mm,853		.vmi = &vmi,854	};855	struct vm_area_struct *vma_prev = alloc_and_link_vma(&mm, 0, 0x2000, 0, flags);856	struct vm_area_struct *vma_next = alloc_and_link_vma(&mm, 0x5000, 0x7000, 5, flags);857	const struct vm_operations_struct vm_ops = {858		.close = dummy_close,859	};860	struct vm_area_struct *vma;861 862	/*863	 * We should allow the partial merge of a proposed new VMA if the864	 * surrounding VMAs have vm_ops->close() hooks (but are otherwise865	 * compatible), e.g.:866	 *867	 *        New VMA868	 *    A  v-------v  B869	 * |-----|       |-----|870	 *  close         close871	 *872	 * Since the rule is to not DELETE a VMA with a close operation, this873	 * should be permitted, only rather than expanding A and deleting B, we874	 * should simply expand A and leave B intact, e.g.:875	 *876	 *        New VMA877	 *       A          B878	 * |------------||-----|879	 *  close         close880	 */881 882	/* Have prev and next have a vm_ops->close() hook. */883	vma_prev->vm_ops = &vm_ops;884	vma_next->vm_ops = &vm_ops;885 886	vmg_set_range(&vmg, 0x2000, 0x5000, 2, flags);887	vma = merge_new(&vmg);888	ASSERT_NE(vma, NULL);889	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);890	ASSERT_EQ(vma->vm_start, 0);891	ASSERT_EQ(vma->vm_end, 0x5000);892	ASSERT_EQ(vma->vm_pgoff, 0);893	ASSERT_EQ(vma->vm_ops, &vm_ops);894	ASSERT_TRUE(vma_write_started(vma));895	ASSERT_EQ(mm.map_count, 2);896 897	cleanup_mm(&mm, &vmi);898	return true;899}900 901static bool test_merge_existing(void)902{903	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;904	struct mm_struct mm = {};905	VMA_ITERATOR(vmi, &mm, 0);906	struct vm_area_struct *vma, *vma_prev, *vma_next;907	struct vma_merge_struct vmg = {908		.mm = &mm,909		.vmi = &vmi,910	};911	const struct vm_operations_struct vm_ops = {912		.close = dummy_close,913	};914 915	/*916	 * Merge right case - partial span.917	 *918	 *    <->919	 * 0123456789920	 *   VVVVNNN921	 *            ->922	 * 0123456789923	 *   VNNNNNN924	 */925	vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, flags);926	vma->vm_ops = &vm_ops; /* This should have no impact. */927	vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, flags);928	vma_next->vm_ops = &vm_ops; /* This should have no impact. */929	vmg_set_range(&vmg, 0x3000, 0x6000, 3, flags);930	vmg.vma = vma;931	vmg.prev = vma;932	vma->anon_vma = &dummy_anon_vma;933	ASSERT_EQ(merge_existing(&vmg), vma_next);934	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);935	ASSERT_EQ(vma_next->vm_start, 0x3000);936	ASSERT_EQ(vma_next->vm_end, 0x9000);937	ASSERT_EQ(vma_next->vm_pgoff, 3);938	ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);939	ASSERT_EQ(vma->vm_start, 0x2000);940	ASSERT_EQ(vma->vm_end, 0x3000);941	ASSERT_EQ(vma->vm_pgoff, 2);942	ASSERT_TRUE(vma_write_started(vma));943	ASSERT_TRUE(vma_write_started(vma_next));944	ASSERT_EQ(mm.map_count, 2);945 946	/* Clear down and reset. */947	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);948 949	/*950	 * Merge right case - full span.951	 *952	 *   <-->953	 * 0123456789954	 *   VVVVNNN955	 *            ->956	 * 0123456789957	 *   NNNNNNN958	 */959	vma = alloc_and_link_vma(&mm, 0x2000, 0x6000, 2, flags);960	vma_next = alloc_and_link_vma(&mm, 0x6000, 0x9000, 6, flags);961	vma_next->vm_ops = &vm_ops; /* This should have no impact. */962	vmg_set_range(&vmg, 0x2000, 0x6000, 2, flags);963	vmg.vma = vma;964	vma->anon_vma = &dummy_anon_vma;965	ASSERT_EQ(merge_existing(&vmg), vma_next);966	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);967	ASSERT_EQ(vma_next->vm_start, 0x2000);968	ASSERT_EQ(vma_next->vm_end, 0x9000);969	ASSERT_EQ(vma_next->vm_pgoff, 2);970	ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);971	ASSERT_TRUE(vma_write_started(vma_next));972	ASSERT_EQ(mm.map_count, 1);973 974	/* Clear down and reset. We should have deleted vma. */975	ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);976 977	/*978	 * Merge left case - partial span.979	 *980	 *    <->981	 * 0123456789982	 * PPPVVVV983	 *            ->984	 * 0123456789985	 * PPPPPPV986	 */987	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);988	vma_prev->vm_ops = &vm_ops; /* This should have no impact. */989	vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, flags);990	vma->vm_ops = &vm_ops; /* This should have no impact. */991	vmg_set_range(&vmg, 0x3000, 0x6000, 3, flags);992	vmg.prev = vma_prev;993	vmg.vma = vma;994	vma->anon_vma = &dummy_anon_vma;995 996	ASSERT_EQ(merge_existing(&vmg), vma_prev);997	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);998	ASSERT_EQ(vma_prev->vm_start, 0);999	ASSERT_EQ(vma_prev->vm_end, 0x6000);1000	ASSERT_EQ(vma_prev->vm_pgoff, 0);1001	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1002	ASSERT_EQ(vma->vm_start, 0x6000);1003	ASSERT_EQ(vma->vm_end, 0x7000);1004	ASSERT_EQ(vma->vm_pgoff, 6);1005	ASSERT_TRUE(vma_write_started(vma_prev));1006	ASSERT_TRUE(vma_write_started(vma));1007	ASSERT_EQ(mm.map_count, 2);1008 1009	/* Clear down and reset. */1010	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);1011 1012	/*1013	 * Merge left case - full span.1014	 *1015	 *    <-->1016	 * 01234567891017	 * PPPVVVV1018	 *            ->1019	 * 01234567891020	 * PPPPPPP1021	 */1022	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1023	vma_prev->vm_ops = &vm_ops; /* This should have no impact. */1024	vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, flags);1025	vmg_set_range(&vmg, 0x3000, 0x7000, 3, flags);1026	vmg.prev = vma_prev;1027	vmg.vma = vma;1028	vma->anon_vma = &dummy_anon_vma;1029	ASSERT_EQ(merge_existing(&vmg), vma_prev);1030	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1031	ASSERT_EQ(vma_prev->vm_start, 0);1032	ASSERT_EQ(vma_prev->vm_end, 0x7000);1033	ASSERT_EQ(vma_prev->vm_pgoff, 0);1034	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1035	ASSERT_TRUE(vma_write_started(vma_prev));1036	ASSERT_EQ(mm.map_count, 1);1037 1038	/* Clear down and reset. We should have deleted vma. */1039	ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);1040 1041	/*1042	 * Merge both case.1043	 *1044	 *    <-->1045	 * 01234567891046	 * PPPVVVVNNN1047	 *             ->1048	 * 01234567891049	 * PPPPPPPPPP1050	 */1051	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1052	vma_prev->vm_ops = &vm_ops; /* This should have no impact. */1053	vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, flags);1054	vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, flags);1055	vmg_set_range(&vmg, 0x3000, 0x7000, 3, flags);1056	vmg.prev = vma_prev;1057	vmg.vma = vma;1058	vma->anon_vma = &dummy_anon_vma;1059	ASSERT_EQ(merge_existing(&vmg), vma_prev);1060	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1061	ASSERT_EQ(vma_prev->vm_start, 0);1062	ASSERT_EQ(vma_prev->vm_end, 0x9000);1063	ASSERT_EQ(vma_prev->vm_pgoff, 0);1064	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1065	ASSERT_TRUE(vma_write_started(vma_prev));1066	ASSERT_EQ(mm.map_count, 1);1067 1068	/* Clear down and reset. We should have deleted prev and next. */1069	ASSERT_EQ(cleanup_mm(&mm, &vmi), 1);1070 1071	/*1072	 * Non-merge ranges. the modified VMA merge operation assumes that the1073	 * caller always specifies ranges within the input VMA so we need only1074	 * examine these cases.1075	 *1076	 *     -1077	 *      -1078	 *       -1079	 *     <->1080	 *     <>1081	 *      <>1082	 * 0123456789a1083	 * PPPVVVVVNNN1084	 */1085 1086	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1087	vma = alloc_and_link_vma(&mm, 0x3000, 0x8000, 3, flags);1088	vma_next = alloc_and_link_vma(&mm, 0x8000, 0xa000, 8, flags);1089 1090	vmg_set_range(&vmg, 0x4000, 0x5000, 4, flags);1091	vmg.prev = vma;1092	vmg.vma = vma;1093	ASSERT_EQ(merge_existing(&vmg), NULL);1094	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1095 1096	vmg_set_range(&vmg, 0x5000, 0x6000, 5, flags);1097	vmg.prev = vma;1098	vmg.vma = vma;1099	ASSERT_EQ(merge_existing(&vmg), NULL);1100	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1101 1102	vmg_set_range(&vmg, 0x6000, 0x7000, 6, flags);1103	vmg.prev = vma;1104	vmg.vma = vma;1105	ASSERT_EQ(merge_existing(&vmg), NULL);1106	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1107 1108	vmg_set_range(&vmg, 0x4000, 0x7000, 4, flags);1109	vmg.prev = vma;1110	vmg.vma = vma;1111	ASSERT_EQ(merge_existing(&vmg), NULL);1112	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1113 1114	vmg_set_range(&vmg, 0x4000, 0x6000, 4, flags);1115	vmg.prev = vma;1116	vmg.vma = vma;1117	ASSERT_EQ(merge_existing(&vmg), NULL);1118	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1119 1120	vmg_set_range(&vmg, 0x5000, 0x6000, 5, flags);1121	vmg.prev = vma;1122	vmg.vma = vma;1123	ASSERT_EQ(merge_existing(&vmg), NULL);1124	ASSERT_EQ(vmg.state, VMA_MERGE_NOMERGE);1125 1126	ASSERT_EQ(cleanup_mm(&mm, &vmi), 3);1127 1128	return true;1129}1130 1131static bool test_anon_vma_non_mergeable(void)1132{1133	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1134	struct mm_struct mm = {};1135	VMA_ITERATOR(vmi, &mm, 0);1136	struct vm_area_struct *vma, *vma_prev, *vma_next;1137	struct vma_merge_struct vmg = {1138		.mm = &mm,1139		.vmi = &vmi,1140	};1141	struct anon_vma_chain dummy_anon_vma_chain1 = {1142		.anon_vma = &dummy_anon_vma,1143	};1144	struct anon_vma_chain dummy_anon_vma_chain2 = {1145		.anon_vma = &dummy_anon_vma,1146	};1147 1148	/*1149	 * In the case of modified VMA merge, merging both left and right VMAs1150	 * but where prev and next have incompatible anon_vma objects, we revert1151	 * to a merge of prev and VMA:1152	 *1153	 *    <-->1154	 * 01234567891155	 * PPPVVVVNNN1156	 *            ->1157	 * 01234567891158	 * PPPPPPPNNN1159	 */1160	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1161	vma = alloc_and_link_vma(&mm, 0x3000, 0x7000, 3, flags);1162	vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, flags);1163 1164	/*1165	 * Give both prev and next single anon_vma_chain fields, so they will1166	 * merge with the NULL vmg->anon_vma.1167	 *1168	 * However, when prev is compared to next, the merge should fail.1169	 */1170 1171	INIT_LIST_HEAD(&vma_prev->anon_vma_chain);1172	list_add(&dummy_anon_vma_chain1.same_vma, &vma_prev->anon_vma_chain);1173	ASSERT_TRUE(list_is_singular(&vma_prev->anon_vma_chain));1174	vma_prev->anon_vma = &dummy_anon_vma;1175	ASSERT_TRUE(is_mergeable_anon_vma(NULL, vma_prev->anon_vma, vma_prev));1176 1177	INIT_LIST_HEAD(&vma_next->anon_vma_chain);1178	list_add(&dummy_anon_vma_chain2.same_vma, &vma_next->anon_vma_chain);1179	ASSERT_TRUE(list_is_singular(&vma_next->anon_vma_chain));1180	vma_next->anon_vma = (struct anon_vma *)2;1181	ASSERT_TRUE(is_mergeable_anon_vma(NULL, vma_next->anon_vma, vma_next));1182 1183	ASSERT_FALSE(is_mergeable_anon_vma(vma_prev->anon_vma, vma_next->anon_vma, NULL));1184 1185	vmg_set_range(&vmg, 0x3000, 0x7000, 3, flags);1186	vmg.prev = vma_prev;1187	vmg.vma = vma;1188 1189	ASSERT_EQ(merge_existing(&vmg), vma_prev);1190	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1191	ASSERT_EQ(vma_prev->vm_start, 0);1192	ASSERT_EQ(vma_prev->vm_end, 0x7000);1193	ASSERT_EQ(vma_prev->vm_pgoff, 0);1194	ASSERT_TRUE(vma_write_started(vma_prev));1195	ASSERT_FALSE(vma_write_started(vma_next));1196 1197	/* Clear down and reset. */1198	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);1199 1200	/*1201	 * Now consider the new VMA case. This is equivalent, only adding a new1202	 * VMA in a gap between prev and next.1203	 *1204	 *    <-->1205	 * 01234567891206	 * PPP****NNN1207	 *            ->1208	 * 01234567891209	 * PPPPPPPNNN1210	 */1211	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1212	vma_next = alloc_and_link_vma(&mm, 0x7000, 0x9000, 7, flags);1213 1214	INIT_LIST_HEAD(&vma_prev->anon_vma_chain);1215	list_add(&dummy_anon_vma_chain1.same_vma, &vma_prev->anon_vma_chain);1216	vma_prev->anon_vma = (struct anon_vma *)1;1217 1218	INIT_LIST_HEAD(&vma_next->anon_vma_chain);1219	list_add(&dummy_anon_vma_chain2.same_vma, &vma_next->anon_vma_chain);1220	vma_next->anon_vma = (struct anon_vma *)2;1221 1222	vmg_set_range(&vmg, 0x3000, 0x7000, 3, flags);1223	vmg.prev = vma_prev;1224 1225	ASSERT_EQ(merge_new(&vmg), vma_prev);1226	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1227	ASSERT_EQ(vma_prev->vm_start, 0);1228	ASSERT_EQ(vma_prev->vm_end, 0x7000);1229	ASSERT_EQ(vma_prev->vm_pgoff, 0);1230	ASSERT_TRUE(vma_write_started(vma_prev));1231	ASSERT_FALSE(vma_write_started(vma_next));1232 1233	/* Final cleanup. */1234	ASSERT_EQ(cleanup_mm(&mm, &vmi), 2);1235 1236	return true;1237}1238 1239static bool test_dup_anon_vma(void)1240{1241	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1242	struct mm_struct mm = {};1243	VMA_ITERATOR(vmi, &mm, 0);1244	struct vma_merge_struct vmg = {1245		.mm = &mm,1246		.vmi = &vmi,1247	};1248	struct anon_vma_chain dummy_anon_vma_chain = {1249		.anon_vma = &dummy_anon_vma,1250	};1251	struct vm_area_struct *vma_prev, *vma_next, *vma;1252 1253	reset_dummy_anon_vma();1254 1255	/*1256	 * Expanding a VMA delete the next one duplicates next's anon_vma and1257	 * assigns it to the expanded VMA.1258	 *1259	 * This covers new VMA merging, as these operations amount to a VMA1260	 * expand.1261	 */1262	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1263	vma_next = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1264	vma_next->anon_vma = &dummy_anon_vma;1265 1266	vmg_set_range(&vmg, 0, 0x5000, 0, flags);1267	vmg.vma = vma_prev;1268	vmg.next = vma_next;1269 1270	ASSERT_EQ(expand_existing(&vmg), 0);1271 1272	/* Will have been cloned. */1273	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1274	ASSERT_TRUE(vma_prev->anon_vma->was_cloned);1275 1276	/* Cleanup ready for next run. */1277	cleanup_mm(&mm, &vmi);1278 1279	/*1280	 * next has anon_vma, we assign to prev.1281	 *1282	 *         |<----->|1283	 * |-------*********-------|1284	 *   prev     vma     next1285	 *  extend   delete  delete1286	 */1287 1288	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1289	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1290	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, flags);1291 1292	/* Initialise avc so mergeability check passes. */1293	INIT_LIST_HEAD(&vma_next->anon_vma_chain);1294	list_add(&dummy_anon_vma_chain.same_vma, &vma_next->anon_vma_chain);1295 1296	vma_next->anon_vma = &dummy_anon_vma;1297	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);1298	vmg.prev = vma_prev;1299	vmg.vma = vma;1300 1301	ASSERT_EQ(merge_existing(&vmg), vma_prev);1302	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1303 1304	ASSERT_EQ(vma_prev->vm_start, 0);1305	ASSERT_EQ(vma_prev->vm_end, 0x8000);1306 1307	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1308	ASSERT_TRUE(vma_prev->anon_vma->was_cloned);1309 1310	cleanup_mm(&mm, &vmi);1311 1312	/*1313	 * vma has anon_vma, we assign to prev.1314	 *1315	 *         |<----->|1316	 * |-------*********-------|1317	 *   prev     vma     next1318	 *  extend   delete  delete1319	 */1320 1321	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1322	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1323	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, flags);1324 1325	vma->anon_vma = &dummy_anon_vma;1326	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);1327	vmg.prev = vma_prev;1328	vmg.vma = vma;1329 1330	ASSERT_EQ(merge_existing(&vmg), vma_prev);1331	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1332 1333	ASSERT_EQ(vma_prev->vm_start, 0);1334	ASSERT_EQ(vma_prev->vm_end, 0x8000);1335 1336	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1337	ASSERT_TRUE(vma_prev->anon_vma->was_cloned);1338 1339	cleanup_mm(&mm, &vmi);1340 1341	/*1342	 * vma has anon_vma, we assign to prev.1343	 *1344	 *         |<----->|1345	 * |-------*************1346	 *   prev       vma1347	 *  extend shrink/delete1348	 */1349 1350	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1351	vma = alloc_and_link_vma(&mm, 0x3000, 0x8000, 3, flags);1352 1353	vma->anon_vma = &dummy_anon_vma;1354	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);1355	vmg.prev = vma_prev;1356	vmg.vma = vma;1357 1358	ASSERT_EQ(merge_existing(&vmg), vma_prev);1359	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1360 1361	ASSERT_EQ(vma_prev->vm_start, 0);1362	ASSERT_EQ(vma_prev->vm_end, 0x5000);1363 1364	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1365	ASSERT_TRUE(vma_prev->anon_vma->was_cloned);1366 1367	cleanup_mm(&mm, &vmi);1368 1369	/*1370	 * vma has anon_vma, we assign to next.1371	 *1372	 *     |<----->|1373	 * *************-------|1374	 *      vma       next1375	 * shrink/delete extend1376	 */1377 1378	vma = alloc_and_link_vma(&mm, 0, 0x5000, 0, flags);1379	vma_next = alloc_and_link_vma(&mm, 0x5000, 0x8000, 5, flags);1380 1381	vma->anon_vma = &dummy_anon_vma;1382	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);1383	vmg.prev = vma;1384	vmg.vma = vma;1385 1386	ASSERT_EQ(merge_existing(&vmg), vma_next);1387	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1388 1389	ASSERT_EQ(vma_next->vm_start, 0x3000);1390	ASSERT_EQ(vma_next->vm_end, 0x8000);1391 1392	ASSERT_EQ(vma_next->anon_vma, &dummy_anon_vma);1393	ASSERT_TRUE(vma_next->anon_vma->was_cloned);1394 1395	cleanup_mm(&mm, &vmi);1396	return true;1397}1398 1399static bool test_vmi_prealloc_fail(void)1400{1401	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1402	struct mm_struct mm = {};1403	VMA_ITERATOR(vmi, &mm, 0);1404	struct vma_merge_struct vmg = {1405		.mm = &mm,1406		.vmi = &vmi,1407	};1408	struct vm_area_struct *vma_prev, *vma;1409 1410	/*1411	 * We are merging vma into prev, with vma possessing an anon_vma, which1412	 * will be duplicated. We cause the vmi preallocation to fail and assert1413	 * the duplicated anon_vma is unlinked.1414	 */1415 1416	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1417	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1418	vma->anon_vma = &dummy_anon_vma;1419 1420	vmg_set_range(&vmg, 0x3000, 0x5000, 3, flags);1421	vmg.prev = vma_prev;1422	vmg.vma = vma;1423 1424	fail_prealloc = true;1425 1426	/* This will cause the merge to fail. */1427	ASSERT_EQ(merge_existing(&vmg), NULL);1428	ASSERT_EQ(vmg.state, VMA_MERGE_ERROR_NOMEM);1429	/* We will already have assigned the anon_vma. */1430	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1431	/* And it was both cloned and unlinked. */1432	ASSERT_TRUE(dummy_anon_vma.was_cloned);1433	ASSERT_TRUE(dummy_anon_vma.was_unlinked);1434 1435	cleanup_mm(&mm, &vmi); /* Resets fail_prealloc too. */1436 1437	/*1438	 * We repeat the same operation for expanding a VMA, which is what new1439	 * VMA merging ultimately uses too. This asserts that unlinking is1440	 * performed in this case too.1441	 */1442 1443	vma_prev = alloc_and_link_vma(&mm, 0, 0x3000, 0, flags);1444	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1445	vma->anon_vma = &dummy_anon_vma;1446 1447	vmg_set_range(&vmg, 0, 0x5000, 3, flags);1448	vmg.vma = vma_prev;1449	vmg.next = vma;1450 1451	fail_prealloc = true;1452	ASSERT_EQ(expand_existing(&vmg), -ENOMEM);1453	ASSERT_EQ(vmg.state, VMA_MERGE_ERROR_NOMEM);1454 1455	ASSERT_EQ(vma_prev->anon_vma, &dummy_anon_vma);1456	ASSERT_TRUE(dummy_anon_vma.was_cloned);1457	ASSERT_TRUE(dummy_anon_vma.was_unlinked);1458 1459	cleanup_mm(&mm, &vmi);1460	return true;1461}1462 1463static bool test_merge_extend(void)1464{1465	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1466	struct mm_struct mm = {};1467	VMA_ITERATOR(vmi, &mm, 0x1000);1468	struct vm_area_struct *vma;1469 1470	vma = alloc_and_link_vma(&mm, 0, 0x1000, 0, flags);1471	alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, flags);1472 1473	/*1474	 * Extend a VMA into the gap between itself and the following VMA.1475	 * This should result in a merge.1476	 *1477	 * <->1478	 * *  *1479	 *1480	 */1481 1482	ASSERT_EQ(vma_merge_extend(&vmi, vma, 0x2000), vma);1483	ASSERT_EQ(vma->vm_start, 0);1484	ASSERT_EQ(vma->vm_end, 0x4000);1485	ASSERT_EQ(vma->vm_pgoff, 0);1486	ASSERT_TRUE(vma_write_started(vma));1487	ASSERT_EQ(mm.map_count, 1);1488 1489	cleanup_mm(&mm, &vmi);1490	return true;1491}1492 1493static bool test_copy_vma(void)1494{1495	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1496	struct mm_struct mm = {};1497	bool need_locks = false;1498	VMA_ITERATOR(vmi, &mm, 0);1499	struct vm_area_struct *vma, *vma_new, *vma_next;1500 1501	/* Move backwards and do not merge. */1502 1503	vma = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1504	vma_new = copy_vma(&vma, 0, 0x2000, 0, &need_locks);1505 1506	ASSERT_NE(vma_new, vma);1507	ASSERT_EQ(vma_new->vm_start, 0);1508	ASSERT_EQ(vma_new->vm_end, 0x2000);1509	ASSERT_EQ(vma_new->vm_pgoff, 0);1510 1511	cleanup_mm(&mm, &vmi);1512 1513	/* Move a VMA into position next to another and merge the two. */1514 1515	vma = alloc_and_link_vma(&mm, 0, 0x2000, 0, flags);1516	vma_next = alloc_and_link_vma(&mm, 0x6000, 0x8000, 6, flags);1517	vma_new = copy_vma(&vma, 0x4000, 0x2000, 4, &need_locks);1518 1519	ASSERT_EQ(vma_new, vma_next);1520 1521	cleanup_mm(&mm, &vmi);1522	return true;1523}1524 1525static bool test_expand_only_mode(void)1526{1527	unsigned long flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE;1528	struct mm_struct mm = {};1529	VMA_ITERATOR(vmi, &mm, 0);1530	struct vm_area_struct *vma_prev, *vma;1531	VMG_STATE(vmg, &mm, &vmi, 0x5000, 0x9000, flags, 5);1532 1533	/*1534	 * Place a VMA prior to the one we're expanding so we assert that we do1535	 * not erroneously try to traverse to the previous VMA even though we1536	 * have, through the use of VMG_FLAG_JUST_EXPAND, indicated we do not1537	 * need to do so.1538	 */1539	alloc_and_link_vma(&mm, 0, 0x2000, 0, flags);1540 1541	/*1542	 * We will be positioned at the prev VMA, but looking to expand to1543	 * 0x9000.1544	 */1545	vma_iter_set(&vmi, 0x3000);1546	vma_prev = alloc_and_link_vma(&mm, 0x3000, 0x5000, 3, flags);1547	vmg.prev = vma_prev;1548	vmg.merge_flags = VMG_FLAG_JUST_EXPAND;1549 1550	vma = vma_merge_new_range(&vmg);1551	ASSERT_NE(vma, NULL);1552	ASSERT_EQ(vma, vma_prev);1553	ASSERT_EQ(vmg.state, VMA_MERGE_SUCCESS);1554	ASSERT_EQ(vma->vm_start, 0x3000);1555	ASSERT_EQ(vma->vm_end, 0x9000);1556	ASSERT_EQ(vma->vm_pgoff, 3);1557	ASSERT_TRUE(vma_write_started(vma));1558	ASSERT_EQ(vma_iter_addr(&vmi), 0x3000);1559 1560	cleanup_mm(&mm, &vmi);1561	return true;1562}1563 1564int main(void)1565{1566	int num_tests = 0, num_fail = 0;1567 1568	maple_tree_init();1569 1570#define TEST(name)							\1571	do {								\1572		num_tests++;						\1573		if (!test_##name()) {					\1574			num_fail++;					\1575			fprintf(stderr, "Test " #name " FAILED\n");	\1576		}							\1577	} while (0)1578 1579	/* Very simple tests to kick the tyres. */1580	TEST(simple_merge);1581	TEST(simple_modify);1582	TEST(simple_expand);1583	TEST(simple_shrink);1584 1585	TEST(merge_new);1586	TEST(vma_merge_special_flags);1587	TEST(vma_merge_with_close);1588	TEST(vma_merge_new_with_close);1589	TEST(merge_existing);1590	TEST(anon_vma_non_mergeable);1591	TEST(dup_anon_vma);1592	TEST(vmi_prealloc_fail);1593	TEST(merge_extend);1594	TEST(copy_vma);1595	TEST(expand_only_mode);1596 1597#undef TEST1598 1599	printf("%d tests run, %d passed, %d failed.\n",1600	       num_tests, num_tests - num_fail, num_fail);1601 1602	return num_fail == 0 ? EXIT_SUCCESS : EXIT_FAILURE;1603}1604