diff options
| author | Guillaume Nault <g.nault@alphalink.fr> | 2018-04-12 14:50:35 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2018-04-13 12:17:26 -0400 |
| commit | f726214d9b23e5fce8c11937577a289a3202498f (patch) | |
| tree | 7143db7e1e7c2286a02f5f03a19bb0935e24456f /net | |
| parent | 0e0c3fee3a59a387aeecc4fca6f3a2e9615a5443 (diff) | |
l2tp: hold reference on tunnels printed in l2tp/tunnels debugfs file
Use l2tp_tunnel_get_nth() instead of l2tp_tunnel_find_nth(), to be safe
against concurrent tunnel deletion.
Use the same mechanism as in l2tp_ppp.c for dropping the reference
taken by l2tp_tunnel_get_nth(). That is, drop the reference just
before looking up the next tunnel. In case of error, drop the last
accessed tunnel in l2tp_dfs_seq_stop().
That was the last use of l2tp_tunnel_find_nth().
Fixes: 0ad6614048cf ("l2tp: Add debugfs files for dumping l2tp debug info")
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/l2tp/l2tp_core.c | 20 | ||||
| -rw-r--r-- | net/l2tp/l2tp_core.h | 1 | ||||
| -rw-r--r-- | net/l2tp/l2tp_debugfs.c | 15 |
3 files changed, 13 insertions, 23 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c8c4183f0f37..40261cb68e83 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -355,26 +355,6 @@ err_tlock: | |||
| 355 | } | 355 | } |
| 356 | EXPORT_SYMBOL_GPL(l2tp_session_register); | 356 | EXPORT_SYMBOL_GPL(l2tp_session_register); |
| 357 | 357 | ||
| 358 | struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth) | ||
| 359 | { | ||
| 360 | struct l2tp_net *pn = l2tp_pernet(net); | ||
| 361 | struct l2tp_tunnel *tunnel; | ||
| 362 | int count = 0; | ||
| 363 | |||
| 364 | rcu_read_lock_bh(); | ||
| 365 | list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { | ||
| 366 | if (++count > nth) { | ||
| 367 | rcu_read_unlock_bh(); | ||
| 368 | return tunnel; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | rcu_read_unlock_bh(); | ||
| 373 | |||
| 374 | return NULL; | ||
| 375 | } | ||
| 376 | EXPORT_SYMBOL_GPL(l2tp_tunnel_find_nth); | ||
| 377 | |||
| 378 | /***************************************************************************** | 358 | /***************************************************************************** |
| 379 | * Receive data handling | 359 | * Receive data handling |
| 380 | *****************************************************************************/ | 360 | *****************************************************************************/ |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index e4896413b2b6..c199020f8a8a 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
| @@ -222,7 +222,6 @@ struct l2tp_session *l2tp_session_get(const struct net *net, | |||
| 222 | struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth); | 222 | struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth); |
| 223 | struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, | 223 | struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, |
| 224 | const char *ifname); | 224 | const char *ifname); |
| 225 | struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth); | ||
| 226 | 225 | ||
| 227 | int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, | 226 | int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, |
| 228 | u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, | 227 | u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, |
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c index 72e713da4733..b8f9d45bfeb1 100644 --- a/net/l2tp/l2tp_debugfs.c +++ b/net/l2tp/l2tp_debugfs.c | |||
| @@ -47,7 +47,11 @@ struct l2tp_dfs_seq_data { | |||
| 47 | 47 | ||
| 48 | static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) | 48 | static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) |
| 49 | { | 49 | { |
| 50 | pd->tunnel = l2tp_tunnel_find_nth(pd->net, pd->tunnel_idx); | 50 | /* Drop reference taken during previous invocation */ |
| 51 | if (pd->tunnel) | ||
| 52 | l2tp_tunnel_dec_refcount(pd->tunnel); | ||
| 53 | |||
| 54 | pd->tunnel = l2tp_tunnel_get_nth(pd->net, pd->tunnel_idx); | ||
| 51 | pd->tunnel_idx++; | 55 | pd->tunnel_idx++; |
| 52 | } | 56 | } |
| 53 | 57 | ||
| @@ -96,7 +100,14 @@ static void *l2tp_dfs_seq_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 96 | 100 | ||
| 97 | static void l2tp_dfs_seq_stop(struct seq_file *p, void *v) | 101 | static void l2tp_dfs_seq_stop(struct seq_file *p, void *v) |
| 98 | { | 102 | { |
| 99 | /* nothing to do */ | 103 | struct l2tp_dfs_seq_data *pd = v; |
| 104 | |||
| 105 | if (!pd || pd == SEQ_START_TOKEN) | ||
| 106 | return; | ||
| 107 | |||
| 108 | /* Drop reference taken by last invocation of l2tp_dfs_next_tunnel() */ | ||
| 109 | if (pd->tunnel) | ||
| 110 | l2tp_tunnel_dec_refcount(pd->tunnel); | ||
| 100 | } | 111 | } |
| 101 | 112 | ||
| 102 | static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) | 113 | static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) |
