git: fae2a8cad398 - stable/13 - pf: fallback if $pf_rules fails to load

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 24 Jan 2022 22:55:02 UTC
The branch stable/13 has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=fae2a8cad398518c473f67fc210206c6dac02610

commit fae2a8cad398518c473f67fc210206c6dac02610
Author:     Thomas Steen Rasmussen <thomas@gibfest.dk>
AuthorDate: 2021-06-16 18:29:06 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-01-24 20:11:02 +0000

    pf: fallback if $pf_rules fails to load
    
    Support loading a default pf ruleset in case of invalid pf.conf.
    
    If no pf rules are loaded pf will pass/allow all traffic, assuming the
    kernel is compiled without PF_DEFAULT_TO_DROP, as is the case in
    GENERIC.
    
    In other words: if there's a typo in the main pf_rules we would allow
    all traffic. The new default rules minimise the impact of this.
    
    If $pf_program (i.e. pfctl) fails to set $pf_fules and
    $pf_fallback_rules_enable is YES we will load $pf_fallback_rules_file if
    set, or $pf_fallback_rules.
    
    $pf_fallback_rules can include multiple rules, for example to permit
    traffic on a management interface.
    
    $pf_fallback_rules_enable defaults to "NO", preserving historic behaviour.
    
    man page changes by ceri@.
    
    PR:             256410
    Reviewed by:    donner, kp
    Sponsored by:   semaphor.dk
    Differential Revision:  https://reviews.freebsd.org/D30791
    
    (cherry picked from commit 28f47a199cfd8749ab30a0327b0a3f8977ec2b43)
---
 libexec/rc/rc.conf       |  5 +++++
 libexec/rc/rc.d/pf       | 19 ++++++++++++++++++-
 share/man/man5/rc.conf.5 | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf
index 58865aae7753..c6f1a4d2b9c4 100644
--- a/libexec/rc/rc.conf
+++ b/libexec/rc/rc.conf
@@ -224,6 +224,11 @@ pf_rules="/etc/pf.conf"		# rules definition file for pf (nonexistent
 				# by default)
 pf_program="/sbin/pfctl"	# where the pfctl program lives
 pf_flags=""			# additional flags for pfctl
+pf_fallback_rules_enable="NO"	# fallback if loading ruleset fails
+pf_fallback_rules="block drop log all"	# rules to load on pf ruleset failure
+#pf_fallback_rules="block drop log all
+#pass quick on em4"		# multi-rule
+pf_fallback_rules_file="/etc/pf-fallback.conf"	# rules file on ruleset failure
 pflog_enable="NO"		# Set to YES to enable packet filter logging
 pflog_logfile="/var/log/pflog"	# where pflogd should store the logfile
 pflog_program="/sbin/pflogd"	# where the pflogd program lives
diff --git a/libexec/rc/rc.d/pf b/libexec/rc/rc.d/pf
index 1f7394007667..fa1b49643cc5 100755
--- a/libexec/rc/rc.d/pf
+++ b/libexec/rc/rc.d/pf
@@ -23,11 +23,28 @@ extra_commands="check reload resync"
 required_files="$pf_rules"
 required_modules="pf"
 
+pf_fallback()
+{
+	warn "Unable to load $pf_rules."
+
+	if ! checkyesno pf_fallback_rules_enable; then
+		return
+	fi
+
+	if [ -f $pf_fallback_rules_file ]; then
+		warn "Loading fallback rules file: $pf_fallback_rules_file"
+		$pf_program -f "$pf_fallback_rules_file" $pf_flags
+	else
+		warn "Loading fallback rules: $pf_fallback_rules"
+		echo $pf_fallback_rules | $pf_program -f - $pf_flags
+	fi
+}
+
 pf_start()
 {
 	check_startmsgs && echo -n 'Enabling pf'
 	$pf_program -F all > /dev/null 2>&1
-	$pf_program -f "$pf_rules" $pf_flags
+	$pf_program -f "$pf_rules" $pf_flags || pf_fallback
 	if ! $pf_program -s info | grep -q "Enabled" ; then
 		$pf_program -eq
 	fi
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index 883937a619ee..e3b05f75f641 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -1000,6 +1000,42 @@ is set to
 these flags are passed to the
 .Xr pfctl 8
 program when loading the ruleset.
+.It Va pf_fallback_rules_enable
+.Pq Vt bool
+Set to
+.Dq Li NO
+by default.
+Setting this to
+.Dq Li YES
+enables loading
+.Va pf_fallback_rules_file
+or
+.Va pf_fallback_rules
+in case of a problem when loading the ruleset in
+.Va pf_rules .
+.It Va pf_fallback_rules_file
+.Pq Vt str
+Path to a pf ruleset to load in case of failure when loading the
+ruleset in
+.Va pf_rules
+(default
+.Pa /etc/pf-fallback.conf ) .
+.It Va pf_fallback_rules
+.Pq Vt str
+A pf ruleset to load in case of failure when loading the ruleset in
+.Va pf_rules
+and
+.Va pf_fallback_rules_file
+is not found.
+Multiple rules can be set as follows:
+.Bd -literal
+pf_fallback_rules="\\
+	block drop log all\\
+	pass in quick on em0"
+.Pp
+.Ed
+The default fallback rule is
+.Dq block drop log all
 .It Va pflog_enable
 .Pq Vt bool
 Set to