Subject: kern/7802: PFIL_HOOKS doesn't always load PFIL_OUT hooks in the correct order
To: None <gnats-bugs@gnats.netbsd.org>
From: None <mike@pelley.com>
List: netbsd-bugs
Date: 06/17/1999 19:20:49
>Number:         7802
>Category:       kern
>Synopsis:       PFIL_HOOKS doesn't always load PFIL_OUT hooks in the correct order
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Jun 17 19:20:00 1999
>Last-Modified:
>Originator:     Mike Pelley
>Organization:
	Worldmap.Net
>Release:        NetBSD 1.4
>Environment:
System: NetBSD rossem 1.4 NetBSD 1.4 (ROSSEM) #1: Mon May 31 21:09:01 EDT 1999 mike@rossem:/usr/src-mike/sys/arch/i386/compile/ROSSEM i386


>Description:
In pfil.c, the function pfil_list_add has the following section:

    if (flags & PFIL_IN)
        TAILQ_INSERT_HEAD(list, pfh, pfil_link);
    else
        TAILQ_INSERT_TAIL(list, pfh, pfil_link);

which is called from the function pfil_add_hook from the following section:

    if (flags & PFIL_IN)
        pfil_list_add(&pfil_in_list, func, flags);
    if (flags & PFIL_OUT)
        pfil_list_add(&pfil_out_list, func, flags);

In ip_fil.c (IPFilter), pfil_add_hook is called as follows:

    pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);

This means that pfil_add_hook is set to PFIL_IN|PFIL_OUT, and pfil_add_hook
calls pfil_list_add twice.  However, since flags contains both PFIL_IN and
PFIL_OUT, the second call to pfil_list_add will still match the (flags &
PFIL_IN) and so add the hook to the top of the out queue, instead of the
bottom of the out queue as intended.

>How-To-Repeat:
Add another pseudo device that uses pfil_add_hook with both PFIL_IN and PFIL_OUT and notice that the order promised in the history section of pfil(9) is not followed.

>Fix:
This is a simple patch:

--- sys/net/pfil.c      Thu Mar 19 10:45:30 1998
+++ sys-mike/net/pfil.c Thu Jun 17 18:55:37 1999
@@ -79,9 +79,9 @@
                pfil_init();
 
        if (flags & PFIL_IN)
-               pfil_list_add(&pfil_in_list, func, flags);
+               pfil_list_add(&pfil_in_list, func, PFIL_IN);
        if (flags & PFIL_OUT)
-               pfil_list_add(&pfil_out_list, func, flags);
+               pfil_list_add(&pfil_out_list, func, PFIL_OUT);
 }
 
 static void
>Audit-Trail:
>Unformatted: