inet: fix possible seqlock deadlocks
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / ping.c
index 7d93d62cd5fdae9f7f8a3f2e5c35f2a203df92e0..8cae28f5c3cf000e75c158551140010dc0e9e65f 100644 (file)
@@ -570,7 +570,7 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                err = PTR_ERR(rt);
                rt = NULL;
                if (err == -ENETUNREACH)
-                       IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
+                       IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);
                goto out;
        }
 
@@ -626,7 +626,6 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        size_t len, int noblock, int flags, int *addr_len)
 {
        struct inet_sock *isk = inet_sk(sk);
-       struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
        struct sk_buff *skb;
        int copied, err;
 
@@ -636,11 +635,8 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (flags & MSG_OOB)
                goto out;
 
-       if (addr_len)
-               *addr_len = sizeof(*sin);
-
        if (flags & MSG_ERRQUEUE)
-               return ip_recv_error(sk, msg, len);
+               return ip_recv_error(sk, msg, len, addr_len);
 
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
@@ -660,11 +656,14 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        sock_recv_timestamp(msg, sk, skb);
 
        /* Copy the address. */
-       if (sin) {
+       if (msg->msg_name) {
+               struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
+
                sin->sin_family = AF_INET;
                sin->sin_port = 0 /* skb->h.uh->source */;
                sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
+               *addr_len = sizeof(*sin);
        }
        if (isk->cmsg_flags)
                ip_cmsg_recv(msg, skb);