aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2018-04-12 14:50:35 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-13 12:17:26 -0400
commitf726214d9b23e5fce8c11937577a289a3202498f (patch)
tree7143db7e1e7c2286a02f5f03a19bb0935e24456f /net
parent0e0c3fee3a59a387aeecc4fca6f3a2e9615a5443 (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.c20
-rw-r--r--net/l2tp/l2tp_core.h1
-rw-r--r--net/l2tp/l2tp_debugfs.c15
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}
356EXPORT_SYMBOL_GPL(l2tp_session_register); 356EXPORT_SYMBOL_GPL(l2tp_session_register);
357 357
358struct 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}
376EXPORT_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,
222struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth); 222struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
223struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, 223struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
224 const char *ifname); 224 const char *ifname);
225struct l2tp_tunnel *l2tp_tunnel_find_nth(const struct net *net, int nth);
226 225
227int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, 226int 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
48static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) 48static 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
97static void l2tp_dfs_seq_stop(struct seq_file *p, void *v) 101static 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
102static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) 113static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)