On Thu, 23 Dec 2010, Robert B Mills wrote:

Date: Thu, 23 Dec 2010 20:35:13
From: Robert B Mills <[email protected]>
To: [email protected]
Subject: Small coding error in /usr/src/sys/net/pf.c

Hello

I have been having a problem trying to use the stateful tracking
option "override <TABLE> flush" in OpenBSD 4.7-stable. I'm running
an i386 GENERIC system as a vmware guest under Windows XP.

To reproduce:

 1. Install the following basic ruleset on a 4.7 system

    table <BLACKLIST> persist
    block drop all
    block drop quick from <BLACKLIST> to any
    pass out all
    pass in inet proto tcp from any to any port ssh keep state \
     (max 20, max-src-conn-rate 2/20, overload <BLACKLIST> flush)

 2. I tested the ruleset by starting 3 ssh sessions from a
    Windows host to the 4.7 system. When the 3rd ssh session is
    started, the overload rule is triggered, adding my Windows host
    to the <BLACKLIST> table. What I see at this point is that the
    3rd ssh session does not complete the login, but the first two
    sessions are fully operational. Using "systat states" I see that
    the PF states for the 1st two ssh sessions are still up.

    This means the "flush" has not occurred.

I have investigated the source code concerned with this behaviour and
I believe there is a coding error in /usr/src/sys/net/pf.c. The following
diff shows the small change I made to solve the problem:

obsd47> cd /usr/src/sys/net
obsd47> diff -c pf.c.orig pf.c
*** pf.c.orig   Sun Feb 21 05:01:14 2010
--- pf.c        Thu Dec 23 19:11:49 2010
***************
*** 477,485 ****
                               if (sk->af ==
                                   (*state)->key[PF_SK_WIRE]->af &&
                                   (((*state)->direction == PF_OUT &&
! PF_AEQ(&sn->addr, &sk->addr[0], sk->af)) ||
                                   ((*state)->direction == PF_IN &&
! PF_AEQ(&sn->addr, &sk->addr[1], sk->af))) &&
                                   ((*state)->rule.ptr->flush &
                                   PF_FLUSH_GLOBAL ||
                                   (*state)->rule.ptr == st->rule.ptr)) {
--- 477,485 ----
                               if (sk->af ==
                                   (*state)->key[PF_SK_WIRE]->af &&
                                   (((*state)->direction == PF_OUT &&
! PF_AEQ(&sn->addr, &sk->addr[1], sk->af)) ||
                                   ((*state)->direction == PF_IN &&
! PF_AEQ(&sn->addr, &sk->addr[0], sk->af))) &&
                                   ((*state)->rule.ptr->flush &
                                   PF_FLUSH_GLOBAL ||
                                   (*state)->rule.ptr == st->rule.ptr)) {

Furthermore, I believe this problem exists in all versions since OpenBSD 4.4

The dmesg output from my system is below.

Please let me know if you need any additional information.

Kind regards and Merry Christmas
Robert Mills

-----------------------------------------
OpenBSD 4.7-stable (GENERIC) #4: Thu Dec 23 18:10:36 EST 2010
   [email protected]:/usr/src/sys/arch/i386/compile/GENERIC
cpu0: Intel(R) Pentium(R) 4 CPU 3.00GHz ("GenuineIntel" 686-class) 3 GHz
cpu0: FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,SSE3
real mem  = 804810752 (767MB)
avail mem = 771088384 (735MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 08/15/08, BIOS32 rev. 0 @ 0xfd780, SMBIOS rev. 2.4 @ 0xe4010 (45 entries)
bios0: vendor Phoenix Technologies LTD version "6.00" date 08/15/2008
bios0: VMware, Inc. VMware Virtual Platform
acpi0 at bios0: rev 2
acpi0: tables DSDT FACP BOOT APIC
acpi0: wakeup devices PCI0(S3) USB_(S1) SLPB(S4)
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: apic clock running at 66MHz
ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 11, 24 pins
acpiprt0 at acpi0: bus 0 (PCI0)
acpicpu0 at acpi0
acpibat0 at acpi0: BAT1 not present
acpibat1 at acpi0: BAT2 not present
acpiac0 at acpi0: AC unit online
acpibtn0 at acpi0: SLPB
bios0: ROM list: 0xc0000/0x8000 0xc8000/0x1000 0xc9000/0x1000 0xdc000/0x4000! 0xe4000/0x4000!
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 "Intel 82443BX AGP" rev 0x01
ppb0 at pci0 dev 1 function 0 "Intel 82443BX AGP" rev 0x01
pci1 at ppb0 bus 1
piixpcib0 at pci0 dev 7 function 0 "Intel 82371AB PIIX4 ISA" rev 0x08
pciide0 at pci0 dev 7 function 1 "Intel 82371AB IDE" rev 0x01: DMA, channel 0 configured to compatibility, channel 1 configured to compatibility
wd0 at pciide0 channel 0 drive 0: <VMware Virtual IDE Hard Drive>
wd0: 64-sector PIO, LBA, 8192MB, 16777216 sectors
wd1 at pciide0 channel 0 drive 1: <VMware Virtual IDE Hard Drive>
wd1: 64-sector PIO, LBA, 8192MB, 16777216 sectors
wd0(pciide0:0:0): using PIO mode 4, Ultra-DMA mode 2
wd1(pciide0:0:1): using PIO mode 4, Ultra-DMA mode 2
atapiscsi0 at pciide0 channel 1 drive 0
scsibus0 at atapiscsi0: 2 targets
cd0 at scsibus0 targ 0 lun 0: <NECVMWar, VMware IDE CDR10, 1.00> ATAPI 5/cdrom removable
cd0(pciide0:1:0): using PIO mode 4, Ultra-DMA mode 2
uhci0 at pci0 dev 7 function 2 "Intel 82371AB USB" rev 0x00: apic 1 int 19 (irq 9) piixpm0 at pci0 dev 7 function 3 "Intel 82371AB Power" rev 0x08: SMBus disabled
vga1 at pci0 dev 15 function 0 "VMware Virtual SVGA II" rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
em0 at pci0 dev 16 function 0 "Intel PRO/1000MT (82545EM)" rev 0x01: apic 1 int 17 (irq 11), address 00:0c:29:68:ad:ef em1 at pci0 dev 17 function 0 "Intel PRO/1000MT (82545EM)" rev 0x01: apic 1 int 18 (irq 10), address 00:0c:29:68:ad:f9 eap0 at pci0 dev 18 function 0 "Ensoniq AudioPCI97" rev 0x02: apic 1 int 19 (irq 9)
ac97: codec id 0x43525913 (Cirrus Logic CS4297A rev 3)
audio0 at eap0
midi0 at eap0: <AudioPCI MIDI UART>
ehci0 at pci0 dev 19 function 0 "VMware Virtual EHCI" rev 0x00: apic 1 int 16 (irq 5)
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "VMware EHCI root hub" rev 2.00/1.00 addr 1
isa0 at piixpcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pmsi0 at pckbc0 (aux slot)
pckbc0: using irq 12 for aux slot
wsmouse0 at pmsi0 mux 0
pcppi0 at isa0 port 0x61
midi1 at pcppi0: <PC speaker>
spkr0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
usb1 at uhci0: USB revision 1.0
uhub1 at usb1 "Intel UHCI root hub" rev 1.00/1.00 addr 1
mtrr: Pentium Pro MTRR support
vscsi0 at root
scsibus1 at vscsi0: 256 targets
softraid0 at root
root on wd0a swap on wd0b dump on wd0b


Hi

Sorry. It was suggested to me that developers prefer
"diff -up ...", so here's my diff in that format:

obsd47> diff -up pf.c.orig pf.c --- pf.c.orig Sun Feb 21 05:01:14 2010
+++ pf.c        Thu Dec 23 19:11:49 2010
@@ -477,9 +477,9 @@ pf_src_connlimit(struct pf_state **state)
                                if (sk->af ==
                                    (*state)->key[PF_SK_WIRE]->af &&
                                    (((*state)->direction == PF_OUT &&
-                                   PF_AEQ(&sn->addr, &sk->addr[0], sk->af)) ||
+                                   PF_AEQ(&sn->addr, &sk->addr[1], sk->af)) ||
                                    ((*state)->direction == PF_IN &&
-                                   PF_AEQ(&sn->addr, &sk->addr[1], sk->af))) &&
+                                   PF_AEQ(&sn->addr, &sk->addr[0], sk->af))) &&
                                    ((*state)->rule.ptr->flush &
                                    PF_FLUSH_GLOBAL ||
                                    (*state)->rule.ptr == st->rule.ptr)) {

Kind regards
Robert Mills

Reply via email to