* Re: Resend: One bug in the xt_hashlimit.c
[not found] <CA+6hz4oJ3g3z49z44nN02DJtkHDkF5tiNH-nDH3thdD3GYUg7A@mail.gmail.com>
@ 2012-12-16 17:39 ` Jan Engelhardt
2012-12-16 23:01 ` Pablo Neira Ayuso
0 siblings, 1 reply; 2+ messages in thread
From: Jan Engelhardt @ 2012-12-16 17:39 UTC (permalink / raw)
To: Feng Gao; +Cc: Pablo Neira Ayuso, laforge, Netfilter Developer Mailing List
On Sunday 2012-12-16 16:19, Feng Gao wrote:
>
>Hi Harald & Jan,
>
>Because there is no any response for this issue,so I send the egmail again a
>s a reminder.
Sorry to not have responded. This sort of went under the radar since
netfilter-devel was initially not Cced. More answers to the patch
below.
>The following codes are from function "hashlimit_mt".
>dh = dsthash_find(hinfo, &dst);
>if (dh == NULL) {
>dh = dsthash_alloc_init(hinfo, &dst);
>
>When two or more threads invoke dsthash_find(hinfo, &dst) at the same time
>and fail to find the dh, then all of them will enter the dsthash_alloc_init
>to create one new node.
>As a result, it will casue that these multiple threads create multle nodes
>with same IP. It is not expected behavior.
>--- net/netfilter/xt_hashlimit.c.orig 2012-12-02 13:54:45.376382165 +0800
>+++ net/netfilter/xt_hashlimit.c 2012-12-02 13:59:32.083381142 +0800
>@@ -157,11 +157,20 @@ dsthash_find(const struct xt_hashlimit_h
> /* allocate dsthash_ent, initialize dst, put in htable and lock it */
> static struct dsthash_ent *
> dsthash_alloc_init(struct xt_hashlimit_htable *ht,
>- const struct dsthash_dst *dst)
>+ const struct dsthash_dst *dst,
>+ bool *new_node)
> {
> struct dsthash_ent *ent;
>
> spin_lock(&ht->lock);
>+
>+ ent = dsthash_find(ht, dst);
Hm. In hashlimit_mt(), dsthash_find() has already been called once
(within a RCU_bh section), and now you are doing the lookup again
(within spin_lock section).
>+ if (ent) {
You have trailing squatspaces (remove them). I suggest that you
use `mcedit` or `git log -1 -p`, as both these tools highlight
such unwanted trailing spaces.
>@@ -539,7 +555,7 @@ hashlimit_mt(const struct sk_buff *skb,
> dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
> rateinfo_recalc(dh, now);
> }
>-
>+
> if (dh->rateinfo.credit >= dh->rateinfo.cost) {
> /* below the limit */
> dh->rateinfo.credit -= dh->rateinfo.cost;
Same spacing issue here.
====
What would you think of the following patch?
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 26a668a..0d17032 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -591,9 +591,11 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
goto hotdrop;
rcu_read_lock_bh();
+ spin_lock_bh();
dh = dsthash_find(hinfo, &dst);
if (dh == NULL) {
dh = dsthash_alloc_init(hinfo, &dst);
+ spin_unlock_bh();
if (dh == NULL) {
rcu_read_unlock_bh();
goto hotdrop;
@@ -601,6 +603,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
rateinfo_init(dh, hinfo);
} else {
+ spin_unlock_bh();
/* update expiration timeout */
dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
rateinfo_recalc(dh, now, hinfo->cfg.mode);
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: Resend: One bug in the xt_hashlimit.c
2012-12-16 17:39 ` Resend: One bug in the xt_hashlimit.c Jan Engelhardt
@ 2012-12-16 23:01 ` Pablo Neira Ayuso
0 siblings, 0 replies; 2+ messages in thread
From: Pablo Neira Ayuso @ 2012-12-16 23:01 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Feng Gao, laforge, Netfilter Developer Mailing List
On Sun, Dec 16, 2012 at 06:39:56PM +0100, Jan Engelhardt wrote:
[...]
> What would you think of the following patch?
>
> diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
> index 26a668a..0d17032 100644
> --- a/net/netfilter/xt_hashlimit.c
> +++ b/net/netfilter/xt_hashlimit.c
> @@ -591,9 +591,11 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
> goto hotdrop;
>
> rcu_read_lock_bh();
> + spin_lock_bh();
> dh = dsthash_find(hinfo, &dst);
> if (dh == NULL) {
> dh = dsthash_alloc_init(hinfo, &dst);
> + spin_unlock_bh();
This is sub-optimal and RCU becomes almost useless with this approach.
The way to fix this is to follow a similar approach to what
nf_conntrack does to avoid this race.
> if (dh == NULL) {
> rcu_read_unlock_bh();
> goto hotdrop;
> @@ -601,6 +603,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
> dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
> rateinfo_init(dh, hinfo);
> } else {
> + spin_unlock_bh();
> /* update expiration timeout */
> dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
> rateinfo_recalc(dh, now, hinfo->cfg.mode);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-12-16 23:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CA+6hz4oJ3g3z49z44nN02DJtkHDkF5tiNH-nDH3thdD3GYUg7A@mail.gmail.com>
2012-12-16 17:39 ` Resend: One bug in the xt_hashlimit.c Jan Engelhardt
2012-12-16 23:01 ` Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).