|
@@ -3511,6 +3511,19 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
|
|
|
}
|
|
|
EXPORT_SYMBOL(sock_dequeue_err_skb);
|
|
|
|
|
|
+/**
|
|
|
+ * skb_clone_sk - create clone of skb, and take reference to socket
|
|
|
+ * @skb: the skb to clone
|
|
|
+ *
|
|
|
+ * This function creates a clone of a buffer that holds a reference on
|
|
|
+ * sk_refcnt. Buffers created via this function are meant to be
|
|
|
+ * returned using sock_queue_err_skb, or free via kfree_skb.
|
|
|
+ *
|
|
|
+ * When passing buffers allocated with this function to sock_queue_err_skb
|
|
|
+ * it is necessary to wrap the call with sock_hold/sock_put in order to
|
|
|
+ * prevent the socket from being released prior to being enqueued on
|
|
|
+ * the sk_error_queue.
|
|
|
+ */
|
|
|
struct sk_buff *skb_clone_sk(struct sk_buff *skb)
|
|
|
{
|
|
|
struct sock *sk = skb->sk;
|
|
@@ -3615,9 +3628,14 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
|
|
|
serr->ee.ee_errno = ENOMSG;
|
|
|
serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
|
|
|
|
|
|
+ /* take a reference to prevent skb_orphan() from freeing the socket */
|
|
|
+ sock_hold(sk);
|
|
|
+
|
|
|
err = sock_queue_err_skb(sk, skb);
|
|
|
if (err)
|
|
|
kfree_skb(skb);
|
|
|
+
|
|
|
+ sock_put(sk);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
|
|
|
|