OracleLogo

Contents

  1. SSM Introduction
  2. Using Discover SSM Library to Find Memory Access Errors
  3. Converting a Custom Memory Allocator
  4. The Example Code of a Custom Memory Allocator

SSM Introduction

The revolutionary new Oracle SPARC M7 chip offers new functionality that enables software to run faster and more reliably. This functionality is known as Software in Silicon. One important Software in Silicon feature is Silicon Secured Memory. The Silicon Secured Memory circuitry detects common memory access errors, thereby limiting run-time data corruption due to such errors. It can be used to detect:

Such memory access errors can be caused by errant code or a malicious attack on a server's memory. Buffer overflows are known to be a major source of security exploits and in-memory databases increase an application's exposure to such errors since they may have terabytes of critical data in-memory.

Silicon Secured Memory (ADI) stops memory corruptions in optimized production code by adding extra "color" bits to the application's memory pointers and the memory they point to. The pointer color must match the content color or the memory access is aborted. Application Data Integrity works with applications written in systems-level programming languages (e.g. C, C++), which are more vulnerable to memory corruption caused by software errors. Oracle is supplying updated malloc() library routines that will ensure adjacent data structures are given different colors, which will allow the ADI chip functionality to detect buffer overflows, and that memory content colors are changed when memory structures are freed to prevent stale pointer accesses.

ADI can be used in production to detect potential memory corruption issues. Also, it can be used during application development to ensure such errors are caught during application testing and certification. Memory corruption bugs are extremely hard to find since it is very typical for applications to encounter corrupted data long after the corruption happens. The discover memory detection tool and its associated libadidiscover library, part of the Oracle Solaris Studio developer tool suite, provide developers with additional application information making it easier to locate and fix the errant code.

Using Discover ADI Library to Find Memory Access Errors

The discover ADI library reports programming errors that result in invalid memory accesses. The discover ADI library can be used in real time by preloading it into your application. For example, if you normally run an application named server, the command would be:
$ LD_PRELOAD=install-area/lib/compilers/sparcv9/libdiscoverADI.so  server
        
The errors are reported on stderr (terminal).

Errors caught by discover ADI library

There are three kinds of errors the library catches
  1. Buffer Overflow ErrorsThis happens when a program allocates memory using malloc(), say, 64 bytes and then tries to read beyond that. Here is an example. See the code sample for a complete program that you can try.
    int *area1 = malloc(sizeof(int)*16);
    for (int i = 0; i <= 16; i++)
      area1[i] = 0;     // Array Out of Bounds
                    
  2. Freed Memory Access ErrorsThis happens when a program frees a previously allocated memory and then tries to access it. Here is an example. See the code sample for a complete program that you can try.
    free(area1);
    area1[0] = 0;       // Freed Memory Access
                    
  3. Stale Pointer Access ErrorsThis happens when a program frees a previously allocated memory and then tries to access it. In addition, an intervening allocation uses the memory for another purpose. Here is an example. See the code sample for a complete program that you can try.
    int *area1 = malloc(sizeof(int)*16);
    free(area1);
    char *area3 = malloc(sizeof(char)*64); // area3 gets the memory area just freed by area1
    area1[0] = 0;       // Stale Pointer Access
                    
    Stale pointer accesses are reported as a Freed Memory Access because they are a special form of freed memory access.

If your application manages its own memory allocation and free lists, for example by allocating large chunks of memory and subdividing it in your program, see the custom memory allocator information for how you can use the ADI versioning APIs to catch errors within your managed memory.

Configuration options for discover ADI

You can set environment variables to control the operations of the library. The method for setting an environment variable depends on which shell you are using.

The following variables control ADI reporting behavior in libdiscover.so:

Code sample and sample discover ADI output

Assume the following sample code resides in a file named testcode.c

  1  #include <stdlib.h>
  2  #include <stdio.h>
  3  int main() {
  4    int *area1 = malloc(sizeof(int)*16);
  5    int *area2 = malloc(sizeof(int)*100);
  6  
  7    for (int i = 0; i <= 16; i++)
  8      area1[i] = 0;     // Array Out of Bounds
  9  
 10    free(area1);
 11    area1[0] = 0;       // Freed Memory Access
 12  
 13    
 14    char *area3 = malloc(sizeof(char)*64);
 15    if ((void *)area1 == (void *)area3)
 16     printf("New area3 is same as old area1\n");
 17    area1[0] = 0;       // Stale Pointer Access
 18  
 19    return 0;
 20  }
    

You can build this test code with the following command:

$ cc t.c -g -m64
    

You can execute this sample application the ADI feature enabled using the following command:

$ LD_PRELOAD=\lib/compilers/sparcv9/libdiscoverADI.so \
    ADP_PRECISE_MODE=1 \
    ADP_REPORT_STACK_TRACES=1 \
    a.out
    

This will generate the following out (the final format is subject to change):

ADP enabled for map address: 210400000-210480000
Precise Error
 Version Mismatch at instruction (100000b38) : 0xc0240013
Disassembling instruction at 0x100000b38: 0xc0240013
ABA: Array out of bounds Access at address 0x100000021047e000.
Stack trace(depth 2) of the error at pc 100000b38: 
  pc0: 100000b38.   main + 0x38
         6:    
         7:      for (int i = 0; i <= 16; i++)
         8:=>      area1[i] = 0;     // Array Out of Bounds
         9:    
        10:      free(area1);
  pc1: 100000ac8.   _start + 0x108
Stack trace of allocation:
  pc0: 100000b08.   main + 0x8
        2:    #include 
        3:    int main() {
        4:=>    int *area1 = malloc(sizeof(int)*16);
        5:      int *area2 = malloc(sizeof(int)*100);
        6:    
  pc1: 100000ac8.   _start + 0x108
Precise Error
 Version Mismatch at instruction (100000b6c) : 0xc0240013
Disassembling instruction at 0x100000b6c: 0xc0240013
FMA: Freed Memory Access at address 0x100000021047e000.
Stack trace(depth 2) of the error at pc 100000b6c: 
  pc0: 100000b6c.   main + 0x6c
         9:    
        10:      free(area1);
        11:=>    area1[0] = 0;       // Freed Memory Access
        12:    
        13:      
  pc1: 100000ac8.   _start + 0x108
Stack trace for free():
  pc0: 100000b5c.   main + 0x5c
         8:        area1[i] = 0;     // Array Out of Bounds
         9:    
        10:=>    free(area1);
        11:      area1[0] = 0;       // Freed Memory Access
        12:    
  pc1: 100000ac8.   _start + 0x108
Precise Error
 Version Mismatch at instruction (100000bb4) : 0xc0240013
Disassembling instruction at 0x100000bb4: 0xc0240013
FMA: Freed Memory Access at address 0x100000021047e000.
Stack trace(depth 2) of the error at pc 100000bb4: 
  pc0: 100000bb4.   main + 0xb4
        15:      if (area1 == area3)
        16:       printf("New area3 is same as old area1\n");
        17:=>    area1[0] = 0;       // Stale pointer access
        18:    
        19:      return 0;
  pc1: 100000ac8.   _start + 0x108
Stack trace for free():
  pc0: 100000b5c.   main + 0x5c
         8:        area1[i] = 0;     // Array Out of Bounds
         9:    
        10:=>    free(area1);
        11:      area1[0] = 0;       // Freed Memory Access
        12:    
  pc1: 100000ac8.   _start + 0x108
    


Go to the next page.