Re: [PATCH v3 1/2] Add check of clientaddr argument

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

 




On 06/05/2018 03:29 PM, Olga Kornievskaia wrote:
> If the NFS client administrator supplies the clientaddr mount
> option, it should be either a special value of either IPv4/IPv6
> any address or one of the machine's network addresses. Otherwise,
> warn the administrator about the use of an arbitrary value for
> the clientaddr value.
> 
> Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx>
Committed... 

steved.
> `
> ---
>  utils/mount/network.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  utils/mount/network.h |  2 ++
>  utils/mount/stropts.c | 24 ++++++++++++++++++++++--
>  3 files changed, 69 insertions(+), 2 deletions(-)
> 
> diff --git a/utils/mount/network.c b/utils/mount/network.c
> index e490399..2a54f82 100644
> --- a/utils/mount/network.c
> +++ b/utils/mount/network.c
> @@ -50,6 +50,8 @@
>  #include <rpc/rpc.h>
>  #include <rpc/pmap_prot.h>
>  #include <rpc/pmap_clnt.h>
> +#include <net/if.h>
> +#include <ifaddrs.h>
>  
>  #include "sockaddr.h"
>  #include "xcommon.h"
> @@ -1759,3 +1761,46 @@ int nfs_umount_do_umnt(struct mount_options *options,
>  
>  	return EX_SUCCESS;
>  }
> +
> +int nfs_is_inaddr_any(struct sockaddr *nfs_saddr)
> +{
> +	switch (nfs_saddr->sa_family) {
> +	case AF_INET: {
> +		if (((struct sockaddr_in *)nfs_saddr)->sin_addr.s_addr ==
> +				INADDR_ANY)
> +			return 1;
> +	}
> +	case AF_INET6:
> +		if (!memcmp(&((struct sockaddr_in6 *)nfs_saddr)->sin6_addr,
> +				&in6addr_any, sizeof(in6addr_any)))
> +			return 1;
> +	}
> +	return 0;
> +}
> +
> +int nfs_addr_matches_localips(struct sockaddr *nfs_saddr)
> +{
> +	struct ifaddrs *myaddrs, *ifa;
> +	int found = 0;
> +
> +	/* acquire exiting network interfaces */
> +	if (getifaddrs(&myaddrs) != 0)
> +		return 0;
> +
> +	/* interate over the available interfaces and check if we
> +	 * we find a match to the supplied clientaddr value
> +	 */
> +	for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
> +		if (ifa->ifa_addr == NULL)
> +			continue;
> +		if (!(ifa->ifa_flags & IFF_UP))
> +			continue;
> +		if (!memcmp(ifa->ifa_addr, nfs_saddr,
> +				sizeof(struct sockaddr))) {
> +			found = 1;
> +			break;
> +		}
> +	}
> +	freeifaddrs(myaddrs);
> +	return found;
> +}
> diff --git a/utils/mount/network.h b/utils/mount/network.h
> index ecaac33..0fc98ac 100644
> --- a/utils/mount/network.h
> +++ b/utils/mount/network.h
> @@ -54,6 +54,8 @@ int nfs_callback_address(const struct sockaddr *, const socklen_t,
>  int clnt_ping(struct sockaddr_in *, const unsigned long,
>  		const unsigned long, const unsigned int,
>  		struct sockaddr_in *);
> +int nfs_is_inaddr_any(struct sockaddr *);
> +int nfs_addr_matches_localips(struct sockaddr *);
>  
>  struct mount_options;
>  
> diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
> index d1b0708..4d2e37e 100644
> --- a/utils/mount/stropts.c
> +++ b/utils/mount/stropts.c
> @@ -229,7 +229,8 @@ static int nfs_append_addr_option(const struct sockaddr *sap,
>  
>  /*
>   * Called to discover our address and append an appropriate 'clientaddr='
> - * option to the options string.
> + * option to the options string. If the supplied 'clientaddr=' value does
> + * not match either IPV4/IPv6 any or a local address, then fail the mount.
>   *
>   * Returns 1 if 'clientaddr=' option created successfully or if
>   * 'clientaddr=' option is already present; otherwise zero.
> @@ -242,8 +243,27 @@ static int nfs_append_clientaddr_option(const struct sockaddr *sap,
>  	struct sockaddr *my_addr = &address.sa;
>  	socklen_t my_len = sizeof(address);
>  
> -	if (po_contains(options, "clientaddr") == PO_FOUND)
> +	if (po_contains(options, "clientaddr") == PO_FOUND) {
> +		char *addr = po_get(options, "clientaddr");
> +		union nfs_sockaddr nfs_address;
> +		struct sockaddr *nfs_saddr = &nfs_address.sa;
> +		socklen_t nfs_salen = sizeof(nfs_address);
> +
> +		/* translate the input for clientaddr to nfs_sockaddr */
> +		if (!nfs_string_to_sockaddr(addr, nfs_saddr, &nfs_salen))
> +			return 0;
> +
> +		/* check for IPV4_ANY and IPV6_ANY */
> +		if (nfs_is_inaddr_any(nfs_saddr))
> +			return 1;
> +
> +		/* check if ip matches local network addresses */
> +		if (!nfs_addr_matches_localips(nfs_saddr))
> +			nfs_error(_("%s: [warning] supplied clientaddr=%s "
> +				"does not match any existing network "
> +				"addresses"), progname, addr);
>  		return 1;
> +	}
>  
>  	nfs_callback_address(sap, salen, my_addr, &my_len);
>  
> 
--
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