Skip to content

Commit 9521409

Browse files
kaberdavem330
authored andcommitted
[NETFILTER]: ip_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 b43d8d8 commit 9521409

File tree

1 file changed

+37
-64
lines changed

1 file changed

+37
-64
lines changed

net/ipv4/netfilter/ip_queue.c

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

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

106+
static void __ipq_flush(ipq_cmpfn cmpfn, unsigned long data);
107+
152108
static inline void
153109
__ipq_reset(void)
154110
{
155111
peer_pid = 0;
156112
net_disable_timestamp();
157113
__ipq_set_mode(IPQ_COPY_NONE, 0);
158-
__ipq_flush(NF_DROP);
114+
__ipq_flush(NULL, 0);
159115
}
160116

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

166122
write_lock_bh(&queue_lock);
167-
entry = __ipq_find_dequeue_entry(cmpfn, data);
123+
124+
list_for_each_entry(i, &queue_list, list) {
125+
if ((unsigned long)i == id) {
126+
entry = i;
127+
break;
128+
}
129+
}
130+
131+
if (entry) {
132+
list_del(&entry->list);
133+
queue_total--;
134+
}
135+
168136
write_unlock_bh(&queue_lock);
169137
return entry;
170138
}
171139

172140
static void
173-
ipq_flush(int verdict)
141+
__ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
142+
{
143+
struct ipq_queue_entry *entry, *next;
144+
145+
list_for_each_entry_safe(entry, next, &queue_list, list) {
146+
if (!cmpfn || cmpfn(entry, data)) {
147+
list_del(&entry->list);
148+
queue_total--;
149+
ipq_issue_verdict(entry, NF_DROP);
150+
}
151+
}
152+
}
153+
154+
static void
155+
ipq_flush(ipq_cmpfn cmpfn, unsigned long data)
174156
{
175157
write_lock_bh(&queue_lock);
176-
__ipq_flush(verdict);
158+
__ipq_flush(cmpfn, data);
177159
write_unlock_bh(&queue_lock);
178160
}
179161

@@ -367,12 +349,6 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
367349
return 0;
368350
}
369351

370-
static inline int
371-
id_cmp(struct ipq_queue_entry *e, unsigned long id)
372-
{
373-
return (id == (unsigned long )e);
374-
}
375-
376352
static int
377353
ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
378354
{
@@ -381,7 +357,7 @@ ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len)
381357
if (vmsg->value > NF_MAX_VERDICT)
382358
return -EINVAL;
383359

384-
entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
360+
entry = ipq_find_dequeue_entry(vmsg->id);
385361
if (entry == NULL)
386362
return -ENOENT;
387363
else {
@@ -460,10 +436,7 @@ dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex)
460436
static void
461437
ipq_dev_drop(int ifindex)
462438
{
463-
struct ipq_queue_entry *entry;
464-
465-
while ((entry = ipq_find_dequeue_entry(dev_cmp, ifindex)) != NULL)
466-
ipq_issue_verdict(entry, NF_DROP);
439+
ipq_flush(dev_cmp, ifindex);
467440
}
468441

469442
#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
@@ -699,7 +672,7 @@ static void __exit ip_queue_fini(void)
699672
{
700673
nf_unregister_queue_handlers(&nfqh);
701674
synchronize_net();
702-
ipq_flush(NF_DROP);
675+
ipq_flush(NULL, 0);
703676

704677
unregister_sysctl_table(ipq_sysctl_header);
705678
unregister_netdevice_notifier(&ipq_dev_notifier);

0 commit comments

Comments
 (0)