lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Tue, 23 Apr 2013 17:05:50 -0700
From:	Eric Dumazet <eric.dumazet@...il.com>
To:	Pravin B Shelar <pshelar@...ira.com>
Cc:	davem@...emloft.net, netdev@...r.kernel.org
Subject: Re: [PATCH RFC net-next] ipv6: Kill ipv6 dependency of
 icmpv6_send().

On Tue, 2013-04-23 at 16:49 -0700, Pravin B Shelar wrote:
> Following patch adds icmp-registration module for ipv6.  It allows
> ipv6 protocol to register icmp_sender which is used for sending
> ipv6 icmp msgs.  This extra layer allows us to kill dependency
> on ipv6 for icmpv6_send() function.
> 
> This patch also fixes ip_tunnel compilation problem when ip_tunnel
> is statically compiled in kernel but ipv6 is module.
> 
> Signed-off-by: Pravin B Shelar <pshelar@...ira.com>
> ---
>  include/linux/icmpv6.h |   18 +++++++++++--
>  net/ipv6/Makefile      |    2 +-
>  net/ipv6/icmp.c        |   35 +++++++++++++++-----------
>  net/ipv6/ip6_icmp.c    |   64 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 100 insertions(+), 19 deletions(-)
>  create mode 100644 net/ipv6/ip6_icmp.c
> 
> diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
> index b4f6c29..630f453 100644
> --- a/include/linux/icmpv6.h
> +++ b/include/linux/icmpv6.h
> @@ -11,9 +11,21 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb)
>  
>  #include <linux/netdevice.h>
>  
> -extern void				icmpv6_send(struct sk_buff *skb,
> -						    u8 type, u8 code,
> -						    __u32 info);
> +#if IS_ENABLED(CONFIG_IPV6)
> +extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info);
> +
> +typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info);
> +extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn);
> +extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn);
> +
> +#else
> +
> +static inline void icmpv6_send(struct sk_buff *skb,
> +			       u8 type, u8 code, __u32 info)
> +{
> +
> +}
> +#endif
>  
>  extern int				icmpv6_init(void);
>  extern int				icmpv6_err_convert(u8 type, u8 code,
> diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
> index 309af19..9af088d 100644
> --- a/net/ipv6/Makefile
> +++ b/net/ipv6/Makefile
> @@ -40,7 +40,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o
>  obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
>  obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
>  
> -obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o
> +obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o
>  obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
>  
>  obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
> diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
> index 71b900c..2a53a79 100644
> --- a/net/ipv6/icmp.c
> +++ b/net/ipv6/icmp.c
> @@ -124,15 +124,6 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
>  }
>  
>  /*
> - * Slightly more convenient version of icmpv6_send.
> - */
> -void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos)
> -{
> -	icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos);
> -	kfree_skb(skb);
> -}
> -
> -/*
>   * Figure out, may we reply to this packet with icmp error.
>   *
>   * We do not reply, if:
> @@ -332,7 +323,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *sk
>  	 * anycast.
>  	 */
>  	if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
> -		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n");
> +		LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: acast source\n");
>  		dst_release(dst);
>  		return ERR_PTR(-EINVAL);
>  	}
> @@ -381,7 +372,7 @@ relookup_failed:
>  /*
>   *	Send an ICMP message in response to a packet in error
>   */
> -void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
> +static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
>  {
>  	struct net *net = dev_net(skb->dev);
>  	struct inet6_dev *idev = NULL;
> @@ -406,7 +397,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
>  	/*
>  	 *	Make sure we respect the rules
>  	 *	i.e. RFC 1885 2.4(e)
> -	 *	Rule (e.1) is enforced by not using icmpv6_send
> +	 *	Rule (e.1) is enforced by not using icmp6_send
>  	 *	in any code that processes icmp errors.
>  	 */
>  	addr_type = ipv6_addr_type(&hdr->daddr);
> @@ -444,7 +435,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
>  	 *	and anycast addresses will be checked later.
>  	 */
>  	if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
> -		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
> +		LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: addr_any/mcast source\n");
>  		return;
>  	}
>  
> @@ -452,7 +443,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
>  	 *	Never answer to a ICMP packet.
>  	 */
>  	if (is_ineligible(skb)) {
> -		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n");
> +		LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: no reply to icmp error\n");
>  		return;
>  	}
>  
> @@ -529,7 +520,14 @@ out_dst_release:
>  out:
>  	icmpv6_xmit_unlock(sk);
>  }
> -EXPORT_SYMBOL(icmpv6_send);
> +
> +/* Slightly more convenient version of icmp6_send.
> + */
> +void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos)
> +{
> +	icmp6_send(skb, ICMPV6_PARAMPROB, code, pos);
> +	kfree_skb(skb);
> +}
>  
>  static void icmpv6_echo_reply(struct sk_buff *skb)
>  {
> @@ -885,8 +883,14 @@ int __init icmpv6_init(void)
>  	err = -EAGAIN;
>  	if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0)
>  		goto fail;
> +
> +	err = inet6_register_icmp_sender(icmp6_send);
> +	if (err)
> +		goto sender_reg_err;
>  	return 0;
>  
> +sender_reg_err:
> +	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
>  fail:
>  	pr_err("Failed to register ICMP6 protocol\n");
>  	unregister_pernet_subsys(&icmpv6_sk_ops);
> @@ -895,6 +899,7 @@ fail:
>  
>  void icmpv6_cleanup(void)
>  {
> +	inet6_unregister_icmp_sender(icmp6_send);
>  	unregister_pernet_subsys(&icmpv6_sk_ops);
>  	inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
>  }
> diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c
> new file mode 100644
> index 0000000..cfcc563
> --- /dev/null
> +++ b/net/ipv6/ip6_icmp.c
> @@ -0,0 +1,64 @@
> +#include <linux/export.h>
> +#include <linux/icmpv6.h>
> +#include <linux/mutex.h>
> +#include <linux/netdevice.h>
> +#include <linux/spinlock.h>
> +
> +#include <net/ipv6.h>
> +
> +#if IS_ENABLED(CONFIG_IPV6)
> +
> +static ip6_icmp_send_t __rcu *ip6_icmp_send;
> +static DEFINE_MUTEX(handler_lock);
> +
> +int inet6_register_icmp_sender(ip6_icmp_send_t *fn)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&handler_lock);
> +	if (rcu_dereference(ip6_icmp_send)) {

rcu_dereference_protected()

> +		ret = -EBUSY;
> +		goto out;
> +	}
> +	rcu_assign_pointer(ip6_icmp_send, fn);
> +
> +out:
> +	mutex_unlock(&handler_lock);
> +	return ret;
> +}
> +EXPORT_SYMBOL(inet6_register_icmp_sender);
> +
> +int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&handler_lock);
> +	if (rcu_dereference(ip6_icmp_send) != fn) {

rcu_dereference_protected()

> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	rcu_assign_pointer(ip6_icmp_send, NULL);
> +
> +out:
> +	mutex_unlock(&handler_lock);
> +	synchronize_net();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(inet6_unregister_icmp_sender);
> +
> +void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
> +{
> +	ip6_icmp_send_t *send;
> +
> +	rcu_read_lock();
> +	send = rcu_dereference(ip6_icmp_send);
> +
> +	if (!send)
> +		goto out;
> +	send(skb, type, code, info);
> +out:
> +	rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(icmpv6_send);
> +#endif


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

Powered by blists - more mailing lists