Subject: Re: NFS misbehaviour with Linux server
To: Jason Thorpe <thorpej@shagadelic.org>
From: Matthias Drochner <M.Drochner@fz-juelich.de>
List: tech-net
Date: 09/28/2006 20:16:21
This is a multipart MIME message.

--==_Exmh_71246116125570
Content-Type: text/plain; charset=us-ascii


thorpej@shagadelic.org said:
> This sounds like a bug in the Linux NFS server to me. 

To me too... But this is caused by an obviously intentional and
even commented piece of code (see fs/nfsd/vfs.c:nfsd_vfs_write()).
I don't have any hope that this will be fixed in Linux, and while
I could fix the kernel on our server, this would get lost when
someone else (or myself after having forgot about the issue) installs
a kernel update.
A workaround on the NetBSD side is easy: just flush the file before
the SETATTR call, see the appended patch. (Actually, it would probably
not hurt to flush regular files before every SETATTR to simplify the code.)

Just to share what I've found out wrt write() vs. suid bits:
SUSv3 says that the system _may_ delete suid flags on writes. OSF/1
deletes them always. NetBSD keeps them if the write() is done by
root and deletes otherwise. (This is hardwired in the ufs code,
w/o consulting the secmodel stuff btw.) In any case this should be a
local policy thing and not forced to NFS clients, that's why I think
that Linux is wrong.

best regards
Matthias



--==_Exmh_71246116125570
Content-Type: text/plain ; name="chmod.txt"; charset=us-ascii
Content-Description: chmod.txt
Content-Disposition: attachment; filename="chmod.txt"

Index: nfs_vnops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vnops.c,v
retrieving revision 1.241
diff -u -p -r1.241 nfs_vnops.c
--- nfs_vnops.c	23 Jul 2006 22:06:14 -0000	1.241
+++ nfs_vnops.c	28 Sep 2006 17:47:32 -0000
@@ -701,7 +701,8 @@ nfs_setattr(v)
  			np->n_vattr->va_size = vap->va_size;
   		}
   	} else if ((vap->va_mtime.tv_sec != VNOVAL ||
-		vap->va_atime.tv_sec != VNOVAL) &&
+		vap->va_atime.tv_sec != VNOVAL ||
+		vap->va_mode != VNOVAL) &&
 		vp->v_type == VREG &&
   		(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
 		 ap->a_l, 1)) == EINTR)

--==_Exmh_71246116125570--