Module Name: src Committed By: maxv Date: Sun Dec 31 06:57:12 UTC 2017
Modified Files: src/sys/kern: uipc_mbuf.c Log Message: Check MT_FREE by default, and not just under DEBUG (or DIAGNOSTIC). This code is fast, with an nonexistent overhead - and we already take care of setting MT_FREE, so why not check it. In addition, stop registering the function name, that's not helpful since the MBUFFREE macro is local. Instead, set m_data to NULL, so that any access to a freed mbuf's data after mtod() or similar will page fault. The combination of these two changes provides a fast and efficient way of detecting use-after-frees in the network stack. To generate a diff of this commit: cvs rdiff -u -r1.173 -r1.174 src/sys/kern/uipc_mbuf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/uipc_mbuf.c diff -u src/sys/kern/uipc_mbuf.c:1.173 src/sys/kern/uipc_mbuf.c:1.174 --- src/sys/kern/uipc_mbuf.c:1.173 Thu Nov 9 22:21:27 2017 +++ src/sys/kern/uipc_mbuf.c Sun Dec 31 06:57:12 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_mbuf.c,v 1.173 2017/11/09 22:21:27 christos Exp $ */ +/* $NetBSD: uipc_mbuf.c,v 1.174 2017/12/31 06:57:12 maxv Exp $ */ /*- * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.173 2017/11/09 22:21:27 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.174 2017/12/31 06:57:12 maxv Exp $"); #ifdef _KERNEL_OPT #include "opt_mbuftrace.h" @@ -1932,27 +1932,16 @@ m_claim(struct mbuf *m, struct mowner *m MBUFFREE(f, l, m); \ } \ -#ifdef DEBUG #define MBUFFREE(f, l, m) \ do { \ - if ((m)->m_type == MT_FREE) \ - panic("mbuf was already freed at %s,%d", \ - m->m_data, m->m_len); \ + if (__predict_false((m)->m_type == MT_FREE)) { \ + panic("mbuf %p already freed", m); \ + } \ (m)->m_type = MT_FREE; \ - (m)->m_data = __UNCONST(f); \ - (m)->m_len = l; \ + (m)->m_data = NULL; \ pool_cache_put(mb_cache, (m)); \ } while (/*CONSTCOND*/0) -#else -#define MBUFFREE(f, l, m) \ - do { \ - KASSERT((m)->m_type != MT_FREE); \ - (m)->m_type = MT_FREE; \ - pool_cache_put(mb_cache, (m)); \ - } while (/*CONSTCOND*/0) -#endif - struct mbuf * m__free(const char *f, int l, struct mbuf *m) {