We have weird `rt_refcnt' check in rtfree(): 497 rtfree(struct rtentry *rt) 498 { ... 504 refcnt = (int)atomic_dec_int_nv(&rt->rt_refcnt); 505 if (refcnt <= 0) { 506 KASSERT(!ISSET(rt->rt_flags, RTF_UP)); 507 KASSERT(!RT_ROOT(rt)); 508 atomic_dec_int(&rttrash); 509 if (refcnt < 0) { 510 printf("rtfree: %p not freed (neg refs)\n", rt); 511 return; 512 }
We underflow `rt_refcnt' when we missed to get reference to this `rt' or we did extra release. This is the bug which should be exposed. But according current code this `rt' is just leaked. Also it's easy to miss this error condition because we only print error message. I propose to put "rt->rt_refcnt > 0" assertion before we decrement `rt_refcnt'. This makes reference counting errors more notable when they are. Also I changed `rt_refcnt' definition to unsigned integer. I didn't find any "rtfree: ... not freed (neg refs)" report, so it looks like we can't hit this assertion, but I like to commit this diff after release. But nothing stops to test it and provide feedback :) Index: sys/net/route.c =================================================================== RCS file: /cvs/src/sys/net/route.c,v retrieving revision 1.399 diff -u -p -r1.399 route.c --- sys/net/route.c 25 May 2021 22:45:09 -0000 1.399 +++ sys/net/route.c 14 Sep 2021 21:47:11 -0000 @@ -496,20 +496,15 @@ rtref(struct rtentry *rt) void rtfree(struct rtentry *rt) { - int refcnt; - if (rt == NULL) return; - refcnt = (int)atomic_dec_int_nv(&rt->rt_refcnt); - if (refcnt <= 0) { + KASSERT(rt->rt_refcnt > 0); + + if (atomic_dec_int_nv(&rt->rt_refcnt) == 0) { KASSERT(!ISSET(rt->rt_flags, RTF_UP)); KASSERT(!RT_ROOT(rt)); atomic_dec_int(&rttrash); - if (refcnt < 0) { - printf("rtfree: %p not freed (neg refs)\n", rt); - return; - } KERNEL_LOCK(); rt_timer_remove_all(rt); Index: sys/net/route.h =================================================================== RCS file: /cvs/src/sys/net/route.h,v retrieving revision 1.185 diff -u -p -r1.185 route.h --- sys/net/route.h 17 Mar 2021 09:05:42 -0000 1.185 +++ sys/net/route.h 14 Sep 2021 21:47:11 -0000 @@ -113,7 +113,7 @@ struct rtentry { struct rt_kmetrics rt_rmx; /* metrics used by rx'ing protocols */ unsigned int rt_ifidx; /* the answer: interface to use */ unsigned int rt_flags; /* up/down?, host/net */ - int rt_refcnt; /* # held references */ + unsigned int rt_refcnt; /* # held references */ int rt_plen; /* prefix length */ uint16_t rt_labelid; /* route label ID */ uint8_t rt_priority; /* routing priority to use */