Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
secure_allocator.c
00001 /* 00002 * Copyright (c) 2016, ARM Limited, All Rights Reserved 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00006 * not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "rt_TypeDef.h" 00019 #include "rt_Memory.h" 00020 00021 #include "secure_allocator.h" 00022 #include "uvisor-lib/uvisor-lib.h" 00023 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #include <string.h> 00027 00028 /* Use printf with caution inside malloc: printf may allocate memory itself, 00029 so using printf in malloc may lead to recursive calls! */ 00030 #define DPRINTF(...) {} 00031 00032 /* offsetof is a gcc built-in function, this is the manual implementation */ 00033 #define OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member))) 00034 00035 /* Internal structure currently only contains the page table. */ 00036 typedef struct { 00037 UvisorPageTable table; 00038 } SecureAllocatorInternal; 00039 00040 static inline UvisorPageTable * table(SecureAllocator allocator) { 00041 return &(((SecureAllocatorInternal *) allocator)->table); 00042 } 00043 00044 SecureAllocator secure_allocator_create_with_pool( 00045 void * mem, 00046 size_t bytes) 00047 { 00048 SecureAllocatorInternal * allocator = mem; 00049 /* Signal that this is non-page allocated memory. */ 00050 allocator->table.page_size = bytes; 00051 allocator->table.page_count = 0; 00052 /* The internal rt_Memory MEMP structure must be placed AFTER table.page_origins[0] !!! */ 00053 size_t offset = OFFSETOF(SecureAllocatorInternal, table.page_origins) + sizeof(((UvisorPageTable) {0}).page_origins); 00054 /* Create MEMP structure inside the memory. */ 00055 if (rt_init_mem(mem + offset, bytes - offset)) { 00056 /* Abort if failed. */ 00057 DPRINTF("secure_allocator_create_with_pool: MEMP allocator creation failed\n\n"); 00058 return NULL; 00059 } 00060 /* Remember the MEMP pointer though. */ 00061 allocator->table.page_origins[0] = mem + offset; 00062 DPRINTF("secure_allocator_create_with_pool: Created MEMP allocator %p with offset %d\n\n", mem + offset, offset); 00063 return allocator; 00064 } 00065 00066 SecureAllocator secure_allocator_create_with_pages( 00067 size_t size, 00068 size_t maximum_malloc_size) 00069 { 00070 const uint32_t page_size = uvisor_get_page_size(); 00071 /* The rt_Memory allocator puts one MEMP structure at both the 00072 * beginning and end of the memory pool. */ 00073 const size_t block_overhead = 2 * sizeof(MEMP); 00074 const size_t page_size_with_overhead = page_size + block_overhead; 00075 /* Calculate the integer part of required the page count. */ 00076 size_t page_count = size / page_size_with_overhead; 00077 /* Add another page if the remainder is not zero. */ 00078 if (size - page_count * page_size_with_overhead) { 00079 page_count++; 00080 } 00081 DPRINTF("secure_allocator_create_with_pages: Requesting %u pages for at least %uB\n", page_count, size); 00082 00083 /* Compute the maximum allocation within our blocks. */ 00084 size_t maximum_allocation_size = page_size - block_overhead; 00085 /* If the required maximum allocation is larger than we can provide, abort. */ 00086 if (maximum_malloc_size > maximum_allocation_size) { 00087 DPRINTF("secure_allocator_create_with_pages: Maximum allocation request %uB is larger then available %uB\n\n", maximum_malloc_size, maximum_allocation_size); 00088 return NULL; 00089 } 00090 00091 /* Compute the required memory size for the page table. */ 00092 size_t allocator_type_size = sizeof(SecureAllocatorInternal); 00093 /* Add size for each additional page. */ 00094 allocator_type_size += (page_count - 1) * sizeof(((UvisorPageTable) {0}).page_origins); 00095 /* Allocate this much memory. */ 00096 SecureAllocatorInternal * const allocator = malloc(allocator_type_size); 00097 /* If malloc failed, abort. */ 00098 if (allocator == NULL) { 00099 DPRINTF("secure_allocator_create_with_pages: SecureAllocatorInternal failed to be allocated!\n\n"); 00100 return NULL; 00101 } 00102 00103 /* Prepare the page table. */ 00104 allocator->table.page_size = page_size; 00105 allocator->table.page_count = page_count; 00106 /* Get me some pages. */ 00107 if (uvisor_page_malloc((UvisorPageTable *) &(allocator->table))) { 00108 free(allocator); 00109 DPRINTF("secure_allocator_create_with_pages: Not enough free pages available!\n\n"); 00110 return NULL; 00111 } 00112 00113 /* Initialize a MEMP structure in all pages. */ 00114 for(size_t ii = 0; ii < page_count; ii++) { 00115 /* Add each page as a pool. */ 00116 rt_init_mem(allocator->table.page_origins[ii], page_size); 00117 DPRINTF("secure_allocator_create_with_pages: Created MEMP allocator %p with offset %d\n", allocator->table.page_origins[ii], 0); 00118 } 00119 DPRINTF("\n"); 00120 /* Aaaand across the line. */ 00121 return (SecureAllocator) allocator; 00122 } 00123 00124 int secure_allocator_destroy( 00125 SecureAllocator allocator) 00126 { 00127 DPRINTF("secure_allocator_destroy: Destroying MEMP allocator at %p\n", table(allocator)->page_origins[0]); 00128 00129 /* Check if we are working on statically allocated memory. */ 00130 SecureAllocatorInternal * alloc = (SecureAllocatorInternal * const) allocator; 00131 if (alloc->table.page_count == 0) { 00132 DPRINTF("secure_allocator_destroy: %p is not page-backed memory, not freeing!\n", allocator); 00133 return -1; 00134 } 00135 00136 /* Free all pages. */ 00137 if (uvisor_page_free(&(alloc->table))) { 00138 DPRINTF("secure_allocator_destroy: Unable to free pages!\n\n"); 00139 return -1; 00140 } 00141 00142 /* Free the allocator structure. */ 00143 free(allocator); 00144 00145 DPRINTF("\n"); 00146 return 0; 00147 } 00148 00149 void * secure_malloc( 00150 SecureAllocator allocator, 00151 size_t size) 00152 { 00153 size_t index = 0; 00154 do { 00155 /* Search in this page. */ 00156 void * mem = rt_alloc_mem(table(allocator)->page_origins[index], size); 00157 /* Return if we found something. */ 00158 if (mem) { 00159 DPRINTF("secure_malloc: Found %4uB in page %u at %p\n", size, index, mem); 00160 return mem; 00161 } 00162 /* Otherwise, go to the next page. */ 00163 index++; 00164 } /* Continue search if more pages are available. */ 00165 while (index < table(allocator)->page_count); 00166 00167 DPRINTF("secure_malloc: Out of memory in allocator %p \n", allocator); 00168 /* We found nothing. */ 00169 return NULL; 00170 } 00171 00172 void * secure_realloc( 00173 SecureAllocator allocator, 00174 void * ptr, 00175 size_t new_size) 00176 { 00177 /* TODO: THIS IS A NAIVE IMPLEMENTATION, which always allocates new 00178 memory, and copies the memory, then frees the old memory. */ 00179 00180 /* Allocate new memory. */ 00181 void * new_ptr = secure_malloc(allocator, new_size); 00182 /* If memory allocation failed, abort. */ 00183 if (new_ptr == NULL) { 00184 return NULL; 00185 } 00186 00187 /* Passing NULL as ptr is legal, realloc acts as malloc then. */ 00188 if (ptr) { 00189 /* Get the size of the ptr memory. */ 00190 size_t size = ((MEMP *) ((uint32_t) ptr - sizeof(MEMP)))->len; 00191 /* Copy the memory to the new location, min(new_size, size). */ 00192 memcpy(new_ptr, ptr, new_size < size ? new_size : size); 00193 /* Free the previous memory. */ 00194 secure_free(allocator, ptr); 00195 } 00196 return new_ptr; 00197 } 00198 00199 void secure_free( 00200 SecureAllocator allocator, 00201 void * ptr) 00202 { 00203 size_t index = 0; 00204 do { 00205 /* Search in this page. */ 00206 int ret = rt_free_mem(table(allocator)->page_origins[index], ptr); 00207 /* Return if free was successful. */ 00208 if (ret == 0) { 00209 DPRINTF("secure_free: Freed %p in page %u.\n", ptr, index); 00210 return; 00211 } 00212 /* Otherwise, go to the next page. */ 00213 index++; 00214 } /* Continue search if more pages are available. */ 00215 while (index < table(allocator)->page_count); 00216 00217 DPRINTF("secure_free: %p not found in allocator %p!\n", ptr, allocator); 00218 /* We found nothing. */ 00219 return; 00220 }
Generated on Tue Jul 12 2022 13:16:04 by
