Re: [PATCH v3 14/14] SUNRPC: add AF_VSOCK support to auth.unix.ip

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Without CONFIG_SUNRPC_BACKCHANNEL, many things such as “svc_vsock_bc_class” are undefined, and then used throughout the code.
Most of the “CONFIG_SUNRPC_XPRT_VSOCK” guards in sunrpc/svcsock.c should also be guarded by CONFIG_SUNRPC_BACKCHANNEL.

-A

> On Jun 30, 2017, at 6:23 AM, Stefan Hajnoczi <stefanha@xxxxxxxxxx> wrote:
> 
> The ip_map currently supports AF_INET and AF_INET6.  It actually
> converts IPv4 to IPv6 addresses.  We can't do that for AF_VSOCK but a
> union will allow both IPv6 and vsock sockaddr structs to be used.
> 
> The cache userspace interface now supports 'vsock:CID' syntax for
> AF_VSOCK addresses.
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@xxxxxxxxxx>
> ---
> net/sunrpc/svcauth_unix.c | 146 ++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 115 insertions(+), 31 deletions(-)
> 
> diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
> index f81eaa8..b33ea0b 100644
> --- a/net/sunrpc/svcauth_unix.c
> +++ b/net/sunrpc/svcauth_unix.c
> @@ -89,7 +89,15 @@ EXPORT_SYMBOL_GPL(unix_domain_find);
> struct ip_map {
> 	struct cache_head	h;
> 	char			m_class[8]; /* e.g. "nfsd" */
> -	struct in6_addr		m_addr;
> +	union {
> +		struct sockaddr		m_sa;
> +
> +		/* For AF_INET6 and AF_INET (we map to IPv6) */
> +		struct sockaddr_in6	m_sin6;
> +
> +		/* For AF_VSOCK */
> +		struct sockaddr_vm	m_svm;
> +	};
> 	struct unix_domain	*m_client;
> };
> 
> @@ -112,8 +120,22 @@ static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
> {
> 	struct ip_map *orig = container_of(corig, struct ip_map, h);
> 	struct ip_map *new = container_of(cnew, struct ip_map, h);
> -	return strcmp(orig->m_class, new->m_class) == 0 &&
> -	       ipv6_addr_equal(&orig->m_addr, &new->m_addr);
> +
> +	if (strcmp(orig->m_class, new->m_class) != 0)
> +		return 0;
> +
> +	if (orig->m_sa.sa_family != new->m_sa.sa_family)
> +		return 0;
> +
> +	switch (orig->m_sa.sa_family) {
> +	case AF_INET6:
> +		return ipv6_addr_equal(&orig->m_sin6.sin6_addr,
> +				       &new->m_sin6.sin6_addr);
> +
> +	case AF_VSOCK:
> +		return orig->m_svm.svm_cid == new->m_svm.svm_cid;
> +	}
> +	return 0;
> }
> static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -121,7 +143,14 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> 	struct ip_map *item = container_of(citem, struct ip_map, h);
> 
> 	strcpy(new->m_class, item->m_class);
> -	new->m_addr = item->m_addr;
> +	switch (item->m_sa.sa_family) {
> +	case AF_INET6:
> +		new->m_sin6 = item->m_sin6;
> +		break;
> +	case AF_VSOCK:
> +		new->m_svm = item->m_svm;
> +		break;
> +	}
> }
> static void update(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -145,19 +174,30 @@ static void ip_map_request(struct cache_detail *cd,
> 				  char **bpp, int *blen)
> {
> 	char text_addr[40];
> +	struct in6_addr *addr;
> 	struct ip_map *im = container_of(h, struct ip_map, h);
> 
> -	if (ipv6_addr_v4mapped(&(im->m_addr))) {
> -		snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
> -	} else {
> -		snprintf(text_addr, 40, "%pI6", &im->m_addr);
> +	switch (im->m_sa.sa_family) {
> +	case AF_INET6:
> +		addr = &im->m_sin6.sin6_addr;
> +		if (ipv6_addr_v4mapped(addr)) {
> +			snprintf(text_addr, 20, "%pI4", &addr->s6_addr32[3]);
> +		} else {
> +			snprintf(text_addr, 40, "%pI6", addr);
> +		}
> +		break;
> +
> +	case AF_VSOCK:
> +		snprintf(text_addr, 10, "vsock:%u", im->m_svm.svm_cid);
> +		break;
> 	}
> +
> 	qword_add(bpp, blen, im->m_class);
> 	qword_add(bpp, blen, text_addr);
> 	(*bpp)[-1] = '\n';
> }
> 
> -static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
> +static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct sockaddr *sap);
> static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
> 
> static int ip_map_parse(struct cache_detail *cd,
> @@ -173,6 +213,7 @@ static int ip_map_parse(struct cache_detail *cd,
> 		struct sockaddr		sa;
> 		struct sockaddr_in	s4;
> 		struct sockaddr_in6	s6;
> +		struct sockaddr_vm	svm;
> 	} address;
> 	struct sockaddr_in6 sin6;
> 	int err;
> @@ -201,11 +242,15 @@ static int ip_map_parse(struct cache_detail *cd,
> 		sin6.sin6_family = AF_INET6;
> 		ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
> 				&sin6.sin6_addr);
> +		address.s6 = sin6;
> 		break;
> #if IS_ENABLED(CONFIG_IPV6)
> 	case AF_INET6:
> -		memcpy(&sin6, &address.s6, sizeof(sin6));
> -		break;
> +		break; /* Do nothing */
> +#endif
> +#ifdef CONFIG_SUNRPC_XPRT_VSOCK
> +	case AF_VSOCK:
> +		break; /* Do nothing */
> #endif
> 	default:
> 		return -EINVAL;
> @@ -227,7 +272,7 @@ static int ip_map_parse(struct cache_detail *cd,
> 		dom = NULL;
> 
> 	/* IPv6 scope IDs are ignored for now */
> -	ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
> +	ipmp = __ip_map_lookup(cd, class, &address.sa);
> 	if (ipmp) {
> 		err = __ip_map_update(cd, ipmp,
> 			     container_of(dom, struct unix_domain, h),
> @@ -247,7 +292,7 @@ static int ip_map_show(struct seq_file *m,
> 		       struct cache_head *h)
> {
> 	struct ip_map *im;
> -	struct in6_addr addr;
> +	struct in6_addr *addr;
> 	char *dom = "-no-domain-";
> 
> 	if (h == NULL) {
> @@ -256,33 +301,67 @@ static int ip_map_show(struct seq_file *m,
> 	}
> 	im = container_of(h, struct ip_map, h);
> 	/* class addr domain */
> -	addr = im->m_addr;
> -
> +	addr = &im->m_sin6.sin6_addr;
> 	if (test_bit(CACHE_VALID, &h->flags) &&
> 	    !test_bit(CACHE_NEGATIVE, &h->flags))
> 		dom = im->m_client->h.name;
> 
> -	if (ipv6_addr_v4mapped(&addr)) {
> -		seq_printf(m, "%s %pI4 %s\n",
> -			im->m_class, &addr.s6_addr32[3], dom);
> -	} else {
> -		seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
> +	switch (im->m_sa.sa_family) {
> +	case AF_INET6:
> +		if (ipv6_addr_v4mapped(addr)) {
> +			seq_printf(m, "%s %pI4 %s\n",
> +				im->m_class,
> +				&addr->s6_addr32[3],
> +				dom);
> +		} else {
> +			seq_printf(m, "%s %pI6 %s\n", im->m_class, addr, dom);
> +		}
> +		break;
> +
> +	case AF_VSOCK:
> +		seq_printf(m, "%s %u %s\n",
> +			im->m_class, im->m_svm.svm_cid, dom);
> +		break;
> 	}
> 	return 0;
> }
> 
> +static int __ip_map_hash(struct ip_map *ipm)
> +{
> +	int hash;
> +
> +	switch (ipm->m_sa.sa_family) {
> +	case AF_INET6:
> +		hash = hash_ip6(&ipm->m_sin6.sin6_addr);
> +		break;
> +	case AF_VSOCK:
> +		hash = hash_32(ipm->m_svm.svm_cid, IP_HASHBITS);
> +		break;
> +	default:
> +		BUG();
> +	}
> +
> +	return hash_str(ipm->m_class, IP_HASHBITS) ^ hash;
> +}
> 
> static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
> -		struct in6_addr *addr)
> +		struct sockaddr *sap)
> {
> 	struct ip_map ip;
> 	struct cache_head *ch;
> 
> 	strcpy(ip.m_class, class);
> -	ip.m_addr = *addr;
> -	ch = sunrpc_cache_lookup(cd, &ip.h,
> -				 hash_str(class, IP_HASHBITS) ^
> -				 hash_ip6(addr));
> +	switch (sap->sa_family) {
> +	case AF_INET6:
> +		ip.m_sin6 = *(struct sockaddr_in6 *)sap;
> +		break;
> +	case AF_VSOCK:
> +		ip.m_svm = *(struct sockaddr_vm *)sap;
> +		break;
> +	default:
> +		return NULL;
> +	}
> +	ch = sunrpc_cache_lookup(cd, &ip.h, __ip_map_hash(&ip));
> 
> 	if (ch)
> 		return container_of(ch, struct ip_map, h);
> @@ -291,12 +370,12 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
> }
> 
> static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
> -		struct in6_addr *addr)
> +		struct sockaddr *sap)
> {
> 	struct sunrpc_net *sn;
> 
> 	sn = net_generic(net, sunrpc_net_id);
> -	return __ip_map_lookup(sn->ip_map_cache, class, addr);
> +	return __ip_map_lookup(sn->ip_map_cache, class, sap);
> }
> 
> static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
> @@ -311,8 +390,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
> 		set_bit(CACHE_NEGATIVE, &ip.h.flags);
> 	ip.h.expiry_time = expiry;
> 	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
> -				 hash_str(ipm->m_class, IP_HASHBITS) ^
> -				 hash_ip6(&ipm->m_addr));
> +				 __ip_map_hash(ipm));
> 	if (!ch)
> 		return -ENOMEM;
> 	cache_put(ch, cd);
> @@ -654,6 +732,7 @@ static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
> int
> svcauth_unix_set_client(struct svc_rqst *rqstp)
> {
> +	struct sockaddr *sap;
> 	struct sockaddr_in *sin;
> 	struct sockaddr_in6 *sin6, sin6_storage;
> 	struct ip_map *ipm;
> @@ -667,10 +746,15 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
> 	case AF_INET:
> 		sin = svc_addr_in(rqstp);
> 		sin6 = &sin6_storage;
> +		sin6->sin6_family = AF_INET6;
> 		ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
> +		sap = (struct sockaddr *)sin6;
> 		break;
> 	case AF_INET6:
> -		sin6 = svc_addr_in6(rqstp);
> +		sap = svc_addr(rqstp);
> +		break;
> +	case AF_VSOCK:
> +		sap = svc_addr(rqstp);
> 		break;
> 	default:
> 		BUG();
> @@ -683,7 +767,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
> 	ipm = ip_map_cached_get(xprt);
> 	if (ipm == NULL)
> 		ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
> -				    &sin6->sin6_addr);
> +				    sap);
> 
> 	if (ipm == NULL)
> 		return SVC_DENIED;
> -- 
> 2.9.4
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux