Bug 156177 - [fdescfs] [patch] linuxulator + fdescfs panic
Summary: [fdescfs] [patch] linuxulator + fdescfs panic
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 9.0-CURRENT
Hardware: Any Any
: Normal Affects Only Me
Assignee: Konstantin Belousov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-04 15:50 UTC by Vladyslav Movchan
Modified: 2011-04-16 13:50 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladyslav Movchan 2011-04-04 15:50:08 UTC
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.

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
How-To-Repeat: mount -t fdescfs null /dev/fd
/compat/linux/bin/ls /dev/fd

(second command could be executed by unprivileged user)
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2011-04-09 20:59:57 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-fs

Over to maintainer(s).
Comment 2 dfilter service freebsd_committer freebsd_triage 2011-04-09 22:40:58 UTC
Author: kib
Date: Sat Apr  9 21:40:48 2011
New Revision: 220506
URL: http://svn.freebsd.org/changeset/base/220506

Log:
  Linuxolator calls VOP_READDIR with ncookies pointer. Implement a
  workaround for fdescfs to not panic when ncookies is not NULL, similar
  to the one committed as r152254, but simpler, due to fdescfs_readdir()
  not calling vfs_read_dirent().
  
  PR:	kern/156177
  MFC after:	1 week

Modified:
  head/sys/fs/fdescfs/fdesc_vnops.c

Modified: head/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- head/sys/fs/fdescfs/fdesc_vnops.c	Sat Apr  9 19:07:44 2011	(r220505)
+++ head/sys/fs/fdescfs/fdesc_vnops.c	Sat Apr  9 21:40:48 2011	(r220506)
@@ -500,16 +500,12 @@ fdesc_readdir(ap)
 	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");
 
+	if (ap->a_ncookies != NULL)
+		*ap->a_ncookies = 0;
+
 	off = (int)uio->uio_offset;
 	if (off != uio->uio_offset || off < 0 || (u_int)off % UIO_MX != 0 ||
 	    uio->uio_resid < UIO_MX)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 3 Konstantin Belousov freebsd_committer freebsd_triage 2011-04-09 22:47:15 UTC
State Changed
From-To: open->patched

Patched in HEAD. 


Comment 4 Konstantin Belousov freebsd_committer freebsd_triage 2011-04-09 22:47:15 UTC
Responsible Changed
From-To: freebsd-fs->kib

Patched in HEAD.
Comment 5 dfilter service freebsd_committer freebsd_triage 2011-04-16 13:45:22 UTC
Author: kib
Date: Sat Apr 16 12:45:09 2011
New Revision: 220717
URL: http://svn.freebsd.org/changeset/base/220717

Log:
  MFC r220506:
  Implement a workaround for fdescfs to not panic when ncookies is not NULL.
  
  PR:	kern/156177

Modified:
  stable/8/sys/fs/fdescfs/fdesc_vnops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- stable/8/sys/fs/fdescfs/fdesc_vnops.c	Sat Apr 16 12:43:04 2011	(r220716)
+++ stable/8/sys/fs/fdescfs/fdesc_vnops.c	Sat Apr 16 12:45:09 2011	(r220717)
@@ -500,16 +500,12 @@ fdesc_readdir(ap)
 	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");
 
+	if (ap->a_ncookies != NULL)
+		*ap->a_ncookies = 0;
+
 	off = (int)uio->uio_offset;
 	if (off != uio->uio_offset || off < 0 || (u_int)off % UIO_MX != 0 ||
 	    uio->uio_resid < UIO_MX)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 6 Konstantin Belousov freebsd_committer freebsd_triage 2011-04-16 13:45:57 UTC
State Changed
From-To: patched->closed

Merged to 8.