⬢ DragonFlyBSD Kernel Audit
DF-3296 / fix.diff
← back to finding ↓ download raw
--- sys/net/pf/pf_ioctl.c
+++ sys/net/pf/pf_ioctl.c
@@ -2311,6 +2311,18 @@
 		}
 
 		if (pca->action == PF_CHANGE_REMOVE) {
+			/*
+			 * Do not allow the last address of a pool to be
+			 * removed.  Rules that use the pool (nat/rdr/binat,
+			 * route-to) would be left with rpool.cur == NULL,
+			 * taking a NULL dereference in the PF_ACPY below
+			 * and in pf_map_addr() on the packet path.
+			 */
+			if (TAILQ_FIRST(&pool->list) == oldpa &&
+			    TAILQ_NEXT(oldpa, entries) == NULL) {
+				error = EBUSY;
+				break;
+			}
 			TAILQ_REMOVE(&pool->list, oldpa, entries);
 			pfi_dynaddr_remove(&oldpa->addr);
 			pf_tbladdr_remove(&oldpa->addr);
@@ -2328,8 +2340,9 @@
 		}
 
 		pool->cur = TAILQ_FIRST(&pool->list);
-		PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
-		    pca->af);
+		if (pool->cur != NULL)
+			PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
+			    pca->af);
 		break;
 	}