[17] in linux-net channel archive
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 ;
};
/*