mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 13:35:48 +01:00 
			
		
		
		
	There is one long-standing problem in CRT realloc wrapper, which will
cause the obvious buffer overflow issue when re-allocating one bigger
memory block:
    void *realloc (void *ptr, size_t size)
    {
      //
      // BUG: hardcode OldSize == size! We have no any knowledge about
      // memory size of original pointer ptr.
      //
      return ReallocatePool ((UINTN) size, (UINTN) size, ptr);
    }
This patch introduces one extra header to record the memory buffer size
information when allocating memory block from malloc routine, and re-wrap
the realloc() and free() routines to remove this BUG.
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ting Ye <ting.ye@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Qin Long <qin.long@intel.com>
Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
Validated-by: Jian J Wang <jian.j.wang@intel.com>
		
	
			
		
			
				
	
	
		
			119 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Base Memory Allocation Routines Wrapper for Crypto library over OpenSSL
 | 
						|
  during PEI & DXE phases.
 | 
						|
 | 
						|
Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <CrtLibSupport.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
 | 
						|
//
 | 
						|
// Extra header to record the memory buffer size from malloc routine.
 | 
						|
//
 | 
						|
#define CRYPTMEM_HEAD_SIGNATURE    SIGNATURE_32('c','m','h','d')
 | 
						|
typedef struct {
 | 
						|
  UINT32    Signature;
 | 
						|
  UINT32    Reserved;
 | 
						|
  UINTN     Size;
 | 
						|
} CRYPTMEM_HEAD;
 | 
						|
 | 
						|
#define CRYPTMEM_OVERHEAD      sizeof(CRYPTMEM_HEAD)
 | 
						|
 | 
						|
//
 | 
						|
// -- Memory-Allocation Routines --
 | 
						|
//
 | 
						|
 | 
						|
/* Allocates memory blocks */
 | 
						|
void *malloc (size_t size)
 | 
						|
{
 | 
						|
  CRYPTMEM_HEAD  *PoolHdr;
 | 
						|
  UINTN          NewSize;
 | 
						|
  VOID           *Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Adjust the size by the buffer header overhead
 | 
						|
  //
 | 
						|
  NewSize = (UINTN)(size) + CRYPTMEM_OVERHEAD;
 | 
						|
 | 
						|
  Data  = AllocatePool (NewSize);
 | 
						|
  if (Data != NULL) {
 | 
						|
    PoolHdr = (CRYPTMEM_HEAD *)Data;
 | 
						|
    //
 | 
						|
    // Record the memory brief information
 | 
						|
    //
 | 
						|
    PoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
 | 
						|
    PoolHdr->Size      = size;
 | 
						|
 | 
						|
    return (VOID *)(PoolHdr + 1);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // The buffer allocation failed.
 | 
						|
    //
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* Reallocate memory blocks */
 | 
						|
void *realloc (void *ptr, size_t size)
 | 
						|
{
 | 
						|
  CRYPTMEM_HEAD  *OldPoolHdr;
 | 
						|
  CRYPTMEM_HEAD  *NewPoolHdr;
 | 
						|
  UINTN          OldSize;
 | 
						|
  UINTN          NewSize;
 | 
						|
  VOID           *Data;
 | 
						|
 | 
						|
  NewSize = (UINTN)size + CRYPTMEM_OVERHEAD;
 | 
						|
  Data = AllocatePool (NewSize);
 | 
						|
  if (Data != NULL) {
 | 
						|
    NewPoolHdr = (CRYPTMEM_HEAD *)Data;
 | 
						|
    NewPoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
 | 
						|
    NewPoolHdr->Size      = size;
 | 
						|
    if (ptr != NULL) {
 | 
						|
      //
 | 
						|
      // Retrieve the original size from the buffer header.
 | 
						|
      //
 | 
						|
      OldPoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
 | 
						|
      ASSERT (OldPoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
 | 
						|
      OldSize = OldPoolHdr->Size;
 | 
						|
 | 
						|
      //
 | 
						|
      // Duplicate the buffer content.
 | 
						|
      //
 | 
						|
      CopyMem ((VOID *)(NewPoolHdr + 1), ptr, MIN (OldSize, size));
 | 
						|
      FreePool ((VOID *)OldPoolHdr);
 | 
						|
    }
 | 
						|
 | 
						|
    return (VOID *)(NewPoolHdr + 1);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // The buffer allocation failed.
 | 
						|
    //
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* De-allocates or frees a memory block */
 | 
						|
void free (void *ptr)
 | 
						|
{
 | 
						|
  CRYPTMEM_HEAD  *PoolHdr;
 | 
						|
 | 
						|
  //
 | 
						|
  // In Standard C, free() handles a null pointer argument transparently. This
 | 
						|
  // is not true of FreePool() below, so protect it.
 | 
						|
  //
 | 
						|
  if (ptr != NULL) {
 | 
						|
    PoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
 | 
						|
    ASSERT (PoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
 | 
						|
    FreePool (PoolHdr);
 | 
						|
  }
 | 
						|
}
 |