kern/156177: [patch] linuxulator + fdescfs panic

Vladislav Movchan vladislav.movchan at gmail.com
Mon Apr 4 14:50:09 UTC 2011


>Number:         156177
>Category:       kern
>Synopsis:       [patch] linuxulator + fdescfs 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:   Mon Apr 04 14:50:08 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     Vladislav Movchan
>Release:        FreeBSD 9.0-CURRENT r220318 amd64
>Organization:
>Environment:
FreeBSD ground 9.0-CURRENT FreeBSD 9.0-CURRENT #0 r220318M: Mon Apr  4 12:27:48 EEST 2011     user at ground:/usr/obj/usr/src/sys/Mephistophelis  amd64
>Description:
It is possible to cause kernel panic by reading content of fdescfs from linuxulator:
mount -t fdescfs null /dev/fd
/compat/linux/bin/ls /dev/fd

Panic is:
panic: fdesc_readdir: not hungry
cpuid = 1
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
kdb_backtrace() at kdb_backtrace+0x37
panic() at panic+0x183
fdesc_readdir() at fdesc_readdir+0x2b1
VOP_READDIR_APV() at VOP_READDIR_APV+0x4a
getdents_common() at getdents_common+0x3bc
syscallenter() at syscallenter+0x331
ia32_syscall() at ia32_syscall+0x4b
Xint0x80_syscall() at Xint0x80_syscall+0x8e
--- syscall (220, Linux ELF32, linux_getdents64), rip = 0x2815aa1d, rsp = 0xffffc840, rbp = 0xffffc84c ---
KDB: enter: panic

0xfffffe0007cca5a0: tag fdescfs, type VDIR
    usecount 2, writecount 0, refcount 2 mountedhere 0
    flags (VV_ROOT)
    lock type fdescfs: EXCL by thread 0xfffffe01095428c0 (pid 3102)
Physical memory: 6108 MB
Dumping 707 MB: 692 676 660 644 628 612 596 580 564 548 532 516 500 484 468 452 436 420 404 388 372 356 340 324 308 292 276 260 244 228 212 196 180 164 148 132 116 100 84 68 52 36 20 4

Reading symbols from /boot/kernel/zfs.ko...Reading symbols from /boot/kernel/zfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/zfs.ko
Reading symbols from /boot/kernel/opensolaris.ko...Reading symbols from /boot/kernel/opensolaris.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/opensolaris.ko
Reading symbols from /boot/kernel/geom_mirror.ko...Reading symbols from /boot/kernel/geom_mirror.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/geom_mirror.ko
Reading symbols from /boot/kernel/linux.ko...Reading symbols from /boot/kernel/linux.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/linux.ko
Reading symbols from /boot/kernel/snd_emu10kx.ko...Reading symbols from /boot/kernel/snd_emu10kx.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/snd_emu10kx.ko
Reading symbols from /boot/kernel/sound.ko...Reading symbols from /boot/kernel/sound.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/sound.ko
Reading symbols from /boot/kernel/ahci.ko...Reading symbols from /boot/kernel/ahci.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/ahci.ko
Reading symbols from /boot/modules/nvidia.ko...done.
Loaded symbols for /boot/modules/nvidia.ko
Reading symbols from /boot/modules/vboxdrv.ko...done.
Loaded symbols for /boot/modules/vboxdrv.ko
Reading symbols from /boot/kernel/dtraceall.ko...Reading symbols from /boot/kernel/dtraceall.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/dtraceall.ko
Reading symbols from /boot/kernel/cyclic.ko...Reading symbols from /boot/kernel/cyclic.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/cyclic.ko
Reading symbols from /boot/kernel/dtrace.ko...Reading symbols from /boot/kernel/dtrace.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/dtrace.ko
Reading symbols from /boot/kernel/dtmalloc.ko...Reading symbols from /boot/kernel/dtmalloc.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/dtmalloc.ko
Reading symbols from /boot/kernel/dtnfsclient.ko...Reading symbols from /boot/kernel/dtnfsclient.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/dtnfsclient.ko
Reading symbols from /boot/kernel/fbt.ko...Reading symbols from /boot/kernel/fbt.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/fbt.ko
Reading symbols from /boot/kernel/fasttrap.ko...Reading symbols from /boot/kernel/fasttrap.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/fasttrap.ko
Reading symbols from /boot/kernel/lockstat.ko...Reading symbols from /boot/kernel/lockstat.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/lockstat.ko
Reading symbols from /boot/kernel/sdt.ko...Reading symbols from /boot/kernel/sdt.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/sdt.ko
Reading symbols from /boot/kernel/systrace.ko...Reading symbols from /boot/kernel/systrace.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/systrace.ko
Reading symbols from /boot/kernel/systrace_freebsd32.ko...Reading symbols from /boot/kernel/systrace_freebsd32.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/systrace_freebsd32.ko
Reading symbols from /boot/kernel/profile.ko...Reading symbols from /boot/kernel/profile.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/profile.ko
Reading symbols from /boot/kernel/ntfs_iconv.ko...Reading symbols from /boot/kernel/ntfs_iconv.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/ntfs_iconv.ko
Reading symbols from /boot/kernel/libiconv.ko...Reading symbols from /boot/kernel/libiconv.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/libiconv.ko
Reading symbols from /boot/kernel/ntfs.ko...Reading symbols from /boot/kernel/ntfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/ntfs.ko
Reading symbols from /boot/kernel/msdosfs_iconv.ko...Reading symbols from /boot/kernel/msdosfs_iconv.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/msdosfs_iconv.ko
Reading symbols from /boot/kernel/linprocfs.ko...Reading symbols from /boot/kernel/linprocfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/linprocfs.ko
Reading symbols from /boot/kernel/fdescfs.ko...Reading symbols from /boot/kernel/fdescfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/fdescfs.ko
Reading symbols from /boot/modules/vboxnetflt.ko...done.
Loaded symbols for /boot/modules/vboxnetflt.ko
Reading symbols from /boot/kernel/netgraph.ko...Reading symbols from /boot/kernel/netgraph.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/netgraph.ko
Reading symbols from /boot/kernel/ng_ether.ko...Reading symbols from /boot/kernel/ng_ether.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/ng_ether.ko
Reading symbols from /boot/modules/vboxnetadp.ko...done.
Loaded symbols for /boot/modules/vboxnetadp.ko
#0  doadump () at /usr/src/sys/kern/kern_shutdown.c:250
250             if (textdump_pending)
(kgdb) #0  doadump () at /usr/src/sys/kern/kern_shutdown.c:250
#1  0xffffffff802f508c in db_fncall (dummy1=Variable "dummy1" is not available.
)
    at /usr/src/sys/ddb/db_command.c:548
#2  0xffffffff802f533d in db_command (last_cmdp=0xffffffff80d78a40, cmd_table=Variable "cmd_table" is not available.

) at /usr/src/sys/ddb/db_command.c:445
#3  0xffffffff802f99d3 in db_script_exec (
    scriptname=0xffffff81a99a1340 "kdb.enter.panic", warnifnotfound=0)
    at /usr/src/sys/ddb/db_script.c:302
#4  0xffffffff802f9aa2 in db_script_kdbenter (eventname=Variable "eventname" is not available.
)
    at /usr/src/sys/ddb/db_script.c:324
#5  0xffffffff802f764f in db_trap (type=Variable "type" is not available.
) at /usr/src/sys/ddb/db_main.c:228
#6  0xffffffff8064da01 in kdb_trap (type=3, code=0, tf=0xffffff81a99a1620)
    at /usr/src/sys/kern/subr_kdb.c:533
#7  0xffffffff808e7c37 in trap (frame=0xffffff81a99a1620)
    at /usr/src/sys/amd64/amd64/trap.c:588
#8  0xffffffff808d2453 in calltrap ()
    at /usr/src/sys/amd64/amd64/exception.S:228
#9  0xffffffff8064d85b in kdb_enter (why=0xffffffff809c978c "panic", 
    msg=0xa <Address 0xa out of bounds>) at cpufunc.h:63
#10 0xffffffff80616b3c in panic (fmt=Variable "fmt" is not available.
)
    at /usr/src/sys/kern/kern_shutdown.c:574
#11 0xffffffff8242ec01 in fdesc_readdir (ap=Variable "ap" is not available.
)
    at /usr/src/sys/modules/fdescfs/../../fs/fdescfs/fdesc_vnops.c:508
#12 0xffffffff8093963a in VOP_READDIR_APV (vop=0xffffffff8242f320, 
    a=0xffffff81a99a1a20) at vnode_if.c:1737
#13 0xffffffff812dbfbc in getdents_common (td=0xfffffe01095428c0, 
    args=0xffffff81a99a1bc0, is64bit=1) at vnode_if.h:758
#14 0xffffffff8065b011 in syscallenter (td=0xfffffe01095428c0, 
    sa=0xffffff81a99a1bb0) at /usr/src/sys/kern/subr_trap.c:344
#15 0xffffffff8091533b in ia32_syscall (frame=0xffffff81a99a1c50)
    at /usr/src/sys/amd64/ia32/ia32_syscall.c:179
#16 0xffffffff808d299e in Xint0x80_syscall () at ia32_exception.S:73
#17 0x000000002815aa1d in ?? ()
Previous frame inner to this frame (corrupt stack?)
(kgdb) 


Panic happening because of this check in /usr/src/sys/fs/fdescfs/fdesc_vnops.c:fdesc_readdir():
..
        /*
         * We don't allow exporting fdesc mounts, and currently local
         * requests do not need cookies.
         */
        if (ap->a_ncookies)
                panic("fdesc_readdir: not hungry");
..

Looks like this comment is no longer valid (and panic is not necessary) because of requests from linuxulator in linux_file.c:getdents_common():
..
if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)))
..

are always come with "&ncookies" pointed to real address (not NULL), so "if (ap->a_ncookies)" check in fdesc_readdir() is always true and leads to panic.


Similar problem was discussed in kern/88249 related to devfs + linuxulator panic.


I see two ways how it is possible to fix this problem. 

First is using patch from kern/88249 adopted for fdescfs:
Index: /usr/src/sys/fs/fdescfs/fdesc_vnops.c
===================================================================
--- /usr/src/sys/fs/fdescfs/fdesc_vnops.c       (revision 220323)
+++ /usr/src/sys/fs/fdescfs/fdesc_vnops.c       (working copy)
@@ -499,21 +499,33 @@
        struct dirent d;
        struct dirent *dp = &d;
        int error, i, off, fcnt;
+       int *tmp_ncookies = NULL;
 
        /*
-        * We don't allow exporting fdesc mounts, and currently local
-        * requests do not need cookies.
+        * XXX: This is a temporary hack to get around this filesystem not
+        * supporting cookies. We store the location of the ncookies pointer
+        * in a temporary variable and set the number of cookies to 0.
+        * We then set the pointer to NULL so none of VFS functions will try
+        * to do any manipulations with cookies. Later in this function, we
+        * restore the ap->a_ncookies pointer to its original location before
+        * returning to the caller.
         */
-       if (ap->a_ncookies)
-               panic("fdesc_readdir: not hungry");
+       if (ap->a_ncookies != NULL) {
+               tmp_ncookies = ap->a_ncookies;
+               *ap->a_ncookies = 0;
+               ap->a_ncookies = NULL;
+       }
 
        if (VTOFDESC(ap->a_vp)->fd_type != Froot)
                panic("fdesc_readdir: not dir");
 
        off = (int)uio->uio_offset;
        if (off != uio->uio_offset || off < 0 || (u_int)off % UIO_MX != 0 ||
-           uio->uio_resid < UIO_MX)
+           uio->uio_resid < UIO_MX) {
+               if (tmp_ncookies != NULL)
+                   ap->a_ncookies = tmp_ncookies;
                return (EINVAL);
+       }
        i = (u_int)off / UIO_MX;
        fdp = uio->uio_td->td_proc->p_fd;
        error = 0;
@@ -559,6 +571,12 @@
 
 done:
        uio->uio_offset = i * UIO_MX;
+       /*
+        * Restore ap->a_ncookies if it wasn't originally NULL in the first
+        * place.
+        */
+       if (tmp_ncookies != NULL)
+               ap->a_ncookies = tmp_ncookies;
        return (error);
 }

After closer look on fdesc_vnops.c:fdesc_readdir() it seems like all this saving a_ncookies into temporary variable, resetting and later restoring it to original state is not necessary because in body of fdesc_readdir() there is no any manipulations with ap structure pointer that may depend on value of ap->a_ncookies. So alternative patch is much smaller (but first one is "safer"):
Index: /usr/src/sys/fs/fdescfs/fdesc_vnops.c
===================================================================
--- /usr/src/sys/fs/fdescfs/fdesc_vnops.c       (revision 220323)
+++ /usr/src/sys/fs/fdescfs/fdesc_vnops.c       (working copy)
@@ -500,13 +500,6 @@
        struct dirent *dp = &d;
        int error, i, off, fcnt;
 
-       /*
-        * We don't allow exporting fdesc mounts, and currently local
-        * requests do not need cookies.
-        */
-       if (ap->a_ncookies)
-               panic("fdesc_readdir: not hungry");
-
        if (VTOFDESC(ap->a_vp)->fd_type != Froot)
                panic("fdesc_readdir: not dir");
 


And few words about importance of this problem:
I think finding solution for this problem is quite important because I've seen this panic caused by flash player (nspluginwrapper + linux-f10-flashplugin) several times:
db:0:kdb.enter.panic>  show pcpu
cpuid        = 1
dynamic pcpu = 0xffffff807f2a4c00
curthread    = 0xfffffe0115f5c8c0: pid 3384 "npviewer.bin"
curpcb       = 0xffffff81a9ebdd10
fpcurthread  = none
idlethread   = 0xfffffe0003ea1460: tid 100003 "idle: cpu1"
curpmap      = 0xfffffe00405a08d8
tssp         = 0xffffffff80df01c8
commontssp   = 0xffffffff80df01c8
rsp0         = 0xffffff81a9ebdd10
gs32p        = 0xffffffff80def020
ldt          = 0xffffffff80def060
tss          = 0xffffffff80def050
db:0:kdb.enter.panic>  trace
Tracing pid 3384 tid 100510 td 0xfffffe0115f5c8c0
kdb_enter() at kdb_enter+0x3b
panic() at panic+0x17c
fdesc_readdir() at fdesc_readdir+0x2b1
VOP_READDIR_APV() at VOP_READDIR_APV+0x4a
getdents_common() at getdents_common+0x3bc
syscallenter() at syscallenter+0x331
ia32_syscall() at ia32_syscall+0x4b
Xint0x80_syscall() at Xint0x80_syscall+0x8e
--- syscall (220, Linux ELF32, linux_getdents64), rip = 0x28858a1d, rsp = 0x3f3f99b0, rbp = 0x3f3f99bc ---
db:0:kdb.enter.panic>  ps
  pid  ppid  pgrp   uid   state   wmesg         wchan        cmd
 3384  3383  3165  1002  R       CPU 1                       npviewer.bin
 3383  3339  3165  1002  S       piperd   0xfffffe01894ac888 npviewer.bin
 3382  3339  3165  1002  S       select   0xfffffe0189d76040 npviewer.bin
 3381  3339  3165  1002  S       select   0xfffffe0132621340 npviewer.bin
 3380  3339  3165  1002  S       nanslp   0xffffffff80d9d848 npviewer.bin
 3379  3339  3165  1002  S       futex    0xfffffe01895d1700 npviewer.bin
 3376  3339  3165  1002  S       futex    0xfffffe01895d2a00 npviewer.bin
 3375  3339  3165  1002  S       futex    0xfffffe01898562c0 npviewer.bin
 3374  3339  3165  1002  S       futex    0xfffffe0189e1d800 npviewer.bin
 3366  3339  3165  1002  S       select   0xfffffe0189989d40 npviewer.bin
 3362     1  3148  1002  S       select   0xfffffe0132c7fdc0 initial thread
 3360     1  3358  1002  S       select   0xfffffe0132c7fb40 nepomukserver
..


If any other information is necessary from my side - please let me know - I'll try to provide as much info as I have.
>How-To-Repeat:
mount -t fdescfs null /dev/fd
/compat/linux/bin/ls /dev/fd

(second command could be executed by unprivileged user)
>Fix:
Using any of two patches mentioned above fixed this problem for me.

Looks like there is no way ta attach more than one file via web form, so 
first patch is available here: http://pastebin.com/raw.php?i=G8KwAK4W
second one is here: http://pastebin.com/raw.php?i=XwRfSFjp

>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list