diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 15b5d845fc3b..86c8c88b702c 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -2355,9 +2355,9 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) struct gtp_dev *gtp; struct flowi4 fl4; struct rtable *rt; + int len, ret = 0; struct sock *sk; __be16 port; - int len; if (!info->attrs[GTPA_VERSION] || !info->attrs[GTPA_LINK] || @@ -2369,14 +2369,21 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) dst_ip = nla_get_be32(info->attrs[GTPA_PEER_ADDRESS]); src_ip = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); + rcu_read_lock(); gtp = gtp_find_dev(sock_net(skb->sk), info->attrs); - if (!gtp) - return -ENODEV; + if (!gtp) { + ret = -ENODEV; + goto unlock; + } - if (!gtp->sk_created) - return -EOPNOTSUPP; - if (!(gtp->dev->flags & IFF_UP)) - return -ENETDOWN; + if (!gtp->sk_created) { + ret = -EOPNOTSUPP; + goto unlock; + } + if (!(gtp->dev->flags & IFF_UP)) { + ret = -ENETDOWN; + goto unlock; + } if (version == GTP_V0) { struct gtp0_header *gtp0_h; @@ -2385,8 +2392,10 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) sizeof(struct iphdr) + sizeof(struct udphdr); skb_to_send = netdev_alloc_skb_ip_align(gtp->dev, len); - if (!skb_to_send) - return -ENOMEM; + if (!skb_to_send) { + ret = -ENOMEM; + goto unlock; + } sk = gtp->sk0; port = htons(GTP0_PORT); @@ -2402,8 +2411,10 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) sizeof(struct iphdr) + sizeof(struct udphdr); skb_to_send = netdev_alloc_skb_ip_align(gtp->dev, len); - if (!skb_to_send) - return -ENOMEM; + if (!skb_to_send) { + ret = -ENOMEM; + goto unlock; + } sk = gtp->sk1u; port = htons(GTP1U_PORT); @@ -2413,7 +2424,8 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) memset(gtp1u_h, 0, sizeof(struct gtp1_header_long)); gtp1u_build_echo_msg(gtp1u_h, GTP_ECHO_REQ); } else { - return -ENODEV; + ret = -ENODEV; + goto unlock; } rt = ip4_route_output_gtp(&fl4, sk, dst_ip, src_ip); @@ -2421,7 +2433,8 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) netdev_dbg(gtp->dev, "no route for echo request to %pI4\n", &dst_ip); kfree_skb(skb_to_send); - return -ENODEV; + ret = -ENODEV; + goto unlock; } local_bh_disable(); @@ -2435,7 +2448,10 @@ static int gtp_genl_send_echo_req(struct sk_buff *skb, struct genl_info *info) dev_net(gtp->dev)), false, 0); local_bh_enable(); - return 0; + +unlock: + rcu_read_unlock(); + return ret; } static const struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = {