From nobody  Mon May 25 00:23:42 1998
Received: (from nobody@localhost)
          by hub.freebsd.org (8.8.8/8.8.8) id AAA11830;
          Mon, 25 May 1998 00:23:42 -0700 (PDT)
          (envelope-from nobody)
Message-Id: <199805250723.AAA11830@hub.freebsd.org>
Date: Mon, 25 May 1998 00:23:42 -0700 (PDT)
From: ovg@nusun.jinr.ru
To: freebsd-gnats-submit@freebsd.org
Subject: bad rpc call to nfs crashes system
X-Send-Pr-Version: www-1.0

>Number:         6747
>Category:       kern
>Synopsis:       [PATCH] bad rpc call to nfs crashes system
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon May 25 00:20:00 PDT 1998
>Closed-Date:    Mon May 25 02:16:23 PDT 1998
>Last-Modified:  Mon May 25 02:17:25 PDT 1998
>Originator:     Vladimir Olshevsky
>Release:        FreeBSD 2.2.6
>Organization:
Joint Institute for Nuclear Research
>Environment:
FreeBSD nuraid.jinr.ru 2.2.6-RELEASE FreeBSD 2.2.6-RELEASE #1: 
Fri May 22 19:00:11 MSD 1998     
ovg@nuraid.jinr.ru:/usr/src/sys/compile/NURAID  i386
>Description:
Issuing an rpc call to nfs with negative procedure number
crashes system. Here is a kgdb  session:

nuraid#>gdb -k
(kgdb) symbol-file kernel.debug.3
Reading symbols from kernel.debug.3...done
(kgdb) exec-file kernel.3
(kgdb) core-file vmcore.3
IdlePTD 208000
current pcb at 1ec9ac
panic: page fault
#0  boot (howto=256) at ../../kern/kern_shutdown.c:266
266                                     dumppcb.pcb_cr3 = rcr3();
(kgdb) where
#0  boot (howto=256) at ../../kern/kern_shutdown.c:266
#1  0xf0110f92 in panic (fmt=0xf01bb3df "page fault")
    at ../../kern/kern_shutdown.c:390
#2  0xf01bbf86 in trap_fatal (frame=0xefbffd10) at ../../i386/i386/trap.c:770
#3  0xf01bba74 in trap_pfault (frame=0xefbffd10, usermode=0)
    at ../../i386/i386/trap.c:677
#4  0xf01bb717 in trap (frame={tf_es = 16, tf_ds = 16, tf_edi = -227143168,
      tf_esi = -241365248, tf_ebp = -272630364, tf_isp = -272630472, 
      tf_ebx = -241365144, tf_edx = -241365248, tf_ecx = 2, 
      tf_eax = -1995291404, tf_trapno = 12, tf_err = 0, tf_eip = -266941659, 
      tf_cs = 8, tf_eflags = 66118, tf_esp = -227143168, tf_ss = -241365248})
    at ../../i386/i386/trap.c:324
#5  0xf016cb25 in nfs_getreq (nd=0xf2761200, nfsd=0xf2537c00, has_header=1)
    at ../../nfs/nfs_socket.c:1980
#6  0xf016c8dc in nfsrv_dorec (slp=0xf2500000, nfsd=0xf2537c00, ndp=0xefbffe34)
    at ../../nfs/nfs_socket.c:1894
#7  0xf01715e6 in nfssvc_nfsd (nsd=0xefbffe8c, argp=0x1770c "", p=0xf252f600)
    at ../../nfs/nfs_syscalls.c:520
#8  0xf01710e8 in nfssvc (p=0xf252f600, uap=0xefbfff94, retval=0xefbfff84)
    at ../../nfs/nfs_syscalls.c:344
#9  0xf01bc1c3 in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi = 8, 
      tf_esi = 0, tf_ebp = -272638388, tf_isp = -272629788, tf_ebx = 1, 
      tf_edx = -272638564, tf_ecx = 0, tf_eax = 155, tf_trapno = 12, 
      tf_err = 7, tf_eip = 10805, tf_cs = 31, tf_eflags = 658, 
      tf_esp = -272638556, tf_ss = 39}) at ../../i386/i386/trap.c:918
#10 0x2a35 in ?? ()
#11 0x107e in ?? ()
(kgdb) up 5
#5  0xf016cb25 in nfs_getreq (nd=0xf2761200, nfsd=0xf2537c00, has_header=1)
    at ../../nfs/nfs_socket.c:1980
1980                    nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
(kgdb) print nd->nd_procnum
$1 = -1995291404
(kgdb) 

>How-To-Repeat:
Issue an rpc call to nfs with negative procedure 
number ... Analyze crash dump 
>Fix:
The problem is in comparison of signed variable with 
maximum procedure number in nfs_socket.c:1972 - there is no 
check on (invalid) negative value in nd->nd_procnum

To fix it, apply a following patch:
*** /sys/nfs/nfs_socket.c.orig  Wed May 14 12:19:28 1997
--- /sys/nfs/nfs_socket.c       Mon May 25 11:21:39 1998
***************
*** 1969,1977 ****
        nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
        if (nd->nd_procnum == NFSPROC_NULL)
                return (0);
!       if (nd->nd_procnum >= NFS_NPROCS ||
!               (!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
!               (!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
                nd->nd_repstat = EPROCUNAVAIL;
                nd->nd_procnum = NFSPROC_NOOP;
                return (0);
--- 1969,1977 ----
        nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
        if (nd->nd_procnum == NFSPROC_NULL)
                return (0);
!       if ((unsigned)nd->nd_procnum >= NFS_NPROCS ||
!               (!nqnfs && (unsigned)nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
!               (!nd->nd_flag && (unsigned)nd->nd_procnum > NFSV2PROC_STATFS)) {
                nd->nd_repstat = EPROCUNAVAIL;
                nd->nd_procnum = NFSPROC_NOOP;
                return (0);

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: phk 
State-Changed-When: Mon May 25 00:28:31 PDT 1998 
State-Changed-Why:  
awaiting committer 
State-Changed-From-To: suspended->analyzed 
State-Changed-By: dg 
State-Changed-When: Mon May 25 01:44:30 PDT 1998 
State-Changed-Why:  
Thanks for the bug report. A better fix is to change the type of 
nd_procnum to unsigned. I'll commit the fix shortly. 
State-Changed-From-To: analyzed->closed 
State-Changed-By: dg 
State-Changed-When: Mon May 25 02:16:23 PDT 1998 
State-Changed-Why:  
Fixed in rev 1.18.2.5 of nfs.h. 
>Unformatted:
