Bug 107506 - iconv stuff seem to access freed memory
iconv stuff seem to access freed memory
Status: CLOSED RAWHIDE
Product: Red Hat Linux
Classification: Retired
Component: ElectricFence (Show other bugs)
9
i686 Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
David Lawrence
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2003-10-19 13:33 EDT by Frediano Ziglio
Modified: 2007-04-18 12:58 EDT (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2004-10-16 13:20:32 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
Output of libSegfault.so attached (4.49 KB, text/plain)
2003-10-27 03:37 EST, Ulrich Drepper
no flags Details
Output of strace (27.13 KB, text/plain)
2003-10-27 03:38 EST, Ulrich Drepper
no flags Details
Updated ElectricFence package to fix free bug (36.79 KB, application/octet-stream)
2003-10-29 09:32 EST, Frediano Ziglio
no flags Details

  None (edit)
Description Frediano Ziglio 2003-10-19 13:33:08 EDT
From Bugzilla Helper:
User-Agent: Mozilla/5.0 Galeon/1.2.7 (X11; Linux i686; U;) Gecko/20030131

Description of problem:
Trying to debug FreeTDS library glibc seem to crash using ElectricFence as
memory debugger. iconv seem to access to freed memory. I simplyfied my test
program until I get a simple C program that depend only on glibc and still crash.


Version-Release number of selected component (if applicable):
glibc-2.3.2-27.9

How reproducible:
Always

Steps to Reproduce:
1. Write a C file as
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iconv.h>
#include <pwd.h>
#include <string.h>
 
static char *
tds_get_homedir2(void)
{
        struct passwd *pw, bpw;
        char buf[1024];
 
        if (getpwuid_r(getuid(), &bpw, buf, sizeof(buf), &pw))
                return NULL;
        return strdup(pw->pw_dir);
}
 
int
main(int argc, char **argv)
{
        iconv_t cd;
                                                                                
        void *c = malloc(100);
                                                                                
        printf("line %d\n", __LINE__);
                                                                                
        tds_get_homedir2();
                                                                                
        cd = iconv_open("ISO-8859-1", "UTF-8");
        iconv_close(cd);
                                                                                
        printf("line %d\n", __LINE__);
        free(c);
        printf("line %d\n", __LINE__);
        return 0;
}

2. compile with (you must have ElectricFence installed)
gcc -O2 -Wall -lefence -o iconvbug iconvbug.c
3. enable freed memory protection
export EF_PROTECT_FREE=1
4. launch it 
./iconvbug

    

Actual Results:  A core is reported

  Electric Fence 2.2.0 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
line 28
line 35
line 37
Segmentation fault (core dumped)

gdb ./iconvbug core.3681

(gdb) bt
#0  0x40031fb4 in gconv () from /usr/lib/gconv/ISO8859-1.so
#1  0x42029d40 in exit () from /lib/tls/libc.so.6
#2  0x42015708 in __libc_start_main () from /lib/tls/libc.so.6

Expected Results:  It should not crash

Additional info:

Commenting iconv calls or getpwuid_r call program do not crash.
Comment 1 Ulrich Drepper 2003-10-27 03:34:21 EST
This is no glibc problem, there is something wrong with ElectricFence.  Not
surprising actually, a lot of the functionality it implements is fragile at best.

What happens is that it somehow gets confused about the blocks it allocated. 
This is an excerpt from the strace run:

mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xbf45b000
mprotect(0xbf45c000, 1044480, PROT_NONE) = 0
mprotect(0xbf45b000, 4096, PROT_READ|PROT_WRITE) = 0
mprotect(0xbf45c000, 4096, PROT_READ|PROT_WRITE) = 0
munmap(0xbf45d000, 4096)                = 0
mprotect(0xbf45b000, 4096, PROT_NONE)   = 0

The 0xbf45c000 allocation seems to be done in response to the malloc(100) call.
 The page at 0xbf45b000 seems to be some kind of administrative patch.  Next
comes this:

mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0xbf45d000

This is a mmap call made directly by libc, not EF.  It's the allocation of the
buffer for stdout.  Not that it directly follows the already allocated block.

Before the code crashes this can be seen:

write(1, "line 34\n", 8)                = 8
mprotect(0xbf45b000, 4096, PROT_READ|PROT_WRITE) = 0
munmap(0xbf45c000, 8192)                = 0
mprotect(0xbf45b000, 4096, PROT_NONE)   = 0

The munmap call is made in response to the free() call.  Then the program
crashes since the buffer for stdout at address 0xbf45d000 has also been freed. 
Incorrectly so.


The problem seems to be that initial munmap() call above.  Why did EF create
this 4096 byte hole in mapping?  It's probably meant to be some kind of
protection for the block allocate just below and maybe this should actually be a
mprotect() call.

Anyway, reassigning to EF.
Comment 2 Ulrich Drepper 2003-10-27 03:37:08 EST
Created attachment 95507 [details]
Output of libSegfault.so attached

The failing access is using %ecx
Comment 3 Ulrich Drepper 2003-10-27 03:38:43 EST
Created attachment 95508 [details]
Output of strace

Output of strace for the very same run.  The end of the strace output shows
libSegFault at work.

I used

strace -o STRACE-OUT -E EF_PROTECT_FREE=1 -E LD_PRELOAD=debug/libSegFault.so
./i
Comment 4 Frediano Ziglio 2003-10-29 09:32:46 EST
Created attachment 95575 [details]
Updated ElectricFence package to fix free bug

I updated RawHide version.

freddy77
Comment 5 Jakub Jelinek 2004-10-16 13:20:32 EDT
Should be fixed in ElectricFence-2.2.2-19 in rawhide.
I actually took a different approach, calling Page_Delete for the
guard pages (and in free) always, not just when EF_PROTECT_FREE
and changing Page_Delete, so that it does Page_DenyAccess (== mprotect PROT_NONE)
and madvise MADV_DONTNEED.

Note You need to log in before you can comment on or make changes to this bug.