net: sched: copy tunnel info when setting flow_action entry->tunnel
In order to remove dependency on rtnl lock, modify tc_setup_flow_action() to copy tunnel info, instead of just saving pointer to tunnel_key action tunnel info. This is necessary to prevent concurrent action overwrite from releasing tunnel info while it is being used by rtnl-unlocked driver. Implement helper tcf_tunnel_info_copy() that is used to copy tunnel info with all its options to dynamically allocated memory block. Modify tc_cleanup_flow_action() to free dynamically allocated tunnel info. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5a6ff4b13d
commit
1444c175a3
@ -59,4 +59,21 @@ static inline struct ip_tunnel_info *tcf_tunnel_info(const struct tc_action *a)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline struct ip_tunnel_info *
|
||||
tcf_tunnel_info_copy(const struct tc_action *a)
|
||||
{
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
struct ip_tunnel_info *tun = tcf_tunnel_info(a);
|
||||
|
||||
if (tun) {
|
||||
size_t tun_size = sizeof(*tun) + tun->options_len;
|
||||
struct ip_tunnel_info *tun_copy = kmemdup(tun, tun_size,
|
||||
GFP_KERNEL);
|
||||
|
||||
return tun_copy;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif /* __NET_TC_TUNNEL_KEY_H */
|
||||
|
@ -3279,6 +3279,9 @@ void tc_cleanup_flow_action(struct flow_action *flow_action)
|
||||
if (entry->dev)
|
||||
dev_put(entry->dev);
|
||||
break;
|
||||
case FLOW_ACTION_TUNNEL_ENCAP:
|
||||
kfree(entry->tunnel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3355,7 +3358,11 @@ int tc_setup_flow_action(struct flow_action *flow_action,
|
||||
}
|
||||
} else if (is_tcf_tunnel_set(act)) {
|
||||
entry->id = FLOW_ACTION_TUNNEL_ENCAP;
|
||||
entry->tunnel = tcf_tunnel_info(act);
|
||||
entry->tunnel = tcf_tunnel_info_copy(act);
|
||||
if (!entry->tunnel) {
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
} else if (is_tcf_tunnel_release(act)) {
|
||||
entry->id = FLOW_ACTION_TUNNEL_DECAP;
|
||||
} else if (is_tcf_pedit(act)) {
|
||||
|
Loading…
Reference in New Issue
Block a user