summaryrefslogtreecommitdiffstats
path: root/linux-2.6-nfsd4-proots.patch
diff options
context:
space:
mode:
authorJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
committerJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
commit2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch)
tree118a7b483ae5de4dbf83d20001302f1404866ef0 /linux-2.6-nfsd4-proots.patch
parent64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff)
downloaddom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.gz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.xz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.zip
initial srpm import
Diffstat (limited to 'linux-2.6-nfsd4-proots.patch')
-rw-r--r--linux-2.6-nfsd4-proots.patch226
1 files changed, 226 insertions, 0 deletions
diff --git a/linux-2.6-nfsd4-proots.patch b/linux-2.6-nfsd4-proots.patch
new file mode 100644
index 0000000..84d5894
--- /dev/null
+++ b/linux-2.6-nfsd4-proots.patch
@@ -0,0 +1,226 @@
+diff -up linux-2.6.32.i686/fs/nfsd/export.c.save linux-2.6.32.i686/fs/nfsd/export.c
+--- linux-2.6.32.i686/fs/nfsd/export.c.save 2009-12-04 10:24:17.000000000 -0500
++++ linux-2.6.32.i686/fs/nfsd/export.c 2009-12-04 10:40:52.000000000 -0500
+@@ -372,10 +372,12 @@ static struct svc_export *svc_export_loo
+ static int check_export(struct inode *inode, int flags, unsigned char *uuid)
+ {
+
+- /* We currently export only dirs and regular files.
+- * This is what umountd does.
++ /*
++ * We currently export only dirs, regular files, and (for v4
++ * pseudoroot) symlinks.
+ */
+ if (!S_ISDIR(inode->i_mode) &&
++ !S_ISLNK(inode->i_mode) &&
+ !S_ISREG(inode->i_mode))
+ return -ENOTDIR;
+
+@@ -1425,6 +1427,7 @@ static struct flags {
+ { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
+ { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
+ { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
++ { NFSEXP_V4ROOT, {"v4root", ""}},
+ #ifdef MSNFS
+ { NFSEXP_MSNFS, {"msnfs", ""}},
+ #endif
+@@ -1505,7 +1508,7 @@ static int e_show(struct seq_file *m, vo
+ struct svc_export *exp = container_of(cp, struct svc_export, h);
+
+ if (p == SEQ_START_TOKEN) {
+- seq_puts(m, "# Version 1.1\n");
++ seq_puts(m, "# Version 1.2\n");
+ seq_puts(m, "# Path Client(Flags) # IPs\n");
+ return 0;
+ }
+diff -up linux-2.6.32.i686/fs/nfsd/nfs4xdr.c.save linux-2.6.32.i686/fs/nfsd/nfs4xdr.c
+--- linux-2.6.32.i686/fs/nfsd/nfs4xdr.c.save 2009-12-04 10:24:17.000000000 -0500
++++ linux-2.6.32.i686/fs/nfsd/nfs4xdr.c 2009-12-04 10:26:49.000000000 -0500
+@@ -2204,11 +2204,14 @@ nfsd4_encode_dirent_fattr(struct nfsd4_r
+ * we will not follow the cross mount and will fill the attribtutes
+ * directly from the mountpoint dentry.
+ */
+- if (d_mountpoint(dentry) && !attributes_need_mount(cd->rd_bmval))
+- ignore_crossmnt = 1;
+- else if (d_mountpoint(dentry)) {
++ if (nfsd_mountpoint(dentry, exp)) {
+ int err;
+
++ if (!(exp->ex_flags & NFSEXP_V4ROOT)
++ && !attributes_need_mount(cd->rd_bmval)) {
++ ignore_crossmnt = 1;
++ goto out_encode;
++ }
+ /*
+ * Why the heck aren't we just using nfsd_lookup??
+ * Different "."/".." handling? Something else?
+@@ -2224,6 +2227,7 @@ nfsd4_encode_dirent_fattr(struct nfsd4_r
+ goto out_put;
+
+ }
++out_encode:
+ nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
+ cd->rd_rqstp, ignore_crossmnt);
+ out_put:
+diff -up linux-2.6.32.i686/fs/nfsd/nfsfh.c.save linux-2.6.32.i686/fs/nfsd/nfsfh.c
+--- linux-2.6.32.i686/fs/nfsd/nfsfh.c.save 2009-12-04 10:24:17.000000000 -0500
++++ linux-2.6.32.i686/fs/nfsd/nfsfh.c 2009-12-04 10:38:26.000000000 -0500
+@@ -109,6 +109,36 @@ static __be32 nfsd_setuser_and_check_por
+ return nfserrno(nfsd_setuser(rqstp, exp));
+ }
+
++static inline __be32 check_pseudo_root(struct svc_rqst *rqstp,
++ struct dentry *dentry, struct svc_export *exp)
++{
++ if (!(exp->ex_flags & NFSEXP_V4ROOT))
++ return nfs_ok;
++ /*
++ * v2/v3 clients have no need for the V4ROOT export--they use
++ * the mount protocl instead; also, further V4ROOT checks may be
++ * in v4-specific code, in which case v2/v3 clients could bypass
++ * them.
++ */
++ if (!nfsd_v4client(rqstp))
++ return nfserr_stale;
++ /*
++ * We're exposing only the directories and symlinks that have to be
++ * traversed on the way to real exports:
++ */
++ if (unlikely(!S_ISDIR(dentry->d_inode->i_mode) &&
++ !S_ISLNK(dentry->d_inode->i_mode)))
++ return nfserr_stale;
++ /*
++ * A pseudoroot export gives permission to access only one
++ * single directory; the kernel has to make another upcall
++ * before granting access to anything else under it:
++ */
++ if (unlikely(dentry != exp->ex_path.dentry))
++ return nfserr_stale;
++ return nfs_ok;
++}
++
+ /*
+ * Use the given filehandle to look up the corresponding export and
+ * dentry. On success, the results are used to set fh_export and
+@@ -317,6 +347,13 @@ fh_verify(struct svc_rqst *rqstp, struct
+ goto out;
+ }
+
++ /*
++ * Do some spoof checking if we are on the pseudo root
++ */
++ error = check_pseudo_root(rqstp, dentry, exp);
++ if (error)
++ goto out;
++
+ error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
+ if (error)
+ goto out;
+diff -up linux-2.6.32.i686/fs/nfsd/vfs.c.save linux-2.6.32.i686/fs/nfsd/vfs.c
+--- linux-2.6.32.i686/fs/nfsd/vfs.c.save 2009-12-04 10:24:18.000000000 -0500
++++ linux-2.6.32.i686/fs/nfsd/vfs.c 2009-12-04 10:35:04.000000000 -0500
+@@ -89,12 +89,6 @@ struct raparm_hbucket {
+ #define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
+ static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
+
+-static inline int
+-nfsd_v4client(struct svc_rqst *rq)
+-{
+- return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
+-}
+-
+ /*
+ * Called from nfsd_lookup and encode_dirent. Check if we have crossed
+ * a mount point.
+@@ -116,8 +110,16 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, s
+
+ exp2 = rqst_exp_get_by_name(rqstp, &path);
+ if (IS_ERR(exp2)) {
+- if (PTR_ERR(exp2) != -ENOENT)
+- err = PTR_ERR(exp2);
++ err = PTR_ERR(exp2);
++ /*
++ * We normally allow NFS clients to continue
++ * "underneath" a mountpoint that is not exported.
++ * The exception is V4ROOT, where no traversal is ever
++ * allowed without an explicit export of the new
++ * directory.
++ */
++ if (err == -ENOENT && !(exp->ex_flags & NFSEXP_V4ROOT))
++ err = 0;
+ path_put(&path);
+ goto out;
+ }
+@@ -141,6 +143,19 @@ out:
+ return err;
+ }
+
++/*
++ * For nfsd purposes, we treat V4ROOT exports as though there was an
++ * export at *every* directory.
++ */
++int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
++{
++ if (d_mountpoint(dentry))
++ return 1;
++ if (!(exp->ex_flags & NFSEXP_V4ROOT))
++ return 0;
++ return dentry->d_inode != NULL;
++}
++
+ __be32
+ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ const char *name, unsigned int len,
+@@ -208,7 +223,7 @@ nfsd_lookup_dentry(struct svc_rqst *rqst
+ /*
+ * check if we have crossed a mount point ...
+ */
+- if (d_mountpoint(dentry)) {
++ if (nfsd_mountpoint(dentry, exp)) {
+ if ((host_err = nfsd_cross_mnt(rqstp, &dentry, &exp))) {
+ dput(dentry);
+ goto out_nfserr;
+diff -up linux-2.6.32.i686/include/linux/nfsd/export.h.save linux-2.6.32.i686/include/linux/nfsd/export.h
+--- linux-2.6.32.i686/include/linux/nfsd/export.h.save 2009-12-04 10:24:18.000000000 -0500
++++ linux-2.6.32.i686/include/linux/nfsd/export.h 2009-12-04 10:25:08.000000000 -0500
+@@ -39,7 +39,17 @@
+ #define NFSEXP_FSID 0x2000
+ #define NFSEXP_CROSSMOUNT 0x4000
+ #define NFSEXP_NOACL 0x8000 /* reserved for possible ACL related use */
+-#define NFSEXP_ALLFLAGS 0xFE3F
++/*
++ * The NFSEXP_V4ROOT flag causes the kernel to give access only to NFSv4
++ * clients, and only to the single directory that is the root of the
++ * export; further lookup and readdir operations are treated as if every
++ * subdirectory was a mountpoint, and ignored if they are not themselves
++ * exported. This is used by nfsd and mountd to construct the NFSv4
++ * pseudofilesystem, which provides access only to paths leading to each
++ * exported filesystem.
++ */
++#define NFSEXP_V4ROOT 0x10000
++#define NFSEXP_ALLFLAGS 0x1FE3F
+
+ /* The flags that may vary depending on security flavor: */
+ #define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+diff -up linux-2.6.32.i686/include/linux/nfsd/nfsd.h.save linux-2.6.32.i686/include/linux/nfsd/nfsd.h
+--- linux-2.6.32.i686/include/linux/nfsd/nfsd.h.save 2009-12-04 10:24:18.000000000 -0500
++++ linux-2.6.32.i686/include/linux/nfsd/nfsd.h 2009-12-04 10:39:18.000000000 -0500
+@@ -86,6 +86,7 @@ __be32 nfsd_lookup_dentry(struct svc_r
+ struct svc_export **, struct dentry **);
+ __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *,
+ struct iattr *, int, time_t);
++int nfsd_mountpoint(struct dentry *, struct svc_export *);
+ #ifdef CONFIG_NFSD_V4
+ __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+ struct nfs4_acl *);
+@@ -394,6 +395,10 @@ static inline u32 nfsd_suppattrs2(u32 mi
+ return minorversion ? NFSD4_1_SUPPORTED_ATTRS_WORD2
+ : NFSD4_SUPPORTED_ATTRS_WORD2;
+ }
++static inline int nfsd_v4client(struct svc_rqst *rq)
++{
++ return rq->rq_prog == NFS_PROGRAM && rq->rq_vers == 4;
++}
+
+ /* These will return ERR_INVAL if specified in GETATTR or READDIR. */
+ #define NFSD_WRITEONLY_ATTRS_WORD1 \