From nobody@FreeBSD.org  Mon Jun  9 08:37:26 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 8938C1065670
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  9 Jun 2008 08:37:26 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 72DDC8FC0C
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  9 Jun 2008 08:37:26 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m598bQop060975
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 9 Jun 2008 08:37:26 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id m598bQQ9060974;
	Mon, 9 Jun 2008 08:37:26 GMT
	(envelope-from nobody)
Message-Id: <200806090837.m598bQQ9060974@www.freebsd.org>
Date: Mon, 9 Jun 2008 08:37:26 GMT
From: Rene Schickbauer <rene.schickbauer@magnapowertrain.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: malloc exposes previously free'd memory
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         124410
>Category:       misc
>Synopsis:       malloc exposes previously free'd memory
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jun 09 08:40:01 UTC 2008
>Closed-Date:    Mon Jun 09 12:01:59 UTC 2008
>Last-Modified:  Mon Jun 09 12:01:59 UTC 2008
>Originator:     Rene Schickbauer
>Release:        7.0-stable
>Organization:
Magna Powertrain
>Environment:
FreeBSD magic3.magicbooks.org 7.0-STABLE FreeBSD 7.0-STABLE #1: Thu Mar 20 15:43:26 CET 2008     root@magic3.magicbooks.org:/usr/obj/usr/src/sys/MAGIC3  i386

>Description:
malloc() exposes memory content from previous malloc/memory operations/free cycles.

This can pose a security risk under certain circumstances. For example, a program generates a key, and forgets to memset() before it frees the memory. The memory contents (and the key) *may* be exposed on subsequent library calls or through unsafe network operations. E.g. this may expose security related data within a running process even after the process has "disposed" all of that data.

While the stand-alone risk may (or may not) be very low, this security leak may work in conjuction with other software bugs to create a deep security hole.

This especially the case, as many software developers seem to think that a free() disposes of the data.
>How-To-Repeat:
Source code of test program:

[cavac@magic3 ~/src/memtest]$ cat main.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define NUM_SEGMENTS 10
#define SIZE_SEGMENTS 1000

int main() {
    FILE *fh;
    printf("Opening file...\n");
    fh = fopen("test.dat", "wb");
    if(!fh) {
        fprintf(stderr, "Can't open file for writing!\n");
        exit(1);
    }

    // Test malloc'ing multiple segments
    printf("Test 1: Multiple segments\n");
    void *mem[10];
    for(int i=0; i < NUM_SEGMENTS; i++) {
        printf("  %d / %d\n", i+1, NUM_SEGMENTS);
        void *xmem = malloc(SIZE_SEGMENTS);
        if(!xmem) {
            fprintf(stderr, "Out of memory (or other malloc problem)!\n");
            exit(2);
        }
        fwrite(xmem, SIZE_SEGMENTS, 1, fh);
        mem[i] = xmem;
    }
    //  Free mem again
    for(int i=0; i < NUM_SEGMENTS; i++) {
        free(mem[i]);
    }

    // Test malloc'ing multiple segments
    printf("Test 2: malloc/free cycle with memset(mem,1,SIZE_SEGMENT)\nbefore free\n");
    for(int i=0; i < NUM_SEGMENTS; i++) {
        printf("  %d / %d\n", i+1, NUM_SEGMENTS);
        void *mem = malloc(SIZE_SEGMENTS);
        if(!mem) {
            fprintf(stderr, "Out of memory (or other malloc problem)!\n");
            exit(2);
        }
        fwrite(mem, SIZE_SEGMENTS, 1, fh);
        memset(mem,1,SIZE_SEGMENTS);
        free(mem);
    }


    printf("Closing file...\n");
    fclose(fh);
    printf("DONE\n");
}


Compile with: 
g++ -o memtest main.cpp

And run as:
./memtest

This creates a file "test.dat", which holds all data that we got in "malloc()"

Then run "hexdump":
[cavac@magic3 ~/src/memtest]$ hexdump -C test.dat
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002af0  00 00 00 00 00 00 00 00  01 01 01 01 01 01 01 01  |................|
00002b00  01 01 01 01 01 01 01 01  01 01 01 01 01 01 01 01  |................|
*
00004e20

As shown by hexdump, it gives cleared memory on first malloc (test 1), but holds data (in test 2) previously written before free().
>Fix:
The safest fix would be to change free() to memset() the allocated memory before freeing it. Also, malloc() should memset() in all cases.

As this will decrease system performance, it should be configureable.

>Release-Note:
>Audit-Trail:

From: rene.schickbauer@magnapowertrain.com
To: bug-followup@FreeBSD.org, rene.schickbauer@magnapowertrain.com
Cc:  
Subject: Re: misc/124410: malloc exposes previously free'd memory
Date: Mon, 9 Jun 2008 11:08:13 +0200

 I forgot to mention:
 
 Yes, i know, there is an option for malloc() to automatically initialize
 memory to "0".
 
 But this is doesn't look like it's enough:
 
 For one thing, it looks like the user may override global setting (is
 unsetting an option possible?). According to the man-page, the memset() (if
 option is set) is done in malloc() instead directly in the kernel, and
 realloc() and reallocf() are not covered at all.
 
 Also, free()ing memory should wipe it for security reasons, for example it
 may help against the "RAM freezing hacks", in cases where the application
 has already free()'d but not malloc()'d security relevant data; see also
 <http://www.hackaday.com/2008/02/21/breaking-disk-encryption-with-ram-dumps/>
 

From: Kris Kennaway <kris@FreeBSD.org>
To: Rene Schickbauer <rene.schickbauer@magnapowertrain.com>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: misc/124410: malloc exposes previously free'd memory
Date: Mon, 09 Jun 2008 12:08:44 +0200

 Rene Schickbauer wrote:
 
 >> Description:
 > malloc() exposes memory content from previous malloc/memory operations/free cycles.
 > 
 > This can pose a security risk under certain circumstances. For example, a program generates a key, and forgets to memset() before it frees the memory. The memory contents (and the key) *may* be exposed on subsequent library calls or through unsafe network operations. E.g. this may expose security related data within a running process even after the process has "disposed" all of that data.
 
 Only if the application is badly coded.  The memory managed by malloc() 
 is only shared within a single processes address space, so it never 
 "leaks" to other applications unless the application itself is broken.
 
 It is such an application that is traditionally regarded as insecure, 
 not the OS.
 
 > While the stand-alone risk may (or may not) be very low, this security leak may work in conjuction with other software bugs to create a deep security hole.
 > 
 > This especially the case, as many software developers seem to think that a free() disposes of the data.
 
 This is not a reasonable assumption, I think.  AFAIK free() has never 
 done this in C.
 
 Anyway if you want to protect against this situation, you can set 
 MALLOC_OPTIONS=J.  There is, of course, a substantial performance overhead.
 
 Kris
 

From: rene.schickbauer@magnapowertrain.com
To: freebsd-gnats-submit@FreeBSD.org
Cc: kris@FreeBSD.org
Subject: Re: misc/124410: malloc exposes previously free'd memory
Date: Mon, 9 Jun 2008 12:48:00 +0200

  > Rene Schickbauer wrote:
 >
 > >> Description:
 > > malloc() exposes memory content from previous malloc/memory
 > operations/free cycles.
 
 ...
 
 > It is such an application that is traditionally regarded as insecure,
 > not the OS.
 
 Yes, i know. But given that such bugs in applications are often not exposed
 for a long time (see the Debian OpenSSL fiasco), additional security might
 not be a bad idea.
 
 > > This especially the case, as many software developers seem to
 > think that a free() disposes of the data.
 >
 > This is not a reasonable assumption, I think.
 
 Given that i have to work with newbies quite a lot, i'd say it is, i'm
 afraid.
 
 > AFAIK free() has never done this in C.
 
 I'm very well aware of that. Nevertheless, free'd memory content may live
 on in RAM for a long time. As i wrote, it may be possible to access the
 data even after the process free`d it. Maybe even by pulling the RAM and
 putting it in another computer.
 
 An example, how this could happen: User puts Laptop into standby; Kernel
 notifies the process that it's going to standby, process closes files and
 dumps the access password by freeing the relevant piece of memory. When the
 computer wakes up again, the process asks the user for the access password
 to re-open the files.
 
 Now, the software developer assumes that:
 1) No one can access the password while computer is in sleep mode, because
 he removed it from the processes memory
 2) The encrypted file is secure, because the user MUST input the password
 again, because it is not known to the system
 
 Sadly these are assumptions if seen in many programs.
 
 > Anyway if you want to protect against this situation, you can set
 > MALLOC_OPTIONS=J.  There is, of course, a substantial performance
 overhead.
 
 Where security is concerned, performance is not that much of an issue.
 
 Thanks for the tipp, i seem to have overlooked "J"...
 
 
 LLAP & LG
 Rene
 
State-Changed-From-To: open->closed 
State-Changed-By: kris 
State-Changed-When: Mon Jun 9 12:01:35 UTC 2008 
State-Changed-Why:  
Users can set MALLOC_OPTIONS=J to avoid this behaviour. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=124410 
>Unformatted:
