Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f7eaf83 authored by Liam Mark's avatar Liam Mark Committed by Gerrit - the friendly Code Review server
Browse files

ion: Ensure non-HLOS memory cannot be mapped by CPU



Currently it is possible for an ION client to allocate non-HLOS memory
(ie memory which isn't assigned to the HLOS vmid), map this memory, and
then attempt to access this memory from the CPU.
Attempting to access non-HLOS memory from the CPU will cause a
stage-2 fault.

Fix ION so that non-HLOS memory cannot be mapped by the CPU.

Change-Id: Ifb51de2eabc076cddc744c13f01ef97b4a7c6874
Signed-off-by: default avatarLiam Mark <lmark@codeaurora.org>
parent eb049f73
Loading
Loading
Loading
Loading
+25 −2
Original line number Original line Diff line number Diff line
@@ -313,14 +313,37 @@ err:
	return ret;
	return ret;
}
}


static void *ion_secure_cma_map_kernel(struct ion_heap *heap,
				       struct ion_buffer *buffer)
{
	if (!is_buffer_hlos_assigned(buffer)) {
		pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
			__func__);
		return NULL;
	}
	return ion_cma_map_kernel(heap, buffer);
}

static int ion_secure_cma_map_user(struct ion_heap *mapper,
				   struct ion_buffer *buffer,
				   struct vm_area_struct *vma)
{
	if (!is_buffer_hlos_assigned(buffer)) {
		pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
			__func__);
		return -EINVAL;
	}
	return ion_cma_mmap(mapper, buffer, vma);
}

static struct ion_heap_ops ion_secure_cma_ops = {
static struct ion_heap_ops ion_secure_cma_ops = {
	.allocate = ion_secure_cma_allocate,
	.allocate = ion_secure_cma_allocate,
	.free = ion_secure_cma_free,
	.free = ion_secure_cma_free,
	.map_dma = ion_cma_heap_map_dma,
	.map_dma = ion_cma_heap_map_dma,
	.unmap_dma = ion_cma_heap_unmap_dma,
	.unmap_dma = ion_cma_heap_unmap_dma,
	.phys = ion_cma_phys,
	.phys = ion_cma_phys,
	.map_user = ion_cma_mmap,
	.map_user = ion_secure_cma_map_user,
	.map_kernel = ion_cma_map_kernel,
	.map_kernel = ion_secure_cma_map_kernel,
	.unmap_kernel = ion_cma_unmap_kernel,
	.unmap_kernel = ion_cma_unmap_kernel,
	.print_debug = ion_cma_print_debug,
	.print_debug = ion_cma_print_debug,
};
};
+12 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,11 @@ size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap,
	return total << PAGE_SHIFT;
	return total << PAGE_SHIFT;
}
}


static int ion_heap_is_system_heap_type(enum ion_heap_type type)
{
	return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM);
}

static struct page *alloc_buffer_page(struct ion_system_heap *heap,
static struct page *alloc_buffer_page(struct ion_system_heap *heap,
				      struct ion_buffer *buffer,
				      struct ion_buffer *buffer,
				      unsigned long order,
				      unsigned long order,
@@ -352,6 +357,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
	int vmid = get_secure_vmid(buffer->flags);
	int vmid = get_secure_vmid(buffer->flags);
	struct device *dev = heap->priv;
	struct device *dev = heap->priv;


	if (ion_heap_is_system_heap_type(buffer->heap->type) &&
	    is_secure_vmid_valid(vmid)) {
		pr_info("%s: System heap doesn't support secure allocations\n",
			__func__);
		return -EINVAL;
	}

	if (align > PAGE_SIZE)
	if (align > PAGE_SIZE)
		return -EINVAL;
		return -EINVAL;


+6 −4
Original line number Original line Diff line number Diff line
/*
/*
 *
 *
 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -170,14 +170,15 @@ out:
	sys_heap->ops->free(&buffer);
	sys_heap->ops->free(&buffer);
}
}


static void process_one_shrink(struct ion_heap *sys_heap,
static void process_one_shrink(struct ion_system_secure_heap *secure_heap,
			       struct ion_heap *sys_heap,
			       struct prefetch_info *info)
			       struct prefetch_info *info)
{
{
	struct ion_buffer buffer;
	struct ion_buffer buffer;
	size_t pool_size, size;
	size_t pool_size, size;
	int ret;
	int ret;


	buffer.heap = sys_heap;
	buffer.heap = &secure_heap->heap;
	buffer.flags = info->vmid;
	buffer.flags = info->vmid;


	pool_size = ion_system_heap_secure_page_pool_total(sys_heap,
	pool_size = ion_system_heap_secure_page_pool_total(sys_heap,
@@ -192,6 +193,7 @@ static void process_one_shrink(struct ion_heap *sys_heap,
	}
	}


	buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE;
	buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE;
	buffer.heap = sys_heap;
	sys_heap->ops->free(&buffer);
	sys_heap->ops->free(&buffer);
}
}


@@ -211,7 +213,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work)
		spin_unlock_irqrestore(&secure_heap->work_lock, flags);
		spin_unlock_irqrestore(&secure_heap->work_lock, flags);


		if (info->shrink)
		if (info->shrink)
			process_one_shrink(sys_heap, info);
			process_one_shrink(secure_heap, sys_heap, info);
		else
		else
			process_one_prefetch(sys_heap, info);
			process_one_prefetch(sys_heap, info);


+15 −0
Original line number Original line Diff line number Diff line
@@ -678,6 +678,21 @@ int get_secure_vmid(unsigned long flags)
		return VMID_CP_SPSS_SP_SHARED;
		return VMID_CP_SPSS_SP_SHARED;
	return -EINVAL;
	return -EINVAL;
}
}

bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
{
	bool is_hlos = false;

	if (buffer->heap->type == (enum ion_heap_type)ION_HEAP_TYPE_HYP_CMA &&
	    (buffer->flags & ION_FLAG_CP_HLOS))
		is_hlos = true;

	if (get_secure_vmid(buffer->flags) <= 0)
		is_hlos = true;

	return is_hlos;
}

/* fix up the cases where the ioctl direction bits are incorrect */
/* fix up the cases where the ioctl direction bits are incorrect */
static unsigned int msm_ion_ioctl_dir(unsigned int cmd)
static unsigned int msm_ion_ioctl_dir(unsigned int cmd)
{
{
+8 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * it under the terms of the GNU General Public License version 2 and
@@ -175,6 +175,8 @@ int msm_ion_do_cache_offset_op(
		void *vaddr, unsigned int offset, unsigned long len,
		void *vaddr, unsigned int offset, unsigned long len,
		unsigned int cmd);
		unsigned int cmd);


bool is_buffer_hlos_assigned(struct ion_buffer *buffer);

#else
#else
static inline struct ion_client *msm_ion_client_create(const char *name)
static inline struct ion_client *msm_ion_client_create(const char *name)
{
{
@@ -202,6 +204,11 @@ int msm_ion_do_cache_offset_op(
	return -ENODEV;
	return -ENODEV;
}
}


static bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
{
	return true;
}

#endif /* CONFIG_ION */
#endif /* CONFIG_ION */


#endif
#endif