VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/memsafer-r3.cpp@ 90330

Last change on this file since 90330 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: memsafer-r3.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * IPRT - Memory Allocate for Sensitive Data, generic heap-based implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/memsafer.h>
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/avl.h>
37#include <iprt/critsect.h>
38#include <iprt/err.h>
39#include <iprt/mem.h>
40#include <iprt/once.h>
41#include <iprt/rand.h>
42#include <iprt/param.h>
43#include <iprt/string.h>
44#ifdef IN_SUP_R3
45# include <VBox/sup.h>
46#endif
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52/** Allocation size alignment (power of two). */
53#define RTMEMSAFER_ALIGN 16
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/**
60 * Allocators.
61 */
62typedef enum RTMEMSAFERALLOCATOR
63{
64 /** Invalid method. */
65 RTMEMSAFERALLOCATOR_INVALID = 0,
66 /** RTMemPageAlloc. */
67 RTMEMSAFERALLOCATOR_RTMEMPAGE,
68 /** SUPR3PageAllocEx. */
69 RTMEMSAFERALLOCATOR_SUPR3
70} RTMEMSAFERALLOCATOR;
71
72/**
73 * Tracking node (lives on normal heap).
74 */
75typedef struct RTMEMSAFERNODE
76{
77 /** Node core.
78 * The core key is a scrambled pointer the user memory. */
79 AVLPVNODECORE Core;
80 /** The allocation flags. */
81 uint32_t fFlags;
82 /** The offset into the allocation of the user memory. */
83 uint32_t offUser;
84 /** The requested allocation size. */
85 size_t cbUser;
86 /** The allocation size in pages, this includes the two guard pages. */
87 uint32_t cPages;
88 /** The allocator used for this node. */
89 RTMEMSAFERALLOCATOR enmAllocator;
90 /** XOR scrambler value for memory. */
91 uintptr_t uScramblerXor;
92} RTMEMSAFERNODE;
93/** Pointer to an allocation tracking node. */
94typedef RTMEMSAFERNODE *PRTMEMSAFERNODE;
95
96
97/*********************************************************************************************************************************
98* Global Variables *
99*********************************************************************************************************************************/
100/** Init once structure for this module. */
101static RTONCE g_MemSaferOnce = RTONCE_INITIALIZER;
102/** Critical section protecting the allocation tree. */
103static RTCRITSECTRW g_MemSaferCritSect;
104/** Tree of allocation nodes. */
105static AVLPVTREE g_pMemSaferTree;
106/** XOR scrambler value pointers. */
107static uintptr_t g_uMemSaferPtrScramblerXor;
108/** Pointer rotate shift count.*/
109static uintptr_t g_cMemSaferPtrScramblerRotate;
110
111
112/**
113 * @callback_method_impl{FNRTONCE, Inits globals.}
114 */
115static DECLCALLBACK(int32_t) rtMemSaferOnceInit(void *pvUserIgnore)
116{
117 RT_NOREF_PV(pvUserIgnore);
118
119 g_uMemSaferPtrScramblerXor = (uintptr_t)RTRandU64();
120 g_cMemSaferPtrScramblerRotate = RTRandU32Ex(0, ARCH_BITS - 1);
121 return RTCritSectRwInit(&g_MemSaferCritSect);
122}
123
124
125/**
126 * @callback_method_impl{PFNRTONCECLEANUP, Cleans up globals.}
127 */
128static DECLCALLBACK(void) rtMemSaferOnceTerm(void *pvUser, bool fLazyCleanUpOk)
129{
130 RT_NOREF_PV(pvUser);
131
132 if (!fLazyCleanUpOk)
133 {
134 RTCritSectRwDelete(&g_MemSaferCritSect);
135 Assert(!g_pMemSaferTree);
136 }
137}
138
139
140
141DECLINLINE(void *) rtMemSaferScramblePointer(void *pvUser)
142{
143 uintptr_t uPtr = (uintptr_t)pvUser;
144 uPtr ^= g_uMemSaferPtrScramblerXor;
145#if ARCH_BITS == 64
146 uPtr = ASMRotateRightU64(uPtr, g_cMemSaferPtrScramblerRotate);
147#elif ARCH_BITS == 32
148 uPtr = ASMRotateRightU32(uPtr, g_cMemSaferPtrScramblerRotate);
149#else
150# error "Unsupported/missing ARCH_BITS."
151#endif
152 return (void *)uPtr;
153}
154
155
156/**
157 * Inserts a tracking node into the tree.
158 *
159 * @param pThis The allocation tracking node to insert.
160 */
161static void rtMemSaferNodeInsert(PRTMEMSAFERNODE pThis)
162{
163 RTCritSectRwEnterExcl(&g_MemSaferCritSect);
164 pThis->Core.Key = rtMemSaferScramblePointer(pThis->Core.Key);
165 bool fRc = RTAvlPVInsert(&g_pMemSaferTree, &pThis->Core);
166 RTCritSectRwLeaveExcl(&g_MemSaferCritSect);
167 Assert(fRc); NOREF(fRc);
168}
169
170
171/**
172 * Finds a tracking node into the tree.
173 *
174 * @returns The allocation tracking node for @a pvUser. NULL if not found.
175 * @param pvUser The user pointer to the allocation.
176 */
177static PRTMEMSAFERNODE rtMemSaferNodeLookup(void *pvUser)
178{
179 void *pvKey = rtMemSaferScramblePointer(pvUser);
180 RTCritSectRwEnterShared(&g_MemSaferCritSect);
181 PRTMEMSAFERNODE pThis = (PRTMEMSAFERNODE)RTAvlPVGet(&g_pMemSaferTree, pvKey);
182 RTCritSectRwLeaveShared(&g_MemSaferCritSect);
183 return pThis;
184}
185
186
187/**
188 * Removes a tracking node from the tree.
189 *
190 * @returns The allocation tracking node for @a pvUser. NULL if not found.
191 * @param pvUser The user pointer to the allocation.
192 */
193static PRTMEMSAFERNODE rtMemSaferNodeRemove(void *pvUser)
194{
195 void *pvKey = rtMemSaferScramblePointer(pvUser);
196 RTCritSectRwEnterExcl(&g_MemSaferCritSect);
197 PRTMEMSAFERNODE pThis = (PRTMEMSAFERNODE)RTAvlPVRemove(&g_pMemSaferTree, pvKey);
198 RTCritSectRwLeaveExcl(&g_MemSaferCritSect);
199 return pThis;
200}
201
202
203RTDECL(int) RTMemSaferScramble(void *pv, size_t cb)
204{
205 PRTMEMSAFERNODE pThis = rtMemSaferNodeLookup(pv);
206 AssertReturn(pThis, VERR_INVALID_POINTER);
207 AssertMsgReturn(cb == pThis->cbUser, ("cb=%#zx != %#zx\n", cb, pThis->cbUser), VERR_INVALID_PARAMETER);
208
209 /* First time we get a new xor value. */
210 if (!pThis->uScramblerXor)
211 pThis->uScramblerXor = (uintptr_t)RTRandU64();
212
213 /* Note! This isn't supposed to be safe, just less obvious. */
214 uintptr_t *pu = (uintptr_t *)pv;
215 cb = RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN);
216 while (cb > 0)
217 {
218 *pu ^= pThis->uScramblerXor;
219 pu++;
220 cb -= sizeof(*pu);
221 }
222
223 return VINF_SUCCESS;
224}
225RT_EXPORT_SYMBOL(RTMemSaferScramble);
226
227
228RTDECL(int) RTMemSaferUnscramble(void *pv, size_t cb)
229{
230 PRTMEMSAFERNODE pThis = rtMemSaferNodeLookup(pv);
231 AssertReturn(pThis, VERR_INVALID_POINTER);
232 AssertMsgReturn(cb == pThis->cbUser, ("cb=%#zx != %#zx\n", cb, pThis->cbUser), VERR_INVALID_PARAMETER);
233
234 /* Note! This isn't supposed to be safe, just less obvious. */
235 uintptr_t *pu = (uintptr_t *)pv;
236 cb = RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN);
237 while (cb > 0)
238 {
239 *pu ^= pThis->uScramblerXor;
240 pu++;
241 cb -= sizeof(*pu);
242 }
243
244 return VINF_SUCCESS;
245}
246RT_EXPORT_SYMBOL(RTMemSaferUnscramble);
247
248
249/**
250 * Initializes the pages.
251 *
252 * Fills the memory with random bytes in order to make it less obvious where the
253 * secret data starts and ends. We also zero the user memory in case the
254 * allocator does not do this.
255 *
256 * @param pThis The allocation tracer node. The Core.Key member
257 * will be set.
258 * @param pvPages The pages to initialize.
259 */
260static void rtMemSaferInitializePages(PRTMEMSAFERNODE pThis, void *pvPages)
261{
262 RTRandBytes(pvPages, PAGE_SIZE + pThis->offUser);
263
264 uint8_t *pbUser = (uint8_t *)pvPages + PAGE_SIZE + pThis->offUser;
265 pThis->Core.Key = pbUser;
266 RT_BZERO(pbUser, pThis->cbUser); /* paranoia */
267
268 RTRandBytes(pbUser + pThis->cbUser, (size_t)pThis->cPages * PAGE_SIZE - PAGE_SIZE - pThis->offUser - pThis->cbUser);
269}
270
271
272/**
273 * Allocates and initializes pages from the support driver and initializes it.
274 *
275 * @returns VBox status code.
276 * @param pThis The allocator node. Core.Key will be set on successful
277 * return (unscrambled).
278 */
279static int rtMemSaferSupR3AllocPages(PRTMEMSAFERNODE pThis)
280{
281#ifdef IN_SUP_R3
282 /*
283 * Try allocate the memory.
284 */
285 void *pvPages;
286 int rc = SUPR3PageAllocEx(pThis->cPages, 0 /* fFlags */, &pvPages, NULL /* pR0Ptr */, NULL /* paPages */);
287 if (RT_SUCCESS(rc))
288 {
289 rtMemSaferInitializePages(pThis, pvPages);
290
291 /*
292 * On darwin we cannot allocate pages without an R0 mapping and
293 * SUPR3PageAllocEx falls back to another method which is incompatible with
294 * the way SUPR3PageProtect works. Ignore changing the protection of the guard
295 * pages.
296 */
297#ifdef RT_OS_DARWIN
298 return VINF_SUCCESS;
299#else
300 /*
301 * Configure the guard pages.
302 * SUPR3PageProtect isn't supported on all hosts, we ignore that.
303 */
304 rc = SUPR3PageProtect(pvPages, NIL_RTR0PTR, 0, PAGE_SIZE, RTMEM_PROT_NONE);
305 if (RT_SUCCESS(rc))
306 {
307 rc = SUPR3PageProtect(pvPages, NIL_RTR0PTR, (pThis->cPages - 1) * PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);
308 if (RT_SUCCESS(rc))
309 return VINF_SUCCESS;
310 SUPR3PageProtect(pvPages, NIL_RTR0PTR, 0, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
311 }
312 else if (rc == VERR_NOT_SUPPORTED)
313 return VINF_SUCCESS;
314
315 /* failed. */
316 int rc2 = SUPR3PageFreeEx(pvPages, pThis->cPages); AssertRC(rc2);
317#endif
318 }
319 return rc;
320
321#else /* !IN_SUP_R3 */
322 RT_NOREF_PV(pThis);
323 return VERR_NOT_SUPPORTED;
324#endif /* !IN_SUP_R3 */
325}
326
327
328/**
329 * Allocates and initializes pages using the IPRT page allocator API.
330 *
331 * @returns VBox status code.
332 * @param pThis The allocator node. Core.Key will be set on successful
333 * return (unscrambled).
334 */
335static int rtMemSaferMemAllocPages(PRTMEMSAFERNODE pThis)
336{
337 /*
338 * Try allocate the memory.
339 */
340 int rc = VINF_SUCCESS;
341 void *pvPages = RTMemPageAllocEx((size_t)pThis->cPages * PAGE_SIZE,
342 RTMEMPAGEALLOC_F_ADVISE_LOCKED | RTMEMPAGEALLOC_F_ADVISE_NO_DUMP | RTMEMPAGEALLOC_F_ZERO);
343 if (pvPages)
344 {
345 rtMemSaferInitializePages(pThis, pvPages);
346
347 /*
348 * Configure the guard pages.
349 */
350 rc = RTMemProtect(pvPages, PAGE_SIZE, RTMEM_PROT_NONE);
351 if (RT_SUCCESS(rc))
352 {
353 rc = RTMemProtect((uint8_t *)pvPages + (size_t)(pThis->cPages - 1U) * PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);
354 if (RT_SUCCESS(rc))
355 return VINF_SUCCESS;
356 rc = RTMemProtect(pvPages, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
357 }
358
359 /* failed. */
360 RTMemPageFree(pvPages, (size_t)pThis->cPages * PAGE_SIZE);
361 }
362 else
363 rc = VERR_NO_PAGE_MEMORY;
364
365 return rc;
366}
367
368
369RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, uint32_t fFlags, const char *pszTag) RT_NO_THROW_DEF
370{
371 RT_NOREF_PV(pszTag);
372
373 /*
374 * Validate input.
375 */
376 AssertPtrReturn(ppvNew, VERR_INVALID_PARAMETER);
377 *ppvNew = NULL;
378 AssertReturn(cb, VERR_INVALID_PARAMETER);
379 AssertReturn(cb <= 32U*_1M - PAGE_SIZE * 3U, VERR_ALLOCATION_TOO_BIG); /* Max 32 MB minus padding and guard pages. */
380 AssertReturn(!(fFlags & ~RTMEMSAFER_F_VALID_MASK), VERR_INVALID_FLAGS);
381
382 /*
383 * Initialize globals.
384 */
385 int rc = RTOnceEx(&g_MemSaferOnce, rtMemSaferOnceInit, rtMemSaferOnceTerm, NULL);
386 if (RT_SUCCESS(rc))
387 {
388 /*
389 * Allocate a tracker node first.
390 */
391 PRTMEMSAFERNODE pThis = (PRTMEMSAFERNODE)RTMemAllocZ(sizeof(RTMEMSAFERNODE));
392 if (pThis)
393 {
394 /*
395 * Prepare the allocation.
396 */
397 pThis->cbUser = cb;
398 pThis->offUser = (RTRandU32Ex(0, 128) * RTMEMSAFER_ALIGN) & PAGE_OFFSET_MASK;
399
400 size_t cbNeeded = pThis->offUser + pThis->cbUser;
401 cbNeeded = RT_ALIGN_Z(cbNeeded, PAGE_SIZE);
402
403 pThis->cPages = (uint32_t)(cbNeeded / PAGE_SIZE) + 2; /* +2 for guard pages */
404
405 /*
406 * Try allocate the memory, using the best allocator by default and
407 * falling back on the less safe one.
408 */
409 rc = rtMemSaferSupR3AllocPages(pThis);
410 if (RT_SUCCESS(rc))
411 pThis->enmAllocator = RTMEMSAFERALLOCATOR_SUPR3;
412 else if (!(fFlags & RTMEMSAFER_F_REQUIRE_NOT_PAGABLE))
413 {
414 rc = rtMemSaferMemAllocPages(pThis);
415 if (RT_SUCCESS(rc))
416 pThis->enmAllocator = RTMEMSAFERALLOCATOR_RTMEMPAGE;
417 }
418 if (RT_SUCCESS(rc))
419 {
420 /*
421 * Insert the node.
422 */
423 *ppvNew = pThis->Core.Key;
424 rtMemSaferNodeInsert(pThis); /* (Scrambles Core.Key) */
425 return VINF_SUCCESS;
426 }
427
428 RTMemFree(pThis);
429 }
430 else
431 rc = VERR_NO_MEMORY;
432 }
433 return rc;
434}
435RT_EXPORT_SYMBOL(RTMemSaferAllocZExTag);
436
437
438RTDECL(void) RTMemSaferFree(void *pv, size_t cb) RT_NO_THROW_DEF
439{
440 if (pv)
441 {
442 PRTMEMSAFERNODE pThis = rtMemSaferNodeRemove(pv);
443 AssertReturnVoid(pThis);
444 if (cb == 0) /* for openssl use */
445 cb = pThis->cbUser;
446 else
447 AssertMsg(cb == pThis->cbUser, ("cb=%#zx != %#zx\n", cb, pThis->cbUser));
448
449 /*
450 * Wipe the user memory first.
451 */
452 RTMemWipeThoroughly(pv, RT_ALIGN_Z(cb, RTMEMSAFER_ALIGN), 3);
453
454 /*
455 * Free the pages.
456 */
457 uint8_t *pbPages = (uint8_t *)pv - pThis->offUser - PAGE_SIZE;
458 size_t cbPages = (size_t)pThis->cPages * PAGE_SIZE;
459 switch (pThis->enmAllocator)
460 {
461#ifdef IN_SUP_R3
462 case RTMEMSAFERALLOCATOR_SUPR3:
463 SUPR3PageProtect(pbPages, NIL_RTR0PTR, 0, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
464 SUPR3PageProtect(pbPages, NIL_RTR0PTR, (uint32_t)(cbPages - PAGE_SIZE), PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
465 SUPR3PageFreeEx(pbPages, pThis->cPages);
466 break;
467#endif
468 case RTMEMSAFERALLOCATOR_RTMEMPAGE:
469 RTMemProtect(pbPages, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
470 RTMemProtect(pbPages + cbPages - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
471 RTMemPageFree(pbPages, cbPages);
472 break;
473
474 default:
475 AssertFailed();
476 }
477
478 /*
479 * Free the tracking node.
480 */
481 pThis->Core.Key = NULL;
482 pThis->offUser = 0;
483 pThis->cbUser = 0;
484 RTMemFree(pThis);
485 }
486 else
487 Assert(cb == 0);
488}
489RT_EXPORT_SYMBOL(RTMemSaferFree);
490
491
492RTDECL(size_t) RTMemSaferGetSize(void *pv) RT_NO_THROW_DEF
493{
494 size_t cbRet = 0;
495 if (pv)
496 {
497 void *pvKey = rtMemSaferScramblePointer(pv);
498 RTCritSectRwEnterShared(&g_MemSaferCritSect);
499 PRTMEMSAFERNODE pThis = (PRTMEMSAFERNODE)RTAvlPVGet(&g_pMemSaferTree, pvKey);
500 if (pThis)
501 cbRet = pThis->cbUser;
502 RTCritSectRwLeaveShared(&g_MemSaferCritSect);
503 }
504 return cbRet;
505}
506RT_EXPORT_SYMBOL(RTMemSaferGetSize);
507
508
509/**
510 * The simplest reallocation method: allocate new block, copy over the data,
511 * free old block.
512 */
513static int rtMemSaferReallocSimpler(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, uint32_t fFlags, const char *pszTag)
514{
515 void *pvNew;
516 int rc = RTMemSaferAllocZExTag(&pvNew, cbNew, fFlags, pszTag);
517 if (RT_SUCCESS(rc))
518 {
519 memcpy(pvNew, pvOld, RT_MIN(cbNew, cbOld));
520 RTMemSaferFree(pvOld, cbOld);
521 *ppvNew = pvNew;
522 }
523 return rc;
524}
525
526
527RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, uint32_t fFlags, const char *pszTag) RT_NO_THROW_DEF
528{
529 int rc;
530 /* Real realloc. */
531 if (cbNew && cbOld)
532 {
533 PRTMEMSAFERNODE pThis = rtMemSaferNodeLookup(pvOld);
534 AssertReturn(pThis, VERR_INVALID_POINTER);
535 AssertMsgStmt(cbOld == pThis->cbUser, ("cbOld=%#zx != %#zx\n", cbOld, pThis->cbUser), cbOld = pThis->cbUser);
536
537 if (pThis->fFlags == fFlags)
538 {
539 if (cbNew > cbOld)
540 {
541 /*
542 * Is the enough room for us to grow?
543 */
544 size_t cbMax = (size_t)(pThis->cPages - 2) * PAGE_SIZE;
545 if (cbNew <= cbMax)
546 {
547 size_t const cbAdded = (cbNew - cbOld);
548 size_t const cbAfter = cbMax - pThis->offUser - cbOld;
549 if (cbAfter >= cbAdded)
550 {
551 /*
552 * Sufficient space after the current allocation.
553 */
554 uint8_t *pbNewSpace = (uint8_t *)pvOld + cbOld;
555 RT_BZERO(pbNewSpace, cbAdded);
556 *ppvNew = pvOld;
557 }
558 else
559 {
560 /*
561 * Have to move the allocation to make enough room at the
562 * end. In order to make it a little less predictable and
563 * maybe avoid a relocation or two in the next call, divide
564 * the page offset by four until it it fits.
565 */
566 AssertReturn(rtMemSaferNodeRemove(pvOld) == pThis, VERR_INTERNAL_ERROR_3);
567 uint32_t offNewUser = pThis->offUser;
568 do
569 offNewUser = offNewUser / 2;
570 while ((pThis->offUser - offNewUser) + cbAfter < cbAdded);
571 offNewUser &= ~(RTMEMSAFER_ALIGN - 1U);
572
573 uint32_t const cbMove = pThis->offUser - offNewUser;
574 uint8_t *pbNew = (uint8_t *)pvOld - cbMove;
575 memmove(pbNew, pvOld, cbOld);
576
577 RT_BZERO(pbNew + cbOld, cbAdded);
578 if (cbMove > cbAdded)
579 RTMemWipeThoroughly(pbNew + cbNew, cbMove - cbAdded, 3);
580
581 pThis->offUser = offNewUser;
582 pThis->Core.Key = pbNew;
583 *ppvNew = pbNew;
584
585 rtMemSaferNodeInsert(pThis);
586 }
587 Assert(((uintptr_t)*ppvNew & PAGE_OFFSET_MASK) == pThis->offUser);
588 pThis->cbUser = cbNew;
589 rc = VINF_SUCCESS;
590 }
591 else
592 {
593 /*
594 * Not enough space, allocate a new block and copy over the data.
595 */
596 rc = rtMemSaferReallocSimpler(cbOld, pvOld, cbNew, ppvNew, fFlags, pszTag);
597 }
598 }
599 else
600 {
601 /*
602 * Shrinking the allocation, just wipe the memory that is no longer
603 * being used.
604 */
605 if (cbNew != cbOld)
606 {
607 uint8_t *pbAbandond = (uint8_t *)pvOld + cbNew;
608 RTMemWipeThoroughly(pbAbandond, cbOld - cbNew, 3);
609 }
610 pThis->cbUser = cbNew;
611 *ppvNew = pvOld;
612 rc = VINF_SUCCESS;
613 }
614 }
615 else if (!pThis->fFlags)
616 {
617 /*
618 * New flags added. Allocate a new block and copy over the old one.
619 */
620 rc = rtMemSaferReallocSimpler(cbOld, pvOld, cbNew, ppvNew, fFlags, pszTag);
621 }
622 else
623 {
624 /* Compatible flags. */
625 AssertMsgFailed(("fFlags=%#x old=%#x\n", fFlags, pThis->fFlags));
626 rc = VERR_INVALID_FLAGS;
627 }
628 }
629 /*
630 * First allocation. Pass it on.
631 */
632 else if (!cbOld)
633 {
634 Assert(pvOld == NULL);
635 rc = RTMemSaferAllocZExTag(ppvNew, cbNew, fFlags, pszTag);
636 }
637 /*
638 * Free operation. Pass it on.
639 */
640 else
641 {
642 RTMemSaferFree(pvOld, cbOld);
643 *ppvNew = NULL;
644 rc = VINF_SUCCESS;
645 }
646 return rc;
647}
648RT_EXPORT_SYMBOL(RTMemSaferReallocZExTag);
649
650
651RTDECL(void *) RTMemSaferAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_DEF
652{
653 void *pvNew = NULL;
654 int rc = RTMemSaferAllocZExTag(&pvNew, cb, 0 /*fFlags*/, pszTag);
655 if (RT_SUCCESS(rc))
656 return pvNew;
657 return NULL;
658}
659RT_EXPORT_SYMBOL(RTMemSaferAllocZTag);
660
661
662RTDECL(void *) RTMemSaferReallocZTag(size_t cbOld, void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_DEF
663{
664 void *pvNew = NULL;
665 int rc = RTMemSaferReallocZExTag(cbOld, pvOld, cbNew, &pvNew, 0 /*fFlags*/, pszTag);
666 if (RT_SUCCESS(rc))
667 return pvNew;
668 return NULL;
669}
670RT_EXPORT_SYMBOL(RTMemSaferReallocZTag);
671
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette