Skip to contentSkip to conversation

Introduction

PATCH New NeilBrown 3 participants 11 messages Oct 14, 2005

Subsystems (2)
lore
Share & tools
lore

NeilBrown

author
#0 lore raw

PATCH 1/1 Introduction

4 patches for kNFSd in 2.6

I might have sent the first one already, so if it conflicts, just drop it.

Patch '3' should replace
knfsd-allowing-rpcnfsd-to-setting-of-the-port-transport-and-version-the-server-will-use.patch
which contains some elements that are still under discussion.

Thanks,
NeilBrown

[PATCH kNFSd 001 of 4] fix setattr-on-symlink error return
[PATCH kNFSd 002 of 4] Restore functionality to read from file in /proc/fs/nfsd/ [PATCH kNFSd 003 of 4] Allow run-time selection of NFS versions to export [PATCH kNFSd 004 of 4] Fix some minor sign problems in nfsd/xdr

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#1 lore raw

PATCH 1/1 fix setattr-on-symlink error return

This is a somewhat cosmetic fix to keep the SpecFS validation test from complaining.
SpecFS want's to try chmod on symlinks, and ext3 and reiser (at least) return ENOTSUPP.
Probably both sides are being silly, but it is easiest to simply make it a non-issue and filter out chmod requests on symlinks at the nfsd level.

### Diffstat output

 ./fs/nfsd/vfs.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c renamed from fs/nfsd/vfs.c~current~ +8 -1
diff ./fs/nfsd/vfs.c~current~ ./fs/nfsd/vfs.c
@@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, str
 
 	/* Get inode */
 	err = fh_verify(rqstp, fhp, ftype, accmode);
-	if (err || !iap->ia_valid)
+	if (err)
 		goto out;
 
 	dentry = fhp->fh_dentry;
 	inode = dentry->d_inode;
 
+	/* Ignore any mode updates on symlinks */
+	if (S_ISLNK(inode->i_mode))
+		iap->ia_valid &= ~ATTR_MODE;
+
+	if (!iap->ia_valid)
+		goto out;
+
 	/* NFSv2 does not differentiate between "set-[ac]time-to-now"
 	 * which only requires access, and "set-[ac]time-to-X" which
 	 * requires ownership.

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#2 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

Quoted 7 lines · NeilBrown

This is a somewhat cosmetic fix to keep the SpecFS validation test from complaining.
SpecFS want's to try chmod on symlinks, and ext3 and reiser (at least) return ENOTSUPP.
Probably both sides are being silly, but it is easiest to simply make it a non-issue and filter out chmod requests on symlinks at the nfsd level.

Wouldn't it be better to fix the testsuite to not do this? Doesn't the testsuite also fail when run against ext3 and/or reiser file systems?

This is just overhead which will slow the NFS server a tiny bit.

Just out of curiosity, how does the testsuite even generate a chmod(2) request on a symbolic link? The chmod(2) system call semantics should not allow this.

Thanx...

ps

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#3 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

As I recall, the SpecFS tests exercise the NFS protocols directly, rather than through the filesystem interface provided by the client OS.

Quoted 4 lines · Peter Staubach

Just out of curiosity, how does the testsuite even generate a chmod(2) request on a symbolic link? The chmod(2) system call semantics should not allow this.

Signature · 13 lines
[email protected]
650 933 3124

Let's get ta jigglin'!


-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
#4 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

Quoted 11 lines · James Yarbrough

As I recall, the SpecFS tests exercise the NFS protocols directly, rather than through the filesystem interface provided by the client OS.

Quoted 5 lines · Peter Staubach

Just out of curiosity, how does the testsuite even generate a chmod(2) request on a symbolic link? The chmod(2) system call semantics should not allow this.

Are we talking about the SPEC SFS benchmark or something else?

Thanx...

ps

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#5 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

I thought we were talking about Spec SFS.
I could be confused, though.

Signature · 13 lines
[email protected]
650 933 3124

Let's get ta jigglin'!


-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
#6 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

Quoted 3 lines · James Yarbrough

I thought we were talking about Spec SFS.
I could be confused, though.

I assumed that "SpecFS" was something different than "SPEC SFS". I know that I am confused. :-)

ps

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

#7 lore raw

Re: [PATCH kNFSd 001 of 4] fix setattr-on-symlink error return

Quoted 4 lines · Peter Staubach

I assumed that "SpecFS" was something different than "SPEC SFS". I know that I am confused. :-)

I thought it was just a typo.
It seems that King Crimson was correct: "Confusion will be my epitaph"

Signature · 13 lines
[email protected]
650 933 3124

Let's get ta jigglin'!


-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist  -  [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs
author
#8 lore raw

PATCH 1/1 Allow run-time selection of NFS versions to export

In reply to NeilBrown

Provide a file in the NFSD filesystem that allows setting and querying of which version of NFS are being exported. Changes are only allowed while no server is running.

### Diffstat output

 ./fs/nfsd/nfsctl.c             |   70 ++++++++++++++++++++++++++++++++++++
 ./fs/nfsd/nfssvc.c             |   79 ++++++++++++++++++++++++++---------------
 ./include/linux/nfsd/nfsd.h    |    2 -
 ./include/linux/nfsd/syscall.h |   17 ++++++++
 4 files changed, 139 insertions(+), 29 deletions(-)
fs/nfsd/nfsctl.c renamed from fs/nfsd/nfsctl.c~current~ +70 -0
diff ./fs/nfsd/nfsctl.c~current~ ./fs/nfsd/nfsctl.c
@@ -23,6 +23,7 @@
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/string.h>
 
 #include <linux/nfs.h>
 #include <linux/nfsd_idmap.h>
@@ -35,6 +36,8 @@
 
 #include <asm/uaccess.h>
 
+unsigned int nfsd_versbits = ~0;
+
 /*
  *	We have a single directory with 9 nodes in it.
  */
@@ -51,6 +54,7 @@ enum {
 	NFSD_Fh,
 	NFSD_Threads,
 	NFSD_Leasetime,
+	NFSD_Versions,
 	NFSD_RecoveryDir,
 };
 
@@ -67,6 +71,7 @@ static ssize_t write_getfs(struct file *
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_threads(struct file *file, char *buf, size_t size);
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+static ssize_t write_versions(struct file *file, char *buf, size_t size);
 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
@@ -80,6 +85,7 @@ static ssize_t (*write_op[])(struct file
 	[NFSD_Fh] = write_filehandle,
 	[NFSD_Threads] = write_threads,
 	[NFSD_Leasetime] = write_leasetime,
+	[NFSD_Versions] = write_versions,
 	[NFSD_RecoveryDir] = write_recoverydir,
 };
 
@@ -343,6 +349,69 @@ static ssize_t write_threads(struct file
 	return strlen(buf);
 }
 
+static ssize_t write_versions(struct file *file, char *buf, size_t size)
+{
+	/*
+	 * Format:
+	 *   [-/+]vers [-/+]vers ...
+	 */
+	char *mesg = buf;
+	char *vers, sign;
+	int len, num;
+	ssize_t tlen = 0;
+	char *sep;
+
+	if (size>0) {
+		if (nfsd_serv)
+			return -EBUSY;
+		if (buf[size-1] != '\n')
+			return -EINVAL;
+		buf[size-1] = 0;
+
+		vers = mesg;
+		len = qword_get(&mesg, vers, size);
+		if (len <= 0) return -EINVAL;
+		do {
+			sign = *vers;
+			if (sign == '+' || sign == '-')
+				num = simple_strtol((vers+1), NULL, 0);
+			else
+				num = simple_strtol(vers, NULL, 0);
+			switch(num) {
+			case 2:
+			case 3:
+			case 4:
+				if (sign != '-')
+					NFSCTL_VERSET(nfsd_versbits, num);
+				else
+					NFSCTL_VERUNSET(nfsd_versbits, num);
+				break;
+			default:
+				return -EINVAL;
+			}
+			vers += len + 1;
+			tlen += len;
+		} while ((len = qword_get(&mesg, vers, size)) > 0);
+		/* If all get turned off, turn them back on, as
+		 * having no versions is BAD
+		 */
+		if ((nfsd_versbits & NFSCTL_VERALL)==0)
+			nfsd_versbits = NFSCTL_VERALL;
+	}
+	/* Now write current state into reply buffer */
+	len = 0;
+	sep = "";
+	for (num=2 ; num <= 4 ; num++)
+		if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
+			len += sprintf(buf+len, "%s%c%d", sep,
+				       NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
+				       num);
+			sep = " ";
+		}
+	len += sprintf(buf+len, "\n");
+	return len;
+}
+
 extern time_t nfs4_leasetime(void);
 
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
@@ -407,6 +476,7 @@ static int nfsd_fill_super(struct super_
 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
 		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
 #endif
+		[NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
 		/* last one */ {""}
 	};
 	return simple_fill_super(sb, 0x6e667364, nfsd_files);
fs/nfsd/nfssvc.c renamed from fs/nfsd/nfssvc.c~current~ +51 -28

115 lines not on this page · raw message

include/linux/nfsd/nfsd.h renamed from include/linux/nfsd/nfsd.h~current~ +1 -1
diff ./include/linux/nfsd/nfsd.h~current~ ./include/linux/nfsd/nfsd.h
@@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode
 extern struct svc_program	nfsd_program;
 extern struct svc_version	nfsd_version2, nfsd_version3,
 				nfsd_version4;
-
+extern struct svc_serv		*nfsd_serv;
 /*
  * Function prototypes.
  */
include/linux/nfsd/syscall.h renamed from include/linux/nfsd/syscall.h~current~ +17 -0
diff ./include/linux/nfsd/syscall.h~current~ ./include/linux/nfsd/syscall.h
@@ -39,6 +39,21 @@
 #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
 #define	NFSCTL_GETFS		8	/* get an fh by path with max FH len */
 
+/*
+ * Macros used to set version
+ */
+#define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |=  (1 << (_v)))
+#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
+#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
+
+#if defined(CONFIG_NFSD_V4)
+#define	NFSCTL_VERALL	(0x1c /* 0b011100 */)
+#elif defined(CONFIG_NFSD_V3)
+#define	NFSCTL_VERALL	(0x0c /* 0b001100 */)
+#else
+#define	NFSCTL_VERALL	(0x04 /* 0b000100 */)
+#endif
+
 /* SVC */
 struct nfsctl_svc {
 	unsigned short		svc_port;
@@ -120,6 +135,8 @@ extern int		exp_delclient(struct nfsctl_
 extern int		exp_export(struct nfsctl_export *nxp);
 extern int		exp_unexport(struct nfsctl_export *nxp);
 
+extern unsigned int nfsd_versbits;
+
 #endif /* __KERNEL__ */
 
 #endif /* NFSD_SYSCALL_H */

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#9 lore raw

PATCH 1/1 Fix some minor sign problems in nfsd/xdr

In reply to NeilBrown

There are a couple of tests which could possibly be confused by extremely large numbers appearing in 'xdr' packets.
I think the closest to an exploit you could get would be writing random data from a free page into a file - i.e. leak data out of kernel space.

I'm fairly sure they cannot be used for remote compromise.

### Diffstat output

 ./fs/nfsd/nfs3xdr.c          |    3 ++-
 ./include/linux/nfsd/xdr3.h  |    2 +-
 ./include/linux/sunrpc/svc.h |    3 ++-
 3 files changed, 5 insertions(+), 3 deletions(-)
fs/nfsd/nfs3xdr.c renamed from fs/nfsd/nfs3xdr.c~current~ +2 -1
diff ./fs/nfsd/nfs3xdr.c~current~ ./fs/nfsd/nfs3xdr.c
@@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst
 	len = args->len = ntohl(*p++);
 
 	hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
-	if (rqstp->rq_arg.len < len + hdr)
+	if (rqstp->rq_arg.len < hdr ||
+	    rqstp->rq_arg.len - hdr < len)
 		return 0;
 
 	args->vec[0].iov_base = (void*)p;
include/linux/nfsd/xdr3.h renamed from include/linux/nfsd/xdr3.h~current~ +1 -1
diff ./include/linux/nfsd/xdr3.h~current~ ./include/linux/nfsd/xdr3.h
@@ -42,7 +42,7 @@ struct nfsd3_writeargs {
 	__u64			offset;
 	__u32			count;
 	int			stable;
-	int			len;
+	__u32			len;
 	struct kvec		vec[RPCSVC_MAXPAGES];
 	int			vlen;
 };
include/linux/sunrpc/svc.h renamed from include/linux/sunrpc/svc.h~current~ +2 -1
diff ./include/linux/sunrpc/svc.h~current~ ./include/linux/sunrpc/svc.h
@@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp
 {
 	char *cp = (char *)p;
 	struct kvec *vec = &rqstp->rq_arg.head[0];
-	return cp - (char*)vec->iov_base <= vec->iov_len;
+	return cp >= (char*)vec->iov_base
+		&& cp <= (char*)vec->iov_base + vec->iov_len;
 }
 
 static inline int

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs

author
#10 lore raw

PATCH 1/1 Restore functionality to read from file in /proc/fs/nfsd/

In reply to NeilBrown

Most files in the nfsd filesystems are transaction files. You write a request, and read a response.
For some (e.g. 'threads') it makes sense to just be able to read and get the current value.
This functionality did exist but was broken recently when someone modified nfsctl.c without going through the maintainer. This patch fixes the regression.

### Diffstat output

 ./fs/nfsd/nfsctl.c |   16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)
fs/nfsd/nfsctl.c renamed from fs/nfsd/nfsctl.c~current~ +15 -1
diff ./fs/nfsd/nfsctl.c~current~ ./fs/nfsd/nfsctl.c
@@ -104,9 +104,23 @@ static ssize_t nfsctl_transaction_write(
 	return rv;
 }
 
+static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+	if (! file->private_data) {
+		/* An attempt to read a transaction file without writing
+		 * causes a 0-byte write so that the file can return
+		 * state information
+		 */
+		ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
+		if (rv < 0)
+			return rv;
+	}
+	return simple_transaction_read(file, buf, size, pos);
+}
+
 static struct file_operations transaction_ops = {
 	.write		= nfsctl_transaction_write,
-	.read		= simple_transaction_read,
+	.read		= nfsctl_transaction_read,
 	.release	= simple_transaction_release,
 };
 

-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions, and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
NFS maillist - [email protected]
https://lists.sourceforge.net/lists/listinfo/nfs