From ce2daefbdf5eeb371e1aae15e6dc1928e2c1c627 Mon Sep 17 00:00:00 2001 From: Alex Waterman Date: Wed, 1 Aug 2012 11:02:30 -0700 Subject: video: tegra: nvmap: Add support for zeroed pages Add support to alloc zeroed pages for user space alloc requests. Also define a config option to force userspace allocation requests to be zeroed. Change-Id: I75d3b2bc36e808f1470b423578ec4cba99e0f967 Signed-off-by: Alex Waterman Reviewed-on: http://git-master/r/122549 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/video/tegra/Kconfig | 9 ++++++++ drivers/video/tegra/nvmap/nvmap_handle.c | 39 +++++++++++++++++++++++++++++--- drivers/video/tegra/nvmap/nvmap_ioctl.c | 5 +++- 3 files changed, 49 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig index b5540a5793b2..650c418ccb52 100644 --- a/drivers/video/tegra/Kconfig +++ b/drivers/video/tegra/Kconfig @@ -135,6 +135,15 @@ config NVMAP_VPR Say Y here to enable Video Protection Region(VPR) heap. if unsure, say N. +config NVMAP_FORCE_ZEROED_USER_PAGES + bool "Only alloc zeroed pages for user space" + depends on TEGRA_NVMAP + help + Say Y here to force zeroing of pages allocated for user space. This + avoids leaking kernel secure data to user space. This can add + significant overhead to allocation operations depending on the + allocation size requested. + config TEGRA_DSI bool "Enable DSI panel." default n diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index f12c058042dc..df54f1a1a8e9 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -555,6 +556,17 @@ static int handle_page_alloc(struct nvmap_client *client, struct nvmap_page_pool *pool = NULL; struct nvmap_share *share = nvmap_get_share_from_dev(h->dev); #endif + gfp_t gfp = GFP_NVMAP; + unsigned long kaddr, paddr; + pte_t **pte = NULL; + + if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) { + gfp |= __GFP_ZERO; + prot = nvmap_pgprot(h, pgprot_kernel); + pte = nvmap_alloc_pte(client->dev, (void **)&kaddr); + if (IS_ERR(pte)) + return -ENOMEM; + } pages = altalloc(nr_page * sizeof(*pages)); if (!pages) @@ -565,7 +577,7 @@ static int handle_page_alloc(struct nvmap_client *client, h->pgalloc.area = NULL; if (contiguous) { struct page *page; - page = nvmap_alloc_pages_exact(GFP_NVMAP, size); + page = nvmap_alloc_pages_exact(gfp, size); if (!page) goto fail; @@ -582,12 +594,29 @@ static int handle_page_alloc(struct nvmap_client *client, pages[i] = nvmap_page_pool_alloc(pool); if (!pages[i]) break; + if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) { + /* + * Just memset low mem pages; they will for + * sure have a virtual address. Otherwise, build + * a mapping for the page in the kernel. + */ + if (!PageHighMem(pages[i])) { + memset(page_address(pages[i]), 0, + PAGE_SIZE); + } else { + paddr = page_to_phys(pages[i]); + set_pte_at(&init_mm, kaddr, *pte, + pfn_pte(__phys_to_pfn(paddr), + prot)); + flush_tlb_kernel_page(kaddr); + memset((char *)kaddr, 0, PAGE_SIZE); + } + } page_index++; } #endif for (; i < nr_page; i++) { - pages[i] = nvmap_alloc_pages_exact(GFP_NVMAP, - PAGE_SIZE); + pages[i] = nvmap_alloc_pages_exact(gfp, PAGE_SIZE); if (!pages[i]) goto fail; } @@ -618,6 +647,8 @@ static int handle_page_alloc(struct nvmap_client *client, nr_page - page_index); skip_attr_change: + if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) + nvmap_free_pte(client->dev, pte); h->size = size; h->pgalloc.pages = pages; h->pgalloc.contig = contiguous; @@ -625,6 +656,8 @@ skip_attr_change: return 0; fail: + if (h->userflags & NVMAP_HANDLE_ZEROED_PAGES) + nvmap_free_pte(client->dev, pte); while (i--) { set_pages_array_wb(&pages[i], 1); __free_page(pages[i]); diff --git a/drivers/video/tegra/nvmap/nvmap_ioctl.c b/drivers/video/tegra/nvmap/nvmap_ioctl.c index 5bfbbf60f8ff..bb15699ad855 100644 --- a/drivers/video/tegra/nvmap/nvmap_ioctl.c +++ b/drivers/video/tegra/nvmap/nvmap_ioctl.c @@ -3,7 +3,7 @@ * * User-space interface to nvmap * - * Copyright (c) 2011, NVIDIA Corporation. + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -175,6 +175,9 @@ int nvmap_ioctl_alloc(struct file *filp, void __user *arg) /* user-space handles are aligned to page boundaries, to prevent * data leakage. */ op.align = max_t(size_t, op.align, PAGE_SIZE); +#if defined(CONFIG_NVMAP_FORCE_ZEROED_USER_PAGES) + op.flags |= NVMAP_HANDLE_ZEROED_PAGES; +#endif return nvmap_alloc_handle_id(client, op.handle, op.heap_mask, op.align, op.flags); -- cgit v1.2.3