From 8f9a091d3049a56871cc813f39b3006e91dc148e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Thu, 12 May 2022 13:50:18 +0200 Subject: [PATCH] babel: Don't try to remove multicast seqno request objects from neighbour list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Babel seqno request code keeps track of which seqno requests are outstanding for a neighbour by putting them onto a per-neighbour list. When reusing a seqno request, it will try to remove this node, but if the seqno request in question was a multicast request with no neighbour attached this will result in a crash because it tries to remove a list node that wasn't added to any list. Fix this by making the list remove conditional. Also add a check so that seqno requests are only reused if the neighbour also matches, allowing multiple outstanding requests for the same router ID. Fixes: ebd5751cdeb4 ("Babel: Seqno requests are properly decoupled from neighbors when the underlying interface disappears") Reported-by: Stefan Haller Signed-off-by: Toke Høiland-Jørgensen --- proto/babel/babel.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 4a7d550f..03f1cb50 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -304,7 +304,7 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr; WALK_LIST(sr, e->requests) - if (sr->router_id == router_id) + if (sr->router_id == router_id && sr->nbr == nbr) { /* Found matching or newer */ if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr)) @@ -312,7 +312,8 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e, /* Found older */ rem_node(NODE sr); - rem_node(&sr->nbr_node); + if (sr->nbr) + rem_node(&sr->nbr_node); goto found; } @@ -349,17 +350,20 @@ static int babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e, u64 router_id, u16 seqno) { - struct babel_seqno_request *sr; + struct babel_seqno_request *sr, *srx; + int ret = 0; - WALK_LIST(sr, e->requests) + WALK_LIST_DELSAFE(sr, srx, e->requests) if ((sr->router_id == router_id) && ge_mod64k(seqno, sr->seqno)) { - /* Found the request, remove it */ + /* Found a matching request, remove it; there may be multiple outstanding + * requests, so continue looping + */ babel_remove_seqno_request(p, sr); - return 1; + ret = 1; } - return 0; + return ret; } static void