Memory safety

From Wikipedia, the free encyclopedia
Jump to: navigation, search

Memory safety is a concern in software development that aims to avoid software bugs that cause security vulnerabilities dealing with random-access memory (RAM) access, such as buffer overflows and dangling pointers.

Computer languages such as C and C++ that support arbitrary pointer arithmetic, casting, and deallocation are typically not memory safe. There are several different approaches to find errors in such languages, see the Detection section below.

The Cyclone language uses a hybrid approach, including "fat pointers" (pointers that carry their metadata directly)[1] and regions[2] to give programmers some low-level control while still ensuring memory safety.

Most high-level programming languages avoid the problem by disallowing pointer arithmetic and casting entirely, and by enforcing tracing garbage collection as the sole memory management scheme.[citation needed]

A language could support even more uses of pointer arithmetic, casting, and deallocation without sacrificing memory safety by using automated theorem proving as a form of static code analysis. ESC/Java and D demonstrate two ways that programmers can declare their invariants in ways that can be understood by a theorem prover.[citation needed]

Contents

[edit] Types of Memory Errors

Several types of memory errors can occur, depending on which programming language is used:

  • Buffer overflow - Out-of bound writes can corrupt the content of adjacent objects, or internal data like bookkeeping information for the heap or return addresses.
  • Dynamic memory errors - Incorrect management of dynamic memory and pointers:
    • Dangling pointer - A pointer storing the address of an object that has been deleted.
    • Double frees - Repeated call to free though the object has been already freed can cause freelist-based allocators to fail.
    • Invalid Free - Passing an invalid address to free can corrupt the heap. Or sometimes will lead to an undefined behavior.
    • Null pointer accesses will cause an exception or program termination in most environments, but can cause corruption in operating system kernels or systems without memory protection, or when use of the null pointer involves a large or negative offset.
  • Uninitialized variables - A variable that has not been assigned a value is used. It may contain an undesired or, in some languages, a corrupt value.
    • Wild pointers arise when a pointer is used prior to initialization to some known state. They show the same erratic behaviour as dangling pointers, though they are less likely to stay undetected.
  • Out of memory errors:
    • Stack overflow - Occurs when a program runs out of stack space, typically because of too deep recursion.
    • Allocation failures - The program tries to use more memory than the amount available. In some languages, this condition must be checked for manually after each allocation.

[edit] Dangling pointer

Dangling Pointer

A pointer which refers to memory which has been deallocated is called a dangling pointer. In languages with manual memory management, dangling pointers can arise when a programmer deallocates a pointers associated memory, then dereferences the pointer.

    int *a = new int;
    int *b = a;
    delete b;
    /* a and b are now dangling pointers */
    *a = 4; /* Memory error: we may be overwriting another pointer's data */

The simple existence of dangling pointers does not constitute a memory error. However, reading from or writing to a dangling pointer would be erroneous, as the referenced memory may have been overwritten or reassigned.

[edit] Buffer overflow

A buffer is a temporary data storage area. Buffer overflow is the most common way for an attacker outside the system to gain unauthorized access to the target system. A buffer overflow occurs when a program tries to store more data in a buffer than it was intended to hold. Since buffers are created to contain a finite amount of data, the extra information can overflow into adjacent buffers, corrupting or overwriting the valid data held in them.It allows attacker to interfere into the existing process code. Attacker uses buffer or stack overflow to do following,

  • Overflow the input field, command line space or input buffer.
  • Overwrite the current return address on the stack with the address of the attacking code.
  • write a simple code that attacker wishes to execute.

E.g.consider the following program

#include <stdio.h>
#define ARRAY_SIZE 128
int main(int argc, char *argv[])
{
   char arr[ARRAY_SIZE];
   if(argc < 2)
       return -1;
   else
   {
       strcpy(arr, argv[1]);
       return 0;
   }
}

As long as the size of this array is less than ARRAY_SIZE program works properly.If the size of the command line argument is greater than that ARRAY_SIZE then it won't work properly. strcpy function will work until it encounters NULL terminator(\0) or until the program crashes.This program suffers from the buffer overflow problem.

  • Solution for this problem is the feature that will not allow execution of code in stack section of memory.[3]

Some programming languages are immune to buffer overflow.Perl automatically resizes arrays, and Ada95 detects and prevents buffer overflow.

[edit] Detection

There are many different ways to detect memory errors in programs written in unsafe languages:

  • By using special heap allocators that provide dead zones around heap allocated storage, and check that accesses don't reach into such dead zones. DieHard[4] does this by allocating objects in their own virtual memory page.
  • By instrumenting the source code. Tools like SoftBound[5] and CheckPointer[6] do this to collect and track legitimate values for pointers ("metadata") and check each pointer access against the metadata for validity.
  • By running the compiled program in a memory-checking virtual machine. The memcheck tool of Valgrind works this way.
  • Static code analysis can detect errors in some cases as well.

[edit] References

  1. ^ Pointers
  2. ^ Region based
  3. ^ Operating Systeme Concepts, 8
  4. ^ DieHard
  5. ^ SoftBound
  6. ^ CheckPointer
Personal tools
Namespaces

Variants
Actions
Navigation
Interaction
Toolbox
Print/export
Languages