diff options
author | Marko Zec <zec@FreeBSD.org> | 2024-05-17 15:55:43 +0000 |
---|---|---|
committer | Marko Zec <zec@FreeBSD.org> | 2024-05-23 04:29:22 +0000 |
commit | 782f02004251f68d144ea7914e390297b6edad48 (patch) | |
tree | 19f94342320caa6f36a84249ea80b69cd16d4e1b | |
parent | 0e5e6a9419ea1c966cfe1afe4c5e46e9bbcd43c8 (diff) | |
download | src-782f02004251f68d144ea7914e390297b6edad48.tar.gz src-782f02004251f68d144ea7914e390297b6edad48.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
Approved by: re (cperciva)
(cherry picked from commit 4ab122e8ef127d36d95f874e85600c36c87c8c22)
(cherry picked from commit d6e32525c778d92c26a37f4e1b562e80b18a9af7)
-rw-r--r-- | sys/netinet/in_fib_dxr.c | 5 |
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); |