[svn-commits] fjoe: freebsd/trunk r8860 - /freebsd/trunk/drivers/dahdi/dahdi-base.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Tue Jul 6 16:12:04 CDT 2010
Author: fjoe
Date: Tue Jul 6 16:12:01 2010
New Revision: 8860
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8860
Log:
Fix use of free'd memory by kern_poll() and friends after dahdi_free_pseudo() call:
'struct dahdi_chan' includes 'struct selinfo' which should not be free'd because
current thread can still have references to it after selrecord() call.
Modified:
freebsd/trunk/drivers/dahdi/dahdi-base.c
Modified: freebsd/trunk/drivers/dahdi/dahdi-base.c
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/drivers/dahdi/dahdi-base.c?view=diff&rev=8860&r1=8859&r2=8860
==============================================================================
--- freebsd/trunk/drivers/dahdi/dahdi-base.c (original)
+++ freebsd/trunk/drivers/dahdi/dahdi-base.c Tue Jul 6 16:12:01 2010
@@ -47,7 +47,6 @@
#include <sys/module.h>
#include <sys/poll.h>
#include <net/ppp_defs.h>
-#include <sys/selinfo.h>
#include "version.h"
@@ -358,6 +357,52 @@
dahdi_copy_from_user(void *to, const void *from, int n)
{
return copyin(from, to, n);
+}
+
+struct pseudo_free {
+ LIST_ENTRY(pseudo_free) pf_link;
+ struct dahdi_chan *pf_pseudo;
+ struct thread *pf_thread;
+};
+
+static DEFINE_SPINLOCK(pseudo_free_list_lock);
+
+static LIST_HEAD(, pseudo_free) pseudo_free_list =
+ LIST_HEAD_INITIALIZER(pseudo_free_list);
+
+static void
+free_pseudo(struct dahdi_chan *pseudo)
+{
+ unsigned long flags;
+ struct pseudo_free *pf;
+
+ pf = kmalloc(sizeof(*pf), GFP_KERNEL);
+ pf->pf_pseudo = pseudo;
+ pf->pf_thread = curthread;
+
+ spin_lock_irqsave(&pseudo_free_list_lock, flags);
+ LIST_INSERT_HEAD(&pseudo_free_list, pf, pf_link);
+ spin_unlock_irqrestore(&pseudo_free_list_lock, flags);
+}
+
+static eventhandler_tag free_pseudo_tag;
+
+static void
+thread_dtor_free_pseudo(void *arg, struct thread *td)
+{
+ unsigned long flags;
+ struct pseudo_free *pf, *pf_next;
+
+ spin_lock_irqsave(&pseudo_free_list_lock, flags);
+ LIST_FOREACH_SAFE(pf, &pseudo_free_list, pf_link, pf_next) {
+ if (pf->pf_thread != td)
+ continue;
+
+ LIST_REMOVE(pf, pf_link);
+ kfree(pf->pf_pseudo);
+ kfree(pf);
+ }
+ spin_unlock_irqrestore(&pseudo_free_list_lock, flags);
}
#else /* !__FreeBSD__ */
@@ -3146,7 +3191,11 @@
{
if (pseudo) {
dahdi_chan_unreg(pseudo);
+#if defined(__FreeBSD__)
+ free_pseudo(pseudo);
+#else
kfree(pseudo);
+#endif
}
}
@@ -5711,7 +5760,6 @@
int fflags = dahdi_get_flags(file->dev);
get_user(j, data);
- printf("F_SETFL: 0x%x\n", j);
/*
* XXX: On the moment we're interested only in O_NONBLOCK
@@ -9160,6 +9208,9 @@
#endif
#if defined(__FreeBSD__)
+ free_pseudo_tag = EVENTHANDLER_REGISTER(
+ thread_dtor, thread_dtor_free_pseudo, NULL, EVENTHANDLER_PRI_ANY);
+
dev_ctl = make_dev(&dahdi_devsw, 0, UID_ROOT, GID_WHEEL, 0644, "dahdi/ctl");
{
struct cdev *dev;
@@ -9202,6 +9253,18 @@
coretimer_cleanup();
#if defined(__FreeBSD__)
+ EVENTHANDLER_DEREGISTER(thread_dtor, free_pseudo_tag);
+
+ spin_lock_irqsave(&pseudo_free_list_lock, x);
+ while (!LIST_EMPTY(&pseudo_free_list)) {
+ struct pseudo_free *pf = LIST_FIRST(&pseudo_free_list);
+
+ LIST_REMOVE(pf, pf_link);
+ kfree(pf->pf_pseudo);
+ kfree(pf);
+ }
+ spin_unlock_irqrestore(&pseudo_free_list_lock, x);
+
if (dev_ctl != NULL) {
destroy_dev(dev_ctl);
dev_ctl = NULL;
More information about the svn-commits
mailing list