0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/dcache.h>
0013 #include <linux/mount.h>
0014 #include <linux/namei.h>
0015 #include <linux/nfs_fs.h>
0016 #include <linux/nfs_mount.h>
0017 #include <linux/slab.h>
0018 #include <linux/string.h>
0019 #include <linux/sunrpc/clnt.h>
0020 #include <linux/sunrpc/addr.h>
0021 #include <linux/vfs.h>
0022 #include <linux/inet.h>
0023 #include "internal.h"
0024 #include "nfs4_fs.h"
0025 #include "nfs.h"
0026 #include "dns_resolve.h"
0027
0028 #define NFSDBG_FACILITY NFSDBG_VFS
0029
0030
0031
0032
0033
0034 static ssize_t nfs4_pathname_len(const struct nfs4_pathname *pathname)
0035 {
0036 ssize_t len = 0;
0037 int i;
0038
0039 for (i = 0; i < pathname->ncomponents; i++) {
0040 const struct nfs4_string *component = &pathname->components[i];
0041
0042 if (component->len > NAME_MAX)
0043 goto too_long;
0044 len += 1 + component->len;
0045 if (len > PATH_MAX)
0046 goto too_long;
0047 }
0048 return len;
0049
0050 too_long:
0051 return -ENAMETOOLONG;
0052 }
0053
0054
0055
0056
0057 static char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
0058 unsigned short *_len)
0059 {
0060 ssize_t len;
0061 char *buf, *p;
0062 int i;
0063
0064 len = nfs4_pathname_len(pathname);
0065 if (len < 0)
0066 return ERR_PTR(len);
0067 *_len = len;
0068
0069 p = buf = kmalloc(len + 1, GFP_KERNEL);
0070 if (!buf)
0071 return ERR_PTR(-ENOMEM);
0072
0073 for (i = 0; i < pathname->ncomponents; i++) {
0074 const struct nfs4_string *component = &pathname->components[i];
0075
0076 *p++ = '/';
0077 memcpy(p, component->data, component->len);
0078 p += component->len;
0079 }
0080
0081 *p = 0;
0082 return buf;
0083 }
0084
0085
0086
0087
0088
0089
0090
0091 static char *nfs_path_component(const char *nfspath, const char *end)
0092 {
0093 char *p;
0094
0095 if (*nfspath == '[') {
0096
0097 p = strchr(nfspath, ']');
0098 if (p != NULL && ++p < end && *p == ':')
0099 return p + 1;
0100 } else {
0101
0102 p = strchr(nfspath, ':');
0103 if (p != NULL && p < end)
0104 return p + 1;
0105 }
0106 return NULL;
0107 }
0108
0109
0110
0111
0112 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
0113 {
0114 char *limit;
0115 char *path = nfs_path(&limit, dentry, buffer, buflen,
0116 NFS_PATH_CANONICAL);
0117 if (!IS_ERR(path)) {
0118 char *path_component = nfs_path_component(path, limit);
0119 if (path_component)
0120 return path_component;
0121 }
0122 return path;
0123 }
0124
0125
0126
0127
0128
0129 static int nfs4_validate_fspath(struct dentry *dentry,
0130 const struct nfs4_fs_locations *locations,
0131 struct nfs_fs_context *ctx)
0132 {
0133 const char *path;
0134 char *fs_path;
0135 unsigned short len;
0136 char *buf;
0137 int n;
0138
0139 buf = kmalloc(4096, GFP_KERNEL);
0140 if (!buf)
0141 return -ENOMEM;
0142
0143 path = nfs4_path(dentry, buf, 4096);
0144 if (IS_ERR(path)) {
0145 kfree(buf);
0146 return PTR_ERR(path);
0147 }
0148
0149 fs_path = nfs4_pathname_string(&locations->fs_path, &len);
0150 if (IS_ERR(fs_path)) {
0151 kfree(buf);
0152 return PTR_ERR(fs_path);
0153 }
0154
0155 n = strncmp(path, fs_path, len);
0156 kfree(buf);
0157 kfree(fs_path);
0158 if (n != 0) {
0159 dprintk("%s: path %s does not begin with fsroot %s\n",
0160 __func__, path, ctx->nfs_server.export_path);
0161 return -ENOENT;
0162 }
0163
0164 return 0;
0165 }
0166
0167 size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
0168 size_t salen, struct net *net, int port)
0169 {
0170 ssize_t ret;
0171
0172 ret = rpc_pton(net, string, len, sa, salen);
0173 if (ret == 0) {
0174 ret = rpc_uaddr2sockaddr(net, string, len, sa, salen);
0175 if (ret == 0) {
0176 ret = nfs_dns_resolve_name(net, string, len, sa, salen);
0177 if (ret < 0)
0178 ret = 0;
0179 }
0180 } else if (port) {
0181 rpc_set_port(sa, port);
0182 }
0183 return ret;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 static struct rpc_clnt *nfs_find_best_sec(struct rpc_clnt *clnt,
0204 struct nfs_server *server,
0205 struct nfs4_secinfo_flavors *flavors)
0206 {
0207 rpc_authflavor_t pflavor;
0208 struct nfs4_secinfo4 *secinfo;
0209 unsigned int i;
0210
0211 for (i = 0; i < flavors->num_flavors; i++) {
0212 secinfo = &flavors->flavors[i];
0213
0214 switch (secinfo->flavor) {
0215 case RPC_AUTH_NULL:
0216 case RPC_AUTH_UNIX:
0217 case RPC_AUTH_GSS:
0218 pflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
0219 &secinfo->flavor_info);
0220
0221 if (pflavor != RPC_AUTH_MAXFLAVOR &&
0222 nfs_auth_info_match(&server->auth_info, pflavor)) {
0223 struct rpc_clnt *new;
0224 struct rpc_cred *cred;
0225
0226
0227 new = rpc_clone_client_set_auth(clnt, pflavor);
0228 if (IS_ERR(new))
0229 continue;
0230
0231
0232
0233
0234
0235 cred = rpcauth_lookupcred(new->cl_auth, 0);
0236 if (IS_ERR(cred)) {
0237 rpc_shutdown_client(new);
0238 continue;
0239 }
0240 put_rpccred(cred);
0241 return new;
0242 }
0243 }
0244 }
0245 return ERR_PTR(-EPERM);
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 struct rpc_clnt *
0260 nfs4_negotiate_security(struct rpc_clnt *clnt, struct inode *inode,
0261 const struct qstr *name)
0262 {
0263 struct page *page;
0264 struct nfs4_secinfo_flavors *flavors;
0265 struct rpc_clnt *new;
0266 int err;
0267
0268 page = alloc_page(GFP_KERNEL);
0269 if (!page)
0270 return ERR_PTR(-ENOMEM);
0271
0272 flavors = page_address(page);
0273
0274 err = nfs4_proc_secinfo(inode, name, flavors);
0275 if (err < 0) {
0276 new = ERR_PTR(err);
0277 goto out;
0278 }
0279
0280 new = nfs_find_best_sec(clnt, NFS_SERVER(inode), flavors);
0281
0282 out:
0283 put_page(page);
0284 return new;
0285 }
0286
0287 static int try_location(struct fs_context *fc,
0288 const struct nfs4_fs_location *location)
0289 {
0290 struct nfs_fs_context *ctx = nfs_fc2context(fc);
0291 unsigned int len, s;
0292 char *export_path, *source, *p;
0293 int ret = -ENOENT;
0294
0295
0296
0297
0298
0299 len = 0;
0300 for (s = 0; s < location->nservers; s++) {
0301 const struct nfs4_string *buf = &location->servers[s];
0302 if (buf->len > len)
0303 len = buf->len;
0304 }
0305
0306 kfree(ctx->nfs_server.hostname);
0307 ctx->nfs_server.hostname = kmalloc(len + 1, GFP_KERNEL);
0308 if (!ctx->nfs_server.hostname)
0309 return -ENOMEM;
0310
0311 export_path = nfs4_pathname_string(&location->rootpath,
0312 &ctx->nfs_server.export_path_len);
0313 if (IS_ERR(export_path))
0314 return PTR_ERR(export_path);
0315
0316 kfree(ctx->nfs_server.export_path);
0317 ctx->nfs_server.export_path = export_path;
0318
0319 source = kmalloc(len + 1 + ctx->nfs_server.export_path_len + 1,
0320 GFP_KERNEL);
0321 if (!source)
0322 return -ENOMEM;
0323
0324 kfree(fc->source);
0325 fc->source = source;
0326 for (s = 0; s < location->nservers; s++) {
0327 const struct nfs4_string *buf = &location->servers[s];
0328
0329 if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
0330 continue;
0331
0332 ctx->nfs_server.addrlen =
0333 nfs_parse_server_name(buf->data, buf->len,
0334 &ctx->nfs_server.address,
0335 sizeof(ctx->nfs_server._address),
0336 fc->net_ns, 0);
0337 if (ctx->nfs_server.addrlen == 0)
0338 continue;
0339
0340 rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
0341
0342 memcpy(ctx->nfs_server.hostname, buf->data, buf->len);
0343 ctx->nfs_server.hostname[buf->len] = '\0';
0344
0345 p = source;
0346 memcpy(p, buf->data, buf->len);
0347 p += buf->len;
0348 *p++ = ':';
0349 memcpy(p, ctx->nfs_server.export_path, ctx->nfs_server.export_path_len);
0350 p += ctx->nfs_server.export_path_len;
0351 *p = 0;
0352
0353 ret = nfs4_get_referral_tree(fc);
0354 if (ret == 0)
0355 return 0;
0356 }
0357
0358 return ret;
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 static int nfs_follow_referral(struct fs_context *fc,
0368 const struct nfs4_fs_locations *locations)
0369 {
0370 struct nfs_fs_context *ctx = nfs_fc2context(fc);
0371 int loc, error;
0372
0373 if (locations == NULL || locations->nlocations <= 0)
0374 return -ENOENT;
0375
0376 dprintk("%s: referral at %pd2\n", __func__, ctx->clone_data.dentry);
0377
0378
0379 error = nfs4_validate_fspath(ctx->clone_data.dentry, locations, ctx);
0380 if (error < 0)
0381 return error;
0382
0383 error = -ENOENT;
0384 for (loc = 0; loc < locations->nlocations; loc++) {
0385 const struct nfs4_fs_location *location = &locations->locations[loc];
0386
0387 if (location == NULL || location->nservers <= 0 ||
0388 location->rootpath.ncomponents == 0)
0389 continue;
0390
0391 error = try_location(fc, location);
0392 if (error == 0)
0393 return 0;
0394 }
0395
0396 return error;
0397 }
0398
0399
0400
0401
0402
0403
0404 static int nfs_do_refmount(struct fs_context *fc, struct rpc_clnt *client)
0405 {
0406 struct nfs_fs_context *ctx = nfs_fc2context(fc);
0407 struct dentry *dentry, *parent;
0408 struct nfs4_fs_locations *fs_locations = NULL;
0409 struct page *page;
0410 int err = -ENOMEM;
0411
0412
0413 page = alloc_page(GFP_KERNEL);
0414 if (!page)
0415 return -ENOMEM;
0416
0417 fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
0418 if (!fs_locations)
0419 goto out_free;
0420 fs_locations->fattr = nfs_alloc_fattr();
0421 if (!fs_locations->fattr)
0422 goto out_free_2;
0423
0424
0425 dentry = ctx->clone_data.dentry;
0426 parent = dget_parent(dentry);
0427 dprintk("%s: getting locations for %pd2\n",
0428 __func__, dentry);
0429
0430 err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page);
0431 dput(parent);
0432 if (err != 0)
0433 goto out_free_3;
0434
0435 err = -ENOENT;
0436 if (fs_locations->nlocations <= 0 ||
0437 fs_locations->fs_path.ncomponents <= 0)
0438 goto out_free_3;
0439
0440 err = nfs_follow_referral(fc, fs_locations);
0441 out_free_3:
0442 kfree(fs_locations->fattr);
0443 out_free_2:
0444 kfree(fs_locations);
0445 out_free:
0446 __free_page(page);
0447 return err;
0448 }
0449
0450 int nfs4_submount(struct fs_context *fc, struct nfs_server *server)
0451 {
0452 struct nfs_fs_context *ctx = nfs_fc2context(fc);
0453 struct dentry *dentry = ctx->clone_data.dentry;
0454 struct dentry *parent = dget_parent(dentry);
0455 struct inode *dir = d_inode(parent);
0456 struct rpc_clnt *client;
0457 int ret;
0458
0459
0460 client = nfs4_proc_lookup_mountpoint(dir, dentry, ctx->mntfh,
0461 ctx->clone_data.fattr);
0462 dput(parent);
0463 if (IS_ERR(client))
0464 return PTR_ERR(client);
0465
0466 ctx->selected_flavor = client->cl_auth->au_flavor;
0467 if (ctx->clone_data.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
0468 ret = nfs_do_refmount(fc, client);
0469 } else {
0470 ret = nfs_do_submount(fc);
0471 }
0472
0473 rpc_shutdown_client(client);
0474 return ret;
0475 }
0476
0477
0478
0479
0480
0481
0482 static int nfs4_try_replacing_one_location(struct nfs_server *server,
0483 char *page, char *page2,
0484 const struct nfs4_fs_location *location)
0485 {
0486 const size_t addr_bufsize = sizeof(struct sockaddr_storage);
0487 struct net *net = rpc_net_ns(server->client);
0488 struct sockaddr *sap;
0489 unsigned int s;
0490 size_t salen;
0491 int error;
0492
0493 sap = kmalloc(addr_bufsize, GFP_KERNEL);
0494 if (sap == NULL)
0495 return -ENOMEM;
0496
0497 error = -ENOENT;
0498 for (s = 0; s < location->nservers; s++) {
0499 const struct nfs4_string *buf = &location->servers[s];
0500 char *hostname;
0501
0502 if (buf->len <= 0 || buf->len > PAGE_SIZE)
0503 continue;
0504
0505 if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL)
0506 continue;
0507
0508 salen = nfs_parse_server_name(buf->data, buf->len,
0509 sap, addr_bufsize, net, 0);
0510 if (salen == 0)
0511 continue;
0512 rpc_set_port(sap, NFS_PORT);
0513
0514 error = -ENOMEM;
0515 hostname = kmemdup_nul(buf->data, buf->len, GFP_KERNEL);
0516 if (hostname == NULL)
0517 break;
0518
0519 error = nfs4_update_server(server, hostname, sap, salen, net);
0520 kfree(hostname);
0521 if (error == 0)
0522 break;
0523 }
0524
0525 kfree(sap);
0526 return error;
0527 }
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 int nfs4_replace_transport(struct nfs_server *server,
0542 const struct nfs4_fs_locations *locations)
0543 {
0544 char *page = NULL, *page2 = NULL;
0545 int loc, error;
0546
0547 error = -ENOENT;
0548 if (locations == NULL || locations->nlocations <= 0)
0549 goto out;
0550
0551 error = -ENOMEM;
0552 page = (char *) __get_free_page(GFP_USER);
0553 if (!page)
0554 goto out;
0555 page2 = (char *) __get_free_page(GFP_USER);
0556 if (!page2)
0557 goto out;
0558
0559 for (loc = 0; loc < locations->nlocations; loc++) {
0560 const struct nfs4_fs_location *location =
0561 &locations->locations[loc];
0562
0563 if (location == NULL || location->nservers <= 0 ||
0564 location->rootpath.ncomponents == 0)
0565 continue;
0566
0567 error = nfs4_try_replacing_one_location(server, page,
0568 page2, location);
0569 if (error == 0)
0570 break;
0571 }
0572
0573 out:
0574 free_page((unsigned long)page);
0575 free_page((unsigned long)page2);
0576 return error;
0577 }