Commit e508af8a authored by David S. Miller's avatar David S. Miller

Merge branch 'debug-net'

Eric Dumazet says:

====================
net: CONFIG_DEBUG_NET and friends

This patch series is inspired by some syzbot reports
hinting that skb transport_header might be not set
in places we expect it being set.

Add a new CONFIG_DEBUG_NET option
and DEBUG_NET_WARN_ON_ONCE() helper, so that we can start
adding more sanity checks in the future.

Replace two BUG() in skb_checksum_help()
with less risky code.

v2: make first patch compile on more arches/compilers
    add the 5th patch to add more debugging in skb_checksum_help()
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dc3a2001 eeee4b77
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/hashtable.h> #include <linux/hashtable.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <net/net_trackers.h> #include <net/net_trackers.h>
#include <net/net_debug.h>
struct netpoll_info; struct netpoll_info;
struct device; struct device;
...@@ -5071,81 +5072,9 @@ static inline const char *netdev_reg_state(const struct net_device *dev) ...@@ -5071,81 +5072,9 @@ static inline const char *netdev_reg_state(const struct net_device *dev)
return " (unknown)"; return " (unknown)";
} }
__printf(3, 4) __cold
void netdev_printk(const char *level, const struct net_device *dev,
const char *format, ...);
__printf(2, 3) __cold
void netdev_emerg(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_alert(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_crit(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_err(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_warn(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_notice(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_info(const struct net_device *dev, const char *format, ...);
#define netdev_level_once(level, dev, fmt, ...) \
do { \
static bool __section(".data.once") __print_once; \
\
if (!__print_once) { \
__print_once = true; \
netdev_printk(level, dev, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define netdev_emerg_once(dev, fmt, ...) \
netdev_level_once(KERN_EMERG, dev, fmt, ##__VA_ARGS__)
#define netdev_alert_once(dev, fmt, ...) \
netdev_level_once(KERN_ALERT, dev, fmt, ##__VA_ARGS__)
#define netdev_crit_once(dev, fmt, ...) \
netdev_level_once(KERN_CRIT, dev, fmt, ##__VA_ARGS__)
#define netdev_err_once(dev, fmt, ...) \
netdev_level_once(KERN_ERR, dev, fmt, ##__VA_ARGS__)
#define netdev_warn_once(dev, fmt, ...) \
netdev_level_once(KERN_WARNING, dev, fmt, ##__VA_ARGS__)
#define netdev_notice_once(dev, fmt, ...) \
netdev_level_once(KERN_NOTICE, dev, fmt, ##__VA_ARGS__)
#define netdev_info_once(dev, fmt, ...) \
netdev_level_once(KERN_INFO, dev, fmt, ##__VA_ARGS__)
#define MODULE_ALIAS_NETDEV(device) \ #define MODULE_ALIAS_NETDEV(device) \
MODULE_ALIAS("netdev-" device) MODULE_ALIAS("netdev-" device)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netdev_dbg(__dev, format, args...) \
do { \
dynamic_netdev_dbg(__dev, format, ##args); \
} while (0)
#elif defined(DEBUG)
#define netdev_dbg(__dev, format, args...) \
netdev_printk(KERN_DEBUG, __dev, format, ##args)
#else
#define netdev_dbg(__dev, format, args...) \
({ \
if (0) \
netdev_printk(KERN_DEBUG, __dev, format, ##args); \
})
#endif
#if defined(VERBOSE_DEBUG)
#define netdev_vdbg netdev_dbg
#else
#define netdev_vdbg(dev, format, args...) \
({ \
if (0) \
netdev_printk(KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
/* /*
* netdev_WARN() acts like dev_printk(), but with the key difference * netdev_WARN() acts like dev_printk(), but with the key difference
* of using a WARN/WARN_ON to get the message out, including the * of using a WARN/WARN_ON to get the message out, including the
...@@ -5159,74 +5088,6 @@ do { \ ...@@ -5159,74 +5088,6 @@ do { \
WARN_ONCE(1, "netdevice: %s%s: " format, netdev_name(dev), \ WARN_ONCE(1, "netdevice: %s%s: " format, netdev_name(dev), \
netdev_reg_state(dev), ##args) netdev_reg_state(dev), ##args)
/* netif printk helpers, similar to netdev_printk */
#define netif_printk(priv, type, level, dev, fmt, args...) \
do { \
if (netif_msg_##type(priv)) \
netdev_printk(level, (dev), fmt, ##args); \
} while (0)
#define netif_level(level, priv, type, dev, fmt, args...) \
do { \
if (netif_msg_##type(priv)) \
netdev_##level(dev, fmt, ##args); \
} while (0)
#define netif_emerg(priv, type, dev, fmt, args...) \
netif_level(emerg, priv, type, dev, fmt, ##args)
#define netif_alert(priv, type, dev, fmt, args...) \
netif_level(alert, priv, type, dev, fmt, ##args)
#define netif_crit(priv, type, dev, fmt, args...) \
netif_level(crit, priv, type, dev, fmt, ##args)
#define netif_err(priv, type, dev, fmt, args...) \
netif_level(err, priv, type, dev, fmt, ##args)
#define netif_warn(priv, type, dev, fmt, args...) \
netif_level(warn, priv, type, dev, fmt, ##args)
#define netif_notice(priv, type, dev, fmt, args...) \
netif_level(notice, priv, type, dev, fmt, ##args)
#define netif_info(priv, type, dev, fmt, args...) \
netif_level(info, priv, type, dev, fmt, ##args)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netif_dbg(priv, type, netdev, format, args...) \
do { \
if (netif_msg_##type(priv)) \
dynamic_netdev_dbg(netdev, format, ##args); \
} while (0)
#elif defined(DEBUG)
#define netif_dbg(priv, type, dev, format, args...) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args)
#else
#define netif_dbg(priv, type, dev, format, args...) \
({ \
if (0) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
/* if @cond then downgrade to debug, else print at @level */
#define netif_cond_dbg(priv, type, netdev, cond, level, fmt, args...) \
do { \
if (cond) \
netif_dbg(priv, type, netdev, fmt, ##args); \
else \
netif_ ## level(priv, type, netdev, fmt, ##args); \
} while (0)
#if defined(VERBOSE_DEBUG)
#define netif_vdbg netif_dbg
#else
#define netif_vdbg(priv, type, dev, format, args...) \
({ \
if (0) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
/* /*
* The list of packet types we will receive (as opposed to discard) * The list of packet types we will receive (as opposed to discard)
* and the routines to invoke. * and the routines to invoke.
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#if IS_ENABLED(CONFIG_NF_CONNTRACK) #if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/nf_conntrack_common.h>
#endif #endif
#include <net/net_debug.h>
/** /**
* DOC: skb checksums * DOC: skb checksums
...@@ -2904,6 +2905,7 @@ static inline bool skb_transport_header_was_set(const struct sk_buff *skb) ...@@ -2904,6 +2905,7 @@ static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
static inline unsigned char *skb_transport_header(const struct sk_buff *skb) static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{ {
DEBUG_NET_WARN_ON_ONCE(!skb_transport_header_was_set(skb));
return skb->head + skb->transport_header; return skb->head + skb->transport_header;
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_NET_DEBUG_H
#define _LINUX_NET_DEBUG_H
#include <linux/bug.h>
#include <linux/kern_levels.h>
struct net_device;
__printf(3, 4) __cold
void netdev_printk(const char *level, const struct net_device *dev,
const char *format, ...);
__printf(2, 3) __cold
void netdev_emerg(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_alert(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_crit(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_err(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_warn(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_notice(const struct net_device *dev, const char *format, ...);
__printf(2, 3) __cold
void netdev_info(const struct net_device *dev, const char *format, ...);
#define netdev_level_once(level, dev, fmt, ...) \
do { \
static bool __section(".data.once") __print_once; \
\
if (!__print_once) { \
__print_once = true; \
netdev_printk(level, dev, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define netdev_emerg_once(dev, fmt, ...) \
netdev_level_once(KERN_EMERG, dev, fmt, ##__VA_ARGS__)
#define netdev_alert_once(dev, fmt, ...) \
netdev_level_once(KERN_ALERT, dev, fmt, ##__VA_ARGS__)
#define netdev_crit_once(dev, fmt, ...) \
netdev_level_once(KERN_CRIT, dev, fmt, ##__VA_ARGS__)
#define netdev_err_once(dev, fmt, ...) \
netdev_level_once(KERN_ERR, dev, fmt, ##__VA_ARGS__)
#define netdev_warn_once(dev, fmt, ...) \
netdev_level_once(KERN_WARNING, dev, fmt, ##__VA_ARGS__)
#define netdev_notice_once(dev, fmt, ...) \
netdev_level_once(KERN_NOTICE, dev, fmt, ##__VA_ARGS__)
#define netdev_info_once(dev, fmt, ...) \
netdev_level_once(KERN_INFO, dev, fmt, ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netdev_dbg(__dev, format, args...) \
do { \
dynamic_netdev_dbg(__dev, format, ##args); \
} while (0)
#elif defined(DEBUG)
#define netdev_dbg(__dev, format, args...) \
netdev_printk(KERN_DEBUG, __dev, format, ##args)
#else
#define netdev_dbg(__dev, format, args...) \
({ \
if (0) \
netdev_printk(KERN_DEBUG, __dev, format, ##args); \
})
#endif
#if defined(VERBOSE_DEBUG)
#define netdev_vdbg netdev_dbg
#else
#define netdev_vdbg(dev, format, args...) \
({ \
if (0) \
netdev_printk(KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
/* netif printk helpers, similar to netdev_printk */
#define netif_printk(priv, type, level, dev, fmt, args...) \
do { \
if (netif_msg_##type(priv)) \
netdev_printk(level, (dev), fmt, ##args); \
} while (0)
#define netif_level(level, priv, type, dev, fmt, args...) \
do { \
if (netif_msg_##type(priv)) \
netdev_##level(dev, fmt, ##args); \
} while (0)
#define netif_emerg(priv, type, dev, fmt, args...) \
netif_level(emerg, priv, type, dev, fmt, ##args)
#define netif_alert(priv, type, dev, fmt, args...) \
netif_level(alert, priv, type, dev, fmt, ##args)
#define netif_crit(priv, type, dev, fmt, args...) \
netif_level(crit, priv, type, dev, fmt, ##args)
#define netif_err(priv, type, dev, fmt, args...) \
netif_level(err, priv, type, dev, fmt, ##args)
#define netif_warn(priv, type, dev, fmt, args...) \
netif_level(warn, priv, type, dev, fmt, ##args)
#define netif_notice(priv, type, dev, fmt, args...) \
netif_level(notice, priv, type, dev, fmt, ##args)
#define netif_info(priv, type, dev, fmt, args...) \
netif_level(info, priv, type, dev, fmt, ##args)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define netif_dbg(priv, type, netdev, format, args...) \
do { \
if (netif_msg_##type(priv)) \
dynamic_netdev_dbg(netdev, format, ##args); \
} while (0)
#elif defined(DEBUG)
#define netif_dbg(priv, type, dev, format, args...) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args)
#else
#define netif_dbg(priv, type, dev, format, args...) \
({ \
if (0) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
/* if @cond then downgrade to debug, else print at @level */
#define netif_cond_dbg(priv, type, netdev, cond, level, fmt, args...) \
do { \
if (cond) \
netif_dbg(priv, type, netdev, fmt, ##args); \
else \
netif_ ## level(priv, type, netdev, fmt, ##args); \
} while (0)
#if defined(VERBOSE_DEBUG)
#define netif_vdbg netif_dbg
#else
#define netif_vdbg(priv, type, dev, format, args...) \
({ \
if (0) \
netif_printk(priv, type, KERN_DEBUG, dev, format, ##args); \
0; \
})
#endif
#if defined(CONFIG_DEBUG_NET)
#define DEBUG_NET_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond)
#else
#define DEBUG_NET_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond)
#endif
#endif /* _LINUX_NET_DEBUG_H */
...@@ -17,3 +17,10 @@ config NET_NS_REFCNT_TRACKER ...@@ -17,3 +17,10 @@ config NET_NS_REFCNT_TRACKER
help help
Enable debugging feature to track netns references. Enable debugging feature to track netns references.
This adds memory and cpu costs. This adds memory and cpu costs.
config DEBUG_NET
bool "Add generic networking debug"
depends on DEBUG_KERNEL
help
Enable extra sanity checks in networking.
This is mostly used by fuzzers, but is safe to select.
...@@ -3265,12 +3265,18 @@ int skb_checksum_help(struct sk_buff *skb) ...@@ -3265,12 +3265,18 @@ int skb_checksum_help(struct sk_buff *skb)
} }
offset = skb_checksum_start_offset(skb); offset = skb_checksum_start_offset(skb);
BUG_ON(offset >= skb_headlen(skb)); ret = -EINVAL;
if (WARN_ON_ONCE(offset >= skb_headlen(skb))) {
DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false);
goto out;
}
csum = skb_checksum(skb, offset, skb->len - offset, 0); csum = skb_checksum(skb, offset, skb->len - offset, 0);
offset += skb->csum_offset; offset += skb->csum_offset;
BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb)); if (WARN_ON_ONCE(offset + sizeof(__sum16) > skb_headlen(skb))) {
DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false);
goto out;
}
ret = skb_ensure_writable(skb, offset + sizeof(__sum16)); ret = skb_ensure_writable(skb, offset + sizeof(__sum16));
if (ret) if (ret)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment