Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * linux/fs/nfs/nfs4namespace.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * - Modified by David Howells <dhowells@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * NFSv4 namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/nfs_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/nfs_mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/sunrpc/clnt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/sunrpc/addr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/vfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/inet.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include "nfs4_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "nfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "dns_resolve.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define NFSDBG_FACILITY		NFSDBG_VFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Work out the length that an NFSv4 path would render to as a standard posix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * path, with a leading slash but no terminating slash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static ssize_t nfs4_pathname_len(const struct nfs4_pathname *pathname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	ssize_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	for (i = 0; i < pathname->ncomponents; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		const struct nfs4_string *component = &pathname->components[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		if (component->len > NAME_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 			goto too_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		len += 1 + component->len; /* Adding "/foo" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		if (len > PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 			goto too_long;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) too_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * Convert the NFSv4 pathname components into a standard posix path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) static char *nfs4_pathname_string(const struct nfs4_pathname *pathname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 				  unsigned short *_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	ssize_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	char *buf, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	len = nfs4_pathname_len(pathname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (len < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		return ERR_PTR(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	*_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	p = buf = kmalloc(len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	for (i = 0; i < pathname->ncomponents; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		const struct nfs4_string *component = &pathname->components[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		*p++ = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		memcpy(p, component->data, component->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		p += component->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	*p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * return the path component of "<server>:<path>"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  *  nfspath - the "<server>:<path>" string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  *  end - one past the last char that could contain "<server>:"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * returns NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static char *nfs_path_component(const char *nfspath, const char *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (*nfspath == '[') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		/* parse [] escaped IPv6 addrs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		p = strchr(nfspath, ']');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		if (p != NULL && ++p < end && *p == ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 			return p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		/* otherwise split on first colon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		p = strchr(nfspath, ':');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		if (p != NULL && p < end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			return p + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * Determine the mount path as a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	char *limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	char *path = nfs_path(&limit, dentry, buffer, buflen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			      NFS_PATH_CANONICAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (!IS_ERR(path)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		char *path_component = nfs_path_component(path, limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		if (path_component)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			return path_component;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	return path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  * believe to be the server path to this dentry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int nfs4_validate_fspath(struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 				const struct nfs4_fs_locations *locations,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 				struct nfs_fs_context *ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	const char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	char *fs_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	unsigned short len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	buf = kmalloc(4096, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	path = nfs4_path(dentry, buf, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (IS_ERR(path)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		return PTR_ERR(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	fs_path = nfs4_pathname_string(&locations->fs_path, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	if (IS_ERR(fs_path)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return PTR_ERR(fs_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	n = strncmp(path, fs_path, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	kfree(fs_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	if (n != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		dprintk("%s: path %s does not begin with fsroot %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			__func__, path, ctx->nfs_server.export_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) size_t nfs_parse_server_name(char *string, size_t len, struct sockaddr *sa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			     size_t salen, struct net *net, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	ret = rpc_pton(net, string, len, sa, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		ret = rpc_uaddr2sockaddr(net, string, len, sa, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			ret = nfs_dns_resolve_name(net, string, len, sa, salen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 				ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	} else if (port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		rpc_set_port(sa, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  * nfs_find_best_sec - Find a security mechanism supported locally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * @clnt: pointer to rpc_clnt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * @server: NFS server struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * @flavors: List of security tuples returned by SECINFO procedure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * Return an rpc client that uses the first security mechanism in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  * "flavors" that is locally supported.  The "flavors" array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * is searched in the order returned from the server, per RFC 3530
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * recommendation and each flavor is checked for membership in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * sec= mount option list if it exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * Return -EPERM if no matching flavor is found in the array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * Please call rpc_shutdown_client() when you are done with this rpc client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static struct rpc_clnt *nfs_find_best_sec(struct rpc_clnt *clnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 					  struct nfs_server *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 					  struct nfs4_secinfo_flavors *flavors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	rpc_authflavor_t pflavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	struct nfs4_secinfo4 *secinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	for (i = 0; i < flavors->num_flavors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		secinfo = &flavors->flavors[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		switch (secinfo->flavor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		case RPC_AUTH_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		case RPC_AUTH_UNIX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		case RPC_AUTH_GSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			pflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 							&secinfo->flavor_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			/* does the pseudoflavor match a sec= mount opt? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			if (pflavor != RPC_AUTH_MAXFLAVOR &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 			    nfs_auth_info_match(&server->auth_info, pflavor)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				struct rpc_clnt *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 				struct rpc_cred *cred;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 				/* Cloning creates an rpc_auth for the flavor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				new = rpc_clone_client_set_auth(clnt, pflavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				if (IS_ERR(new))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				/**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 				* Check that the user actually can use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 				* flavor. This is mostly for RPC_AUTH_GSS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				* where cr_init obtains a gss context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 				*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				cred = rpcauth_lookupcred(new->cl_auth, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				if (IS_ERR(cred)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 					rpc_shutdown_client(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 				put_rpccred(cred);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 				return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	return ERR_PTR(-EPERM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  * nfs4_negotiate_security - in response to an NFS4ERR_WRONGSEC on lookup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  * return an rpc_clnt that uses the best available security flavor with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * respect to the secinfo flavor list and the sec= mount options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * @clnt: RPC client to clone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * @inode: directory inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  * @name: lookup name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * Please call rpc_shutdown_client() when you are done with this rpc client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct rpc_clnt *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) nfs4_negotiate_security(struct rpc_clnt *clnt, struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 					const struct qstr *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	struct nfs4_secinfo_flavors *flavors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct rpc_clnt *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	page = alloc_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	flavors = page_address(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	err = nfs4_proc_secinfo(inode, name, flavors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		new = ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	new = nfs_find_best_sec(clnt, NFS_SERVER(inode), flavors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int try_location(struct fs_context *fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			const struct nfs4_fs_location *location)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	unsigned int len, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	char *export_path, *source, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	int ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	/* Allocate a buffer big enough to hold any of the hostnames plus a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	 * terminating char and also a buffer big enough to hold the hostname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	 * plus a colon plus the path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	for (s = 0; s < location->nservers; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		const struct nfs4_string *buf = &location->servers[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		if (buf->len > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			len = buf->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	kfree(ctx->nfs_server.hostname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	ctx->nfs_server.hostname = kmalloc(len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	if (!ctx->nfs_server.hostname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	export_path = nfs4_pathname_string(&location->rootpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 					   &ctx->nfs_server.export_path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (IS_ERR(export_path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		return PTR_ERR(export_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	kfree(ctx->nfs_server.export_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	ctx->nfs_server.export_path = export_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	source = kmalloc(len + 1 + ctx->nfs_server.export_path_len + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			 GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	if (!source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	kfree(fc->source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	fc->source = source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	for (s = 0; s < location->nservers; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		const struct nfs4_string *buf = &location->servers[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		ctx->nfs_server.addrlen =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 			nfs_parse_server_name(buf->data, buf->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 					      &ctx->nfs_server.address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 					      sizeof(ctx->nfs_server._address),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 					      fc->net_ns, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		if (ctx->nfs_server.addrlen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		rpc_set_port(&ctx->nfs_server.address, NFS_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		memcpy(ctx->nfs_server.hostname, buf->data, buf->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 		ctx->nfs_server.hostname[buf->len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		p = source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		memcpy(p, buf->data, buf->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		p += buf->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		*p++ = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		memcpy(p, ctx->nfs_server.export_path, ctx->nfs_server.export_path_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		p += ctx->nfs_server.export_path_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		*p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		ret = nfs4_get_referral_tree(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)  * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)  * @fc: pointer to struct nfs_fs_context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)  * @locations: array of NFSv4 server location information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int nfs_follow_referral(struct fs_context *fc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			       const struct nfs4_fs_locations *locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	int loc, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	if (locations == NULL || locations->nlocations <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	dprintk("%s: referral at %pd2\n", __func__, ctx->clone_data.dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	/* Ensure fs path is a prefix of current dentry path */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	error = nfs4_validate_fspath(ctx->clone_data.dentry, locations, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	if (error < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	for (loc = 0; loc < locations->nlocations; loc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		const struct nfs4_fs_location *location = &locations->locations[loc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 		if (location == NULL || location->nservers <= 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 		    location->rootpath.ncomponents == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		error = try_location(fc, location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		if (error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)  * nfs_do_refmount - handle crossing a referral on server
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  * @dentry - dentry of referral
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int nfs_do_refmount(struct fs_context *fc, struct rpc_clnt *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	struct dentry *dentry, *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	struct nfs4_fs_locations *fs_locations = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	int err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	/* BUG_ON(IS_ROOT(dentry)); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	page = alloc_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (!fs_locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	/* Get locations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	dentry = ctx->clone_data.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	parent = dget_parent(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	dprintk("%s: getting locations for %pd2\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		__func__, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	err = nfs4_proc_fs_locations(client, d_inode(parent), &dentry->d_name, fs_locations, page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	dput(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		goto out_free_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	if (fs_locations->nlocations <= 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	    fs_locations->fs_path.ncomponents <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		goto out_free_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	err = nfs_follow_referral(fc, fs_locations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) out_free_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	kfree(fs_locations);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	__free_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int nfs4_submount(struct fs_context *fc, struct nfs_server *server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	struct dentry *dentry = ctx->clone_data.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	struct dentry *parent = dget_parent(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 	struct inode *dir = d_inode(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	struct rpc_clnt *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	/* Look it up again to get its attributes and sec flavor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	client = nfs4_proc_lookup_mountpoint(dir, dentry, ctx->mntfh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 					     ctx->clone_data.fattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	dput(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	if (IS_ERR(client))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		return PTR_ERR(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	ctx->selected_flavor = client->cl_auth->au_flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	if (ctx->clone_data.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		ret = nfs_do_refmount(fc, client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		ret = nfs_do_submount(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	rpc_shutdown_client(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)  * Try one location from the fs_locations array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)  * Returns zero on success, or a negative errno value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) static int nfs4_try_replacing_one_location(struct nfs_server *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		char *page, char *page2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		const struct nfs4_fs_location *location)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	const size_t addr_bufsize = sizeof(struct sockaddr_storage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	struct net *net = rpc_net_ns(server->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	struct sockaddr *sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	unsigned int s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	size_t salen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	sap = kmalloc(addr_bufsize, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	if (sap == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	for (s = 0; s < location->nservers; s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		const struct nfs4_string *buf = &location->servers[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		char *hostname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		if (buf->len <= 0 || buf->len > PAGE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		salen = nfs_parse_server_name(buf->data, buf->len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 						sap, addr_bufsize, net, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		if (salen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		rpc_set_port(sap, NFS_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 		hostname = kmemdup_nul(buf->data, buf->len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		if (hostname == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		error = nfs4_update_server(server, hostname, sap, salen, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		kfree(hostname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		if (error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	kfree(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)  * nfs4_replace_transport - set up transport to destination server
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)  * @server: export being migrated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)  * @locations: fs_locations array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)  * Returns zero on success, or a negative errno value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  * The client tries all the entries in the "locations" array, in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  * order returned by the server, until one works or the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  * array is reached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int nfs4_replace_transport(struct nfs_server *server,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			   const struct nfs4_fs_locations *locations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	char *page = NULL, *page2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	int loc, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	error = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	if (locations == NULL || locations->nlocations <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	page = (char *) __get_free_page(GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	if (!page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	page2 = (char *) __get_free_page(GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	if (!page2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	for (loc = 0; loc < locations->nlocations; loc++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		const struct nfs4_fs_location *location =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 						&locations->locations[loc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		if (location == NULL || location->nservers <= 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		    location->rootpath.ncomponents == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		error = nfs4_try_replacing_one_location(server, page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 							page2, location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		if (error == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	free_page((unsigned long)page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	free_page((unsigned long)page2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }