kern/89784: 6.0-RELEASE panics when applying `type devtype' rule to devfs

Dmitry Marakasov amdmi3 at mail.ru
Thu Dec 1 05:30:37 GMT 2005


>Number:         89784
>Category:       kern
>Synopsis:       6.0-RELEASE panics when applying `type devtype' rule to devfs
>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 Dec 01 05:30:07 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Dmitry Marakasov
>Release:        FreeBSD 6.0-RELEASE i386
>Organization:
>Environment:
System: FreeBSD hades.panopticon 6.0-RELEASE FreeBSD 6.0-RELEASE #0: Wed Nov 23 05:48:39 MSK 2005 amdmi3 at hades.panopticon:/usr/obj/usr/src/sys/HADES i386

>Description:
When applying rules, which match device type (i.e. `rule apply type devtype'), to devfs mountpoint, kernel panic occurs.

The panic:
Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0x4
fault code              = supervisor read, page not present
instruction pointer     = 0x20:0xc04c3124
stack pointer           = 0x28:0xd0c5aaf0
frame pointer           = 0x28:0xd0c5ab04
code segment            = base 0x0, limit 0xfffff, type 0x1b
                        = DPL 0, pres 1, def32 1, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 575 (devfs)


The backtrace (I've said `panic' in ddb, so 1-11 is debugger's frames):
...
#11 0xc067067a in calltrap () at /usr/src/sys/i386/i386/exception.s:139

#12 0xc04c3124 in devfs_rule_match (dk=0xc1701e00, de=0xc1751100)
    at /usr/src/sys/fs/devfs/devfs_rule.c:544
#13 0xc04c3201 in devfs_rule_run (dk=0xc1701e00, de=0xc1751100, depth=1)
    at /usr/src/sys/fs/devfs/devfs_rule.c:586
#14 0xc04c2df7 in devfs_rule_applyde_recursive (dk=0xc1701e00, de=0xc1751100)
    at /usr/src/sys/fs/devfs/devfs_rule.c:341
#15 0xc04c2ddb in devfs_rule_applyde_recursive (dk=0xc1701e00, de=0xc18b0280)
    at /usr/src/sys/fs/devfs/devfs_rule.c:340
#16 0xc04c2e1a in devfs_rule_applydm (dk=0x0, dm=0x0) at /usr/src/sys/fs/devfs/devfs_rule.c:351
#17 0xc04c2bd2 in devfs_rules_ioctl (dm=0xc18b0300, cmd=3245350400, data=0xc1701d00 "z\b\nÛ", td=0x0)
    at /usr/src/sys/fs/devfs/devfs_rule.c:220
...


Panic happens when executing this code (devfs_rule.c:543):

if (dr->dr_icond & DRC_DSWFLAGS)
        if (dev == NULL ||
            (dev->si_devsw->d_flags & dr->dr_dswflags) == 0)
                return (0);

reading dev->si_devsw->d_flags value is the problem, because dev->si_devsw can be a null pointer sometimes (in case of symlinks and directories, as far as I understand).
In my case, that was `urandom' entry, which is a symlink and doesn't have cdevsw.

Here's what dev is in my case:

{
        si_priv = 0xc155c300,
        si_flags = 22,
        si_atime = {
        tv_sec = 0,
        tv_nsec = 0
        },
        si_ctime = {
                tv_sec = 0,
                tv_nsec = 0
        },
        si_mtime = {
                tv_sec = 0,
                tv_nsec = 0
        },
        si_uid = 0,
        si_gid = 0,
        si_mode = 0,
        si_cred = 0x0,
        si_drv0 = 0,
        si_refcount = 1,
        si_list = {
                le_next = 0x0,
                le_prev = 0x0
        },
        si_clone = {
                le_next = 0x0,
                le_prev = 0x0
        },
        si_children = {
                lh_first = 0x0
        },
        si_siblings = {
                le_next = 0x0,
                le_prev = 0xc155c448
        },
        si_parent = 0xc155c400,
        si_name = 0xc155c378 "urandom",
        si_drv1 = 0x0,
        si_drv2 = 0x0,
        si_devsw = 0x0,
        si_iosize_max = 0,
        si_usecount = 0,
        si_threadcount = 0,
        __si_u = {
                __sit_tty = 0x0,
                __sid_snapdata = 0x0
        },
        __si_namebuf = "urandom", '\0' <repeats 56 times>
}

As you can see, si_devsw is null pointer.

FreeBSD 5.4 doesn't have this bug, because devfs_rule_getdev function treated symlinks and dirs specially (devfs_rule.c, rev. 1.12, line 500). So adding the similar check should solve the problem.
	
>How-To-Repeat:
mount_devfs dev /mnt
devfs -m /mnt rule apply type disk hide
>Fix:
As a workaround, don't use `type' rules, use `path' rules instead.

Here's the patch, that adds checks for dirent against symlink or directory. I'm not actually good in devfs inner workings, so I'm not sure this patch is acceptable, but it's similar to how it was done in 5.4 and it solves the panic.

--- devfs.patch begins here ---
--- sys/fs/devfs/devfs_rule.c.orig	Mon Sep 26 18:36:52 2005
+++ sys/fs/devfs/devfs_rule.c	Wed Nov 30 06:38:21 2005
@@ -430,6 +430,9 @@
 static struct cdev *
 devfs_rule_getdev(struct devfs_dirent *de)
 {
+	if (de->de_dirent->d_type == DT_LNK ||
+		de->de_dirent->d_type == DT_DIR )
+		return (NULL);
 
 	if (de->de_cdp == NULL)
 		return (NULL);
--- devfs.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list