X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=5ce77cd3485cf6e80afe36c8ad683b40bcfc8ed5;hb=be6255a8251ae69f8a5d54c5afad9604bf9e907b;hp=69b524c548f8612717b7e0b83b185a1e3bfb242b;hpb=d76195db5a0780626e2742b184b86aeae60972bc;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 69b524c5..5ce77cd3 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -359,7 +359,6 @@ static void copy_and_csum_skb(struct sk_buff *skb, void *to) get_skb_csum_pointers(skb, &csum_start, &csum_offset); csum_start -= skb_headroom(skb); - BUG_ON(csum_start >= skb_headlen(skb)); skb_copy_bits(skb, 0, to, csum_start); @@ -492,6 +491,9 @@ static int queue_control_packets(struct datapath *dp, struct sk_buff *skb, if (unlikely(err)) goto err_kfree_skbs; + if (nla_attr_size(skb->len) > USHRT_MAX) + goto err_kfree_skbs; + len = sizeof(struct odp_header); len += nla_total_size(skb->len); len += nla_total_size(FLOW_BUFSIZE); @@ -680,23 +682,26 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) struct datapath *dp; struct ethhdr *eth; bool is_frag; + int len; int err; err = -EINVAL; if (!a[ODP_PACKET_ATTR_PACKET] || !a[ODP_PACKET_ATTR_ACTIONS] || nla_len(a[ODP_PACKET_ATTR_PACKET]) < ETH_HLEN) - goto exit; + goto err; err = validate_actions(a[ODP_PACKET_ATTR_ACTIONS]); if (err) - goto exit; + goto err; - packet = skb_clone(skb, GFP_KERNEL); + len = nla_len(a[ODP_PACKET_ATTR_PACKET]); + packet = __dev_alloc_skb(NET_IP_ALIGN + len, GFP_KERNEL); err = -ENOMEM; if (!packet) - goto exit; - packet->data = nla_data(a[ODP_PACKET_ATTR_PACKET]); - packet->len = nla_len(a[ODP_PACKET_ATTR_PACKET]); + goto err; + skb_reserve(packet, NET_IP_ALIGN); + + memcpy(__skb_put(packet, len), nla_data(a[ODP_PACKET_ATTR_PACKET]), len); skb_reset_mac_header(packet); eth = eth_hdr(packet); @@ -709,23 +714,29 @@ static int odp_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) else packet->protocol = htons(ETH_P_802_2); - err = flow_extract(packet, -1, &key, &is_frag); - if (err) - goto exit; - /* Initialize OVS_CB (it came from Netlink so might not be zeroed). */ memset(OVS_CB(packet), 0, sizeof(struct ovs_skb_cb)); + err = flow_extract(packet, -1, &key, &is_frag); + if (err) + goto err_kfree_skb; + rcu_read_lock(); dp = get_dp(odp_header->dp_ifindex); err = -ENODEV; - if (dp) - err = execute_actions(dp, packet, &key, - nla_data(a[ODP_PACKET_ATTR_ACTIONS]), - nla_len(a[ODP_PACKET_ATTR_ACTIONS])); + if (!dp) + goto err_unlock; + err = execute_actions(dp, packet, &key, + nla_data(a[ODP_PACKET_ATTR_ACTIONS]), + nla_len(a[ODP_PACKET_ATTR_ACTIONS])); rcu_read_unlock(); + return err; -exit: +err_unlock: + rcu_read_unlock(); +err_kfree_skb: + kfree_skb(packet); +err: return err; } @@ -1302,7 +1313,7 @@ static int odp_dp_cmd_validate(struct nlattr *a[ODP_DP_ATTR_MAX + 1]) return -EINVAL; } - return VERIFY_NUL_STRING(a[ODP_DP_ATTR_NAME], IFNAMSIZ - 1); + return CHECK_NUL_STRING(a[ODP_DP_ATTR_NAME], IFNAMSIZ - 1); } /* Called with genl_mutex and optionally with RTNL lock also. */ @@ -1672,7 +1683,7 @@ static struct sk_buff *odp_vport_cmd_build_info(struct vport *vport, u32 pid, static int odp_vport_cmd_validate(struct nlattr *a[ODP_VPORT_ATTR_MAX + 1]) { - return VERIFY_NUL_STRING(a[ODP_VPORT_ATTR_NAME], IFNAMSIZ - 1); + return CHECK_NUL_STRING(a[ODP_VPORT_ATTR_NAME], IFNAMSIZ - 1); } /* Called with RTNL lock or RCU read lock. */