static int ne_sanity_check_user_mem_region()

in drivers/virt/nitro_enclaves/ne_misc_dev.c [832:880]


static int ne_sanity_check_user_mem_region(struct ne_enclave *ne_enclave,
					   struct ne_user_memory_region mem_region)
{
	struct ne_mem_region *ne_mem_region = NULL;

	if (ne_enclave->mm != current->mm)
		return -EIO;

	if (mem_region.memory_size & (NE_MIN_MEM_REGION_SIZE - 1)) {
		dev_err_ratelimited(ne_misc_dev.this_device,
				    "User space memory size is not multiple of 2 MiB\n");

		return -NE_ERR_INVALID_MEM_REGION_SIZE;
	}

	if (!IS_ALIGNED(mem_region.userspace_addr, NE_MIN_MEM_REGION_SIZE)) {
		dev_err_ratelimited(ne_misc_dev.this_device,
				    "User space address is not 2 MiB aligned\n");

		return -NE_ERR_UNALIGNED_MEM_REGION_ADDR;
	}

	if ((mem_region.userspace_addr & (NE_MIN_MEM_REGION_SIZE - 1)) ||
	    !user_access_ok((void __user *)(unsigned long)mem_region.userspace_addr,
			    mem_region.memory_size)) {
		dev_err_ratelimited(ne_misc_dev.this_device,
				    "Invalid user space address range\n");

		return -NE_ERR_INVALID_MEM_REGION_ADDR;
	}

	list_for_each_entry(ne_mem_region, &ne_enclave->mem_regions_list,
			    mem_region_list_entry) {
		u64 memory_size = ne_mem_region->memory_size;
		u64 userspace_addr = ne_mem_region->userspace_addr;

		if ((userspace_addr <= mem_region.userspace_addr &&
		     mem_region.userspace_addr < (userspace_addr + memory_size)) ||
		    (mem_region.userspace_addr <= userspace_addr &&
		    (mem_region.userspace_addr + mem_region.memory_size) > userspace_addr)) {
			dev_err_ratelimited(ne_misc_dev.this_device,
					    "User space memory region already used\n");

			return -NE_ERR_MEM_REGION_ALREADY_USED;
		}
	}

	return 0;
}