diff options
author | Olav Haugan <ohaugan@codeaurora.org> | 2013-11-04 15:51:51 -0800 |
---|---|---|
committer | Ziyan <jaraidaniel@gmail.com> | 2016-01-05 18:21:22 +0100 |
commit | c2258b5459fa11a40b5d63fcaf339a9f8b364d95 (patch) | |
tree | 3cb17fac8a65b21eace043a3a37356407c4d6090 /drivers/staging | |
parent | 020bde6b7ee99c03c7457bea6329f9fec9879b79 (diff) | |
download | kernel_samsung_tuna-c2258b5459fa11a40b5d63fcaf339a9f8b364d95.zip kernel_samsung_tuna-c2258b5459fa11a40b5d63fcaf339a9f8b364d95.tar.gz kernel_samsung_tuna-c2258b5459fa11a40b5d63fcaf339a9f8b364d95.tar.bz2 |
staging: zsmalloc: Ensure handle is never 0 on success
zsmalloc encodes a handle using the pfn and an object
index. On hardware platforms with physical memory starting
at 0x0 the pfn can be 0. This causes the encoded handle to be
0 and is incorrectly interpreted as an allocation failure.
This issue affects all current and future SoCs with physical
memory starting at 0x0. All MSM8974 SoCs which includes
Google Nexus 5 devices are affected.
To prevent this false error we ensure that the encoded handle
will not be 0 when allocation succeeds.
Change-Id: I5ad31712be4dd5105ebee81fa95927039c0f6935
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/zsmalloc/zsmalloc-main.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 523b937..41a6803 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -430,7 +430,12 @@ static struct page *get_next_page(struct page *page) return next; } -/* Encode <page, obj_idx> as a single handle value */ +/* + * Encode <page, obj_idx> as a single handle value. + * On hardware platforms with physical memory starting at 0x0 the pfn + * could be 0 so we ensure that the handle will never be 0 by adjusting the + * encoded obj_idx value before encoding. + */ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) { unsigned long handle; @@ -441,17 +446,21 @@ static void *obj_location_to_handle(struct page *page, unsigned long obj_idx) } handle = page_to_pfn(page) << OBJ_INDEX_BITS; - handle |= (obj_idx & OBJ_INDEX_MASK); + handle |= ((obj_idx + 1) & OBJ_INDEX_MASK); return (void *)handle; } -/* Decode <page, obj_idx> pair from the given object handle */ +/* + * Decode <page, obj_idx> pair from the given object handle. We adjust the + * decoded obj_idx back to its original value since it was adjusted in + * obj_location_to_handle(). + */ static void obj_handle_to_location(unsigned long handle, struct page **page, unsigned long *obj_idx) { *page = pfn_to_page(handle >> OBJ_INDEX_BITS); - *obj_idx = handle & OBJ_INDEX_MASK; + *obj_idx = (handle & OBJ_INDEX_MASK) - 1; } static unsigned long obj_idx_to_offset(struct page *page, |