Skip to content

Commit 4750005

Browse files
Jozsef Kadlecsikummakynes
authored andcommitted
netfilter: ipset: Fix "don't update counters" mode when counters used at the matching
The matching of the counters was not taken into account, fixed. Signed-off-by: Jozsef Kadlecsik <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent c045337 commit 4750005

File tree

7 files changed

+114
-128
lines changed

7 files changed

+114
-128
lines changed

include/linux/netfilter/ipset/ip_set.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ struct ip_set_ext {
122122
u64 bytes;
123123
char *comment;
124124
u32 timeout;
125+
u8 packets_op;
126+
u8 bytes_op;
125127
};
126128

127129
struct ip_set;
@@ -339,6 +341,10 @@ extern int ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
339341
struct ip_set_ext *ext);
340342
extern int ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
341343
const void *e, bool active);
344+
extern bool ip_set_match_extensions(struct ip_set *set,
345+
const struct ip_set_ext *ext,
346+
struct ip_set_ext *mext,
347+
u32 flags, void *data);
342348

343349
static inline int
344350
ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)

include/linux/netfilter/ipset/ip_set_counter.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,33 @@ ip_set_get_packets(const struct ip_set_counter *counter)
3434
return (u64)atomic64_read(&(counter)->packets);
3535
}
3636

37+
static inline bool
38+
ip_set_match_counter(u64 counter, u64 match, u8 op)
39+
{
40+
switch (op) {
41+
case IPSET_COUNTER_NONE:
42+
return true;
43+
case IPSET_COUNTER_EQ:
44+
return counter == match;
45+
case IPSET_COUNTER_NE:
46+
return counter != match;
47+
case IPSET_COUNTER_LT:
48+
return counter < match;
49+
case IPSET_COUNTER_GT:
50+
return counter > match;
51+
}
52+
return false;
53+
}
54+
3755
static inline void
3856
ip_set_update_counter(struct ip_set_counter *counter,
39-
const struct ip_set_ext *ext,
40-
struct ip_set_ext *mext, u32 flags)
57+
const struct ip_set_ext *ext, u32 flags)
4158
{
4259
if (ext->packets != ULLONG_MAX &&
4360
!(flags & IPSET_FLAG_SKIP_COUNTER_UPDATE)) {
4461
ip_set_add_bytes(ext->bytes, counter);
4562
ip_set_add_packets(ext->packets, counter);
4663
}
47-
if (flags & IPSET_FLAG_MATCH_COUNTERS) {
48-
mext->packets = ip_set_get_packets(counter);
49-
mext->bytes = ip_set_get_bytes(counter);
50-
}
5164
}
5265

5366
static inline bool

net/netfilter/ipset/ip_set_bitmap_gen.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,7 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
127127

128128
if (ret <= 0)
129129
return ret;
130-
if (SET_WITH_TIMEOUT(set) &&
131-
ip_set_timeout_expired(ext_timeout(x, set)))
132-
return 0;
133-
if (SET_WITH_COUNTER(set))
134-
ip_set_update_counter(ext_counter(x, set), ext, mext, flags);
135-
if (SET_WITH_SKBINFO(set))
136-
ip_set_get_skbinfo(ext_skbinfo(x, set), ext, mext, flags);
137-
return 1;
130+
return ip_set_match_extensions(set, ext, mext, flags, x);
138131
}
139132

140133
static int

net/netfilter/ipset/ip_set_core.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,31 @@ ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
472472
}
473473
EXPORT_SYMBOL_GPL(ip_set_put_extensions);
474474

475+
bool
476+
ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext,
477+
struct ip_set_ext *mext, u32 flags, void *data)
478+
{
479+
if (SET_WITH_TIMEOUT(set) &&
480+
ip_set_timeout_expired(ext_timeout(data, set)))
481+
return false;
482+
if (SET_WITH_COUNTER(set)) {
483+
struct ip_set_counter *counter = ext_counter(data, set);
484+
485+
if (flags & IPSET_FLAG_MATCH_COUNTERS &&
486+
!(ip_set_match_counter(ip_set_get_packets(counter),
487+
mext->packets, mext->packets_op) &&
488+
ip_set_match_counter(ip_set_get_bytes(counter),
489+
mext->bytes, mext->bytes_op)))
490+
return false;
491+
ip_set_update_counter(counter, ext, flags);
492+
}
493+
if (SET_WITH_SKBINFO(set))
494+
ip_set_get_skbinfo(ext_skbinfo(data, set),
495+
ext, mext, flags);
496+
return true;
497+
}
498+
EXPORT_SYMBOL_GPL(ip_set_match_extensions);
499+
475500
/* Creating/destroying/renaming/swapping affect the existence and
476501
* the properties of a set. All of these can be executed from userspace
477502
* only and serialized by the nfnl mutex indirectly from nfnetlink.

net/netfilter/ipset/ip_set_hash_gen.h

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -917,12 +917,9 @@ static inline int
917917
mtype_data_match(struct mtype_elem *data, const struct ip_set_ext *ext,
918918
struct ip_set_ext *mext, struct ip_set *set, u32 flags)
919919
{
920-
if (SET_WITH_COUNTER(set))
921-
ip_set_update_counter(ext_counter(data, set),
922-
ext, mext, flags);
923-
if (SET_WITH_SKBINFO(set))
924-
ip_set_get_skbinfo(ext_skbinfo(data, set),
925-
ext, mext, flags);
920+
if (!ip_set_match_extensions(set, ext, mext, flags, data))
921+
return 0;
922+
/* nomatch entries return -ENOTEMPTY */
926923
return mtype_do_data_match(data);
927924
}
928925

@@ -941,9 +938,9 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
941938
struct mtype_elem *data;
942939
#if IPSET_NET_COUNT == 2
943940
struct mtype_elem orig = *d;
944-
int i, j = 0, k;
941+
int ret, i, j = 0, k;
945942
#else
946-
int i, j = 0;
943+
int ret, i, j = 0;
947944
#endif
948945
u32 key, multi = 0;
949946

@@ -969,18 +966,13 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
969966
data = ahash_data(n, i, set->dsize);
970967
if (!mtype_data_equal(data, d, &multi))
971968
continue;
972-
if (SET_WITH_TIMEOUT(set)) {
973-
if (!ip_set_timeout_expired(
974-
ext_timeout(data, set)))
975-
return mtype_data_match(data, ext,
976-
mext, set,
977-
flags);
969+
ret = mtype_data_match(data, ext, mext, set, flags);
970+
if (ret != 0)
971+
return ret;
978972
#ifdef IP_SET_HASH_WITH_MULTI
979-
multi = 0;
973+
/* No match, reset multiple match flag */
974+
multi = 0;
980975
#endif
981-
} else
982-
return mtype_data_match(data, ext,
983-
mext, set, flags);
984976
}
985977
#if IPSET_NET_COUNT == 2
986978
}
@@ -1027,12 +1019,11 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
10271019
if (!test_bit(i, n->used))
10281020
continue;
10291021
data = ahash_data(n, i, set->dsize);
1030-
if (mtype_data_equal(data, d, &multi) &&
1031-
!(SET_WITH_TIMEOUT(set) &&
1032-
ip_set_timeout_expired(ext_timeout(data, set)))) {
1033-
ret = mtype_data_match(data, ext, mext, set, flags);
1022+
if (!mtype_data_equal(data, d, &multi))
1023+
continue;
1024+
ret = mtype_data_match(data, ext, mext, set, flags);
1025+
if (ret != 0)
10341026
goto out;
1035-
}
10361027
}
10371028
out:
10381029
return ret;

net/netfilter/ipset/ip_set_list_set.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,21 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
5555
struct ip_set_adt_opt *opt, const struct ip_set_ext *ext)
5656
{
5757
struct list_set *map = set->data;
58+
struct ip_set_ext *mext = &opt->ext;
5859
struct set_elem *e;
59-
u32 cmdflags = opt->cmdflags;
60+
u32 flags = opt->cmdflags;
6061
int ret;
6162

6263
/* Don't lookup sub-counters at all */
6364
opt->cmdflags &= ~IPSET_FLAG_MATCH_COUNTERS;
6465
if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
6566
opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
6667
list_for_each_entry_rcu(e, &map->members, list) {
67-
if (SET_WITH_TIMEOUT(set) &&
68-
ip_set_timeout_expired(ext_timeout(e, set)))
69-
continue;
7068
ret = ip_set_test(e->id, skb, par, opt);
71-
if (ret > 0) {
72-
if (SET_WITH_COUNTER(set))
73-
ip_set_update_counter(ext_counter(e, set),
74-
ext, &opt->ext,
75-
cmdflags);
76-
if (SET_WITH_SKBINFO(set))
77-
ip_set_get_skbinfo(ext_skbinfo(e, set),
78-
ext, &opt->ext,
79-
cmdflags);
80-
return ret;
81-
}
69+
if (ret <= 0)
70+
continue;
71+
if (ip_set_match_extensions(set, ext, mext, flags, e))
72+
return 1;
8273
}
8374
return 0;
8475
}

0 commit comments

Comments
 (0)