Skip to content

Commit f710dbd

Browse files
Guillaume Naultgregkh
authored andcommitted
l2tp: take reference on sessions being dumped
[ Upstream commit e08293a4ccbcc993ded0fdc46f1e57926b833d63 ] Take a reference on the sessions returned by l2tp_session_find_nth() (and rename it l2tp_session_get_nth() to reflect this change), so that caller is assured that the session isn't going to disappear while processing it. For procfs and debugfs handlers, the session is held in the .start() callback and dropped in .show(). Given that pppol2tp_seq_session_show() dereferences the associated PPPoL2TP socket and that l2tp_dfs_seq_session_show() might call pppol2tp_show(), we also need to call the session's .ref() callback to prevent the socket from going away from under us. Fixes: fd558d1 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") Fixes: 0ad6614 ("l2tp: Add debugfs files for dumping l2tp debug info") Fixes: 309795f ("l2tp: Add netlink control API for L2TP") Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 25adf4e commit f710dbd

5 files changed

Lines changed: 27 additions & 11 deletions

File tree

net/l2tp/l2tp_core.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunn
278278
}
279279
EXPORT_SYMBOL_GPL(l2tp_session_find);
280280

281-
struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
281+
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
282+
bool do_ref)
282283
{
283284
int hash;
284285
struct l2tp_session *session;
@@ -288,6 +289,9 @@ struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
288289
for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
289290
hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
290291
if (++count > nth) {
292+
l2tp_session_inc_refcount(session);
293+
if (do_ref && session->ref)
294+
session->ref(session);
291295
read_unlock_bh(&tunnel->hlist_lock);
292296
return session;
293297
}
@@ -298,7 +302,7 @@ struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
298302

299303
return NULL;
300304
}
301-
EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
305+
EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
302306

303307
/* Lookup a session by interface name.
304308
* This is very inefficient but is only used by management interfaces.

net/l2tp/l2tp_core.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ static inline struct l2tp_tunnel *l2tp_sock_to_tunnel(struct sock *sk)
243243
struct l2tp_session *l2tp_session_find(struct net *net,
244244
struct l2tp_tunnel *tunnel,
245245
u32 session_id);
246-
struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
246+
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
247+
bool do_ref);
247248
struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
248249
struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
249250
struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);

net/l2tp/l2tp_debugfs.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd)
5353

5454
static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
5555
{
56-
pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
56+
pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
5757
pd->session_idx++;
5858

5959
if (pd->session == NULL) {
@@ -238,10 +238,14 @@ static int l2tp_dfs_seq_show(struct seq_file *m, void *v)
238238
}
239239

240240
/* Show the tunnel or session context */
241-
if (pd->session == NULL)
241+
if (!pd->session) {
242242
l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
243-
else
243+
} else {
244244
l2tp_dfs_seq_session_show(m, pd->session);
245+
if (pd->session->deref)
246+
pd->session->deref(pd->session);
247+
l2tp_session_dec_refcount(pd->session);
248+
}
245249

246250
out:
247251
return 0;

net/l2tp/l2tp_netlink.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
827827
goto out;
828828
}
829829

830-
session = l2tp_session_find_nth(tunnel, si);
830+
session = l2tp_session_get_nth(tunnel, si, false);
831831
if (session == NULL) {
832832
ti++;
833833
tunnel = NULL;
@@ -837,8 +837,11 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
837837

838838
if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
839839
cb->nlh->nlmsg_seq, NLM_F_MULTI,
840-
session, L2TP_CMD_SESSION_GET) < 0)
840+
session, L2TP_CMD_SESSION_GET) < 0) {
841+
l2tp_session_dec_refcount(session);
841842
break;
843+
}
844+
l2tp_session_dec_refcount(session);
842845

843846
si++;
844847
}

net/l2tp/l2tp_ppp.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,7 @@ static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd)
15751575

15761576
static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
15771577
{
1578-
pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
1578+
pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
15791579
pd->session_idx++;
15801580

15811581
if (pd->session == NULL) {
@@ -1702,10 +1702,14 @@ static int pppol2tp_seq_show(struct seq_file *m, void *v)
17021702

17031703
/* Show the tunnel or session context.
17041704
*/
1705-
if (pd->session == NULL)
1705+
if (!pd->session) {
17061706
pppol2tp_seq_tunnel_show(m, pd->tunnel);
1707-
else
1707+
} else {
17081708
pppol2tp_seq_session_show(m, pd->session);
1709+
if (pd->session->deref)
1710+
pd->session->deref(pd->session);
1711+
l2tp_session_dec_refcount(pd->session);
1712+
}
17091713

17101714
out:
17111715
return 0;

0 commit comments

Comments
 (0)