From d0cb3ae2be76ce161b5b217d457b2310085270c6 Mon Sep 17 00:00:00 2001 From: Kevin Paul Herbert Date: Tue, 25 Sep 2012 17:39:49 -0700 Subject: [PATCH] packet.cc: Clear tx_flags for kernels with SKBTX_DEV_ZEROCOPY Ensure that tx_flags is cleared for kernels which have SKBTX_DEV_ZEROCOPY when uniqueifying a packet. If the flag is not cleared, the kernel will jump to a random address when the skb is eventually freed. Signed-off-by: Kevin Paul Herbert --- config-linuxmodule.h.in | 3 +++ configure | 57 +++++++++++++++++++++++++++++++++++++++++ configure.in | 10 ++++++++ lib/packet.cc | 3 +++ 4 files changed, 73 insertions(+) diff --git a/config-linuxmodule.h.in b/config-linuxmodule.h.in index 3b5d804e3d..1906885e50 100644 --- a/config-linuxmodule.h.in +++ b/config-linuxmodule.h.in @@ -88,6 +88,9 @@ /* Define if 'struct skb_shared_info' has an 'ip6_frag_id' member. */ #undef HAVE_LINUX_SKB_SHINFO_IP6_FRAG_ID +/* Define if 'struct skb_shared_info' has an 'tx_flags' member defining 'SKBTX_DEV_ZEROCOPY'. */ +#undef HAVE_LINUX_SKB_SHINFO_TX_FLAGS_SKBTX_DEV_ZEROCOPY + /* Define if 'struct skb_shared_info' has a 'tso_size' member. */ #undef HAVE_LINUX_SKB_SHINFO_TSO_SIZE diff --git a/configure b/configure index ad3aa42e37..fbaf3e8668 100755 --- a/configure +++ b/configure @@ -11369,6 +11369,63 @@ $as_echo "#define HAVE_LINUX_SKB_SHINFO_IP6_FRAG_ID 1" >>confdefs.h fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether skb_shinfo has tx_flags defining SKBTX_DEV_ZEROCOPY" >&5 +$as_echo_n "checking whether skb_shinfo has tx_flags defining SKBTX_DEV_ZEROCOPY... " >&6; } +if ${ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if HAVE_LINUXMODULE_2_6 +# define KBUILD_STR(s) #s +# define KBUILD_BASENAME KBUILD_STR(click) +# define KBUILD_MODNAME KBUILD_STR(click) +#endif +#define new linux_new +#define this linux_this +#define delete linux_delete +#define class linux_class +#define virtual linux_virtual +#define typename linux_typename +#define private linux_private +#define protected linux_protected +#define public linux_public +#define namespace linux_namespace +#define false linux_false +#define true linux_true +#define CLICK_CXX_PROTECTED 1 +$linux_autoconf_include +#include +#include +int +main () +{ +extern struct sk_buff *s; skb_shinfo(s)->tx_flags = SKBTX_DEV_ZEROCOPY; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy=yes +else + ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy" >&5 +$as_echo "$ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy" >&6; } + if test $ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy = yes; then + +$as_echo "#define HAVE_LINUX_SKB_SHINFO_TX_FLAGS_SKBTX_DEV_ZEROCOPY 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for device polling kernel extension" >&5 $as_echo_n "checking for device polling kernel extension... " >&6; } if ${ac_cv_linuxmodule_net_device_polling+:} false; then : diff --git a/configure.in b/configure.in index 5804e90dc4..63f30454b7 100644 --- a/configure.in +++ b/configure.in @@ -1430,6 +1430,16 @@ void f1(int64_t) { // will fail if long long and int64_t are the same type AC_DEFINE([HAVE_LINUX_SKB_SHINFO_IP6_FRAG_ID], [1], [Define if 'struct skb_shared_info' has an 'ip6_frag_id' member.]) fi + AC_CACHE_CHECK([whether skb_shinfo has tx_flags defining SKBTX_DEV_ZEROCOPY], [ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy], + [AC_LANG_C + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([CLICK_LINUXMODULE_PROLOGUE()[ +#include ]], +[[extern struct sk_buff *s; skb_shinfo(s)->tx_flags = SKBTX_DEV_ZEROCOPY;]])], + [ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy=yes], [ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy=no])]) + if test $ac_cv_linuxmodule_skb_shinfo_tx_flags_skbtx_dev_zerocopy = yes; then + AC_DEFINE([HAVE_LINUX_SKB_SHINFO_TX_FLAGS_SKBTX_DEV_ZEROCOPY], [1], [Define if 'struct skb_shared_info' has an 'tx_flags' member defining 'SKBTX_DEV_ZEROCOPY'.]) + fi + AC_CACHE_CHECK([for device polling kernel extension], [ac_cv_linuxmodule_net_device_polling], [AC_LANG_C AC_COMPILE_IFELSE([AC_LANG_PROGRAM([CLICK_LINUXMODULE_PROLOGUE()[ diff --git a/lib/packet.cc b/lib/packet.cc index bc24571f6f..3b239f8d73 100644 --- a/lib/packet.cc +++ b/lib/packet.cc @@ -692,6 +692,9 @@ Packet::expensive_uniqueify(int32_t extra_headroom, int32_t extra_tailroom, # if HAVE_LINUX_SKB_SHINFO_IP6_FRAG_ID nskb_shinfo->ip6_frag_id = 0; # endif +# if HAVE_LINUX_SKB_SHINFO_TX_FLAGS_SKBTX_DEV_ZEROCOPY + nskb_shinfo->tx_flags = 0; +# endif shift_header_annotations(old_head, extra_headroom); return static_cast(this);