mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
l2tp: add idr consistency check in session_register
l2tp_session_register uses an idr_alloc then idr_replace pattern to insert sessions into the session IDR. To catch invalid locking, add a WARN_ON_ONCE if the IDR entry is modified by another thread between alloc and replace steps. Also add comments to make expectations clear. Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: Tom Parkin <tparkin@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
89b768ec2d
commit
0aa45570c3
@ -474,6 +474,7 @@ int l2tp_session_register(struct l2tp_session *session,
|
||||
{
|
||||
struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
|
||||
struct l2tp_session *other_session = NULL;
|
||||
void *old = NULL;
|
||||
u32 session_key;
|
||||
int err;
|
||||
|
||||
@ -517,13 +518,19 @@ int l2tp_session_register(struct l2tp_session *session,
|
||||
WRITE_ONCE(session->tunnel, tunnel);
|
||||
list_add_rcu(&session->list, &tunnel->session_list);
|
||||
|
||||
/* this makes session available to lockless getters */
|
||||
if (tunnel->version == L2TP_HDR_VER_3) {
|
||||
if (!other_session)
|
||||
idr_replace(&pn->l2tp_v3_session_idr, session, session_key);
|
||||
old = idr_replace(&pn->l2tp_v3_session_idr, session, session_key);
|
||||
} else {
|
||||
idr_replace(&pn->l2tp_v2_session_idr, session, session_key);
|
||||
old = idr_replace(&pn->l2tp_v2_session_idr, session, session_key);
|
||||
}
|
||||
|
||||
/* old should be NULL, unless something removed or modified
|
||||
* the IDR entry after our idr_alloc_32 above (which shouldn't
|
||||
* happen).
|
||||
*/
|
||||
WARN_ON_ONCE(old);
|
||||
out:
|
||||
spin_unlock_bh(&pn->l2tp_session_idr_lock);
|
||||
spin_unlock_bh(&tunnel->list_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user