Commit d3a24e7a authored by Alexei Starovoitov's avatar Alexei Starovoitov Committed by Peng Zhang
Browse files

mm: Enforce VM_IOREMAP flag and range in ioremap_page_range.

mainline inclusion
from mainline-v6.9-rc1
commit 3e49a866c9dcbd8173e4f3e491293619a9e81fa4
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9CHG1
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3e49a866c9dcbd8173e4f3e491293619a9e81fa4



-------------------------------------------------

There are various users of get_vm_area() + ioremap_page_range() APIs.
Enforce that get_vm_area() was requested as VM_IOREMAP type and range
passed to ioremap_page_range() matches created vm_area to avoid
accidentally ioremap-ing into wrong address range.

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/bpf/20240305030516.41519-2-alexei.starovoitov@gmail.com


(cherry picked from commit 3e49a866c9dcbd8173e4f3e491293619a9e81fa4)
Signed-off-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent fc981322
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -307,8 +307,21 @@ static int vmap_range_noflush(unsigned long addr, unsigned long end,
int ioremap_page_range(unsigned long addr, unsigned long end,
		phys_addr_t phys_addr, pgprot_t prot)
{
	struct vm_struct *area;
	int err;

	area = find_vm_area((void *)addr);
	if (!area || !(area->flags & VM_IOREMAP)) {
		WARN_ONCE(1, "vm_area at addr %lx is not marked as VM_IOREMAP\n", addr);
		return -EINVAL;
	}
	if (addr != (unsigned long)area->addr ||
	    (void *)end != area->addr + get_vm_area_size(area)) {
		WARN_ONCE(1, "ioremap request [%lx,%lx) doesn't match vm_area [%lx, %lx)\n",
			  addr, end, (long)area->addr,
			  (long)area->addr + get_vm_area_size(area));
		return -ERANGE;
	}
	err = vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot),
				 ioremap_max_page_shift);
	flush_cache_vmap(addr, end);