BusyBox Bug and Patch Tracking
BusyBox
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0005784 [uClibc] Shared Library Support major always 10-28-08 10:29 10-31-08 02:02
Reporter estesp View Status public  
Assigned To uClibc
Priority normal Resolution fixed  
Status closed   Product Version 0.9.30
Summary 0005784: ref counting can wrap in libdl.so
Description Recently while investigating a problem with pam authentication+uClibc, my investigation led me to the point where I realized that the dlopen() and dlclose() management of ref. counting is not balanced, which leads to the heaviest "DL_NEEDED" libraries basically getting incremented to the point of overflowing "unsigned short usage_count". This leads to a nasty situation where
libc.so is munmapped (because usage_count == 0), and the next call to a
C runtime function traps, of course.

The exact point of trap is in ldso/libdl/libdl.c around line 533:

529 _dl_munmap((void*)tpnt->loadaddr, end);
530 /* Free elements in RTLD_LOCAL scope list */
531 for (runp = tpnt->rtld_local; runp; runp = tmp) {
532 tmp = runp->next;
533 free(runp);
534 }

When the wrap happens, you will find this code executed where tpnt is pointing at libc.so--therefore the dl_munmap @ 529 will actually unmap the code segment of libc.so. When the free() at line 533 is executed, it will segfault, given the offset of the function free() (which was in libc.so's code segment) is now unmapped/inaccessible memory to this process.
Additional Information I will add a simple testcase that can be used to reproduce this problem. Given a few factors the number of iterations to recreate can vary, but an easy way to 'watch' the libc.so ref count wrap is to add a breakpoint at libdl.c:247 and then use the following commands function of gdb to output the refcount each time:

(at gdb prompt)
> commands <brnum>
> silent
> printf "%d : %s\n",(*tpnt1)->usage_count, lpntstr
> cont
> end

Now you can continue and watch the usage count of each library loaded climb.

A temporary fix, of course, is to make sure that the usage count does not wrap--this can be done easily in the function which increments usage count: ldso/ldso/dl-elf.c around line 381. Right after the usage_count is incremented, a check can be inserted for 0.. an incremented usage_count could never be zero, so when it is you know you have wrapped--simple set back to some large value near unsigned int max (e.g. 0xfff0) and the problem is worked around. I believe the right permanent fix is to understand why ref. counting is not balanced between load and unload of dependent libs, however, that code is more involved and probably needs someone well versed in the dlopen/dlclose design/architecture.
Attached Files  stress-dlopen.c [^] (1,430 bytes) 10-28-08 10:29

- Relationships

- Notes
(0014584)
bernhardf
10-30-08 01:15

I don't have any of those libraries and i cannot reproduce it on trunk with gmp/mpfr/gcc_s/bz2, can you describe what a lib must look like to trip into this?
Perhaps you can provide a couple of dummy libs that fulfill the constraints to reproduce it?
 
(0014684)
estesp
10-30-08 12:56

Hmm..adding some debug code to 0.9.30-rc3 I can see that the usage_count is being managed properly. As I said in my original mailing list report, the changes in svn 17530 gave me a big boost against my 0.9.28 version of code as far as "putting off" the problem, but maybe I am still missing some piece of patching related to that area that makes it totally go away for 0.9.30. I thought someone had tried 0.9.30 and I had done enough code comparison to convince myself the problem still existed. It obviously does not at this point. If you want to close the bug, that's fine.. I assume there really isn't "service" for the older streams of code, and the workaround I mention really controls the issue for pre-0.9.30 code.
 
(0014734)
bernhardf
10-31-08 02:02

Fine, please reopen this issue if need be.
 

- Issue History
Date Modified Username Field Change
10-28-08 10:29 estesp New Issue
10-28-08 10:29 estesp Status new => assigned
10-28-08 10:29 estesp Assigned To  => uClibc
10-28-08 10:29 estesp File Added: stress-dlopen.c
10-30-08 01:15 bernhardf Note Added: 0014584
10-30-08 12:56 estesp Note Added: 0014684
10-31-08 02:02 bernhardf Status assigned => closed
10-31-08 02:02 bernhardf Note Added: 0014734
10-31-08 02:02 bernhardf Resolution open => fixed
10-31-08 02:02 bernhardf Fixed in Version  => 0.9.30


Copyright © 2000 - 2006 Mantis Group
Powered by Mantis Bugtracker