[3/5] gtp: fix cross netns recv on gtp socket

Submitted by Andreas Schultz on Jan. 24, 2017, 5:24 p.m.

Details

Message ID 20170124172402.12096-4-aschultz@tpip.net
State New
Headers show

Commit Message

Andreas Schultz Jan. 24, 2017, 5:24 p.m.
The use of the passed through netlink src_net to check for a
cross netns operation was wrong. Using the GTP socket and the
GTP netdevice is always correct (even if the netdev has been
moved to new netns after link creation).

Remove the now obsolete net field from gtp_dev.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
---
 drivers/net/gtp.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

Comments

Pablo Neira Jan. 24, 2017, 7:15 p.m.
On Tue, Jan 24, 2017 at 06:24:00PM +0100, Andreas Schultz wrote:
> The use of the passed through netlink src_net to check for a
> cross netns operation was wrong. Using the GTP socket and the
> GTP netdevice is always correct (even if the netdev has been
> moved to new netns after link creation).
> 
> Remove the now obsolete net field from gtp_dev.

The net tree can take fixes anytime, so if you target this patch to
[PATCH net] this speeds up integration into mainline kernels. Note, as
soon as this patch hits Linus tree, we can request -stable submission
so older -stable kernels can get this.

If this follows the net-next path, then this fix is going to take
several weeks (sometimes months) to show in mainline kernels.

So please add [PATCH net] or [PATCH net-next] so it's clear to
everyone what is your target, David usually requests this.

BTW, probably you can target this small fix to net, then you can
request David to pull net into net-next so the fix propagates onwards.

Sorry for this bureaucratic stuff, but given the workload we deal
with, you will really helps us if you deal with these nitpicks.

Thanks Andreas!
kbuild test robot Jan. 24, 2017, 11:48 p.m.
Hi Andreas,

[auto build test ERROR on net-next/master]
[also build test ERROR on v4.10-rc5 next-20170124]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Andreas-Schultz/simple-gtp-improvements/20170125-051754
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   drivers/net/gtp.c: In function 'gtp_newlink':
>> drivers/net/gtp.c:677:8: error: too many arguments to function 'gtp_encap_enable'
     err = gtp_encap_enable(dev, gtp, fd0, fd1, src_net);
           ^~~~~~~~~~~~~~~~
   drivers/net/gtp.c:659:12: note: declared here
    static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
               ^~~~~~~~~~~~~~~~
   drivers/net/gtp.c: At top level:
>> drivers/net/gtp.c:822:12: error: conflicting types for 'gtp_encap_enable'
    static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
               ^~~~~~~~~~~~~~~~
   drivers/net/gtp.c:659:12: note: previous declaration of 'gtp_encap_enable' was here
    static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
               ^~~~~~~~~~~~~~~~
>> drivers/net/gtp.c:659:12: warning: 'gtp_encap_enable' used but never defined
   drivers/net/gtp.c:822:12: warning: 'gtp_encap_enable' defined but not used [-Wunused-function]
    static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
               ^~~~~~~~~~~~~~~~

vim +/gtp_encap_enable +677 drivers/net/gtp.c

459aa660 Pablo Neira     2016-05-09  653  				  sizeof(struct udphdr) +
459aa660 Pablo Neira     2016-05-09  654  				  sizeof(struct gtp0_header);
459aa660 Pablo Neira     2016-05-09  655  }
459aa660 Pablo Neira     2016-05-09  656  
459aa660 Pablo Neira     2016-05-09  657  static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
459aa660 Pablo Neira     2016-05-09  658  static void gtp_hashtable_free(struct gtp_dev *gtp);
459aa660 Pablo Neira     2016-05-09 @659  static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
0e9ed139 Andreas Schultz 2017-01-24  660  			    int fd_gtp0, int fd_gtp1);
459aa660 Pablo Neira     2016-05-09  661  
459aa660 Pablo Neira     2016-05-09  662  static int gtp_newlink(struct net *src_net, struct net_device *dev,
459aa660 Pablo Neira     2016-05-09  663  			struct nlattr *tb[], struct nlattr *data[])
459aa660 Pablo Neira     2016-05-09  664  {
459aa660 Pablo Neira     2016-05-09  665  	int hashsize, err, fd0, fd1;
459aa660 Pablo Neira     2016-05-09  666  	struct gtp_dev *gtp;
459aa660 Pablo Neira     2016-05-09  667  	struct gtp_net *gn;
459aa660 Pablo Neira     2016-05-09  668  
459aa660 Pablo Neira     2016-05-09  669  	if (!data[IFLA_GTP_FD0] || !data[IFLA_GTP_FD1])
459aa660 Pablo Neira     2016-05-09  670  		return -EINVAL;
459aa660 Pablo Neira     2016-05-09  671  
459aa660 Pablo Neira     2016-05-09  672  	gtp = netdev_priv(dev);
459aa660 Pablo Neira     2016-05-09  673  
459aa660 Pablo Neira     2016-05-09  674  	fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
459aa660 Pablo Neira     2016-05-09  675  	fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
459aa660 Pablo Neira     2016-05-09  676  
459aa660 Pablo Neira     2016-05-09 @677  	err = gtp_encap_enable(dev, gtp, fd0, fd1, src_net);
459aa660 Pablo Neira     2016-05-09  678  	if (err < 0)
459aa660 Pablo Neira     2016-05-09  679  		goto out_err;
459aa660 Pablo Neira     2016-05-09  680  
459aa660 Pablo Neira     2016-05-09  681  	if (!data[IFLA_GTP_PDP_HASHSIZE])
459aa660 Pablo Neira     2016-05-09  682  		hashsize = 1024;
459aa660 Pablo Neira     2016-05-09  683  	else
459aa660 Pablo Neira     2016-05-09  684  		hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
459aa660 Pablo Neira     2016-05-09  685  
459aa660 Pablo Neira     2016-05-09  686  	err = gtp_hashtable_new(gtp, hashsize);
459aa660 Pablo Neira     2016-05-09  687  	if (err < 0)
459aa660 Pablo Neira     2016-05-09  688  		goto out_encap;
459aa660 Pablo Neira     2016-05-09  689  
459aa660 Pablo Neira     2016-05-09  690  	err = register_netdevice(dev);
459aa660 Pablo Neira     2016-05-09  691  	if (err < 0) {
459aa660 Pablo Neira     2016-05-09  692  		netdev_dbg(dev, "failed to register new netdev %d\n", err);
459aa660 Pablo Neira     2016-05-09  693  		goto out_hashtable;
459aa660 Pablo Neira     2016-05-09  694  	}
459aa660 Pablo Neira     2016-05-09  695  
459aa660 Pablo Neira     2016-05-09  696  	gn = net_generic(dev_net(dev), gtp_net_id);
459aa660 Pablo Neira     2016-05-09  697  	list_add_rcu(&gtp->list, &gn->gtp_dev_list);
459aa660 Pablo Neira     2016-05-09  698  
459aa660 Pablo Neira     2016-05-09  699  	netdev_dbg(dev, "registered new GTP interface\n");
459aa660 Pablo Neira     2016-05-09  700  
459aa660 Pablo Neira     2016-05-09  701  	return 0;
459aa660 Pablo Neira     2016-05-09  702  
459aa660 Pablo Neira     2016-05-09  703  out_hashtable:
459aa660 Pablo Neira     2016-05-09  704  	gtp_hashtable_free(gtp);
459aa660 Pablo Neira     2016-05-09  705  out_encap:
459aa660 Pablo Neira     2016-05-09  706  	gtp_encap_disable(gtp);
459aa660 Pablo Neira     2016-05-09  707  out_err:
459aa660 Pablo Neira     2016-05-09  708  	return err;
459aa660 Pablo Neira     2016-05-09  709  }
459aa660 Pablo Neira     2016-05-09  710  
459aa660 Pablo Neira     2016-05-09  711  static void gtp_dellink(struct net_device *dev, struct list_head *head)
459aa660 Pablo Neira     2016-05-09  712  {
459aa660 Pablo Neira     2016-05-09  713  	struct gtp_dev *gtp = netdev_priv(dev);
459aa660 Pablo Neira     2016-05-09  714  
459aa660 Pablo Neira     2016-05-09  715  	gtp_encap_disable(gtp);
459aa660 Pablo Neira     2016-05-09  716  	gtp_hashtable_free(gtp);
459aa660 Pablo Neira     2016-05-09  717  	list_del_rcu(&gtp->list);
459aa660 Pablo Neira     2016-05-09  718  	unregister_netdevice_queue(dev, head);
459aa660 Pablo Neira     2016-05-09  719  }
459aa660 Pablo Neira     2016-05-09  720  
459aa660 Pablo Neira     2016-05-09  721  static const struct nla_policy gtp_policy[IFLA_GTP_MAX + 1] = {
459aa660 Pablo Neira     2016-05-09  722  	[IFLA_GTP_FD0]			= { .type = NLA_U32 },
459aa660 Pablo Neira     2016-05-09  723  	[IFLA_GTP_FD1]			= { .type = NLA_U32 },
459aa660 Pablo Neira     2016-05-09  724  	[IFLA_GTP_PDP_HASHSIZE]		= { .type = NLA_U32 },
459aa660 Pablo Neira     2016-05-09  725  };
459aa660 Pablo Neira     2016-05-09  726  
459aa660 Pablo Neira     2016-05-09  727  static int gtp_validate(struct nlattr *tb[], struct nlattr *data[])
459aa660 Pablo Neira     2016-05-09  728  {
459aa660 Pablo Neira     2016-05-09  729  	if (!data)
459aa660 Pablo Neira     2016-05-09  730  		return -EINVAL;
459aa660 Pablo Neira     2016-05-09  731  
459aa660 Pablo Neira     2016-05-09  732  	return 0;
459aa660 Pablo Neira     2016-05-09  733  }
459aa660 Pablo Neira     2016-05-09  734  
459aa660 Pablo Neira     2016-05-09  735  static size_t gtp_get_size(const struct net_device *dev)
459aa660 Pablo Neira     2016-05-09  736  {
459aa660 Pablo Neira     2016-05-09  737  	return nla_total_size(sizeof(__u32));	/* IFLA_GTP_PDP_HASHSIZE */
459aa660 Pablo Neira     2016-05-09  738  }
459aa660 Pablo Neira     2016-05-09  739  
459aa660 Pablo Neira     2016-05-09  740  static int gtp_fill_info(struct sk_buff *skb, const struct net_device *dev)
459aa660 Pablo Neira     2016-05-09  741  {
459aa660 Pablo Neira     2016-05-09  742  	struct gtp_dev *gtp = netdev_priv(dev);
459aa660 Pablo Neira     2016-05-09  743  
459aa660 Pablo Neira     2016-05-09  744  	if (nla_put_u32(skb, IFLA_GTP_PDP_HASHSIZE, gtp->hash_size))
459aa660 Pablo Neira     2016-05-09  745  		goto nla_put_failure;
459aa660 Pablo Neira     2016-05-09  746  
459aa660 Pablo Neira     2016-05-09  747  	return 0;
459aa660 Pablo Neira     2016-05-09  748  
459aa660 Pablo Neira     2016-05-09  749  nla_put_failure:
459aa660 Pablo Neira     2016-05-09  750  	return -EMSGSIZE;
459aa660 Pablo Neira     2016-05-09  751  }
459aa660 Pablo Neira     2016-05-09  752  
459aa660 Pablo Neira     2016-05-09  753  static struct rtnl_link_ops gtp_link_ops __read_mostly = {
459aa660 Pablo Neira     2016-05-09  754  	.kind		= "gtp",
459aa660 Pablo Neira     2016-05-09  755  	.maxtype	= IFLA_GTP_MAX,
459aa660 Pablo Neira     2016-05-09  756  	.policy		= gtp_policy,
459aa660 Pablo Neira     2016-05-09  757  	.priv_size	= sizeof(struct gtp_dev),
459aa660 Pablo Neira     2016-05-09  758  	.setup		= gtp_link_setup,
459aa660 Pablo Neira     2016-05-09  759  	.validate	= gtp_validate,
459aa660 Pablo Neira     2016-05-09  760  	.newlink	= gtp_newlink,
459aa660 Pablo Neira     2016-05-09  761  	.dellink	= gtp_dellink,
459aa660 Pablo Neira     2016-05-09  762  	.get_size	= gtp_get_size,
459aa660 Pablo Neira     2016-05-09  763  	.fill_info	= gtp_fill_info,
459aa660 Pablo Neira     2016-05-09  764  };
459aa660 Pablo Neira     2016-05-09  765  
459aa660 Pablo Neira     2016-05-09  766  static struct net *gtp_genl_get_net(struct net *src_net, struct nlattr *tb[])
459aa660 Pablo Neira     2016-05-09  767  {
459aa660 Pablo Neira     2016-05-09  768  	struct net *net;
459aa660 Pablo Neira     2016-05-09  769  
459aa660 Pablo Neira     2016-05-09  770  	/* Examine the link attributes and figure out which network namespace
459aa660 Pablo Neira     2016-05-09  771  	 * we are talking about.
459aa660 Pablo Neira     2016-05-09  772  	 */
459aa660 Pablo Neira     2016-05-09  773  	if (tb[GTPA_NET_NS_FD])
459aa660 Pablo Neira     2016-05-09  774  		net = get_net_ns_by_fd(nla_get_u32(tb[GTPA_NET_NS_FD]));
459aa660 Pablo Neira     2016-05-09  775  	else
459aa660 Pablo Neira     2016-05-09  776  		net = get_net(src_net);
459aa660 Pablo Neira     2016-05-09  777  
459aa660 Pablo Neira     2016-05-09  778  	return net;
459aa660 Pablo Neira     2016-05-09  779  }
459aa660 Pablo Neira     2016-05-09  780  
459aa660 Pablo Neira     2016-05-09  781  static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
459aa660 Pablo Neira     2016-05-09  782  {
459aa660 Pablo Neira     2016-05-09  783  	int i;
459aa660 Pablo Neira     2016-05-09  784  
459aa660 Pablo Neira     2016-05-09  785  	gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL);
459aa660 Pablo Neira     2016-05-09  786  	if (gtp->addr_hash == NULL)
459aa660 Pablo Neira     2016-05-09  787  		return -ENOMEM;
459aa660 Pablo Neira     2016-05-09  788  
459aa660 Pablo Neira     2016-05-09  789  	gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL);
459aa660 Pablo Neira     2016-05-09  790  	if (gtp->tid_hash == NULL)
459aa660 Pablo Neira     2016-05-09  791  		goto err1;
459aa660 Pablo Neira     2016-05-09  792  
459aa660 Pablo Neira     2016-05-09  793  	gtp->hash_size = hsize;
459aa660 Pablo Neira     2016-05-09  794  
459aa660 Pablo Neira     2016-05-09  795  	for (i = 0; i < hsize; i++) {
459aa660 Pablo Neira     2016-05-09  796  		INIT_HLIST_HEAD(&gtp->addr_hash[i]);
459aa660 Pablo Neira     2016-05-09  797  		INIT_HLIST_HEAD(&gtp->tid_hash[i]);
459aa660 Pablo Neira     2016-05-09  798  	}
459aa660 Pablo Neira     2016-05-09  799  	return 0;
459aa660 Pablo Neira     2016-05-09  800  err1:
459aa660 Pablo Neira     2016-05-09  801  	kfree(gtp->addr_hash);
459aa660 Pablo Neira     2016-05-09  802  	return -ENOMEM;
459aa660 Pablo Neira     2016-05-09  803  }
459aa660 Pablo Neira     2016-05-09  804  
459aa660 Pablo Neira     2016-05-09  805  static void gtp_hashtable_free(struct gtp_dev *gtp)
459aa660 Pablo Neira     2016-05-09  806  {
459aa660 Pablo Neira     2016-05-09  807  	struct pdp_ctx *pctx;
459aa660 Pablo Neira     2016-05-09  808  	int i;
459aa660 Pablo Neira     2016-05-09  809  
459aa660 Pablo Neira     2016-05-09  810  	for (i = 0; i < gtp->hash_size; i++) {
459aa660 Pablo Neira     2016-05-09  811  		hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
459aa660 Pablo Neira     2016-05-09  812  			hlist_del_rcu(&pctx->hlist_tid);
459aa660 Pablo Neira     2016-05-09  813  			hlist_del_rcu(&pctx->hlist_addr);
459aa660 Pablo Neira     2016-05-09  814  			kfree_rcu(pctx, rcu_head);
459aa660 Pablo Neira     2016-05-09  815  		}
459aa660 Pablo Neira     2016-05-09  816  	}
459aa660 Pablo Neira     2016-05-09  817  	synchronize_rcu();
459aa660 Pablo Neira     2016-05-09  818  	kfree(gtp->addr_hash);
459aa660 Pablo Neira     2016-05-09  819  	kfree(gtp->tid_hash);
459aa660 Pablo Neira     2016-05-09  820  }
459aa660 Pablo Neira     2016-05-09  821  
459aa660 Pablo Neira     2016-05-09 @822  static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
459aa660 Pablo Neira     2016-05-09  823  			    int fd_gtp0, int fd_gtp1, struct net *src_net)
459aa660 Pablo Neira     2016-05-09  824  {
459aa660 Pablo Neira     2016-05-09  825  	struct udp_tunnel_sock_cfg tuncfg = {NULL};

:::::: The code at line 677 was first introduced by commit
:::::: 459aa660eb1d8ce67080da1983bb81d716aa5a69 gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)

:::::: TO: Pablo Neira <pablo@netfilter.org>
:::::: CC: David S. Miller <davem@davemloft.net>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch hide | download patch | download mbox

diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index 1df54d6..72dd1ba 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -69,7 +69,6 @@  struct gtp_dev {
 	struct socket		*sock0;
 	struct socket		*sock1u;
 
-	struct net		*net;
 	struct net_device	*dev;
 
 	unsigned int		hash_size;
@@ -316,7 +315,7 @@  static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
 	netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk);
 
-	xnet = !net_eq(gtp->net, dev_net(gtp->dev));
+	xnet = !net_eq(sock_net(sk), dev_net(gtp->dev));
 
 	switch (udp_sk(sk)->encap_type) {
 	case UDP_ENCAP_GTP0:
@@ -658,7 +657,7 @@  static void gtp_link_setup(struct net_device *dev)
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
 static void gtp_hashtable_free(struct gtp_dev *gtp);
 static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
-			    int fd_gtp0, int fd_gtp1, struct net *src_net);
+			    int fd_gtp0, int fd_gtp1);
 
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 			struct nlattr *tb[], struct nlattr *data[])
@@ -858,7 +857,6 @@  static int gtp_encap_enable(struct net_device *dev, struct gtp_dev *gtp,
 
 	gtp->sock0 = sock0;
 	gtp->sock1u = sock1u;
-	gtp->net = src_net;
 
 	tuncfg.sk_user_data = gtp;
 	tuncfg.encap_rcv = gtp_encap_recv;