Overview
Comment: | Make +[OFSecureData isSecure] per instance
The reason for this change is that whether non-swappable memory can be It's also called -[isSwappable] now to be more precise. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
60caadeb5de31d6b2588079135062705 |
User & Date: | js on 2019-12-15 14:42:19 |
Other Links: | manifest | tags |
Context
2019-12-27
| ||
00:41 | OFSecureData: Add allowsSwappableMemory property check-in: e629dc83a9 user: js tags: trunk | |
2019-12-15
| ||
15:37 | Merge branch 'master' into 1.0 check-in: 11e303eb3b user: js tags: 1.0 | |
14:42 | Make +[OFSecureData isSecure] per instance check-in: 60caadeb5d user: js tags: trunk | |
2019-12-14
| ||
19:00 | Allow numbers for of_dns_{class,record_type}_parse check-in: 4fc1f15ab2 user: js tags: trunk | |
Changes
Modified src/OFSecureData.h from [4b4455fb4b] to [95d6612ecd].
︙ | ︙ | |||
18 19 20 21 22 23 24 | #import "OFData.h" OF_ASSUME_NONNULL_BEGIN /*! * @class OFSecureData OFSecureData.h ObjFW/OFSecureData.h * | | | | | > > > < > > > | < < < < < < < | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #import "OFData.h" OF_ASSUME_NONNULL_BEGIN /*! * @class OFSecureData OFSecureData.h ObjFW/OFSecureData.h * * @brief A class for storing arbitrary data in secure (non-swappable) memory, * securely wiping it when it gets deallocated. * * @warning Non-swappable memory might be unavailable, in which case this falls * back to swappable memory, but still wipes the data when it gets * deallocated. Check the @ref swappable property to see whether a * particular OFSecureData was allocated in swappable memory. */ OF_SUBCLASSING_RESTRICTED @interface OFSecureData: OFData { struct page *_page; bool _swappable; } /*! * @brief Whether the OFSecureData is in swappable memory. */ @property (readonly, nonatomic, getter=isSwappable) bool swappable; /*! * @brief All items of the OFSecureData as a C array. * * Modifying the returned array directly is allowed and will change the contents * of the data. */ @property (readonly, nonatomic) void *mutableItems OF_RETURNS_INNER_POINTER; /*! * @brief Preallocates the specified number of bytes. * * This is useful to allocate secure memory before enabling a sandbox that does * not allow it anymore. * * @note This may only be called once per thread! |
︙ | ︙ |
Modified src/OFSecureData.m from [4b72bb7708] to [0b2ff22574].
︙ | ︙ | |||
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #endif #define CHUNK_SIZE 16 struct page { struct page *next, *previous; void *map; unsigned char *page; }; #if defined(OF_HAVE_COMPILER_TLS) static thread_local struct page *firstPage = NULL; static thread_local struct page *lastPage = NULL; static thread_local struct page **preallocatedPages = NULL; static thread_local size_t numPreallocatedPages = 0; #elif defined(OF_HAVE_THREADS) static of_tlskey_t firstPageKey, lastPageKey; static of_tlskey_t preallocatedPagesKey, numPreallocatedPagesKey; #else static struct page *firstPage = NULL; static struct page *lastPage = NULL; static struct page **preallocatedPages = NULL; static size_t numPreallocatedPages = 0; #endif static void * | > | | < < > > | > | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #endif #define CHUNK_SIZE 16 struct page { struct page *next, *previous; void *map; bool swappable; unsigned char *page; }; #if defined(OF_HAVE_COMPILER_TLS) static thread_local struct page *firstPage = NULL; static thread_local struct page *lastPage = NULL; static thread_local struct page **preallocatedPages = NULL; static thread_local size_t numPreallocatedPages = 0; #elif defined(OF_HAVE_THREADS) static of_tlskey_t firstPageKey, lastPageKey; static of_tlskey_t preallocatedPagesKey, numPreallocatedPagesKey; #else static struct page *firstPage = NULL; static struct page *lastPage = NULL; static struct page **preallocatedPages = NULL; static size_t numPreallocatedPages = 0; #endif static void * mapPages(size_t numPages, bool *swappable) { size_t pageSize = [OFSystemInfo pageSize]; void *pointer; if (numPages > SIZE_MAX / pageSize) @throw [OFOutOfRangeException exception]; #if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) if ((pointer = mmap(NULL, numPages * pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) @throw [OFOutOfMemoryException exceptionWithRequestedSize: pageSize]; *swappable = (mlock(pointer, numPages * pageSize) != 0); #else if ((pointer = malloc(numPages * pageSize)) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: pageSize]; *swappable = true; #endif return pointer; } static void unmapPages(void *pointer, size_t numPages, bool swappable) { size_t pageSize = [OFSystemInfo pageSize]; if (numPages > SIZE_MAX / pageSize) @throw [OFOutOfRangeException exception]; #if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) if (!swappable) munlock(pointer, numPages * pageSize); munmap(pointer, numPages * pageSize); #else free(pointer); #endif } static struct page * |
︙ | ︙ | |||
150 151 152 153 154 155 156 | @throw [OFOutOfMemoryException exceptionWithRequestedSize: sizeof(*page)]; if ((page->map = calloc(1, mapSize)) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: mapSize]; | | | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | @throw [OFOutOfMemoryException exceptionWithRequestedSize: sizeof(*page)]; if ((page->map = calloc(1, mapSize)) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: mapSize]; page->page = mapPages(1, &page->swappable); of_explicit_memset(page->page, 0, pageSize); #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) lastPage = of_tlskey_get(lastPageKey); #endif page->previous = lastPage; |
︙ | ︙ | |||
189 190 191 192 193 194 195 | size_t pageSize = [OFSystemInfo pageSize]; size_t mapSize = OF_ROUND_UP_POW2(8, pageSize / CHUNK_SIZE) / 8; for (size_t i = 0; i < mapSize; i++) if (map[i] != 0) return; | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | size_t pageSize = [OFSystemInfo pageSize]; size_t mapSize = OF_ROUND_UP_POW2(8, pageSize / CHUNK_SIZE) / 8; for (size_t i = 0; i < mapSize; i++) if (map[i] != 0) return; unmapPages(page->page, 1, page->swappable); free(page->map); if (page->previous != NULL) page->previous->next = page->next; if (page->next != NULL) page->next->previous = page->previous; |
︙ | ︙ | |||
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | of_explicit_memset(pointer, 0, bytes); for (size_t i = 0; i < chunks; i++) of_bitset_clear(page->map, chunkIndex + i); } @implementation OFSecureData #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + (void)initialize { if (self != [OFSecureData class]) return; if (!of_tlskey_new(&firstPageKey) || !of_tlskey_new(&lastPageKey) || !of_tlskey_new(&preallocatedPagesKey) || !of_tlskey_new(&numPreallocatedPagesKey)) @throw [OFInitializationFailedException exceptionWithClass: self]; } #endif | > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | of_explicit_memset(pointer, 0, bytes); for (size_t i = 0; i < chunks; i++) of_bitset_clear(page->map, chunkIndex + i); } @implementation OFSecureData @synthesize swappable = _swappable; #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) + (void)initialize { if (self != [OFSecureData class]) return; if (!of_tlskey_new(&firstPageKey) || !of_tlskey_new(&lastPageKey) || !of_tlskey_new(&preallocatedPagesKey) || !of_tlskey_new(&numPreallocatedPagesKey)) @throw [OFInitializationFailedException exceptionWithClass: self]; } #endif + (void)preallocateMemoryWithSize: (size_t)size { size_t pageSize = [OFSystemInfo pageSize]; size_t numPages = OF_ROUND_UP_POW2(pageSize, size) / pageSize; #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) struct page **preallocatedPages = of_tlskey_get(preallocatedPagesKey); size_t numPreallocatedPages; |
︙ | ︙ | |||
394 395 396 397 398 399 400 | size_t pageSize = [OFSystemInfo pageSize]; if (count > SIZE_MAX / itemSize) @throw [OFOutOfRangeException exception]; if (count * itemSize >= pageSize) _items = mapPages(OF_ROUND_UP_POW2(pageSize, | | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | size_t pageSize = [OFSystemInfo pageSize]; if (count > SIZE_MAX / itemSize) @throw [OFOutOfRangeException exception]; if (count * itemSize >= pageSize) _items = mapPages(OF_ROUND_UP_POW2(pageSize, count * itemSize) / pageSize, &_swappable); else { #if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS) struct page *lastPage = of_tlskey_get(lastPageKey); #endif for (struct page *page = lastPage; page != NULL; page = page->previous) { |
︙ | ︙ | |||
420 421 422 423 424 425 426 427 428 429 430 431 432 433 | count * itemSize); if (_items == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: count * itemSize]; } } _itemSize = itemSize; _count = count; } @catch (id e) { [self release]; @throw e; | > > | 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 | count * itemSize); if (_items == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: count * itemSize]; } _swappable = _page->swappable; } _itemSize = itemSize; _count = count; } @catch (id e) { [self release]; @throw e; |
︙ | ︙ | |||
494 495 496 497 498 499 500 | - (void)dealloc { size_t pageSize = [OFSystemInfo pageSize]; if (_count * _itemSize > pageSize) unmapPages(_items, | | > | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | - (void)dealloc { size_t pageSize = [OFSystemInfo pageSize]; if (_count * _itemSize > pageSize) unmapPages(_items, OF_ROUND_UP_POW2(pageSize, _count * _itemSize) / pageSize, _swappable); else if (_page != NULL) { if (_items != NULL) freeMemory(_page, _items, _count * _itemSize); removePageIfEmpty(_page); } |
︙ | ︙ |