Skip to content

Commit

Permalink
net: sched: copy tunnel info when setting flow_action entry->tunnel
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
w1ldptr authored and davem330 committed Aug 26, 2019
1 parent 5a6ff4b commit 1444c17
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
17 changes: 17 additions & 0 deletions include/net/tc_act/tc_tunnel_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
9 changes: 8 additions & 1 deletion net/sched/cls_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)) {
Expand Down

0 comments on commit 1444c17

Please sign in to comment.