Red Hat Bugzilla – Bug 177429
kernel memory leak in mousedev_release
Last modified: 2007-11-30 17:07:22 EST
From Bugzilla Helper: User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20030225 Description of problem: When the sole user of /dev/input/mice opens and closes that file, the system will eventually invoke the oom_killer, which will kill everything in the system until nothing is left running. Version-Release number of selected component (if applicable): kernel-2.4.9-27EL How reproducible: Always Steps to Reproduce: 1. Make sure nobody has /dev/input/mice open (use lsof or fuser) 2. Run a program that opens and closes /dev/input/mice forever. Here's a sample ruby script, if you're into that sort of thing :) #!/usr/bin/env ruby while (true) f = File.new('/dev/input/mice') f.close end 3. Run "watch -n1 free" and see the available memory draining away, rather quickly. Also, run "watch -n1 'cat /proc/slabinfo | grep size-512'" and see the number of size-512 slabs increase rapidly. Actual Results: oom_killer started shooting everything. Expected Results: memory footprint should have stayed roughly constant Additional info: mousedev_open(...) kmalloc's a mousedev_list structure, which should be freed in mousedev_release(...). Problem is, there's an exit path in mousedev_release(...) that skips the kfree. Note: the mousedev_list structure is just over 300 bytes, which lines up with the observation about the size-512 slab growth. I added some printk debug in that routine to verify it. Here's the unmodified code: static int mousedev_release(struct inode * inode, struct file * file) { struct mousedev_list *list = file->private_data; mousedev_fasync(-1, file, 0); list_del(&list->node); if (!--list->mousedev->open) { if (list->mousedev->minor == MOUSEDEV_MIX) --> We take this exit path, avoiding the kfree below. return mixdev_release(); if (!mousedev_mix.open) { if (list->mousedev->exist) input_close_device(&list->mousedev->handle); else mousedev_free(list->mousedev); } } kfree(list); return 0; } I changed the "return mixdev_release()" line above into a block like this: { int rc = mixdev_release(); kfree(list); return rc; } and that seemed to take care of the leak. This bug exists upstream as well. I've verified the oom_killer behavior against Linus' 2.6.15 git tree.
Created attachment 123766 [details] Candidate #1 - plug the leak
The candidate patch #1 is for upstream, but it applies fine to RHEL 4 U3 (with an offset, but no fuzz). I'm going to turn this with the upstream and post for acks after that.
This is included upstream in 2.6.17-rc1 at least, though slightly modified. The bug seems to be languishing at U4 Proposed list.
committed in stream U5 build 42.7. A test kernel with this patch is available from http://people.redhat.com/~jbaron/rhel4/
This request was evaluated by Red Hat Product Management for inclusion in a Red Hat Enterprise Linux maintenance release. Product Management has requested further review of this request by Red Hat Engineering, for potential inclusion in a Red Hat Enterprise Linux Update release for currently deployed products. This request is not yet committed for inclusion in an Update release.
An advisory has been issued which should help the problem described in this bug report. This report is therefore being closed with a resolution of ERRATA. For more information on the solution and/or where to find the updated files, please follow the link below. You may reopen this bug report if the solution does not work for you. http://rhn.redhat.com/errata/RHBA-2007-0304.html