• X
    tipc: skb_linearize the head skb when reassembling msgs · 29102688
    Xin Long 提交于
    stable inclusion
    from stable-5.10.42
    commit 6da24cfc83ba4f97ea44fc7ae9999a006101755c
    bugzilla: 55093
    CVE: NA
    
    --------------------------------
    
    commit b7df21cf upstream.
    
    It's not a good idea to append the frag skb to a skb's frag_list if
    the frag_list already has skbs from elsewhere, such as this skb was
    created by pskb_copy() where the frag_list was cloned (all the skbs
    in it were skb_get'ed) and shared by multiple skbs.
    
    However, the new appended frag skb should have been only seen by the
    current skb. Otherwise, it will cause use after free crashes as this
    appended frag skb are seen by multiple skbs but it only got skb_get
    called once.
    
    The same thing happens with a skb updated by pskb_may_pull() with a
    skb_cloned skb. Li Shuang has reported quite a few crashes caused
    by this when doing testing over macvlan devices:
    
      [] kernel BUG at net/core/skbuff.c:1970!
      [] Call Trace:
      []  skb_clone+0x4d/0xb0
      []  macvlan_broadcast+0xd8/0x160 [macvlan]
      []  macvlan_process_broadcast+0x148/0x150 [macvlan]
      []  process_one_work+0x1a7/0x360
      []  worker_thread+0x30/0x390
    
      [] kernel BUG at mm/usercopy.c:102!
      [] Call Trace:
      []  __check_heap_object+0xd3/0x100
      []  __check_object_size+0xff/0x16b
      []  simple_copy_to_iter+0x1c/0x30
      []  __skb_datagram_iter+0x7d/0x310
      []  __skb_datagram_iter+0x2a5/0x310
      []  skb_copy_datagram_iter+0x3b/0x90
      []  tipc_recvmsg+0x14a/0x3a0 [tipc]
      []  ____sys_recvmsg+0x91/0x150
      []  ___sys_recvmsg+0x7b/0xc0
    
      [] kernel BUG at mm/slub.c:305!
      [] Call Trace:
      []  <IRQ>
      []  kmem_cache_free+0x3ff/0x400
      []  __netif_receive_skb_core+0x12c/0xc40
      []  ? kmem_cache_alloc+0x12e/0x270
      []  netif_receive_skb_internal+0x3d/0xb0
      []  ? get_rx_page_info+0x8e/0xa0 [be2net]
      []  be_poll+0x6ef/0xd00 [be2net]
      []  ? irq_exit+0x4f/0x100
      []  net_rx_action+0x149/0x3b0
    
      ...
    
    This patch is to fix it by linearizing the head skb if it has frag_list
    set in tipc_buf_append(). Note that we choose to do this before calling
    skb_unshare(), as __skb_linearize() will avoid skb_copy(). Also, we can
    not just drop the frag_list either as the early time.
    
    Fixes: 45c8b7b1 ("tipc: allow non-linear first fragment buffer")
    Reported-by: NLi Shuang <shuali@redhat.com>
    Signed-off-by: NXin Long <lucien.xin@gmail.com>
    Acked-by: NJon Maloy <jmaloy@redhat.com>
    Signed-off-by: NDavid S. Miller <davem@davemloft.net>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: NChen Jun <chenjun102@huawei.com>
    Acked-by: NWeilong Chen <chenweilong@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    29102688
msg.c 22.3 KB