[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#281050: xserver-common: [i810] Memory leak


After a few hours of investigation I've tracked down this bug. At least I've 
discovered what code causes Xserver to leak memory, when the bug is 
"exploited" by gpdf. It's as simple as the following:

cursor = gdk_cursor_new_for_display(display, GDK_WATCH);
// ... //

This code gets repeated approx. twice as many times as there are pages in the 
pdf (when processing both bookmarks and thumbnails). While this is the bug in 
the gpdf itself (the cursor should not be set so many times), it reveals  
the bug in the X server. X footprint keeps growing because of repeatable  
memory allocations for the cursor and gdk_cursor_unref() failures to free that 
memory. However, this doesn't happen with all types of cursors. Only 
*animated* ones are affected (I base this hypothesis on my tests). Memory 
occupied by static cursors gets freed properly by the gdk_cursor_unref() 
routine. This explains why other people are not suffering from this bug.

I've made a simple gtk program, which starts executing the code above infinite 
number times once you press the "Test memleak!" button (thus you will need to 
use CTRL+C or `kill` to terminate the program). Here it's the step-by-step 
guide to reproduce the memleak:

1. Make sure your "watch" cursor is the animated one or change the argument 2 
of the gdk_cursor_new_for_display() accordingly to the cursor which is 
animated in the theme you're using. If neither is animated, you can obtain one 
from [1] or other source. I extracted the "watch" cursor from this theme and 
put it on my web site[2]. Simply place it into ~/.icons/<your current xcursor 
theme name (in case of "core", use "default")>/cursors/watch This should be 
enough to reproduce the bug without restarting X.

2. Compile memleak.c from [3] with the following command (you will need 
libgtk2.0-dev and its dependences for this):

gcc memleak.c -o memleak -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 
-I/usr/lib/gtk-2.0/include -I/usr/lib/glib-2.0/include 
-I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -L/usr/lib -lgtk-x11-2.0

and start the program.

3. Press the "Test memleak!" button in the GUI and observe X server memory 
usage ("RES" field with `top`). If you have a fast pc, X should consume 
hundreds MBs of memory *very* quickly.

4. To kill the program use CTRL+C or `kill` (it's my first gtk program ever, 
so I haven't invested more time in making termination more sophisticated)

Another interesting thing is that X seems to reuse the allocated memory for 
sequent cursor allocations in other programs (like another instance of 
`memleak`) once the program triggering the bug gets terminated. Test this by 
running several instances of `memleak` one after another.

So for now till someone with more knowlegde of XFree86 code fixes the bug a 
simple workaround is to avoid animated cursors. There may be a bug in 
gdk_cursor_unref() too, I haven't checked the code. In any case, I think it's 
a big (security?) problem in the X server code, because any malicious app can 
make X server (which is generally running as root on most systems with DM) 
use large amounts of memory by repeatedly allocating memory for the cursor 
and not freeing it aftwerwards.

It would be great if someone could test this test case on Xorg. Lots of 
distros include animated watch cursors by default these days, and if these 
are big, lots of people might be suffering from this bug.

The "fixed" gpdf (with the offensive code commented out) is available here[4] 
(the binary for i386, provided there, is compiled w/o optimizations and 
debugging symbols are unstripped)

Related bugs in other locations (neither of which is marked as fixed):


[1]. http://www.kde-look.org/content/show.php?content=18214
[2]. http://mif.vu.lt/~mova3971/xf/watch
[3]. http://mif.vu.lt/~mova3971/xf/memleak.c
[4]. http://mif.vu.lt/~mova3971/xf/gpdf

Attachment: pgpe_r6klyMHn.pgp
Description: PGP signature

Reply to: