aboutsummaryrefslogtreecommitdiff
path: root/nixos/modules/kernel-patches/0061-kernel-add-a-new-version-of-my-netfilter-speedup-pat.patch
blob: 8a8c759895b9044a651927f2a95fec2555823a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
From fe64c15c96dfe5b5cbf99c89b5377b056790267c Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 27 Sep 2022 16:22:04 +0200
Subject: [PATCH 61/96] kernel: add a new version of my netfilter speedup
 patches for linux 2.6.39 and 3.0

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 include/uapi/linux/netfilter_ipv4/ip_tables.h |  1 +
 net/ipv4/netfilter/ip_tables.c                | 42 ++++++++++++++++++-
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter_ipv4/ip_tables.h b/include/uapi/linux/netfilter_ipv4/ip_tables.h
index 50c7fee625ae..c31564b13ba3 100644
--- a/include/uapi/linux/netfilter_ipv4/ip_tables.h
+++ b/include/uapi/linux/netfilter_ipv4/ip_tables.h
@@ -89,6 +89,7 @@ struct ipt_ip {
 #define IPT_F_FRAG		0x01	/* Set if rule is a fragment rule */
 #define IPT_F_GOTO		0x02	/* Set if jump is a goto */
 #define IPT_F_MASK		0x03	/* All possible flag bits mask. */
+#define IPT_F_NO_DEF_MATCH	0x80	/* Internal: no default match rules present */
 
 /* Values for "inv" field in struct ipt_ip. */
 #define IPT_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 2ed7c58b471a..76c01661c4e4 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -50,6 +50,9 @@ ip_packet_match(const struct iphdr *ip,
 {
 	unsigned long ret;
 
+	if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
+		return true;
+
 	if (NF_INVF(ipinfo, IPT_INV_SRCIP,
 		    (ip->saddr & ipinfo->smsk.s_addr) != ipinfo->src.s_addr) ||
 	    NF_INVF(ipinfo, IPT_INV_DSTIP,
@@ -80,6 +83,29 @@ ip_packet_match(const struct iphdr *ip,
 	return true;
 }
 
+static void
+ip_checkdefault(struct ipt_ip *ip)
+{
+	static const char iface_mask[IFNAMSIZ] = {};
+
+	if (ip->invflags || ip->flags & IPT_F_FRAG)
+		return;
+
+	if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
+		return;
+
+	if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+		return;
+
+	if (ip->smsk.s_addr || ip->dmsk.s_addr)
+		return;
+
+	if (ip->proto)
+		return;
+
+	ip->flags |= IPT_F_NO_DEF_MATCH;
+}
+
 static bool
 ip_checkentry(const struct ipt_ip *ip)
 {
@@ -525,6 +551,8 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
 	struct xt_mtchk_param mtpar;
 	struct xt_entry_match *ematch;
 
+	ip_checkdefault(&e->ip);
+
 	if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
 		return -ENOMEM;
 
@@ -819,6 +847,7 @@ copy_entries_to_user(unsigned int total_size,
 	const struct xt_table_info *private = table->private;
 	int ret = 0;
 	const void *loc_cpu_entry;
+	u8 flags;
 
 	counters = alloc_counters(table);
 	if (IS_ERR(counters))
@@ -846,6 +875,14 @@ copy_entries_to_user(unsigned int total_size,
 			goto free_counters;
 		}
 
+		flags = e->ip.flags & IPT_F_MASK;
+		if (copy_to_user(userptr + off
+				 + offsetof(struct ipt_entry, ip.flags),
+				 &flags, sizeof(flags)) != 0) {
+			ret = -EFAULT;
+			goto free_counters;
+		}
+
 		for (i = sizeof(struct ipt_entry);
 		     i < e->target_offset;
 		     i += m->u.match_size) {
@@ -1224,12 +1261,15 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
 	compat_uint_t origsize;
 	const struct xt_entry_match *ematch;
 	int ret = 0;
+	u8 flags = e->ip.flags & IPT_F_MASK;
 
 	origsize = *size;
 	ce = *dstptr;
 	if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
 	    copy_to_user(&ce->counters, &counters[i],
-	    sizeof(counters[i])) != 0)
+	    sizeof(counters[i])) != 0 ||
+	    copy_to_user(&ce->ip.flags, &flags,
+	    sizeof(flags)) != 0)
 		return -EFAULT;
 
 	*dstptr += sizeof(struct compat_ipt_entry);
-- 
2.37.2