aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Zec <zec@FreeBSD.org>2024-05-17 15:55:43 +0000
committerMarko Zec <zec@FreeBSD.org>2024-05-22 17:34:05 +0000
commitd6e32525c778d92c26a37f4e1b562e80b18a9af7 (patch)
tree09e1bc6682be775b5cc10f5a238b702d75c0c024
parente5fadc41b48045d8978993d6c4ac72c64542b470 (diff)
downloadsrc-d6e32525c778d92c26a37f4e1b562e80b18a9af7.tar.gz
src-d6e32525c778d92c26a37f4e1b562e80b18a9af7.zip
fib_dxr: check if cached fib_data matches the new request in dxr_init()
When calling dxr_init(), the FIB_ALGO infrastructure may provide a pointer to a previous dxr instance, which permits reuse of auxiliary dxr structures, i.e. incremental lookup structure updates. For dxr this is a crucial feature provided by FIB_ALGO, since dxr incremental updates are typically several orders of magnitude faster than full lookup table rebuilds. However, the auxiliary dxr structure caches a pointer to struct fib_data and relies upon it for performing incremental updates. Apparently, incremental rebuild requests from FIB_ALGO, i.e. a calls to dxr_init() with a pointer old_data set, may (under not yet fully understood circumstances) be invoked within a different fib_data context than the one cached in the previous version of dxr auxiliary structures. In such (rare) events, we ignore the offered old dxr context, and proceed with a full lookup structure rebuild instead of attempting an incremental one using a fib_data context which may or may not no longer be valid, and thus lead to a system crash. PR: 278422 MFC after: 1 week (cherry picked from commit 4ab122e8ef127d36d95f874e85600c36c87c8c22)
-rw-r--r--sys/netinet/in_fib_dxr.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/sys/netinet/in_fib_dxr.c b/sys/netinet/in_fib_dxr.c
index 82245ecf6e66..539d7fe6c96f 100644
--- a/sys/netinet/in_fib_dxr.c
+++ b/sys/netinet/in_fib_dxr.c
@@ -1139,7 +1139,8 @@ dxr_init(uint32_t fibnum, struct fib_data *fd, void *old_data, void **data)
}
/* Check whether we may reuse the old auxiliary structures */
- if (old_dxr != NULL && old_dxr->aux != NULL) {
+ if (old_dxr != NULL && old_dxr->aux != NULL &&
+ old_dxr->aux->fd == fd) {
da = old_dxr->aux;
atomic_add_int(&da->refcnt, 1);
}
@@ -1275,7 +1276,7 @@ dxr_change_rib_batch(struct rib_head *rnh, struct fib_change_queue *q,
da = dxr->aux;
MPASS(da != NULL);
- MPASS(da->fd != NULL);
+ MPASS(da->fd == dxr->fd);
MPASS(da->refcnt > 0);
FIB_PRINTF(LOG_INFO, da->fd, "processing %d update(s)", q->count);