Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Check MT_FREE by default, and not just under DEBUG ...



details:   https://anonhg.NetBSD.org/src/rev/85ed280cb2b1
branches:  trunk
changeset: 358464:85ed280cb2b1
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Dec 31 06:57:12 2017 +0000

description:
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.

diffstat:

 sys/kern/uipc_mbuf.c |  23 ++++++-----------------
 1 files changed, 6 insertions(+), 17 deletions(-)

diffs (50 lines):

diff -r f682930c1efa -r 85ed280cb2b1 sys/kern/uipc_mbuf.c
--- a/sys/kern/uipc_mbuf.c      Sun Dec 31 03:38:06 2017 +0000
+++ b/sys/kern/uipc_mbuf.c      Sun Dec 31 06:57:12 2017 +0000
@@ -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 @@
                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)
 {



Home | Main Index | Thread Index | Old Index