From: Eelco Chaudron <echaudro@xxxxxxxxxx> [ Upstream commit fea07a487c6dd422dc8837237c9d2bc7c33119af ] Silence suspicious RCU usage warning in ovs_flow_tbl_masks_cache_resize() by replacing rcu_dereference() with rcu_dereference_ovsl(). In addition, when creating a new datapath, make sure it's configured under the ovs_lock. Fixes: 9bf24f594c6a ("net: openvswitch: make masks cache size configurable") Reported-by: syzbot+9a8f8bfcc56e8578016c@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Eelco Chaudron <echaudro@xxxxxxxxxx> Link: https://lore.kernel.org/r/160439190002.56943.1418882726496275961.stgit@ebuild Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/openvswitch/datapath.c | 14 +++++++------- net/openvswitch/flow_table.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -1699,13 +1699,13 @@ static int ovs_dp_cmd_new(struct sk_buff parms.port_no = OVSP_LOCAL; parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID]; - err = ovs_dp_change(dp, a); - if (err) - goto err_destroy_meters; - /* So far only local changes have been made, now need the lock. */ ovs_lock(); + err = ovs_dp_change(dp, a); + if (err) + goto err_unlock_and_destroy_meters; + vport = new_vport(&parms); if (IS_ERR(vport)) { err = PTR_ERR(vport); @@ -1721,8 +1721,7 @@ static int ovs_dp_cmd_new(struct sk_buff ovs_dp_reset_user_features(skb, info); } - ovs_unlock(); - goto err_destroy_meters; + goto err_unlock_and_destroy_meters; } err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, @@ -1737,7 +1736,8 @@ static int ovs_dp_cmd_new(struct sk_buff ovs_notify(&dp_datapath_genl_family, reply, info); return 0; -err_destroy_meters: +err_unlock_and_destroy_meters: + ovs_unlock(); ovs_meters_exit(dp); err_destroy_ports: kfree(dp->ports); --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c @@ -387,7 +387,7 @@ static struct mask_cache *tbl_mask_cache } int ovs_flow_tbl_masks_cache_resize(struct flow_table *table, u32 size) { - struct mask_cache *mc = rcu_dereference(table->mask_cache); + struct mask_cache *mc = rcu_dereference_ovsl(table->mask_cache); struct mask_cache *new; if (size == mc->cache_size)