From b41f25bd1a774360c4105d9e1c55139404bed47a Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Tue, 25 Feb 2020 23:28:03 +0800 Subject: [PATCH] kernel/4.9: fix IMQ patch --- .../601-add-kernel-imq-support.patch | 433 ++++++++---------- 1 file changed, 202 insertions(+), 231 deletions(-) diff --git a/target/linux/generic/pending-4.9/601-add-kernel-imq-support.patch b/target/linux/generic/pending-4.9/601-add-kernel-imq-support.patch index 3d5f1de1d2..e4628ad023 100644 --- a/target/linux/generic/pending-4.9/601-add-kernel-imq-support.patch +++ b/target/linux/generic/pending-4.9/601-add-kernel-imq-support.patch @@ -1,6 +1,6 @@ ---- a/drivers/net/Kconfig 2018-04-22 23:17:57.583718674 -0400 -+++ b/drivers/net/Kconfig 2018-04-22 23:20:39.331768961 -0400 -@@ -277,6 +277,125 @@ +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -260,6 +260,125 @@ config RIONET_RX_SIZE depends on RIONET default "128" @@ -126,9 +126,9 @@ config TUN tristate "Universal TUN/TAP device driver support" depends on INET ---- a/drivers/net/Makefile 2018-04-22 23:17:57.583718674 -0400 -+++ b/drivers/net/Makefile 2018-04-22 23:20:39.411768985 -0400 -@@ -13,6 +13,7 @@ +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -11,6 +11,7 @@ obj-$(CONFIG_DUMMY) += dummy.o obj-$(CONFIG_EQUALIZER) += eql.o obj-$(CONFIG_IFB) += ifb.o obj-$(CONFIG_MACSEC) += macsec.o @@ -136,9 +136,9 @@ obj-$(CONFIG_MACVLAN) += macvlan.o obj-$(CONFIG_MACVTAP) += macvtap.o obj-$(CONFIG_MII) += mii.o ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/drivers/net/imq.c 2018-05-20 11:10:23.471713282 -0400 -@@ -0,0 +1,1268 @@ +--- /dev/null ++++ b/drivers/net/imq.c +@@ -0,0 +1,1254 @@ +/* + * Pseudo-driver for the intermediate queue device. + * @@ -151,7 +151,7 @@ + * + * The first version was written by Martin Devera, + * -+ * See Credits.txt ++ * See Creditis.txt + */ + +#include @@ -166,7 +166,7 @@ +#include +#include +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+#include ++ #include +#endif +#include +#include @@ -183,7 +183,7 @@ + +static nf_hookfn imq_nf_hook; + -+/*static struct nf_hook_ops imq_ops[] = { ++/* static struct nf_hook_ops imq_ops[] = { + { + // imq_ingress_ipv4 + .hook = imq_nf_hook, @@ -230,7 +230,7 @@ +#endif + }, +#endif -+};*/ ++}; */ + +#if defined(CONFIG_IMQ_NUM_DEVS) +static int numdevs = CONFIG_IMQ_NUM_DEVS; @@ -457,8 +457,6 @@ +{ + struct nf_queue_entry *entry = skb->nf_queue_entry; + -+ rcu_read_lock(); -+ + skb->nf_queue_entry = NULL; + netif_trans_update(dev); + @@ -486,7 +484,6 @@ + dev->stats.tx_dropped++; + dev_kfree_skb(skb); + -+ rcu_read_unlock(); + return NETDEV_TX_OK; + } + @@ -499,7 +496,6 @@ + + nf_reinject(entry, NF_ACCEPT); + -+ rcu_read_unlock(); + return NETDEV_TX_OK; +} + @@ -535,7 +531,7 @@ + struct nf_queue_entry *entry = kmemdup(e, e->size, GFP_ATOMIC); + if (entry) { + nf_queue_entry_get_refs(entry); -+ return entry; ++ return entry; + } + return NULL; +} @@ -747,14 +743,14 @@ + root_lock = qdisc_lock(q); + spin_lock(root_lock); + -+ users = refcount_read(&skb->users); ++ users = atomic_read(&skb->users); + + skb_shared = skb_get(skb); /* increase reference count by one */ + + /* backup skb->cb, as qdisc layer will overwrite it */ + skb_save_cb(skb_shared); + qdisc_enqueue_root(skb_shared, q, &to_free); /* might kfree_skb */ -+ if (likely(refcount_read(&skb_shared->users) == users + 1)) { ++ if (likely(atomic_read(&skb_shared->users) == users + 1)) { + bool validate; + + kfree_skb(skb_shared); /* decrease reference count by one */ @@ -854,10 +850,6 @@ + return 0; +} + -+static struct device_type imq_device_type = { -+ .name = "imq", -+}; -+ +static const struct net_device_ops imq_netdev_ops = { + .ndo_open = imq_open, + .ndo_stop = imq_close, @@ -879,8 +871,7 @@ + IFF_TX_SKB_SHARING); +} + -+static int imq_validate(struct nlattr *tb[], struct nlattr *data[], -+ struct netlink_ext_ack *extack) ++static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + int ret = 0; + @@ -911,6 +902,14 @@ + .outfn = imq_nf_queue, +}; + ++ ++ ++ ++ ++ ++ ++ ++ +static inline char *kernel_strdup(const char *str) +{ + char *tmp; @@ -1085,15 +1084,18 @@ + #define DEFAULT_POST_TABLE "mangle" +#endif + ++ ++ +static char* hook_chains = "PREROUTING,POSTROUTING"; +static char* hook_tables = DEFAULT_PRE_TABLE","DEFAULT_POST_TABLE; + +static struct nf_hook_ops* hook_list = NULL; +static int hook_list_length = 0; + -+static int __net_init imq_nf_register(struct net *net) ++ ++static int __init imq_init_hooks(void) +{ -+ int ret; ++ /* int ret; */ + char separators[4] = {',', ' ', '\t', '\0' }; + unsigned long num_chains; + unsigned long num_tables; @@ -1101,6 +1103,8 @@ + char** table_list = split_on_separators(hook_tables, separators, 3, -1, 0, &num_tables); + int hook_index = 0; + ++ nf_register_queue_imq_handler(&imq_nfqh); ++ + hook_list_length = 0; + if(num_chains != num_tables) + { @@ -1170,10 +1174,11 @@ + table_id = NF_IP_PRI_FILTER+1; + } + (hook_list[hook_list_length]).hook = imq_nf_hook; ++ /* (hook_list[hook_list_length]).owner = THIS_MODULE; */ + (hook_list[hook_list_length]).pf = PF_INET; + (hook_list[hook_list_length]).hooknum = chain_id; + (hook_list[hook_list_length]).priority = table_id; -+ printk(KERN_INFO "\tIMQv4: Hooking IMQ after %s on %s, pf=%d, hooknum=%d, priority=%d\n", table, chain, (hook_list[hook_list_length]).pf, (hook_list[hook_list_length]).hooknum, (hook_list[hook_list_length]).priority); ++ err = nf_register_hook( (hook_list + hook_list_length) ); + hook_list_length++; + + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) @@ -1195,12 +1200,24 @@ + } + + (hook_list[hook_list_length]).hook = imq_nf_hook; ++ /* (hook_list[hook_list_length]).owner = THIS_MODULE; */ + (hook_list[hook_list_length]).pf = PF_INET6; + (hook_list[hook_list_length]).hooknum = chain_id; + (hook_list[hook_list_length]).priority = table_id; -+ printk(KERN_INFO "\tIMQv6: Hooking IMQ after %s on %s, pf=%d, hooknum=%d, priority=%d\n", table, chain, (hook_list[hook_list_length]).pf, (hook_list[hook_list_length]).hooknum, (hook_list[hook_list_length]).priority); ++ nf_register_hook( (hook_list + hook_list_length) ); + hook_list_length++; + #endif ++ ++ ++ if(err) ++ { ++ printk(KERN_INFO "\tError hooking IMQ after %s on %s\n", table, chain); ++ } ++ else ++ { ++ printk(KERN_INFO "\tHooked IMQ after %s on %s\n", table, chain); ++ } ++ + } + } + if(valid == 0) @@ -1211,60 +1228,23 @@ + free_null_terminated_string_array(chain_list); + free_null_terminated_string_array(table_list); + -+ return nf_register_net_hooks(net, hook_list, -+ hook_list_length); -+}; ++ return 0; + + -+static void __net_exit imq_nf_unregister(struct net *net) -+{ -+ nf_unregister_net_hooks(net, hook_list, -+ hook_list_length); -+}; -+ -+static struct pernet_operations imq_net_ops = { -+ .init = imq_nf_register, -+ .exit = imq_nf_unregister, -+}; -+ -+static int __net_init imq_init_hooks(void) -+{ ++ /* + int ret ; + nf_register_queue_imq_handler(&imq_nfqh); + -+ ret = register_pernet_subsys(&imq_net_ops); ++ ret = nf_register_hooks(imq_ops, ARRAY_SIZE(imq_ops)); + if (ret < 0) + nf_unregister_queue_imq_handler(); + + return ret; ++ */ +} + -+#ifdef CONFIG_LOCKDEP -+ static struct lock_class_key imq_netdev_addr_lock_key; + -+ static void __init imq_dev_set_lockdep_one(struct net_device *dev, -+ struct netdev_queue *txq, void *arg) -+ { -+ /* -+ * the IMQ transmit locks can be taken recursively, -+ * for example with one IMQ rule for input- and one for -+ * output network devices in iptables! -+ * until we find a better solution ignore them. -+ */ -+ lockdep_set_novalidate_class(&txq->_xmit_lock); -+ } + -+ static void imq_dev_set_lockdep_class(struct net_device *dev) -+ { -+ lockdep_set_class_and_name(&dev->addr_list_lock, -+ &imq_netdev_addr_lock_key, "_xmit_addr_IMQ"); -+ netdev_for_each_tx_queue(dev, imq_dev_set_lockdep_one, NULL); -+} -+#else -+ static inline void imq_dev_set_lockdep_class(struct net_device *dev) -+ { -+ } -+#endif + +static int __init imq_init_one(int index) +{ @@ -1280,13 +1260,10 @@ + goto fail; + + dev->rtnl_link_ops = &imq_link_ops; -+ SET_NETDEV_DEVTYPE(dev, &imq_device_type); + ret = register_netdevice(dev); + if (ret < 0) + goto fail; + -+ imq_dev_set_lockdep_class(dev); -+ + return 0; +fail: + free_netdev(dev); @@ -1352,7 +1329,7 @@ + + pr_info("IMQ driver loaded successfully. (numdevs = %d, numqueues = %d, imq_dev_accurate_stats = %d)\n", + numdevs, numqueues, imq_dev_accurate_stats); -+/* ++ +#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB) + pr_info("\tHooking IMQ before NAT on PREROUTING.\n"); +#else @@ -1363,17 +1340,26 @@ +#else + pr_info("\tHooking IMQ after NAT on POSTROUTING.\n"); +#endif -+*/ ++ + return 0; +} + +static void __exit imq_unhook(void) +{ -+ unregister_pernet_subsys(&imq_net_ops); ++ int hook_index = 0; ++ for(hook_index = 0; hook_index < hook_list_length; hook_index++) ++ { ++ nf_unregister_hook( (hook_list+hook_index) ); ++ } + nf_unregister_queue_imq_handler(); + + kfree(hook_list); + hook_list_length = 0; ++ ++ /* ++ nf_unregister_hooks(imq_ops, ARRAY_SIZE(imq_ops)); ++ nf_unregister_queue_imq_handler(); ++ */ +} + +static void __exit imq_cleanup_devs(void) @@ -1407,8 +1393,8 @@ +MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See https://github.com/imq/linuximq/wiki for more information."); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_RTNL_LINK("imq"); ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/include/linux/imq.h 2018-04-22 23:20:39.411768985 -0400 +--- /dev/null ++++ b/include/linux/imq.h @@ -0,0 +1,13 @@ +#ifndef _IMQ_H +#define _IMQ_H @@ -1423,21 +1409,9 @@ + +#endif /* _IMQ_H */ + ---- a/include/linux/netdevice.h 2018-04-22 23:18:14.351723881 -0400 -+++ b/include/linux/netdevice.h 2018-04-22 23:20:39.411768985 -0400 -@@ -1785,6 +1785,11 @@ - /* - * Cache lines mostly used on receive path (including eth_type_trans()) - */ -+ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ unsigned long last_rx; -+#endif -+ - /* Interface address info used in eth_type_trans() */ - unsigned char *dev_addr; - -@@ -3646,6 +3651,19 @@ +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3669,6 +3669,19 @@ static inline void netif_tx_unlock_bh(struct net_device *dev) } \ } @@ -1457,8 +1431,8 @@ static inline void netif_tx_disable(struct net_device *dev) { unsigned int i; ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/include/linux/netfilter/xt_IMQ.h 2018-04-22 23:20:39.415768987 -0400 +--- /dev/null ++++ b/include/linux/netfilter/xt_IMQ.h @@ -0,0 +1,9 @@ +#ifndef _XT_IMQ_H +#define _XT_IMQ_H @@ -1469,8 +1443,8 @@ + +#endif /* _XT_IMQ_H */ + ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h 2018-04-22 23:20:39.415768987 -0400 +--- /dev/null ++++ b/include/linux/netfilter_ipv4/ipt_IMQ.h @@ -0,0 +1,10 @@ +#ifndef _IPT_IMQ_H +#define _IPT_IMQ_H @@ -1482,8 +1456,8 @@ + +#endif /* _IPT_IMQ_H */ + ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h 2018-04-22 23:20:39.415768987 -0400 +--- /dev/null ++++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h @@ -0,0 +1,10 @@ +#ifndef _IP6T_IMQ_H +#define _IP6T_IMQ_H @@ -1495,9 +1469,9 @@ + +#endif /* _IP6T_IMQ_H */ + ---- a/include/linux/skbuff.h 2018-04-22 23:18:15.079724108 -0400 -+++ b/include/linux/skbuff.h 2018-04-22 23:20:39.415768987 -0400 -@@ -40,6 +40,10 @@ +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -39,6 +39,10 @@ #include #include #include @@ -1508,16 +1482,7 @@ /* The interface for checksum offload between the stack and networking drivers * is as follows... -@@ -582,7 +586,7 @@ - typedef unsigned char *sk_buff_data_t; - #endif - --/** -+/** - * struct sk_buff - socket buffer - * @next: Next buffer in list - * @prev: Previous buffer in list -@@ -685,6 +689,9 @@ +@@ -654,6 +658,9 @@ struct sk_buff { * first. This is owned by whoever has the skb queued ATM. */ char cb[48] __aligned(8); @@ -1527,9 +1492,9 @@ unsigned long _skb_refdst; void (*destructor)(struct sk_buff *skb); -@@ -694,6 +701,9 @@ +@@ -663,6 +670,9 @@ struct sk_buff { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - unsigned long _nfct; + struct nf_conntrack *nfct; #endif +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) + struct nf_queue_entry *nf_queue_entry; @@ -1537,28 +1502,19 @@ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) struct nf_bridge_info *nf_bridge; #endif -@@ -771,6 +781,9 @@ - #ifdef CONFIG_NET_SWITCHDEV - __u8 offload_fwd_mark:1; - #endif +@@ -743,6 +753,9 @@ struct sk_buff { + __u8 gro_skip:1; + /* 1, 3 or 4 bit hole */ + +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) + __u8 imq_flags:IMQ_F_BITS; +#endif + #ifdef CONFIG_NET_SCHED + __u16 tc_index; /* traffic control index */ #ifdef CONFIG_NET_CLS_ACT - __u8 tc_skip_classify:1; - __u8 tc_at_ingress:1; -@@ -870,7 +883,7 @@ - */ - static inline struct dst_entry *skb_dst(const struct sk_buff *skb) - { -- /* If refdst was not refcounted, check we still are in a -+ /* If refdst was not refcounted, check we still are in a - * rcu_read_lock section - */ - WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) && -@@ -960,6 +973,12 @@ +@@ -903,6 +916,12 @@ void kfree_skb_list(struct sk_buff *segs); + void skb_tx_error(struct sk_buff *skb); void consume_skb(struct sk_buff *skb); - void __consume_stateless_skb(struct sk_buff *skb); void __kfree_skb(struct sk_buff *skb); + +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) @@ -1569,23 +1525,20 @@ extern struct kmem_cache *skbuff_head_cache; void kfree_skb_partial(struct sk_buff *skb, bool head_stolen); -@@ -3779,8 +3798,12 @@ - dst->_nfct = src->_nfct; - nf_conntrack_get(skb_nfct(src)); +@@ -3594,6 +3613,10 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src, + if (copy) + dst->nfctinfo = src->nfctinfo; #endif +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ dst->imq_flags = src->imq_flags; -+ dst->nf_queue_entry = src->nf_queue_entry; ++ dst->imq_flags = src->imq_flags; ++ dst->nf_queue_entry = src->nf_queue_entry; +#endif #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) -- dst->nf_bridge = src->nf_bridge; -+ dst->nf_bridge = src->nf_bridge; + dst->nf_bridge = src->nf_bridge; nf_bridge_get(src->nf_bridge); - #endif - #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES) ---- a/include/net/netfilter/nf_queue.h 2018-04-22 23:18:15.199724146 -0400 -+++ b/include/net/netfilter/nf_queue.h 2018-04-22 23:20:39.419768987 -0400 -@@ -31,6 +31,12 @@ +--- a/include/net/netfilter/nf_queue.h ++++ b/include/net/netfilter/nf_queue.h +@@ -30,6 +30,12 @@ struct nf_queue_handler { void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh); void nf_unregister_queue_handler(struct net *net); void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); @@ -1598,9 +1551,9 @@ void nf_queue_entry_get_refs(struct nf_queue_entry *entry); void nf_queue_entry_release_refs(struct nf_queue_entry *entry); ---- a/include/net/pkt_sched.h 2018-04-22 23:18:15.219724151 -0400 -+++ b/include/net/pkt_sched.h 2018-04-22 23:20:39.419768987 -0400 -@@ -109,6 +109,8 @@ +--- a/include/net/pkt_sched.h ++++ b/include/net/pkt_sched.h +@@ -105,6 +105,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, void __qdisc_run(struct Qdisc *q); @@ -1609,9 +1562,9 @@ static inline void qdisc_run(struct Qdisc *q) { if (qdisc_run_begin(q)) ---- a/include/net/sch_generic.h 2018-04-22 23:18:15.227724154 -0400 -+++ b/include/net/sch_generic.h 2018-04-22 23:20:39.419768987 -0400 -@@ -567,6 +567,13 @@ +--- a/include/net/sch_generic.h ++++ b/include/net/sch_generic.h +@@ -518,6 +518,13 @@ static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, return sch->enqueue(skb, sch, to_free); } @@ -1625,31 +1578,31 @@ static inline bool qdisc_is_percpu_stats(const struct Qdisc *q) { return q->flags & TCQ_F_CPUSTATS; ---- a/include/uapi/linux/netfilter.h 2018-04-22 23:18:16.159724442 -0400 -+++ b/include/uapi/linux/netfilter.h 2018-04-22 23:20:39.419768987 -0400 +--- a/include/uapi/linux/netfilter.h ++++ b/include/uapi/linux/netfilter.h @@ -14,7 +14,8 @@ #define NF_QUEUE 3 #define NF_REPEAT 4 - #define NF_STOP 5 /* Deprecated, for userspace nf_queue compatibility. */ + #define NF_STOP 5 -#define NF_MAX_VERDICT NF_STOP +#define NF_IMQ_QUEUE 6 +#define NF_MAX_VERDICT NF_IMQ_QUEUE /* we overload the higher bits for encoding auxiliary data such as the queue * number or errno values. Not nice, but better than additional function ---- a/net/core/dev.c 2018-04-22 23:18:24.391727000 -0400 -+++ b/net/core/dev.c 2018-04-22 23:20:39.419768987 -0400 -@@ -143,6 +143,9 @@ - #include +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -141,6 +141,9 @@ #include + #include #include +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +#include +#endif - #include - #include -@@ -2979,7 +2982,12 @@ + #include "net-sysfs.h" + +@@ -2906,7 +2909,12 @@ static int xmit_one(struct sk_buff *skb, struct net_device *dev, unsigned int len; int rc; @@ -1661,8 +1614,8 @@ +#endif dev_queue_xmit_nit(skb, dev); - #ifdef CONFIG_ETHERNET_PACKET_MANGLE -@@ -3028,6 +3036,8 @@ + len = skb->len; +@@ -2945,6 +2953,8 @@ struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *de return skb; } @@ -1671,9 +1624,9 @@ static struct sk_buff *validate_xmit_vlan(struct sk_buff *skb, netdev_features_t features) { ---- a/net/core/skbuff.c 2018-04-22 23:18:24.395727003 -0400 -+++ b/net/core/skbuff.c 2018-04-22 23:20:39.419768987 -0400 -@@ -82,6 +82,87 @@ +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -82,6 +82,87 @@ struct kmem_cache *skbuff_head_cache __read_mostly; static struct kmem_cache *skbuff_fclone_cache __read_mostly; int sysctl_max_skb_frags __read_mostly = MAX_SKB_FRAGS; EXPORT_SYMBOL(sysctl_max_skb_frags); @@ -1761,7 +1714,7 @@ /** * skb_panic - private function for out-of-line support -@@ -628,6 +709,28 @@ +@@ -654,6 +735,28 @@ static void skb_release_head_state(struct sk_buff *skb) WARN_ON(in_irq()); skb->destructor(skb); } @@ -1788,9 +1741,9 @@ + pr_warn("%s\n", "IMQ: kfree_skb: skb->nf_queue_entry != NULL"); +#endif #if IS_ENABLED(CONFIG_NF_CONNTRACK) - nf_conntrack_put(skb_nfct(skb)); + nf_conntrack_put(skb->nfct); #endif -@@ -817,6 +920,10 @@ +@@ -843,6 +946,10 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->sp = secpath_get(old->sp); #endif __nf_copy(new, old, false); @@ -1801,7 +1754,7 @@ /* Note : this field could be in headers_start/headers_end section * It is not yet because we do not want to have a 16 bit hole -@@ -3915,6 +4022,13 @@ +@@ -3464,6 +3571,13 @@ void __init skb_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); @@ -1814,24 +1767,51 @@ +#endif } - static int ---- a/net/netfilter/core.c 2018-04-22 23:18:26.019727507 -0400 -+++ b/net/netfilter/core.c 2018-04-22 23:20:39.419768987 -0400 -@@ -457,6 +457,11 @@ - if (ret == 0) - ret = -EPERM; - return ret; -+ case NF_IMQ_QUEUE: -+ ret = nf_queue(skb, state, e, s, verdict); -+ if (ret == -ECANCELED) -+ continue; -+ return ret; - case NF_QUEUE: - ret = nf_queue(skb, state, e, s, verdict); - if (ret == 1) ---- a/net/netfilter/Kconfig 2018-04-22 23:18:25.751727424 -0400 -+++ b/net/netfilter/Kconfig 2018-04-22 23:20:39.419768987 -0400 -@@ -902,6 +902,18 @@ + /** +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -66,9 +66,6 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + struct in6_addr *nexthop; + int ret; + +- skb->protocol = htons(ETH_P_IPV6); +- skb->dev = dev; +- + if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) { + struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); + +@@ -150,6 +147,13 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb) + return 0; + } + ++ /* ++ * IMQ-patch: moved setting skb->dev and skb->protocol from ++ * ip6_finish_output2 to fix crashing at netif_skb_features(). ++ */ ++ skb->protocol = htons(ETH_P_IPV6); ++ skb->dev = dev; ++ + return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, + net, sk, skb, NULL, dev, + ip6_finish_output, +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -360,8 +360,11 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state) + ret = NF_DROP_GETERR(verdict); + if (ret == 0) + ret = -EPERM; +- } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { ++ } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE || ++ (verdict & NF_VERDICT_MASK) == NF_IMQ_QUEUE) { + ret = nf_queue(skb, state, &entry, verdict); ++ if (ret == -ECANCELED) ++ goto next_hook; + if (ret == 1 && entry) + goto next_hook; + } +--- a/net/netfilter/Kconfig ++++ b/net/netfilter/Kconfig +@@ -833,6 +833,18 @@ config NETFILTER_XT_TARGET_LOG To compile it as a module, choose M here. If unsure, say N. @@ -1850,25 +1830,19 @@ config NETFILTER_XT_TARGET_MARK tristate '"MARK" target support' depends on NETFILTER_ADVANCED ---- a/net/netfilter/Makefile 2018-04-22 23:18:25.711727410 -0400 -+++ b/net/netfilter/Makefile 2018-04-22 23:20:39.423768990 -0400 -@@ -136,6 +136,7 @@ - obj-$(CONFIG_NETFILTER_XT_TARGET_FLOWOFFLOAD) += xt_FLOWOFFLOAD.o +--- a/net/netfilter/Makefile ++++ b/net/netfilter/Makefile +@@ -119,6 +119,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o + obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o obj-$(CONFIG_NETFILTER_XT_TARGET_HMARK) += xt_HMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NETMAP) += xt_NETMAP.o ---- a/net/netfilter/nf_queue.c 2018-04-22 23:18:25.699727407 -0400 -+++ b/net/netfilter/nf_queue.c 2018-04-22 23:22:59.395812579 -0400 -@@ -1,4 +1,4 @@ --/* -+ /* - * Rusty Russell (C)2000 -- This code is GPL. - * Patrick McHardy (c) 2006-2012 - */ -@@ -29,6 +29,23 @@ +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -27,6 +27,23 @@ * receives, no matter what. */ @@ -1892,30 +1866,29 @@ /* return EBUSY when somebody else is registered, return EEXIST if the * same handler is registered, return 0 in case of success. */ void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh) -@@ -144,16 +161,29 @@ +@@ -108,16 +125,28 @@ void nf_queue_nf_hook_drop(struct net *net, const struct nf_hook_entry *entry) + } static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, - const struct nf_hook_entries *entries, -- unsigned int index, unsigned int queuenum) -+ unsigned int index, unsigned int verdict) +- unsigned int queuenum) ++ unsigned int verdict) { int status = -ENOENT; struct nf_queue_entry *entry = NULL; + const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; struct net *net = state->net; - unsigned int route_key_size; + unsigned int queuetype = verdict & NF_VERDICT_MASK; + unsigned int queuenum = verdict >> NF_VERDICT_QBITS; /* QUEUE == DROP if no one is waiting, to be safe. */ - qh = rcu_dereference(net->nf.queue_handler); -+ + if (queuetype == NF_IMQ_QUEUE) { +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ qh = rcu_dereference(queue_imq_handler); ++ qh = rcu_dereference(queue_imq_handler); +#else -+ BUG(); -+ goto err_unlock; ++ BUG(); ++ goto err_unlock; +#endif + } else { + qh = rcu_dereference(net->nf.queue_handler); @@ -1924,34 +1897,32 @@ if (!qh) { status = -ESRCH; goto err; -@@ -217,8 +248,16 @@ - { +@@ -164,8 +193,14 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state, int ret; -- ret = __nf_queue(skb, state, entries, index, verdict >> NF_VERDICT_QBITS); -+ ret = __nf_queue(skb, state, entries, index, verdict); + RCU_INIT_POINTER(state->hook_entries, entry); +- ret = __nf_queue(skb, state, verdict >> NF_VERDICT_QBITS); ++ ret = __nf_queue(skb, state, verdict); if (ret < 0) { -+ +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ /* IMQ Bypass */ -+ if (ret == -ECANCELED && skb->imq_flags == 0) { -+ return 1; -+ } ++ if (ret == -ECANCELED && skb->imq_flags == 0) { // down interface ++ *entryp = rcu_dereference(entry->next); ++ return 1; ++ } +#endif -+ if (ret == -ESRCH && - (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) - return 1; -@@ -302,6 +341,7 @@ + (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS)) { + *entryp = rcu_dereference(entry->next); +@@ -218,6 +253,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) local_bh_enable(); break; case NF_QUEUE: + case NF_IMQ_QUEUE: - err = nf_queue(skb, &entry->state, hooks, i, verdict); - if (err == 1) - goto next_hook; ---- /dev/null 2018-03-30 15:39:24.291451107 -0400 -+++ b/net/netfilter/xt_IMQ.c 2018-04-22 23:20:39.423768990 -0400 + err = nf_queue(skb, &entry->state, &hook_entry, verdict); + if (err == 1) { + if (hook_entry) +--- /dev/null ++++ b/net/netfilter/xt_IMQ.c @@ -0,0 +1,72 @@ +/* + * This target marks packets to be enqueued to an imq device @@ -2025,9 +1996,9 @@ +MODULE_ALIAS("ipt_IMQ"); +MODULE_ALIAS("ip6t_IMQ"); + ---- a/net/sched/sch_generic.c 2018-04-22 23:18:26.623727693 -0400 -+++ b/net/sched/sch_generic.c 2018-04-22 23:20:39.423768990 -0400 -@@ -158,6 +158,14 @@ +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -154,6 +154,14 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate, return skb; } @@ -2041,4 +2012,4 @@ + /* * Transmit possibly several skbs, and handle the return status as - * required. Owning running seqcount bit guarantees that \ No newline at end of file + * required. Owning running seqcount bit guarantees that