Skip to content

Commit 494bea3

Browse files
Liping Zhangdavem330
authored andcommitted
openvswitch: fix skb_panic due to the incorrect actions attrlen
For sw_flow_actions, the actions_len only represents the kernel part's size, and when we dump the actions to the userspace, we will do the convertions, so it's true size may become bigger than the actions_len. But unfortunately, for OVS_PACKET_ATTR_ACTIONS, we use the actions_len to alloc the skbuff, so the user_skb's size may become insufficient and oops will happen like this: skbuff: skb_over_panic: text:ffffffff8148fabf len:1749 put:157 head: ffff881300f39000 data:ffff881300f39000 tail:0x6d5 end:0x6c0 dev:<NULL> ------------[ cut here ]------------ kernel BUG at net/core/skbuff.c:129! [...] Call Trace: <IRQ> [<ffffffff8148be82>] skb_put+0x43/0x44 [<ffffffff8148fabf>] skb_zerocopy+0x6c/0x1f4 [<ffffffffa0290d36>] queue_userspace_packet+0x3a3/0x448 [openvswitch] [<ffffffffa0292023>] ovs_dp_upcall+0x30/0x5c [openvswitch] [<ffffffffa028d435>] output_userspace+0x132/0x158 [openvswitch] [<ffffffffa01e6890>] ? ip6_rcv_finish+0x74/0x77 [ipv6] [<ffffffffa028e277>] do_execute_actions+0xcc1/0xdc8 [openvswitch] [<ffffffffa028e3f2>] ovs_execute_actions+0x74/0x106 [openvswitch] [<ffffffffa0292130>] ovs_dp_process_packet+0xe1/0xfd [openvswitch] [<ffffffffa0292b77>] ? key_extract+0x63c/0x8d5 [openvswitch] [<ffffffffa029848b>] ovs_vport_receive+0xa1/0xc3 [openvswitch] [...] Also we can find that the actions_len is much little than the orig_len: crash> struct sw_flow_actions 0xffff8812f539d000 struct sw_flow_actions { rcu = { next = 0xffff8812f5398800, func = 0xffffe3b00035db32 }, orig_len = 1384, actions_len = 592, actions = 0xffff8812f539d01c } So as a quick fix, use the orig_len instead of the actions_len to alloc the user_skb. Last, this oops happened on our system running a relative old kernel, but the same risk still exists on the mainline, since we use the wrong actions_len from the beginning. Fixes: ccea744 ("openvswitch: include datapath actions with sampled-packet upcall to userspace") Cc: Neil McKee <neil.mckee@inmon.com> Signed-off-by: Liping Zhang <zlpnobody@gmail.com> Acked-by: Pravin B Shelar <pshelar@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent c7b725b commit 494bea3

File tree

3 files changed

+7
-3
lines changed

3 files changed

+7
-3
lines changed

net/openvswitch/actions.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
13371337
goto out;
13381338
}
13391339

1340+
OVS_CB(skb)->acts_origlen = acts->orig_len;
13401341
err = do_execute_actions(dp, skb, key,
13411342
acts->actions, acts->actions_len);
13421343

net/openvswitch/datapath.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
381381
}
382382

383383
static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
384-
unsigned int hdrlen)
384+
unsigned int hdrlen, int actions_attrlen)
385385
{
386386
size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
387387
+ nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */
@@ -398,7 +398,7 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
398398

399399
/* OVS_PACKET_ATTR_ACTIONS */
400400
if (upcall_info->actions_len)
401-
size += nla_total_size(upcall_info->actions_len);
401+
size += nla_total_size(actions_attrlen);
402402

403403
/* OVS_PACKET_ATTR_MRU */
404404
if (upcall_info->mru)
@@ -465,7 +465,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
465465
else
466466
hlen = skb->len;
467467

468-
len = upcall_msg_size(upcall_info, hlen - cutlen);
468+
len = upcall_msg_size(upcall_info, hlen - cutlen,
469+
OVS_CB(skb)->acts_origlen);
469470
user_skb = genlmsg_new(len, GFP_ATOMIC);
470471
if (!user_skb) {
471472
err = -ENOMEM;

net/openvswitch/datapath.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,13 @@ struct datapath {
9999
* when a packet is received by OVS.
100100
* @mru: The maximum received fragement size; 0 if the packet is not
101101
* fragmented.
102+
* @acts_origlen: The netlink size of the flow actions applied to this skb.
102103
* @cutlen: The number of bytes from the packet end to be removed.
103104
*/
104105
struct ovs_skb_cb {
105106
struct vport *input_vport;
106107
u16 mru;
108+
u16 acts_origlen;
107109
u32 cutlen;
108110
};
109111
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)

0 commit comments

Comments
 (0)