NetBSD Problem Report #47749
From genadmin@idlefortress.accessaxis.com Fri Apr 19 23:52:19 2013
Return-Path: <genadmin@idlefortress.accessaxis.com>
Received: from mail.netbsd.org (mail.netbsd.org [149.20.53.66])
by www.NetBSD.org (Postfix) with ESMTP id 1803263E5A8
for <gnats-bugs@gnats.NetBSD.org>; Fri, 19 Apr 2013 23:52:19 +0000 (UTC)
Message-Id: <20130419223512.3DEDA2402BD@idlefortress.accessaxis.com>
Date: Fri, 19 Apr 2013 16:35:12 -0600 (MDT)
From: genadmin@idlefortress.accessaxis.com
Reply-To: inittab@unixdev.net
To: gnats-bugs@gnats.NetBSD.org
Subject: NetBSD 6.0 Only Replies to First ICMP Echo (ping)
X-Send-Pr-Version: 3.95
>Number: 47749
>Category: kern
>Synopsis: IPF: NetBSD 6.0 Only Replies to First ICMP Echo (ping)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Apr 19 23:55:00 +0000 2013
>Last-Modified: Wed May 16 20:26:21 +0000 2018
>Originator: Greg Schenzel
>Release: NetBSD 6.0
>Organization:
unixdev.net
>Environment:
System: NetBSD idlefortress.accessaxis.com 6.0 NetBSD 6.0 (GENERIC.UP) sparc64
Architecture: sparc64
Machine: sparc64
>Description:
NetBSD 6.0 only sends a reply for the first ICMP Echo received. Verified
on NetBSD/sparc64. In the past I believe I've noticed this on NetBSD/i386
and NetBSD/amd64 as well. IPFilter is enabled to allow all traffic on the
internal interface (tlp0). tcpdump shows the requests coming in but only
one reply going out. I dug through sysctl and didn't see any ICMP settings
that might affect it. I've tried with Debian 6 and Solaris 9 ping
utilities, but this is not an issue when pinging from the NetBSD system
itself.
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/47749: NetBSD 6.0 Only Replies to First ICMP Echo (ping)
Date: Sat, 20 Apr 2013 16:58:52 +0200
Can you try with IPF disabled?
Martin
From: Greg Schenzel <inittab@unixdev.net>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/47749: NetBSD 6.0 Only Replies to First ICMP Echo (ping)
Date: Sat, 20 Apr 2013 14:45:44 -0600
--tKW2IUtsqtDRztdT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Works as expected after running "ipf -D". Here are my first 12 rules.
The remaining rules are specific tcp/udp ports on the external
interface (tlp1). This issue occurs on both tlp0 and tlp1 with IPF
enabled.=20
### - completely kill
# too short to be real
block in log quick all with short
# source routing is set
block in log quick all with opt lsrr
block in log quick all with opt ssrr
# reserved address space
block in log quick on tlp1 from 10.0.0.0/8 to any
block in log quick on tlp1 from 172.16.0.0/12 to any
block in log quick on tlp1 from 192.168.0.0/16 to any
### - set default interface rules
pass out log quick proto icmp from any to any keep state
pass out log quick proto tcp/udp from any to any keep state keep frags
pass in log on tlp0 from any to any
pass in log on lo0 from any to any
block in log on tlp1 from any to any
### - icmp
# allow ping and traceroute
#pass in log quick on tlp1 proto icmp from any to any icmp-type 0
#pass in log quick on tlp1 proto icmp from any to any icmp-type 8
#pass in log quick on tlp1 proto icmp from any to any icmp-type 11
pass in log quick proto icmp from any to any
--tKW2IUtsqtDRztdT
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iEYEARECAAYFAlFy/ngACgkQ2ua/BJvbazccCwCdFEX8VUCXCsv75dC/3w9BKxeB
tNoAn26rEJcfkGVoSxVjjTk825VrIsPU
=ANwV
-----END PGP SIGNATURE-----
--tKW2IUtsqtDRztdT--
From: Martin Husemann <martin@duskware.de>
To: gnats-bugs@NetBSD.org
Cc: Darren Reed <darrenr@NetBSD.org>
Subject: Re: kern/47749: NetBSD 6.0 Only Replies to First ICMP Echo (ping)
Date: Sun, 21 Apr 2013 10:04:19 +0200
On Sat, Apr 20, 2013 at 10:10:05PM +0000, Greg Schenzel wrote:
> Works as expected after running "ipf -D". Here are my first 12 rules.
I don't think it is your rules, but a generic bug in IPF.
Darren?
Martin
From: =?ISO-8859-1?Q?Sergio_L=F3pez?= <slp@sinrega.org>
To: gnats-bugs@NetBSD.org
Cc: martin@duskware.de, darrenr@NetBSD.org
Subject: Re: kern/47749
Date: Sat, 24 Aug 2013 11:03:31 +0200
Apparently, IPF gets confused when trying to keep track of an
ICMP_ECHOREPLY packet.
The first time such a packet is found, fr_addstate from fr_scanlist
(fil.c:2146) fails, and if no other rule matches, it returns the
default "pass" value (without FR_KEEPSTATE flag), but leaves
fin->fin_fr pointing to the rule (with FR_KEEPSTATE), and this
structure is saved into frcache. So this first packet is considered to
haven't match any rule, and unless IPF is in block by default, it
passes the filter.
But, when a second packet arrives, its "pass" value is taken from
frcache, which contains the flags from the rule, including
FR_KEEPSTATE. In consequence, fr_addstate fails again when called from
fr_check (fil.c:2586), and this time the packet is marked as blocked.
From an user's perspective, this can be avoided by not using "keep
state" for icmp rules, or by doing so in both the input and output
filters, as this will make all ICMP_ECHOREPLY packets to be matched by
a previous ICMP_ECHO.
But, as Martin said, I don't think IPF should behave this way. I think
a sensible solution, without altering much of IPF behavior, could be
something like this:
--- fil.c.orig 2013-08-24 08:55:50.000000000 +0000
+++ fil.c 2013-08-24 08:56:20.000000000 +0000
@@ -2147,6 +2147,7 @@
ATOMIC_INCL(frstats[out].fr_ads);
} else {
ATOMIC_INCL(frstats[out].fr_bads);
+ fin->fin_fr = NULL;
pass = passo;
continue;
}
This makes that both first and subsequent ICMP_ECHOREPLY packets
without a related ICMP_ECHO, will not match against a rule with "keep
state", much in the same way as (AFAIK) IPF from "-current" does.
From: Darren Reed <darrenr@netbsd.org>
To: =?ISO-8859-1?Q?Sergio_L=F3pez?= <slp@sinrega.org>
Cc: gnats-bugs@NetBSD.org, martin@duskware.de
Subject: Re: kern/47749
Date: Thu, 29 Aug 2013 23:06:18 +1000
Sergio López wrote:
> Apparently, IPF gets confused when trying to keep track of an
> ICMP_ECHOREPLY packet.
>
> The first time such a packet is found, fr_addstate from fr_scanlist
> (fil.c:2146) fails, and if no other rule matches, it returns the
> default "pass" value (without FR_KEEPSTATE flag), but leaves
> fin->fin_fr pointing to the rule (with FR_KEEPSTATE), and this
> structure is saved into frcache. So this first packet is considered to
> haven't match any rule, and unless IPF is in block by default, it
> passes the filter.
>
> But, when a second packet arrives, its "pass" value is taken from
> frcache, which contains the flags from the rule, including
> FR_KEEPSTATE. In consequence, fr_addstate fails again when called from
> fr_check (fil.c:2586), and this time the packet is marked as blocked.
>
> From an user's perspective, this can be avoided by not using "keep
> state" for icmp rules, or by doing so in both the input and output
> filters, as this will make all ICMP_ECHOREPLY packets to be matched by
> a previous ICMP_ECHO.
>
Can you give me an example that uses ipftest to show this behaviour?
Darren
From: Darren Reed <darrenr@netbsd.org>
To: =?ISO-8859-1?Q?Sergio_L=F3pez?= <slp@sinrega.org>
Cc: gnats-bugs@NetBSD.org, martin@duskware.de
Subject: Re: kern/47749
Date: Thu, 29 Aug 2013 23:14:08 +1000
Sergio,
I think that the change should look more like below.
The reason is that when "pass" is restored with "pass = passo",
the old rule from which "passo" belongs to should belong in
fin_fr.
Let me know how you go with testing it.
Cheers,
Darren
Index: fil.c
===================================================================
RCS file: /devel/CVS/IP-Filter/fil.c,v
retrieving revision 2.243.2.164
diff -u -r2.243.2.164 fil.c
--- fil.c 26 Jan 2012 06:03:42 -0000 2.243.2.164
+++ fil.c 29 Aug 2013 12:07:33 -0000
@@ -1952,7 +1952,7 @@
u_32_t pass;
{
int rulen, portcmp, off, skip;
- struct frentry *fr, *fnext;
+ struct frentry *fr, *fnext, *fro;
u_32_t passt, passo;
/*
@@ -2088,6 +2088,7 @@
}
passt = fr->fr_flags;
}
+ fro = fin->fin_fr;
fin->fin_fr = fr;
#ifdef IPFILTER_LOG
@@ -2148,6 +2149,7 @@
ATOMIC_INCL(frstats[out].fr_ads);
} else {
ATOMIC_INCL(frstats[out].fr_bads);
+ fin->fin_fr = fro;
pass = passo;
continue;
}
From: Sergio Lopez <slp@sinrega.org>
To: Darren Reed <darrenr@netbsd.org>
Cc: gnats-bugs@NetBSD.org, martin@duskware.de
Subject: Re: kern/47749
Date: Fri, 30 Aug 2013 08:39:51 +0000
> Can you give me an example that uses ipftest to show this behaviour?
Sure:
stable61164# cat /root/pr44749/rules.out
pass out log quick proto icmp from any to any keep state
stable61164# cat /root/pr44749/rules.out.nostate
pass out log quick proto icmp from any to any
stable61164# cat /root/pr44749/test.out
in on re0 icmp 192.168.0.4 192.168.0.21
out on re0 icmp 192.168.0.21 192.168.0.4
in on re0 icmp 192.168.0.4 192.168.0.21
out on re0 icmp 192.168.0.21 192.168.0.4
in on re0 icmp 192.168.0.4 192.168.0.21
out on re0 icmp 192.168.0.21 192.168.0.4
stable61164# ./ipftest -r /root/pr44749/rules.out -i /root/pr44749/test.out
nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------nomatch ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------block ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------block ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
stable61164# ./ipftest -r /root/pr44749/rules.out.nostate -i /root/pr44749/test.out
nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------pass ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------pass ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------pass ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
Sergio.
From: Sergio Lopez <slp@sinrega.org>
To: Darren Reed <darrenr@netbsd.org>
Cc: gnats-bugs@NetBSD.org, martin@duskware.de
Subject: Re: kern/47749
Date: Fri, 30 Aug 2013 08:48:22 +0000
On Thu, Aug 29, 2013 at 11:14:08PM +1000, Darren Reed wrote:
> Sergio,
>
> I think that the change should look more like below.
>
> The reason is that when "pass" is restored with "pass = passo",
> the old rule from which "passo" belongs to should belong in
> fin_fr.
>
> Let me know how you go with testing it.
You're right. I've tested your patch with ipftest and as kernel's IPF,
and it works nicely in both cases:
stable61164# ./ipftest -r /root/pr44749/rules.out -i /root/pr44749/test.out
nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------nomatch ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------nomatch ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
--------------nomatch ip #0 48(20) 1 192.168.0.4 > 192.168.0.21
--------------nomatch ip #0 48(20) 1 192.168.0.21 > 192.168.0.4
Thanks!
Sergio.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.