kern/124853: [patch] devfs_ruleset_use may use freed memory,
causing panic
Mateusz Guzik
mjguzik at gmail.com
Sat Jun 21 20:30:05 UTC 2008
>Number: 124853
>Category: kern
>Synopsis: [patch] devfs_ruleset_use may use freed memory, causing panic
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Jun 21 20:30:04 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator: Mateusz Guzik
>Release: 8.0-CURRENT
>Organization:
>Environment:
FreeBSD eternal 8.0-CURRENT FreeBSD 8.0-CURRENT #3: Sat Jun 21 21:41:16 CEST 2008 root at eternal:/usr/obj/usr/src/sys/ETERNAL i386
>Description:
Function devfs_ruleset_use follows the following algorithm:
1. Get ruleset; if it doesn't exists, create it.
2. Decrease reference count of current ruleset of dm. Call devfs_ruleset_reap to free it, if it has no references and no rules.
3. Assign ruleset from 1. to dm, increase its reference count.
Ruleset created by this function has no rules.
When user types e. g. `devfs ruleset 100', this function creates ruleset 100 for him. When he types this command again, ruleset 100 is freed due to zeroed reference count and empty rules list, then it's assigned to dm. This causes panic few minutes later.
>How-To-Repeat:
Run `devfs ruleset' twice with non-existent ruleset number, for example `devfs ruleset 100'. Wait a couple of minutes, kernel will panic saying `Most recently used by DEVFS_RULE'.
>Fix:
Patch is attached.
Patch attached with submission follows:
--- devfs_rule.c.orig 2008-06-21 21:31:48.000000000 +0200
+++ devfs_rule.c 2008-06-21 21:33:49.000000000 +0200
@@ -733,19 +733,20 @@
static int
devfs_ruleset_use(devfs_rsnum rsnum, struct devfs_mount *dm)
{
struct devfs_ruleset *cds, *ds;
- ds = devfs_ruleset_bynum(rsnum);
- if (ds == NULL)
- ds = devfs_ruleset_create(rsnum);
if (dm->dm_ruleset != 0) {
cds = devfs_ruleset_bynum(dm->dm_ruleset);
--cds->ds_refcount;
devfs_ruleset_reap(cds);
}
+ ds = devfs_ruleset_bynum(rsnum);
+ if (ds == NULL)
+ ds = devfs_ruleset_create(rsnum);
+
/* These should probably be made atomic somehow. */
++ds->ds_refcount;
dm->dm_ruleset = rsnum;
return (0);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list