On 15/04/2024 15:21, Amit Daniel Kachhap wrote:
@@ -1706,27 +1707,47 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr, struct vm_area_struct *vma, *prev; struct vm_unmapped_area_info info; const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
- unsigned long align_len;
- unsigned long align_addr;
- if (len > mmap_end - mmap_min_addr)
- align_len = reserv_representable_length(len);
- if (align_len > mmap_end - mmap_min_addr) return -ENOMEM;
- if (flags & MAP_FIXED)
- /*
* In case of PCuABI reservation, fixed should not overlap with any
* existing reservation or completely contained inside the reservation.
* Let this scenario fallthrough below for such checks.
*/
- if ((flags & MAP_FIXED) && !reserv_is_supported(mm)) return addr;
if (addr) {
There is a corner case where MAP_FIXED is passed and addr is null. It doesn't look like this is forbidden in theory. At the moment this will result in MAP_FIXED being ignored. I can't think of a particularly elegant way to handle this, we could add || (flags & MAP_FIXED) in this if.
addr = PAGE_ALIGN(addr);
/*
* Here CHERI representable address is aligned down as reservation
* layer holds this unusable aligned down gap.
*/
vma = find_vma_prev(mm, addr, &prev);align_addr = reserv_representable_base(addr, len);
if (mmap_end - len >= addr && addr >= mmap_min_addr &&
(!vma || addr + len <= vm_start_gap(vma)) &&
(!prev || addr >= vm_end_gap(prev)))
if (mmap_end - align_len >= align_addr && align_addr >= mmap_min_addr &&
(!vma || align_addr + align_len <= vm_start_gap(vma)) &&
(!prev || align_addr >= vm_end_gap(prev))) return addr;
else if (flags & MAP_FIXED) {
if ((vma && reserv_vma_range_within_reserv(vma, align_addr, align_len)) ||
(prev && reserv_vma_range_within_reserv(prev, align_addr, align_len)))
If the condition holds, no reservation is created, we just want to check that the mapping bounds fit in either reservation. For that reason it makes more sense to use the unaligned addr and len here (it should make no difference in practice).
Kevin
return addr;
return -ERESERVATION;
}}
info.flags = 0;
- info.length = len;
- info.length = align_len; info.low_limit = mm->mmap_base; info.high_limit = mmap_end; info.align_mask = 0;
- info.align_mask = reserv_representable_alignment(len); info.align_offset = 0; return vm_unmapped_area(&info);
}