]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
DTrace: IP provider use-after-free for drop-out probe points
authorAlan Maguire <alan.maguire@oracle.com>
Wed, 14 Jun 2017 13:06:27 +0000 (14:06 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 20 Jun 2017 14:16:58 +0000 (15:16 +0100)
KASan warnings showed a possible use-after-free for skbs in error handling
codepath after netfilter hooks have run.  Hooks may free the skb, so we
should not derefence it at drop-out probe points after NF_HOOK().

Orabug: 26267376

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Reviewed-by: Girish Moodalbail <girish.moodalbail@oracle.com>
net/ipv4/ip_output.c
net/ipv6/ip6_output.c
net/ipv6/mcast.c

index 3326ba9c04280d5cc533877e8efbd586fbe62a34..c0de7f623b1e487e1c06fa555c3d3a95b364e500 100644 (file)
@@ -1473,15 +1473,14 @@ int ip_send_skb(struct net *net, struct sk_buff *skb)
                if (err > 0)
                        err = net_xmit_errno(err);
                if (err) {
-                       struct iphdr *iph = ip_hdr(skb);
-
                        IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
+                       /* skb may have been freed */
                        DTRACE_IP(drop__out,
-                           struct sk_buff * : pktinfo_t *, skb,
-                           struct sock * : csinfo_t *, skb->sk,
-                           void_ip_t * : ipinfo_t *, iph,
-                           struct net_device * : ifinfo_t *, skb->dev,
-                           struct iphdr * : ipv4info_t *, iph,
+                           struct sk_buff * : pktinfo_t *, NULL,
+                           struct sock * : csinfo_t *, NULL,
+                           void_ip_t * : ipinfo_t *, NULL,
+                           struct net_device * : ifinfo_t *, NULL,
+                           struct iphdr * : ipv4info_t *, NULL,
                            struct ipv6hdr * : ipv6info_t *, NULL,
                            char * : string, "packet too short");
                }
index 4abbd63e6f8d39425c023f1ae9bd2a75abce0227..c5320592b3af5386dbb539e418be60882a08c6f8 100644 (file)
@@ -1800,13 +1800,14 @@ int ip6_send_skb(struct sk_buff *skb)
                if (err > 0)
                        err = net_xmit_errno(err);
                if (err) {
+                       /* skb may have been freed */
                        DTRACE_IP(drop__out,
-                           struct sk_buff * : pktinfo_t *, skb,
-                           struct sock * : csinfo_t *, skb->sk,
-                           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
-                           struct net_device * : ifinfo_t *, skb->dev,
+                           struct sk_buff * : pktinfo_t *, NULL,
+                           struct sock * : csinfo_t *, NULL,
+                           void_ip_t * : ipinfo_t *, NULL,
+                           struct net_device * : ifinfo_t *, NULL,
                            struct iphdr * : ipv4info_t *, NULL,
-                           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb),
+                           struct ipv6hdr * : ipv6info_t *, NULL,
                            char * : string, "out of memory");
 
                        IP6_INC_STATS(net, rt->rt6i_idev,
index 63397220b675b7d614cf45e1bfe898d1196b25eb..c7620faeb2dbfefbd30b32c28802c9eae666c02d 100644 (file)
@@ -1666,13 +1666,14 @@ out:
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
                IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
        } else {
+               /* skb may have been freed */
                DTRACE_IP(drop__out,
-                   struct sk_buff * : pktinfo_t *, skb,
-                   struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-                   void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
-                   struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+                   struct sk_buff * : pktinfo_t *, NULL,
+                   struct sock * : csinfo_t *, NULL,
+                   void_ip_t * : ipinfo_t *, NULL,
+                   struct net_device * : ifinfo_t *, idev->dev,
                    struct iphdr * : ipv4info_t *, NULL,
-                   struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
+                   struct ipv6hdr * : ipv6info_t *, NULL,
                    char * : string, "multicast send error");
 
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
@@ -2054,13 +2055,14 @@ out:
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
                IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len);
        } else {
+               /* skb may have been freed */
                DTRACE_IP(drop__out,
-                   struct sk_buff * : pktinfo_t *, skb,
-                   struct sock * : csinfo_t *, skb ? skb->sk : NULL,
-                   void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
-                   struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+                   struct sk_buff * : pktinfo_t *, NULL,
+                   struct sock * : csinfo_t *, sk,
+                   void_ip_t * : ipinfo_t *, NULL,
+                   struct net_device * : ifinfo_t *, idev->dev,
                    struct iphdr * : ipv4info_t *, NULL,
-                   struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
+                   struct ipv6hdr * : ipv6info_t *, NULL,
                    char * : string, "multicast send error");
 
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);