kern/77463: [PATCH] Local DoS from user-space in NFS client (uid ==
0 needed)
Wojciech A. Koszek
dunstan at freebsd.czest.pl
Sun Feb 13 12:00:55 PST 2005
>Number: 77463
>Category: kern
>Synopsis: [PATCH] Local DoS from user-space in NFS client (uid == 0 needed)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sun Feb 13 20:00:34 GMT 2005
>Closed-Date:
>Last-Modified:
>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 at 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 at 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:
>Unformatted:
More information about the freebsd-bugs
mailing list