Received: by 10.223.185.116 with SMTP id b49csp7024592wrg; Wed, 28 Feb 2018 21:19:27 -0800 (PST) X-Google-Smtp-Source: AG47ELtaE5w/zRUjuI1w75haQvOpo6uu73sCNF7KB4GWLVKrmbXqYVDfWjLcxkwKibP6ghsMat3C X-Received: by 10.99.178.6 with SMTP id x6mr583132pge.98.1519881567553; Wed, 28 Feb 2018 21:19:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519881567; cv=none; d=google.com; s=arc-20160816; b=yZhzJuReBibHKhXJ2AMx3tmuNfeLyxZuO4i4npI7z7b2H9jMHbYN5pIbXYouhFPmeT EiA4HN+JqKu28mp2tbICTQtG5K1xPSQxt93DYMUjmNi8B5l/BwM5mrWIJ6oi7rQrgHqs eFMJ4wXv/ye/pGLocGhNWccgX9BjLCXViGywQtu0Oq7jQGOcHXh0wnPoh3CD0VLvZu7g pLLAWJ6upnG5zjjHFCcFyymC4xh5NI3MBMHpXN2HT4iSfGoLIKOy4bvXeFmCuQ3Pah7O gYDK8XwWyWr2ydfz8c8qt/alcWaI8lgpzLsEz2v3MGcl2jRdc7DIxS8ycL2oTK1RZT4G CTHg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:message-id :subject:cc:to:from:date:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=GMtAr4NfXKKxf9/uHrEDvIOrReaCYVb4qVu62NI2fno=; b=w+sXJ1DDXA7rEUhxFhaux+ax5rxPoWdzGCqVWzzGm456owl+m9jHWbSvP0JvHC2Jmb SUTNp5egtXHQP4zH7BmcCkiIktShDzGcM/E4u7s3bKh6o/4Ea10Tm2SsLh7O2t0uh3sk RDLYWYl3ZAkAvTw3YLREmPUlOPE+9kY/HT/5hMIFF0XNhd41mbEBIs6SAyJKyckoUjVY y2CsjliphEeXGGwuA67iYm5zjrdGryl+UCDMKv21QmjUbGbrtj+SXBEkXOUIGsb2EpW+ chq+DCzhuPOcu2Re9aCjd8kxgPhm8QCzTo40Uc1TE4G5VmcTXx4g517RQlSwkp4tGXIH 3JZg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=nH2mmTPB; dkim=pass header.i=@codeaurora.org header.s=default header.b=OsuW9qQT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o190si1984507pga.553.2018.02.28.21.19.11; Wed, 28 Feb 2018 21:19:27 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=nH2mmTPB; dkim=pass header.i=@codeaurora.org header.s=default header.b=OsuW9qQT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965984AbeCAFSc (ORCPT + 99 others); Thu, 1 Mar 2018 00:18:32 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:43872 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932157AbeCAFSa (ORCPT ); Thu, 1 Mar 2018 00:18:30 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id C771E607A2; Thu, 1 Mar 2018 05:18:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1519881509; bh=euD01ZBtQLZMYOzUno9pVQwjsqceE00LitKMiKsOtOQ=; h=Date:From:To:cc:Subject:From; b=nH2mmTPBS0ETDzIE6S18taUlhHFFen6SEwsLTzlkvExmGx12dCOp60kvbpHjIAmZ/ eKnbY5bjGYz+hpZF6ighK2OuLU0fbv+1QNYrIk4qjvapNKi+x+wAkr6tNGpPRhGnpD i6BUkwgGtCYso+60iq16YIXiqBWYOcTp2I2GKV9A= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from lmark-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: lmark@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 33E2B60117; Thu, 1 Mar 2018 05:18:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1519881508; bh=euD01ZBtQLZMYOzUno9pVQwjsqceE00LitKMiKsOtOQ=; h=Date:From:To:cc:Subject:From; b=OsuW9qQT02ASW/FV+mGjNURsBOuH8qkHs+goMqt0n9EJuupM5RdUWFIJSVjTByuja bRiBbS+FDk62YSmYsVRGK7yUy05PLneVveIA1rpMezyH+dmgliyljm7Q+q3OkGag8E 4ayB3BqfRYCZU9sP2AItMgCYhIp+kCHDrwQ3jP8s= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 33E2B60117 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=lmark@codeaurora.org Date: Wed, 28 Feb 2018 21:18:27 -0800 (PST) From: Liam Mark X-X-Sender: lmark@lmark-linux.qualcomm.com To: Laura Abbott , Sumit Semwal cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org, Martijn Coenen , Todd Kjos , =?ISO-8859-15?Q?Arve_Hj=F8nnev=E5g?= , linaro-mm-sig@lists.linaro.org Subject: [RFC] android: ion: How to properly clean caches for uncached allocations Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The issue: Currently in ION if you allocate uncached memory it is possible that there are still dirty lines in the cache. And often these dirty lines in the cache are the zeros which were meant to clear out any sensitive kernel data. What this means is that if you allocate uncached memory from ION, and then subsequently write to that buffer (using the uncached mapping you are provided by ION) then the data you have written could be corrupted at some point in the future if a dirty line is evicted from the cache. Also this means there is a potential security issue. If an un-privileged userspace user allocated uncached memory (for example from the system heap) and then if they were to read from that buffer (through the un-cached mapping they are provided by ION), and if some of the zeros which were written to that memory are still in the cache then this un-privileged userspace user could read potentially sensitive kernel data. An unacceptable fix: I have included some sample code which should resolve this issue for the system heap and the cma heap on some architectures, however this code would not be acceptable for upstreaming since it uses hacks to clean the cache. Similar changes would need to be made to carveout heap and chunk heap. I would appreciate some feedback on the proper way for ION to clean the caches for memory it has allocated that is intended for uncached access. I realize that it may be tempting, as a solution to this problem, to simply strip uncached support from ION. I hope that we can try to find a solution which preserves uncached memory support as ION uncached memory is often used (though perhaps not in upstreamed code) in cases such as multimedia use cases where there is no CPU access required, in secure heap allocations, and in some cases where there is minimal CPU access and therefore uncached memory performs better. Signed-off-by: Liam Mark --- drivers/staging/android/ion/ion.c | 16 ++++++++++++++++ drivers/staging/android/ion/ion.h | 5 ++++- drivers/staging/android/ion/ion_cma_heap.c | 3 +++ drivers/staging/android/ion/ion_page_pool.c | 8 ++++++-- drivers/staging/android/ion/ion_system_heap.c | 7 ++++++- 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index 57e0d8035b2e..10e967b0a0f4 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -38,6 +38,22 @@ bool ion_buffer_cached(struct ion_buffer *buffer) return !!(buffer->flags & ION_FLAG_CACHED); } +void ion_pages_sync_for_device(struct page *page, size_t size, + enum dma_data_direction dir) +{ + struct scatterlist sg; + struct device dev = {0}; + + /* hack, use dummy device */ + arch_setup_dma_ops(&dev, 0, 0, NULL, false); + + sg_init_table(&sg, 1); + sg_set_page(&sg, page, size, 0); + /* hack, use phys address for dma address */ + sg_dma_address(&sg) = page_to_phys(page); + dma_sync_sg_for_device(&dev, &sg, 1, dir); +} + /* this function should only be called while dev->lock is held */ static void ion_buffer_add(struct ion_device *dev, struct ion_buffer *buffer) diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index a238f23c9116..227b9928d185 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -192,6 +192,9 @@ struct ion_heap { */ bool ion_buffer_cached(struct ion_buffer *buffer); +void ion_pages_sync_for_device(struct page *page, size_t size, + enum dma_data_direction dir); + /** * ion_buffer_fault_user_mappings - fault in user mappings of this buffer * @buffer: buffer @@ -333,7 +336,7 @@ struct ion_page_pool { struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order, bool cached); void ion_page_pool_destroy(struct ion_page_pool *pool); -struct page *ion_page_pool_alloc(struct ion_page_pool *pool); +struct page *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool); void ion_page_pool_free(struct ion_page_pool *pool, struct page *page); /** ion_page_pool_shrink - shrinks the size of the memory cached in the pool diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c index 49718c96bf9e..82e80621d114 100644 --- a/drivers/staging/android/ion/ion_cma_heap.c +++ b/drivers/staging/android/ion/ion_cma_heap.c @@ -59,6 +59,9 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, memset(page_address(pages), 0, size); } + if (!ion_buffer_cached(buffer)) + ion_pages_sync_for_device(pages, size, DMA_BIDIRECTIONAL); + table = kmalloc(sizeof(*table), GFP_KERNEL); if (!table) goto err; diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index b3017f12835f..169a321778ed 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -63,7 +63,7 @@ static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high) return page; } -struct page *ion_page_pool_alloc(struct ion_page_pool *pool) +struct page *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool) { struct page *page = NULL; @@ -76,8 +76,12 @@ struct page *ion_page_pool_alloc(struct ion_page_pool *pool) page = ion_page_pool_remove(pool, false); mutex_unlock(&pool->mutex); - if (!page) + if (!page) { page = ion_page_pool_alloc_pages(pool); + *from_pool = false; + } else { + *from_pool = true; + } return page; } diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index bc19cdd30637..3bb4604e032b 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -57,13 +57,18 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap, bool cached = ion_buffer_cached(buffer); struct ion_page_pool *pool; struct page *page; + bool from_pool; if (!cached) pool = heap->uncached_pools[order_to_index(order)]; else pool = heap->cached_pools[order_to_index(order)]; - page = ion_page_pool_alloc(pool); + page = ion_page_pool_alloc(pool, &from_pool); + + if (!from_pool && !ion_buffer_cached(buffer)) + ion_pages_sync_for_device(page, PAGE_SIZE << order, + DMA_BIDIRECTIONAL); return page; } -- 1.8.5.2 Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project