aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4namespace.c')
-rw-r--r--fs/nfs/nfs4namespace.c110
1 files changed, 85 insertions, 25 deletions
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index faed9bcba50f..24e47f3bbd17 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -2,6 +2,7 @@
2 * linux/fs/nfs/nfs4namespace.c 2 * linux/fs/nfs/nfs4namespace.c
3 * 3 *
4 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com> 4 * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
5 * - Modified by David Howells <dhowells@redhat.com>
5 * 6 *
6 * NFSv4 namespace 7 * NFSv4 namespace
7 */ 8 */
@@ -47,6 +48,68 @@ Elong:
47 return ERR_PTR(-ENAMETOOLONG); 48 return ERR_PTR(-ENAMETOOLONG);
48} 49}
49 50
51/*
52 * Determine the mount path as a string
53 */
54static char *nfs4_path(const struct vfsmount *mnt_parent,
55 const struct dentry *dentry,
56 char *buffer, ssize_t buflen)
57{
58 const char *srvpath;
59
60 srvpath = strchr(mnt_parent->mnt_devname, ':');
61 if (srvpath)
62 srvpath++;
63 else
64 srvpath = mnt_parent->mnt_devname;
65
66 return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen);
67}
68
69/*
70 * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
71 * believe to be the server path to this dentry
72 */
73static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
74 const struct dentry *dentry,
75 const struct nfs4_fs_locations *locations,
76 char *page, char *page2)
77{
78 const char *path, *fs_path;
79
80 path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE);
81 if (IS_ERR(path))
82 return PTR_ERR(path);
83
84 fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE);
85 if (IS_ERR(fs_path))
86 return PTR_ERR(fs_path);
87
88 if (strncmp(path, fs_path, strlen(fs_path)) != 0) {
89 dprintk("%s: path %s does not begin with fsroot %s\n",
90 __FUNCTION__, path, fs_path);
91 return -ENOENT;
92 }
93
94 return 0;
95}
96
97/*
98 * Check if the string represents a "valid" IPv4 address
99 */
100static inline int valid_ipaddr4(const char *buf)
101{
102 int rc, count, in[4];
103
104 rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
105 if (rc != 4)
106 return -EINVAL;
107 for (count = 0; count < 4; count++) {
108 if (in[count] > 255)
109 return -EINVAL;
110 }
111 return 0;
112}
50 113
51/** 114/**
52 * nfs_follow_referral - set up mountpoint when hitting a referral on moved error 115 * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
@@ -68,10 +131,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
68 .dentry = dentry, 131 .dentry = dentry,
69 .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, 132 .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
70 }; 133 };
71 char *page, *page2; 134 char *page = NULL, *page2 = NULL;
72 char *path, *fs_path;
73 char *devname; 135 char *devname;
74 int loc, s; 136 int loc, s, error;
75 137
76 if (locations == NULL || locations->nlocations <= 0) 138 if (locations == NULL || locations->nlocations <= 0)
77 goto out; 139 goto out;
@@ -79,31 +141,25 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
79 dprintk("%s: referral at %s/%s\n", __FUNCTION__, 141 dprintk("%s: referral at %s/%s\n", __FUNCTION__,
80 dentry->d_parent->d_name.name, dentry->d_name.name); 142 dentry->d_parent->d_name.name, dentry->d_name.name);
81 143
82 /* Ensure fs path is a prefix of current dentry path */
83 page = (char *) __get_free_page(GFP_USER); 144 page = (char *) __get_free_page(GFP_USER);
84 if (page == NULL) 145 if (!page)
85 goto out; 146 goto out;
147
86 page2 = (char *) __get_free_page(GFP_USER); 148 page2 = (char *) __get_free_page(GFP_USER);
87 if (page2 == NULL) 149 if (!page2)
88 goto out; 150 goto out;
89 151
90 path = nfs4_path(dentry, page, PAGE_SIZE); 152 /* Ensure fs path is a prefix of current dentry path */
91 if (IS_ERR(path)) 153 error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2);
92 goto out_free; 154 if (error < 0) {
93 155 mnt = ERR_PTR(error);
94 fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); 156 goto out;
95 if (IS_ERR(fs_path))
96 goto out_free;
97
98 if (strncmp(path, fs_path, strlen(fs_path)) != 0) {
99 dprintk("%s: path %s does not begin with fsroot %s\n", __FUNCTION__, path, fs_path);
100 goto out_free;
101 } 157 }
102 158
103 devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); 159 devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
104 if (IS_ERR(devname)) { 160 if (IS_ERR(devname)) {
105 mnt = (struct vfsmount *)devname; 161 mnt = (struct vfsmount *)devname;
106 goto out_free; 162 goto out;
107 } 163 }
108 164
109 loc = 0; 165 loc = 0;
@@ -140,7 +196,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
140 addr.sin_port = htons(NFS_PORT); 196 addr.sin_port = htons(NFS_PORT);
141 mountdata.addr = &addr; 197 mountdata.addr = &addr;
142 198
143 mnt = vfs_kern_mount(&nfs_referral_nfs4_fs_type, 0, devname, &mountdata); 199 mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata);
144 if (!IS_ERR(mnt)) { 200 if (!IS_ERR(mnt)) {
145 break; 201 break;
146 } 202 }
@@ -149,10 +205,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
149 loc++; 205 loc++;
150 } 206 }
151 207
152out_free:
153 free_page((unsigned long)page);
154 free_page((unsigned long)page2);
155out: 208out:
209 free_page((unsigned long) page);
210 free_page((unsigned long) page2);
156 dprintk("%s: done\n", __FUNCTION__); 211 dprintk("%s: done\n", __FUNCTION__);
157 return mnt; 212 return mnt;
158} 213}
@@ -165,7 +220,7 @@ out:
165 */ 220 */
166struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) 221struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
167{ 222{
168 struct vfsmount *mnt = ERR_PTR(-ENOENT); 223 struct vfsmount *mnt = ERR_PTR(-ENOMEM);
169 struct dentry *parent; 224 struct dentry *parent;
170 struct nfs4_fs_locations *fs_locations = NULL; 225 struct nfs4_fs_locations *fs_locations = NULL;
171 struct page *page; 226 struct page *page;
@@ -183,11 +238,16 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
183 goto out_free; 238 goto out_free;
184 239
185 /* Get locations */ 240 /* Get locations */
241 mnt = ERR_PTR(-ENOENT);
242
186 parent = dget_parent(dentry); 243 parent = dget_parent(dentry);
187 dprintk("%s: getting locations for %s/%s\n", __FUNCTION__, parent->d_name.name, dentry->d_name.name); 244 dprintk("%s: getting locations for %s/%s\n",
245 __FUNCTION__, parent->d_name.name, dentry->d_name.name);
246
188 err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page); 247 err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page);
189 dput(parent); 248 dput(parent);
190 if (err != 0 || fs_locations->nlocations <= 0 || 249 if (err != 0 ||
250 fs_locations->nlocations <= 0 ||
191 fs_locations->fs_path.ncomponents <= 0) 251 fs_locations->fs_path.ncomponents <= 0)
192 goto out_free; 252 goto out_free;
193 253