diff options
Diffstat (limited to 'net/core/timestamping.c')
| -rw-r--r-- | net/core/timestamping.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 98a52640e7cd..82fb28857b64 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
| @@ -57,9 +57,13 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
| 57 | case PTP_CLASS_V2_VLAN: | 57 | case PTP_CLASS_V2_VLAN: |
| 58 | phydev = skb->dev->phydev; | 58 | phydev = skb->dev->phydev; |
| 59 | if (likely(phydev->drv->txtstamp)) { | 59 | if (likely(phydev->drv->txtstamp)) { |
| 60 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
| 61 | return; | ||
| 60 | clone = skb_clone(skb, GFP_ATOMIC); | 62 | clone = skb_clone(skb, GFP_ATOMIC); |
| 61 | if (!clone) | 63 | if (!clone) { |
| 64 | sock_put(sk); | ||
| 62 | return; | 65 | return; |
| 66 | } | ||
| 63 | clone->sk = sk; | 67 | clone->sk = sk; |
| 64 | phydev->drv->txtstamp(phydev, clone, type); | 68 | phydev->drv->txtstamp(phydev, clone, type); |
| 65 | } | 69 | } |
| @@ -77,8 +81,11 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
| 77 | struct sock_exterr_skb *serr; | 81 | struct sock_exterr_skb *serr; |
| 78 | int err; | 82 | int err; |
| 79 | 83 | ||
| 80 | if (!hwtstamps) | 84 | if (!hwtstamps) { |
| 85 | sock_put(sk); | ||
| 86 | kfree_skb(skb); | ||
| 81 | return; | 87 | return; |
| 88 | } | ||
| 82 | 89 | ||
| 83 | *skb_hwtstamps(skb) = *hwtstamps; | 90 | *skb_hwtstamps(skb) = *hwtstamps; |
| 84 | serr = SKB_EXT_ERR(skb); | 91 | serr = SKB_EXT_ERR(skb); |
| @@ -87,6 +94,7 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
| 87 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 94 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
| 88 | skb->sk = NULL; | 95 | skb->sk = NULL; |
| 89 | err = sock_queue_err_skb(sk, skb); | 96 | err = sock_queue_err_skb(sk, skb); |
| 97 | sock_put(sk); | ||
| 90 | if (err) | 98 | if (err) |
| 91 | kfree_skb(skb); | 99 | kfree_skb(skb); |
| 92 | } | 100 | } |
