diff options
| -rw-r--r-- | mm/mseal.c | 51 | 
1 files changed, 28 insertions, 23 deletions
| diff --git a/mm/mseal.c b/mm/mseal.c index adbcc65e9660..d140f569c4c3 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -38,31 +38,40 @@ out:  }  /* - * Check for do_mseal: - * 1> start is part of a valid vma. - * 2> end is part of a valid vma. - * 3> No gap (unallocated address) between start and end. - * 4> map is sealable. + * mseal() disallows an input range which contain unmapped ranges (VMA holes). + * + * It disallows unmapped regions from start to end whether they exist at the + * start, in the middle, or at the end of the range, or any combination thereof. + * + * This is because after sealng a range, there's nothing to stop memory mapping + * of ranges in the remaining gaps later, meaning that the user might then + * wrongly consider the entirety of the mseal()'d range to be sealed when it + * in fact isn't. + */ + +/* + * Does the [start, end) range contain any unmapped memory? + * + * We ensure that: + * - start is part of a valid VMA. + * - end is part of a valid VMA. + * - no gap (unallocated memory) exists between start and end.   */ -static int check_mm_seal(unsigned long start, unsigned long end) +static bool range_contains_unmapped(struct mm_struct *mm, +		unsigned long start, unsigned long end)  {  	struct vm_area_struct *vma; -	unsigned long nstart = start; +	unsigned long prev_end = start;  	VMA_ITERATOR(vmi, current->mm, start); -	/* going through each vma to check. */  	for_each_vma_range(vmi, vma, end) { -		if (vma->vm_start > nstart) -			/* unallocated memory found. */ -			return -ENOMEM; - -		if (vma->vm_end >= end) -			return 0; +		if (vma->vm_start > prev_end) +			return true; -		nstart = vma->vm_end; +		prev_end = vma->vm_end;  	} -	return -ENOMEM; +	return prev_end < end;  }  /* @@ -184,14 +193,10 @@ int do_mseal(unsigned long start, size_t len_in, unsigned long flags)  	if (mmap_write_lock_killable(mm))  		return -EINTR; -	/* -	 * First pass, this helps to avoid -	 * partial sealing in case of error in input address range, -	 * e.g. ENOMEM error. -	 */ -	ret = check_mm_seal(start, end); -	if (ret) +	if (range_contains_unmapped(mm, start, end)) { +		ret = -ENOMEM;  		goto out; +	}  	/*  	 * Second pass, this should success, unless there are errors | 
