linuxkm: on kernels >= 4.12, use kvmalloc()/kvfree() and a partial implementation of realloc() leveraging them, rather than kmalloc()/kfree()/krealloc(). this makes large allocations possible and relatively safe. note that the realloc() implementation fails gracefully when the supplied pointer is larger than the page size, but otherwise works normally.

This commit is contained in:
Daniel Pouzzner
2020-12-31 00:30:35 -06:00
parent 7fb2c0f63f
commit 9dc8721032
2 changed files with 58 additions and 0 deletions

View File

@@ -2464,6 +2464,54 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n)
#endif /* WOLFSSL_NUCLEUS_1_2 */
#ifdef WOLFSSL_LINUXKM
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
/* adapted from kvrealloc() draft by Changli Gao, 2010-05-13 */
void *lkm_realloc(void *ptr, size_t newsize) {
void *nptr;
size_t oldsize;
if (unlikely(newsize == 0)) {
kvfree(ptr);
return ZERO_SIZE_PTR;
}
if (unlikely(ptr == NULL))
return kvmalloc(newsize, GFP_KERNEL);
if (is_vmalloc_addr(ptr)) {
/* no way to discern the size of the old allocation,
* because the kernel doesn't export find_vm_area(). if
* it did, we could then call get_vm_area_size() on the
* returned struct vm_struct.
*/
return NULL;
} else {
struct page *page;
page = virt_to_head_page(ptr);
if (PageSlab(page) || PageCompound(page)) {
if (newsize < PAGE_SIZE)
return krealloc(ptr, newsize, GFP_KERNEL);
oldsize = ksize(ptr);
} else {
oldsize = page->private;
if (newsize <= oldsize)
return ptr;
}
}
nptr = kvmalloc(newsize, GFP_KERNEL);
if (nptr != NULL) {
memcpy(nptr, ptr, oldsize);
kvfree(ptr);
}
return nptr;
}
#endif /* >= 4.12 */
#endif /* WOLFSSL_LINUXKM */
#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH)
#include <wolfcrypt/src/port/ti/ti-ccm.c> /* initialize and Mutex for TI Crypt Engine */
#include <wolfcrypt/src/port/ti/ti-hash.c> /* md5, sha1, sha224, sha256 */

View File

@@ -81,6 +81,7 @@
_Pragma("GCC diagnostic ignored \"-Wsign-compare\"");
_Pragma("GCC diagnostic ignored \"-Wpointer-sign\"");
_Pragma("GCC diagnostic ignored \"-Wbad-function-cast\"");
_Pragma("GCC diagnostic ignored \"-Wdiscarded-qualifiers\"");
#include <linux/kconfig.h>
#include <linux/kernel.h>
@@ -88,6 +89,7 @@
#include <linux/ctype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#ifndef SINGLE_THREADED
#include <linux/kthread.h>
#endif
@@ -155,9 +157,17 @@
*/
#define _MM_MALLOC_H_INCLUDED
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
/* kvmalloc()/kvfree() and friends added in linux commit a7c3e901 */
#define malloc(x) kvmalloc(x, GFP_KERNEL)
#define free(x) kvfree(x)
void *lkm_realloc(void *ptr, size_t newsize);
#define realloc(x, y) lkm_realloc(x, y)
#else
#define malloc(x) kmalloc(x, GFP_KERNEL)
#define free(x) kfree(x)
#define realloc(x,y) krealloc(x, y, GFP_KERNEL)
#endif
/* min() and max() in linux/kernel.h over-aggressively type-check, producing
* myriad spurious -Werrors throughout the codebase.