From dunstan@freebsd.czest.pl  Sun Feb 13 19:50:32 2005
Return-Path: <dunstan@freebsd.czest.pl>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 57C5016A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 13 Feb 2005 19:50:32 +0000 (GMT)
Received: from freebsd.czest.pl (silver.iplus.pl [80.48.250.4])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 822CD43D45
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 13 Feb 2005 19:50:21 +0000 (GMT)
	(envelope-from dunstan@freebsd.czest.pl)
Received: from freebsd.czest.pl (freebsd.czest.pl [80.48.250.4])
	by freebsd.czest.pl (8.12.10/8.12.9) with ESMTP id j1DJtf9r006739
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 13 Feb 2005 19:55:41 GMT
	(envelope-from dunstan@freebsd.czest.pl)
Received: (from dunstan@localhost)
	by freebsd.czest.pl (8.12.10/8.12.9/Submit) id j1DJtf7d006738;
	Sun, 13 Feb 2005 19:55:41 GMT
	(envelope-from dunstan)
Message-Id: <200502131955.j1DJtf7d006738@freebsd.czest.pl>
Date: Sun, 13 Feb 2005 19:55:41 GMT
From: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
Reply-To: "Wojciech A. Koszek" <dunstan@freebsd.czest.pl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] Local DoS from user-space in NFS client (uid == 0 needed)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         77463
>Category:       kern
>Synopsis:       [nfs] [patch] Local DoS from user-space in NFS client (uid == 0 needed)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    cel
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 13 20:00:34 GMT 2005
>Closed-Date:    Mon May 29 20:09:57 GMT 2006
>Last-Modified:  Mon May 29 20:09:57 GMT 2006
>Originator:     Wojciech A. Koszek
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
>Environment:
System: FreeBSD dunstan.freebsd.czest.pl 5.3-STABLE FreeBSD 5.3-STABLE #0: Sat Feb 12 11:15:23 CET 2005 root@dunstan.freebsd.czest.pl:/usr/obj/usr/src/sys/HOME6 i386

Tested on:
--
kern.ostype: FreeBSD
kern.osrelease: 5.3-STABLE
kern.osrevision: 199506
kern.version: FreeBSD 5.3-STABLE #0: Sat Feb 12 11:15:23 CET 2005
   root@dunstan.freebsd.czest.pl:/usr/obj/usr/src/sys/HOME6
--
kern.ostype: FreeBSD
kern.osrelease: 6.0-CURRENT
kern.osrevision: 199506
kern.version: FreeBSD 6.0-CURRENT #2: Sat Feb 12 10:43:18 UTC 2005
    root@:/usr/obj/usr/src/sys/GENERIC
--

>Description:

There is a bug in NFS client code (/usr/src/sys/nfs4client/nfs4_dev.c,
function nfs4dev_reply(caddr_t addr)). This file is used to build nfsclient
and nfs4client. Both are vulnerable.
FreeBSD kernel panics when trying to call ioctl(fd, NFS4DEVIOCPUT, &m) where
m is pointer to nfs4dev_msg structure containg msg_len variable set to weird
values (1,2,3,...). These lengts doesn't make sense, since other data
(bigger than for example 1 byte) have to be kept in that structure. uid == 0
is needed (/dev/nfs4 has to be opened in read/write mode).

>How-To-Repeat:

Make sure your system has NFS support. Line:
[..]
options         NFSCLIENT
[..]
Should appear in your kernel config file. You may also load nfs*client
support as kernel module:

# cd /usr/src/sys/modules/nfsclient && make load

After running attached code [nfstest.c] kernel will panic:
$ gcc nfstest.c -o nfstest

Usage:
./nfstest <digit>

Example:
# ./nfstest 2

>Fix:

I've decided to limit minimal size of msg_len to sizeof(struct nfs4dev_msg) -
NFS4DEV_MSG_MAX_DATALEN (which is size of internal array placed in that
structure). Packet with smaller length doesn't make sense (we have to get
other values: msg_vers, msg_type, msg_len, but 1 byte is to small to handle
them).

--- nfstest.c begins here ---
#include <sys/param.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include </sys/nfs4client/nfs4_dev.h>

int
main (int argc, char **argv)
{
	int fd;
	int error = 0;
	struct nfs4dev_msg m;
  
	if (argc < 2) {
		fprintf(stderr, "usage number\n");
		exit(1);
	}
	
	fd = open("/dev/nfs4", O_RDWR);
	if (fd == -1)
		exit(111);

	bzero(&m ,sizeof(m));
	m.msg_vers =  NFS4DEV_VERSION;
	m.msg_type = 1; /* XXX You may change this */
	m.msg_len = atoi(*++argv);
	error = ioctl(fd, NFS4DEVIOCPUT, &m);
	if (error)
		errx(error, "ioctl!:%s\n", strerror(errno));
	
	_exit(0);
}
--- nfstest.c ends here ---

--- diff.0.nfs4client begins here ---

diff -upr /usr/src/sys/nfs4client/nfs4_dev.c src/sys/nfs4client/nfs4_dev.c
--- /usr/src/sys/nfs4client/nfs4_dev.c	Thu Nov 11 12:34:17 2004
+++ src/sys/nfs4client/nfs4_dev.c	Sun Nov 14 23:49:05 2004
@@ -152,11 +152,12 @@ nfs4dev_reply(caddr_t addr)
 		return EINVAL;
 	}
 
-	if (m->msg_len == 0 || m->msg_len > NFS4DEV_MSG_MAX_DATALEN) {
+	if (m->msg_len < sizeof(m) - NFS4DEV_MSG_MAX_DATALEN ||
+		m->msg_len > NFS4DEV_MSG_MAX_DATALEN) {
 	  	NFS4DEV_DEBUG("bad message length\n");
 		return EINVAL;
 	}
-	  	
+	
 	/* match the reply with a request */
 	mtx_lock(&nfs4dev_waitq_mtx);
 	TAILQ_FOREACH(u, &nfs4dev_waitq, up_entry) {
--- diff.0.nfs4client ends here ---


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->rees 
Responsible-Changed-By: maxim 
Responsible-Changed-When: Fri Apr 14 10:31:05 UTC 2006 
Responsible-Changed-Why:  
Jim, this PR is related to NFS4 code.  Could you please look at it? 

http://www.freebsd.org/cgi/query-pr.cgi?pr=77463 
Responsible-Changed-From-To: rees->cel 
Responsible-Changed-By: rees 
Responsible-Changed-When: Tue Apr 18 15:37:47 EDT 2006 
Responsible-Changed-Why:  
cel has agreed to fix this 

http://www.freebsd.org/cgi/query-pr.cgi?pr=77463 
State-Changed-From-To: open->closed 
State-Changed-By: cel 
State-Changed-When: Mon May 29 20:09:14 UTC 2006 
State-Changed-Why:  
Bug is now fixed in CURRENT and RELENG_6. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=77463 
>Unformatted:
