[17] in linux-net channel archive

home help back first fref pref prev next nref lref last post

Re: old mount ??? bug in nfs ???? bug in new kernel ????? FEATURE ????

daemon@ATHENA.MIT.EDU (Swen Thuemmler)
Wed Jan 11 03:48:28 1995

Date: Tue, 10 Jan 1995 14:36:17 +0100 (MET)
From: Swen Thuemmler <swen@uni-paderborn.de>
To: Linux Activists <linux-activists@niksula.hut.fi>
Cc: Linux Net <linux-net@vger.rutgers.edu>
In-Reply-To: <94Dec27.202944eet.59428-3@niksula.hut.fi>
Resent-From: Swen Thuemmler <swen@uni-paderborn.de>
Resent-To: linux-net@vger.rutgers.edu

X-Mn-Key: NET
On Tue, 27 Dec 1994, Matthias Urlichs wrote:

> In linux.act.net, article <niksula-net-digest-941120-0829.2@fidogate.nuars.nwu.edu>,
>   Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI> writes:
> > 
> > The reason this won't go in is that I don't consider it a bug in the
> > kernel at all: I consider it a problem of the mount binary and/or the
> > NFS protocol.  The current kernel does the right thing: it accepts nfs
> > packets only from the host we mounted, and these patches essentially
> > make it accept them from any machine. 
> > 
> Actually, it's a problem with the NFS server.
> 
> The server should use one (bound) listener socket per local address instead
> of one global (unbound) socket, and send replies back to the socket a
> request came in from. That way, packets will be addressed correctly and
> Linux clients will work.
> 
> Its current behavior causes NFS replies to have the source address of the
> interface it gets sent to, not the address where the reply is addressed to.
> This is a bug.

Problem is, our servers run SunOS 4.1.3 and SunOS 5.3. No easy way of 
fixing :(

> > I don't consider it a good idea to "solve" the problem by just accepting
> > NFS replies from any address.. 
> > 
> True.

Well, here are some new patches, which should partially solve this 
problem. The client inspects the source address of the first NFS packet 
from server and then connect()s to this address. From then on, it should 
only receive packets from this address. 

Question: should the client still send its requests to the old address or 
should it send them to the new one (like in my patches)?

I think, this behaviour should be secure enough, given all the other 
security problems with NFS.

Comments?

--Swen

diff -u -r linux.orig/fs/nfs/inode.c linux/fs/nfs/inode.c
--- linux.orig/fs/nfs/inode.c	Sat Jan  7 11:57:54 1995
+++ linux/fs/nfs/inode.c	Mon Jan  9 15:00:05 1995
@@ -128,6 +128,8 @@
 	server->acdirmin = data->acdirmin*HZ;
 	server->acdirmax = data->acdirmax*HZ;
 	strcpy(server->hostname, data->hostname);
+	memcpy(&server->addr, &data->addr, sizeof(struct sockaddr_in));
+	server->connected = 0;
 	sb->u.nfs_sb.s_root = data->root;
 	unlock_super(sb);
 	if (!(sb->s_mounted = nfs_fhget(sb, &data->root, NULL))) {
diff -u -r linux.orig/fs/nfs/sock.c linux/fs/nfs/sock.c
--- linux.orig/fs/nfs/sock.c	Thu Jan  5 12:55:40 1995
+++ linux/fs/nfs/sock.c	Mon Jan  9 16:33:59 1995
@@ -101,7 +101,7 @@
 	fs = get_fs();
 	set_fs(get_ds());
 	for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
-		result = sock->ops->send(sock, (void *) start, len, 0, 0);
+		result = sock->ops->sendto(sock, (void *) start, len, 0, 0, (struct sockaddr *)&server->addr, sizeof(server->addr));
 		if (result < 0) {
 			printk("nfs_rpc_call: send error = %d\n", result);
 			break;
@@ -161,7 +161,7 @@
 		 * we don't now need, so discard it */
 		result = sock->ops->recvfrom(sock, (void *)&recv_xid,
 					     sizeof(recv_xid), 1, MSG_PEEK,
-					     NULL, &addrlen);
+					     NULL, NULL);
 		if (result < 0) {
 			if (result == -EAGAIN) {
 #if 0
@@ -192,7 +192,7 @@
 		 * a null buffer yet. */
 		(void)sock->ops->recvfrom(sock, (void *)&recv_xid,
 					  sizeof(recv_xid), 1, 0, NULL,
-					  &addrlen);
+					  NULL);
 #if 0
 		printk("nfs_rpc_call: XID mismatch\n");
 #endif
@@ -205,7 +205,7 @@
 	 *
 	 */
 	result=sock->ops->recvfrom(sock, (void *)start, 
-				  size + 1024, 1, 0, NULL,
+				  size + 1024, 1, 0, (struct sockaddr *)&server->addr,
 			/* Here is NFS_SLACK_SPACE..., hack */
 				  &addrlen);
 	if (result < 0) {
@@ -215,6 +215,11 @@
 		printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
 		result = -EIO;
 	}
+	if (1 != server->connected) {
+		if (0 == sock->ops->connect(sock, (struct sockaddr *)&server->addr, addrlen, 0))
+			server->connected = 1;
+	}
+
 	current->blocked = old_mask;
 	set_fs(fs);
 	return result;
diff -u -r linux.orig/include/linux/nfs_fs_sb.h linux/include/linux/nfs_fs_sb.h
--- linux.orig/include/linux/nfs_fs_sb.h	Wed Dec  1 13:44:15 1993
+++ linux/include/linux/nfs_fs_sb.h	Mon Jan  9 14:59:19 1995
@@ -2,6 +2,7 @@
 #define _NFS_FS_SB
 
 #include <linux/nfs.h>
+#include <linux/in.h>
 
 struct nfs_server {
 	struct file *file;
@@ -17,6 +18,8 @@
 	int acdirmin;
 	int acdirmax;
 	char hostname[256];
+	struct sockaddr_in addr;
+	int connected ;
 };
 
 /*



home help back first fref pref prev next nref lref last post