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 OmniWheels 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 "rtx_lib.h" 00019 00020 /* uVisor uses rtx_memory instead of implementing its own dynamic, 00021 * non-fixed-size memory allocator. To do this, uVisor creates multiple 00022 * non-fixed-size allocator pools (one per page) and allocates memory from 00023 * these pools. uVisor must manage the memory for these pools' control blocks, 00024 * so it must know the size of these control blocks. */ 00025 00026 /* The following memory pool control block structs are copied from 00027 * rtx_memory.c, so that uVisor can manage the memory for these control blocks 00028 * within pages. */ 00029 typedef struct mem_head_s { 00030 uint32_t size; // Memory Pool size 00031 uint32_t used; // Used Memory 00032 } mem_head_t; 00033 00034 // Memory Block Header structure 00035 typedef struct mem_block_s { 00036 struct mem_block_s *next; // Next Memory Block in list 00037 uint32_t info; // Info: length = <31:2>:'00', type = <1:0> 00038 } mem_block_t; 00039 /* End copy */ 00040 00041 #include "secure_allocator.h" 00042 #include "uvisor-lib/uvisor-lib.h" 00043 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 #include <string.h> 00047 00048 /* Use printf with caution inside malloc: printf may allocate memory itself, 00049 so using printf in malloc may lead to recursive calls! */ 00050 #define DPRINTF(...) {} 00051 00052 /* offsetof is a gcc built-in function, this is the manual implementation */ 00053 #define OFFSETOF(type, member) ((uint32_t) (&(((type *)(0))->member))) 00054 00055 /* Internal structure currently only contains the page table. */ 00056 typedef struct { 00057 UvisorPageTable table; 00058 } SecureAllocatorInternal; 00059 00060 static inline UvisorPageTable * table(SecureAllocator allocator) { 00061 return &(((SecureAllocatorInternal *) allocator)->table); 00062 } 00063 00064 SecureAllocator secure_allocator_create_with_pool( 00065 void * mem, 00066 size_t bytes) 00067 { 00068 SecureAllocatorInternal * allocator = mem; 00069 /* Signal that this is non-page allocated memory. */ 00070 allocator->table.page_size = bytes; 00071 allocator->table.page_count = 0; 00072 /* The internal rtx_Memory memory pool structure must be placed AFTER 00073 * table.page_origins[0] !!! */ 00074 size_t offset = OFFSETOF(SecureAllocatorInternal, table.page_origins) + sizeof(((UvisorPageTable) {0}).page_origins); 00075 uintptr_t page_origin = (uintptr_t) mem + offset; 00076 00077 /* Align page_origin to a multiple of 8 (because RTX requries 8-byte 00078 * alignment of the origin). */ 00079 page_origin = (page_origin + (0x8 - 1)) & -0x8; 00080 offset = page_origin - (uintptr_t) mem; 00081 size_t size = bytes - offset; 00082 /* Align size to a multiple of 8 (because RTX requires 8-byte alignment of 00083 * the size) */ 00084 size &= -0x8; 00085 00086 /* Create pool allocator structure inside the memory. */ 00087 if (!osRtxMemoryInit((void *) page_origin, size)) { 00088 /* Abort if failed. */ 00089 DPRINTF("secure_allocator_create_with_pool: pool allocator %p with offset %d creation failed (size %u bytes)\n\n", page_origin, offset, bytes - offset); 00090 return NULL; 00091 } 00092 /* Remember the pool allocator pointer though. */ 00093 allocator->table.page_origins[0] = (void *) page_origin; 00094 DPRINTF("secure_allocator_create_with_pool: Created pool allocator %p with offset %d\n\n", page_origin, offset); 00095 return allocator; 00096 } 00097 00098 SecureAllocator secure_allocator_create_with_pages( 00099 size_t size, 00100 size_t maximum_malloc_size) 00101 { 00102 const uint32_t page_size = uvisor_get_page_size(); 00103 /* The rtx_Memory allocator puts one pool allocator structure at both the 00104 * beginning and end of the memory pool. */ 00105 const size_t block_overhead = 2 * sizeof(mem_block_t); 00106 const size_t page_size_with_overhead = page_size + block_overhead; 00107 /* Calculate the integer part of required the page count. */ 00108 size_t page_count = size / page_size_with_overhead; 00109 /* Add another page if the remainder is not zero. */ 00110 if (size - page_count * page_size_with_overhead) { 00111 page_count++; 00112 } 00113 DPRINTF("secure_allocator_create_with_pages: Requesting %u pages for at least %uB\n", page_count, size); 00114 00115 /* Compute the maximum allocation within our blocks. */ 00116 size_t maximum_allocation_size = page_size - block_overhead; 00117 /* If the required maximum allocation is larger than we can provide, abort. */ 00118 if (maximum_malloc_size > maximum_allocation_size) { 00119 DPRINTF("secure_allocator_create_with_pages: Maximum allocation request %uB is larger then available %uB\n\n", maximum_malloc_size, maximum_allocation_size); 00120 return NULL; 00121 } 00122 00123 /* Compute the required memory size for the page table. */ 00124 size_t allocator_type_size = sizeof(SecureAllocatorInternal); 00125 /* Add size for each additional page. */ 00126 allocator_type_size += (page_count - 1) * sizeof(((UvisorPageTable) {0}).page_origins); 00127 /* Allocate this much memory. */ 00128 SecureAllocatorInternal * const allocator = malloc(allocator_type_size); 00129 /* If malloc failed, abort. */ 00130 if (allocator == NULL) { 00131 DPRINTF("secure_allocator_create_with_pages: SecureAllocatorInternal failed to be allocated!\n\n"); 00132 return NULL; 00133 } 00134 00135 /* Prepare the page table. */ 00136 allocator->table.page_size = page_size; 00137 allocator->table.page_count = page_count; 00138 /* Get me some pages. */ 00139 if (uvisor_page_malloc((UvisorPageTable *) &(allocator->table))) { 00140 free(allocator); 00141 DPRINTF("secure_allocator_create_with_pages: Not enough free pages available!\n\n"); 00142 return NULL; 00143 } 00144 00145 /* Initialize a memory pool structure in all pages. */ 00146 for(size_t ii = 0; ii < page_count; ii++) { 00147 /* Add each page as a pool. */ 00148 osStatus_t status = osRtxMemoryInit(allocator->table.page_origins[ii], page_size); 00149 if (status == osOK) { 00150 DPRINTF("secure_allocator_create_with_pages: Created memory pool allocator %p with offset %d page %u\n", allocator->table.page_origins[ii], 0, ii); 00151 } else { 00152 DPRINTF("secure_allocator_create_with_pages: Failed creating memory pool allocator %p with offset %d page %u\n", allocator->table.page_origins[ii], 0, ii); 00153 } 00154 } 00155 DPRINTF("\n"); 00156 /* Aaaand across the line. */ 00157 return (SecureAllocator) allocator; 00158 } 00159 00160 int secure_allocator_destroy( 00161 SecureAllocator allocator) 00162 { 00163 DPRINTF("secure_allocator_destroy: Destroying memory pool allocator at %p\n", table(allocator)->page_origins[0]); 00164 00165 /* Check if we are working on statically allocated memory. */ 00166 SecureAllocatorInternal * alloc = (SecureAllocatorInternal * const) allocator; 00167 if (alloc->table.page_count == 0) { 00168 DPRINTF("secure_allocator_destroy: %p is not page-backed memory, not freeing!\n", allocator); 00169 return -1; 00170 } 00171 00172 /* Free all pages. */ 00173 if (uvisor_page_free(&(alloc->table))) { 00174 DPRINTF("secure_allocator_destroy: Unable to free pages!\n\n"); 00175 return -1; 00176 } 00177 00178 /* Free the allocator structure. */ 00179 free(allocator); 00180 00181 DPRINTF("\n"); 00182 return 0; 00183 } 00184 00185 void * secure_malloc( 00186 SecureAllocator allocator, 00187 size_t size) 00188 { 00189 size_t index = 0; 00190 do { 00191 /* Search in this page. */ 00192 void * mem = osRtxMemoryAlloc(table(allocator)->page_origins[index], size, 0); 00193 /* Return if we found something. */ 00194 if (mem) { 00195 DPRINTF("secure_malloc: Found %4uB in page %u at %p\n", size, index, mem); 00196 return mem; 00197 } 00198 /* Otherwise, go to the next page. */ 00199 index++; 00200 } /* Continue search if more pages are available. */ 00201 while (index < table(allocator)->page_count); 00202 00203 DPRINTF("secure_malloc: Out of memory in allocator %p \n", allocator); 00204 /* We found nothing. */ 00205 return NULL; 00206 } 00207 00208 void * secure_aligned_alloc( 00209 SecureAllocator allocator, 00210 size_t alignment, 00211 size_t size) 00212 { 00213 /* Alignment must be a power of two! */ 00214 if (alignment & ((1UL << ((31UL - __builtin_clz(alignment)) - 1)))) { 00215 return NULL; 00216 } 00217 /* TODO: THIS IS A NAIVE IMPLEMENTATION, which wastes much memory. */ 00218 void * ptr = secure_malloc(allocator, size + alignment - 1); 00219 if (ptr == NULL) { 00220 return NULL; 00221 } 00222 return (void *) (((uint32_t) ptr + alignment - 1) & ~(alignment - 1)); 00223 } 00224 00225 void * secure_calloc( 00226 SecureAllocator allocator, 00227 size_t nmemb, 00228 size_t size) 00229 { 00230 if ((uint64_t) nmemb * size > SIZE_MAX) { 00231 /* (size * nmemb) has overflowed. */ 00232 return NULL; 00233 } 00234 void * ptr = secure_malloc(allocator, size * nmemb); 00235 if (ptr == NULL) { 00236 return NULL; 00237 } 00238 memset(ptr, 0, size * nmemb); 00239 return ptr; 00240 } 00241 00242 void * secure_realloc( 00243 SecureAllocator allocator, 00244 void * ptr, 00245 size_t new_size) 00246 { 00247 /* TODO: THIS IS A NAIVE IMPLEMENTATION, which always allocates new 00248 memory, and copies the memory, then frees the old memory. */ 00249 00250 /* Allocate new memory. */ 00251 void * new_ptr = secure_malloc(allocator, new_size); 00252 /* If memory allocation failed, abort. */ 00253 if (new_ptr == NULL) { 00254 return NULL; 00255 } 00256 00257 /* Passing NULL as ptr is legal, realloc acts as malloc then. */ 00258 if (ptr) { 00259 /* Get the size of the ptr memory. */ 00260 size_t size = ((mem_block_t *) ((uint32_t) ptr - sizeof(mem_block_t)))->info & ~0x3; 00261 /* Copy the memory to the new location, min(new_size, size). */ 00262 memcpy(new_ptr, ptr, new_size < size ? new_size : size); 00263 /* Free the previous memory. */ 00264 secure_free(allocator, ptr); 00265 } 00266 return new_ptr; 00267 } 00268 00269 void secure_free( 00270 SecureAllocator allocator, 00271 void * ptr) 00272 { 00273 size_t index = 0; 00274 do { 00275 /* Search in this page. */ 00276 int ret = osRtxMemoryFree(table(allocator)->page_origins[index], ptr); 00277 /* Return if free was successful. */ 00278 if (ret == 1) { 00279 DPRINTF("secure_free: Freed %p in page %u.\n", ptr, index); 00280 return; 00281 } 00282 /* Otherwise, go to the next page. */ 00283 index++; 00284 } /* Continue search if more pages are available. */ 00285 while (index < table(allocator)->page_count); 00286 00287 DPRINTF("secure_free: %p not found in allocator %p!\n", ptr, allocator); 00288 /* We found nothing. */ 00289 return; 00290 }
Generated on Fri Jul 22 2022 04:53:59 by
 1.7.2
 1.7.2 
    