struct scatterlist *sge = sk_msg_elem(msg, i);
        u32 len = sge->length;
 
-       if (charge)
-               sk_mem_uncharge(sk, len);
-       if (!msg->skb)
+       /* When the skb owns the memory we free it from consume_skb path. */
+       if (!msg->skb) {
+               if (charge)
+                       sk_mem_uncharge(sk, len);
                put_page(sg_page(sge));
+       }
        memset(sge, 0, sizeof(*sge));
        return len;
 }
        int copied = 0, num_sge;
        struct sk_msg *msg;
 
+       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+               return -EAGAIN;
+
        msg = kzalloc(sizeof(*msg), __GFP_NOWARN | GFP_ATOMIC);
        if (unlikely(!msg))
                return -EAGAIN;
                return num_sge;
        }
 
-       sk_mem_charge(sk, skb->len);
+       /* This will transition ownership of the data from the socket where
+        * the BPF program was run initiating the redirect to the socket
+        * we will eventually receive this data on. The data will be released
+        * from skb_consume found in __tcp_bpf_recvmsg() after its been copied
+        * into user buffers.
+        */
+       skb_set_owner_r(skb, sk);
+
        copied = skb->len;
        msg->sg.start = 0;
        msg->sg.size = copied;