Date: Thu, 1 May 2008 07:36:31 GMT From: Arthur Hartwig <arthur.hartwig@nokia.com> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/123287: structure used after freed in destroy_devl() in kern/kern_conf.c Message-ID: <200805010736.m417aVxE042215@www.freebsd.org> Resent-Message-ID: <200805010740.m417e1IF086242@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 123287 >Category: kern >Synopsis: structure used after freed in destroy_devl() in kern/kern_conf.c >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu May 01 07:40:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Arthur Hartwig >Release: 6.3 >Organization: Nokia >Environment: >Description: In kern/kern_conf.c destroy_devl() calls devfs_destroy() in fs/devfs/devfs_devs.c. devfs_destroy() clears CDP_ACTIVE in cdp_flags in the structure pointed to by si_priv in the cdev structure. Then destroy_devl() calls msleep() giving devmtx as the mutex to be released then reacquired before returning. Since devmtx is released, it opens the way for another thread to notice that CDP_ACTIVE has been cleared and free the structure pointed to be si_priv in the cdev structure. It might happen like this: open() calls devfs_populate() in fs/devfs/devfs_devs.c which calls devfs_populate_loop() in the same file. devfs_populate_loop() walks the cdevp_list and finds the cdev with associated cdev_priv with CDP_ACTIVE cleared and calls dev_rel() in kern/kern_conf.c which calls devfs_free() which frees the structure pointed to be si_priv in the cdev struct. Some time later, the thread in destroy_devl() wakes from its sleep but now si_priv points to a freed structure. The cdev is either put on the dead_cdevsw.devs list or given to dev_free_devlocked() in kern/kern_conf.c. dev_free_devlocked() puts the address of the already freed structure pointed to by si_priv in the cdev onto the cdev_free_list and hence modifies it. It's possible no-one will notice this use of a structure after it has been freed, but it may cause havoc if the structure has already been reallocated and will certainly cause a panic if the kernel has been build with options INVARIANTS. >How-To-Repeat: Unknown. This is a race condition which has not proved easy to reproduce. >Fix: In destroy_devl() move the call to devfs_destroy() to somewhere after the msleep() call, for example, just before the test on dev->si_refcount. A quick glance at the 7.0-RELEASE code suggests this problem is also present there. I haven't checked HEAD. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805010736.m417aVxE042215>