lkml.org 
[lkml]   [2021]   [Aug]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 23/35] net: Fix zero-copy head len calculation.
    Date
    From: Pravin B Shelar <pshelar@ovn.org>

    [ Upstream commit a17ad0961706244dce48ec941f7e476a38c0e727 ]

    In some cases skb head could be locked and entire header
    data is pulled from skb. When skb_zerocopy() called in such cases,
    following BUG is triggered. This patch fixes it by copying entire
    skb in such cases.
    This could be optimized incase this is performance bottleneck.

    ---8<---
    kernel BUG at net/core/skbuff.c:2961!
    invalid opcode: 0000 [#1] SMP PTI
    CPU: 2 PID: 0 Comm: swapper/2 Tainted: G OE 5.4.0-77-generic #86-Ubuntu
    Hardware name: OpenStack Foundation OpenStack Nova, BIOS 1.13.0-1ubuntu1.1 04/01/2014
    RIP: 0010:skb_zerocopy+0x37a/0x3a0
    RSP: 0018:ffffbcc70013ca38 EFLAGS: 00010246
    Call Trace:
    <IRQ>
    queue_userspace_packet+0x2af/0x5e0 [openvswitch]
    ovs_dp_upcall+0x3d/0x60 [openvswitch]
    ovs_dp_process_packet+0x125/0x150 [openvswitch]
    ovs_vport_receive+0x77/0xd0 [openvswitch]
    netdev_port_receive+0x87/0x130 [openvswitch]
    netdev_frame_hook+0x4b/0x60 [openvswitch]
    __netif_receive_skb_core+0x2b4/0xc90
    __netif_receive_skb_one_core+0x3f/0xa0
    __netif_receive_skb+0x18/0x60
    process_backlog+0xa9/0x160
    net_rx_action+0x142/0x390
    __do_softirq+0xe1/0x2d6
    irq_exit+0xae/0xb0
    do_IRQ+0x5a/0xf0
    common_interrupt+0xf/0xf

    Code that triggered BUG:
    int
    skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
    {
    int i, j = 0;
    int plen = 0; /* length of skb->head fragment */
    int ret;
    struct page *page;
    unsigned int offset;

    BUG_ON(!from->head_frag && !hlen);

    Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/core/skbuff.c | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

    diff --git a/net/core/skbuff.c b/net/core/skbuff.c
    index 30ca61d91b69..17b93177a68f 100644
    --- a/net/core/skbuff.c
    +++ b/net/core/skbuff.c
    @@ -3006,8 +3006,11 @@ skb_zerocopy_headlen(const struct sk_buff *from)

    if (!from->head_frag ||
    skb_headlen(from) < L1_CACHE_BYTES ||
    - skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
    + skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) {
    hlen = skb_headlen(from);
    + if (!hlen)
    + hlen = from->len;
    + }

    if (skb_has_frag_list(from))
    hlen = from->len;
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-08-06 10:24    [W:4.102 / U:1.304 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site