Skip to content

Commit 171b7fc

Browse files
kaberdavem330
authored andcommitted
[NETFILTER]: ip6_queue: deobfuscate entry lookups
A queue entry lookup currently looks like this: ipq_find_dequeue_entry -> __ipq_find_dequeue_entry -> __ipq_find_entry -> cmpfn -> id_cmp Use simple open-coded list walking and kill the cmpfn for ipq_find_dequeue_entry. Instead add it to ipq_flush (after similar cleanups) and use ipq_flush for both complete flushes and flushing entries related to a device. Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9521409 commit 171b7fc

File tree

1 file changed

+37
-64
lines changed

1 file changed

+37
-64
lines changed

net/ipv6/netfilter/ip6_queue.c

Lines changed: 37 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -75,52 +75,6 @@ __ipq_enqueue_entry(struct ipq_queue_entry *entry)
7575
queue_total++;
7676
}
7777

78-
/*
79-
* Find and return a queued entry matched by cmpfn, or return the last
80-
* entry if cmpfn is NULL.
81-
*/
82-
static inline struct ipq_queue_entry *
83-
__ipq_find_entry(ipq_cmpfn cmpfn, unsigned long data)
84-
{
85-
struct ipq_queue_entry *entry;
86-
87-
list_for_each_entry(entry, &queue_list, list) {
88-
if (!cmpfn || cmpfn(entry, data))
89-
return entry;
90-
}
91-
return NULL;
92-
}
93-
94-
static inline void
95-
__ipq_dequeue_entry(struct ipq_queue_entry *entry)
96-
{
97-
list_del(&entry->list);
98-
queue_total--;
99-
}
100-
101-
static inline struct ipq_queue_entry *
102-
__ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
103-
{
104-
struct ipq_queue_entry *entry;
105-
106-
entry = __ipq_find_entry(cmpfn, data);
107-
if (entry == NULL)
108-
return NULL;
109-
110-
__ipq_dequeue_entry(entry);
111-
return entry;
112-
}
113-
114-
115-
static inline void
116-
__ipq_flush(int verdict)
117-
{
118-
struct ipq_queue_entry *entry;
119-
120-
while ((entry = __ipq_find_dequeue_entry(NULL, 0)))
121-
ipq_issue_verdict(entry, verdict);
122-
}
123-
12478
static inline int
12579
__ipq_set_mode(unsigned char mode, unsigned int range)
12680
{
@@ -147,31 +101,59 @@ __ipq_set_mode(unsigned char mode, unsigned int range)
147101
return status;
148102
}
149103

104+
static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data);
105+
150106
static inline void
151107
__ipq_reset(void)
152108
{
153109
peer_pid = 0;
154110
net_disable_timestamp();
155111
__ipq_set_mode(IPQ_COPY_NONE, 0);
156-
__ipq_flush(NF_DROP);
112+
__ipq_flush(NULL, 0);
157113
}
158114

159115
static struct ipq_queue_entry *
160-
ipq_find_dequeue_entry(ipq_cmpfn cmpfn, unsigned long data)
116+
ipq_find_dequeue_entry(unsigned long id)
161117
{
162-
struct ipq_queue_entry *entry;
118+
struct ipq_queue_entry *entry = NULL, *i;
163119

164120
write_lock_bh(&queue_lock);
165-
entry = __ipq_find_dequeue_entry(cmpfn, data);
121+
122+
list_for_each_entry(i, &queue_list, list) {
123+
if ((unsigned long)i == id) {
124+
entry = i;
125+
break;
126+
}
127+
}
128+
129+
if (entry) {
130+
list_del(&entry->list);
131+
queue_total--;
132+
}
133+
166134
write_unlock_bh(&queue_lock);
167135
return entry;
168136
}
169137

170138
static void
171-
ipq_flush(int verdict)
139+
__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
140+
{
141+
struct ipq_queue_entry *entry, *next;
142+
143+
list_for_each_entry_safe(entry, next, &queue_list, list) {
144+
if (!cmpfn || cmpfn(entry, data)) {
145+
list_del(&entry->list);
146+
queue_total--;
147+
ipq_issue_verdict(entry, NF_DROP);
148+
}
149+
}
150+
}
151+
152+
static void
153+
ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
172154
{
173155
write_lock_bh(&queue_lock);
174-
__ipq_flush(verdict);
156+
__ipq_flush(cmpfn, data);
175157
write_unlock_bh(&queue_lock);
176158
}
177159

@@ -364,12 +346,6 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
364346
return 0;
365347
}
366348

367-
static inline int
368-
id_cmp(struct ipq_queue_entry *e, unsigned long id)
369-
{
370-
return (id == (unsigned long )e);
371-
}
372-
373349
static int
374350
ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
375351
{
@@ -378,7 +354,7 @@ ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
378354
if (vmsg->value > NF_MAX_VERDICT)
379355
return -EINVAL;
380356

381-
entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
357+
entry = ipq_find_dequeue_entry(vmsg->id);
382358
if (entry == NULL)
383359
return -ENOENT;
384360
else {
@@ -449,10 +425,7 @@ dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
449425
static void
450426
ipq_dev_drop(int ifindex)
451427
{
452-
struct ipq_queue_entry *entry;
453-
454-
while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
455-
ipq_issue_verdict(entry, NF_DROP);
428+
ipq_flush(dev_cmp, ifindex);
456429
}
457430

458431
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
@@ -689,7 +662,7 @@ static void __exit ip6_queue_fini(void)
689662
{
690663
nf_unregister_queue_handlers(&nfqh);
691664
synchronize_net();
692-
ipq_flush(NF_DROP);
665+
ipq_flush(NULL, 0);
693666

694667
unregister_sysctl_table(ipq_sysctl_header);
695668
unregister_netdevice_notifier(&ipq_dev_notifier);

0 commit comments

Comments
 (0)