NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/54169: correct bpf code is not generated when multiple conditions including range specification are specified for the port variable in npf.conf



>Number:         54169
>Category:       bin
>Synopsis:       correct bpf code is not generated when multiple conditions including range specification are specified for the port variable in npf.conf
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon May 06 19:55:00 +0000 2019
>Originator:     Ryo Shimizu
>Release:        NetBSD 8.99.37
>Organization:
>Environment:
System: NetBSD netbsd 8.99.37 NetBSD 8.99.37 (GENERIC) #3: Fri Apr 19 02:08:38 JST 2019 ryo@moveq:/usr/src/sys/arch/amd64/compile/GENERIC amd64
Architecture: x86_64
Machine: amd64
>Description:

npfctl generated incorrect bpf code for the LINE 6 of the following npf.conf.
There is no problem for LINE 5.

	% cat -n npf.conf
	     1  $var1 = { 137, 138, 139, 445 }
	     2  $var2 = { 137-139, 445 }
	     3  
	     4  group default {
	     5  	pass in from any port $var1
	     6  	pass in from any port $var2
	     7  }
	     8  

	# npfctl debug npf.conf /dev/null
	
	RULE AT LINE 5
	(000) ld       M[0]
	(001) jeq      #0x0             jt 18   jf 2
	(002) ld       M[2]
	(003) jeq      #0x6             jt 7    jf 4
	(004) ld       M[2]
	(005) jeq      #0x11            jt 7    jf 6
	(006) ret      #0
	(007) ldx      M[1]
	(008) ldh      [x + 0]
	(009) jeq      #0x89            jt 17   jf 10	# if (port == 137) goto match(17); else goto 10;
	(010) ldh      [x + 0]
	(011) jeq      #0x8a            jt 17   jf 12	# if (port == 138) goto match(17); else goto 12;
	(012) ldh      [x + 0]
	(013) jeq      #0x8b            jt 17   jf 14	# if (port == 139) goto match(17); else goto 14;
	(014) ldh      [x + 0]
	(015) jeq      #0x1bd           jt 17   jf 16	# if (port == 445) goto match(17); else goto 16;
	(016) ret      #0
	(017) ret      #-1
	(018) ret      #0
	
	RULE AT LINE 6
	(000) ld       M[0]
	(001) jeq      #0x0             jt 15   jf 2
	(002) ld       M[2]
	(003) jeq      #0x6             jt 7    jf 4
	(004) ld       M[2]
	(005) jeq      #0x11            jt 7    jf 6
	(006) ret      #0
	(007) ldx      M[1]
	(008) ldh      [x + 0]
	(009) jge      #0x89            jt 14   jf 10	# if (port >= 137) goto match(14); else goto 10;	/* incorrect! */
	(010) jgt      #0x8b            jt 11   jf 14	# if (port > 139) goto 11; else goto match(14);
	(011) ldh      [x + 0]
	(012) jeq      #0x1bd           jt 14   jf 13
	(013) ret      #0
	(014) ret      #-1
	(015) ret      #0


bpf code for LINE 6 should be

	RULE AT LINE 6
	(000) ld       M[0]
	(001) jeq      #0x0             jt 15   jf 2
	(002) ld       M[2]
	(003) jeq      #0x6             jt 7    jf 4
	(004) ld       M[2]
	(005) jeq      #0x11            jt 7    jf 6
	(006) ret      #0
	(007) ldx      M[1]
	(008) ldh      [x + 0]
	(009) jge      #0x89            jt 10   jf 11	# if (port >= 137) goto 10; else goto 11;
	(010) jgt      #0x8b            jt 11   jf 14	# if (port > 139) goto 11; else goto match(14);
	(011) ldh      [x + 0]
	(012) jeq      #0x1bd           jt 14   jf 13
	(013) ret      #0
	(014) ret      #-1
	(015) ret      #0


This happens because fixup_jumps() only take into account a single bpf jump code
when converting a condition enumeration to "or".


>How-To-Repeat:

>Fix:

It's not elegant code :-(

cvs -q diff -aup npf_bpf_comp.c
Index: npf_bpf_comp.c
===================================================================
RCS file: /src/cvs/cvsroot-netbsd/src/usr.sbin/npf/npfctl/npf_bpf_comp.c,v
retrieving revision 1.12
diff -a -u -p -r1.12 npf_bpf_comp.c
--- npf_bpf_comp.c	17 Apr 2019 20:41:58 -0000	1.12
+++ npf_bpf_comp.c	6 May 2019 11:55:43 -0000
@@ -129,9 +129,34 @@ fixup_jumps(npf_bpf_t *ctx, u_int start,
 			continue;
 		}
 		if (swap) {
-			uint8_t jt = insn->jt;
-			insn->jt = insn->jf;
-			insn->jf = jt;
+			/*
+			 * XXX: depend on the bpf code generated by
+			 *      npfctl_bpf_ports().
+			 */
+			if ((i + 1 < end) &&
+			    (insn[0].code == (BPF_JMP+BPF_JGE+BPF_K)) &&
+			    (insn[0].jt == 0) && (insn[0].jf == JUMP_MAGIC) &&
+			    (insn[1].code == (BPF_JMP+BPF_JGT+BPF_K)) &&
+			    (insn[1].jt == JUMP_MAGIC) && (insn[1].jf == 0)) {
+				/*
+				 * <begin>-<end> range check insns
+				 *
+				 *   JGE #<begin> jt 0 jf JUMP_MAGIC
+				 *   JGT #<end>   jt JUMP_MAGIC jf 0
+				 *    :
+				 *
+				 * should be changed to
+				 *
+				 *   JGE #<begin> jt 0 jt 1
+				 *   JGT #<end>   jt 0 jt JUMP_MAGIC
+				 *    :
+				 */
+				insn->jf = 1;
+			} else {
+				uint8_t jt = insn->jt;
+				insn->jt = insn->jf;
+				insn->jf = jt;
+			}
 		}
 		if (insn->jt == JUMP_MAGIC)
 			insn->jt = fail_off;



Home | Main Index | Thread Index | Old Index