From e7951d0b04e6464b37264b8166b1e9ce368a9f1d Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Thu, 1 Feb 2024 17:43:05 -0500 Subject: [PATCH 01/17] rtld-elf: Avoid unnecessary lock_restart_for_upgrade() calls In order to atomically upgrade the rtld bind lock, load_filtees() may trigger a longjmp back to _rtld_bind() so that the binding can be done with the write lock held. However, the write lock is only needed when filtee objects haven't already been loaded, so move the lock_restart_for_upgrade() call to avoid unnecessary lock upgrades when a filtee is defined. Reviewed by: kib Tested by: brooks MFC after: 1 week Sponsored by: Innovate UK --- libexec/rtld-elf/rtld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 2c4111cc457a..24abc4580f53 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -2583,8 +2583,8 @@ static void load_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate) { - lock_restart_for_upgrade(lockstate); if (!obj->filtees_loaded) { + lock_restart_for_upgrade(lockstate); load_filtee1(obj, obj->needed_filtees, flags, lockstate); load_filtee1(obj, obj->needed_aux_filtees, flags, lockstate); obj->filtees_loaded = true; From 7edb49a1152eb7c70a0806fabbe7ce3ff0d810a4 Mon Sep 17 00:00:00 2001 From: Graham Perrin Date: Fri, 2 Feb 2024 08:25:41 -0700 Subject: [PATCH 02/17] freebsd-tips: freebsd-update fetch, then install In end of life (EOL) warning cases: freebsd-update fetch install (the two commands, combined) may fetch and patch, but not install. Instead: run the two consecutively. Consistent with installation information in /releases/ areas and with accepted https://reviews.freebsd.org/D42722 Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1096 --- usr.bin/fortune/datfiles/freebsd-tips | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/usr.bin/fortune/datfiles/freebsd-tips b/usr.bin/fortune/datfiles/freebsd-tips index aed66f2295e2..028a9e9b1430 100644 --- a/usr.bin/fortune/datfiles/freebsd-tips +++ b/usr.bin/fortune/datfiles/freebsd-tips @@ -533,9 +533,10 @@ Run "etcupdate extract" once when your sources match your running system, then r Do you want to do a binary upgrade of your running FreeBSD installation? Use freebsd-update(8). To install updates and patches for the running branch use -# freebsd-update fetch install +# freebsd-update fetch +# freebsd-update install -To upgrade to a newer release use +Then, to upgrade to a newer release use # freebsd-update upgrade -r ${name_of_release} -- Lars Engels From 4339f1e667ffb6e0ed8626cc1ae1cd92c910bde2 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Fri, 2 Feb 2024 08:29:01 -0700 Subject: [PATCH 03/17] share/examples/IPv6/USAGE: remove This document dates from the KAME days and, among other things, references the 'prefix' command which has not existed for a long time. Since IPv6 configuration is now documented in the Handbook, remove this obsolete file. Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1094 --- share/examples/IPv6/USAGE | 528 -------------------------------------- share/examples/Makefile | 4 - 2 files changed, 532 deletions(-) delete mode 100644 share/examples/IPv6/USAGE diff --git a/share/examples/IPv6/USAGE b/share/examples/IPv6/USAGE deleted file mode 100644 index 83cfb43595c8..000000000000 --- a/share/examples/IPv6/USAGE +++ /dev/null @@ -1,528 +0,0 @@ - USAGE - KAME Project - $KAME: USAGE,v 1.33 2000/11/22 10:22:57 itojun Exp $ - -This is an introduction of how to use the commands provided in the KAME -kit. For more information, please refer to each man page. - - -<<>> - -A link-local address is automatically assigned to each interface, when -the interface becomes up for the first time. Even if you find an interface -without a link-local address, do not panic. The link-local address will be -assigned when it becomes up (with "ifconfig IF up"). - -If you do not see a link-local address assigned to an interface on "ifconfig -up", the interface does not support IPv6 for some reasons - for example, -if the interface does not support link-layer multicast (IFF_MULTICAST is not -set), the interface cannot be used for IPv6. - -Some network drivers allow an interface to become up even without a -hardware address (for example, PCMCIA network cards). In such cases, it is -possible that an interface has no link-local address even if the -interface is up. If you see such situation, please disable the -interface once and then re-enable it (i.e. do `ifconfig IF down; -ifconfig IF up'). - -Pseudo interfaces (like "gif" tunnel device) will borrow IPv6 -interface identifier (lowermost 64bit of the address) from -EUI64/IEEE802 sources, like ethernet cards. Pseudo interfaces will be -able to get an IPv6 link-local address, if you have other "real" -interface configured beforehand. If you have no EUI64/IEEE802 sources -on the node, we have last-resort code in the kernel, which generates -interface identifier from MD5(hostname). MD5(hostname) may not be suitable -for your usage (for example, if you configure same hostname on both sides of -gif tunnel, you will be doomed), and if so, you may need to configure -link-local address manually. -See RFC2472 for more discussion on how to generate an interface ID for -pseudo interfaces. - -If you have a router announcing Router Advertisement, -global addresses will be assigned automatically. So, neither -"ifconfig" nor "prefix" is necessary for your *host* (non-router node). -(Please refer to "sysctl" section for configuring a host to accept -Router Advertisement.) - -If you want to set up a router, you need to assign global addresses -for two or more interfaces by "ifconfig" or "prefix" (prefix command -is described at next section). -If you want to assign a global address by "ifconfig", don't forget to -specify the "alias" argument to keep the link-local address. - -# ifconfig de0 inet6 3ffe:501:808:1:200:f8ff:fe01:6317 prefixlen 64 alias -# ifconfig de0 -de0: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe01:6317%de0 prefixlen 64 scopeid 0x1 - inet 163.221.202.12 netmask 0xffffff00 broadcast 163.221.202.255 - inet6 3ffe:501:808:1:200:f8ff:fe01:6317 prefixlen 64 - ether 00:00:f8:01:63:17 - media: 100baseTX status: active - -See also "/etc/rc.network6" for actual examples. - -<> - -In the IPv6 architecture, an IPv6 address of an interface can be -generated from a prefix assigned to the interface, and a -link-dependent identifier for the interface. So assigning a full IPv6 -address by ifconfig is not necessary anymore, because user can only -take care of prefix, by letting system take care of interface -identifier. - -The newly added "prefix" command enables user to just assign prefixes -for interfaces, and let your system automatically generate IPv6 -addresses. Prefixes added by the "prefix" command is maintained in -the kernel consistently with prefixes assigned by Router -Advertisement (in case of hosts) and with prefixes assigned by Router -Renumbering (in case of routers). Manual assignment of prefixes or -change of prefix properties take precedence over ones assigned by -Router Advertisement or Router Renumbering. - -prefix command works only on routers. - -If you want to assign a prefix (and consequently address) manually, do -as follows: - -# ifconfig de0 -de0: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe01:6317%de0 prefixlen 64 scopeid 0x1 - inet 163.221.202.12 netmask 0xffffff00 broadcast 163.221.202.255 - ether 00:00:f8:01:63:17 - media: 100baseTX status: active -# prefix de0 3ffe:501:808:1:: -# ifconfig de0 -de0: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe01:6317%de0 prefixlen 64 scopeid 0x1 - inet 163.221.202.12 netmask 0xffffff00 broadcast 163.221.202.255 - inet6 3ffe:501:808:1:200:f8ff:fe01:6317 prefixlen 64 - ether 00:00:f8:01:63:17 - media: 100baseTX status: active - -To check assigned prefix, use the "ndp" command (See description of -ndp command about its usage). - -# ndp -p -3ffe:501:808:1::/64 if=de0 - flags=LA, vltime=2592000, pltime=604800, expire=Never, origin=RR - No advertising router - -The "prefix" command also has node internal prefix renumbering -ability. - -If you have multiple prefixes which have 3ffe:501:808:/48 at the top, -and would like to renumber them to 3ffe:501:4819:/48, then use the -"prefix" command with the "matchpr" argument and the "usepr" argument. - -Suppose that current state of before renumbering as follows: - -# ifconfig de0 -de0: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe01:6317%de0 prefixlen 64 scopeid 0x1 - inet 163.221.202.12 netmask 0xffffff00 broadcast 163.221.202.255 - inet6 3ffe:501:808:1:200:f8ff:fe01:6317 prefixlen 64 - ether 00:00:f8:01:63:17 - media: 100baseTX status: active -# ifconfig de1 -de1: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe55:7011%de1 prefixlen 64 scopeid 0x2 - inet 163.221.203.12 netmask 0xffffff00 broadcast 163.221.203.255 - inet6 3ffe:501:808:2:200:f8ff:fe55:7011 prefixlen 64 - ether 00:00:f8:55:70:11 - media: 100baseTX status: active -# ndp -p -3ffe:501:808:1::/64 if=de0 - flags=LA, vltime=2592000, pltime=604800, expire=Never, origin=RR - No advertising router -3ffe:501:808:2::/64 if=de1 - flags=LA, vltime=2592000, pltime=604800, expire=Never, origin=RR - No advertising router - -Then do as follows: - -# prefix -a matchpr 3ffe:501:808:: mp_len 48 usepr 3ffe:501:4819:: up_uselen 48 change - -If command is successful, prefixes and addresses will be renumbered as -follows. - -# ifconfig de0 -de0: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe01:6317%de0 prefixlen 64 scopeid 0x1 - inet 163.221.202.12 netmask 0xffffff00 broadcast 163.221.202.255 - inet6 3ffe:501:4819:1:200:f8ff:fe01:6317 prefixlen 64 - ether 00:00:f8:01:63:17 - media: 100baseTX status: active -# ifconfig de1 -de1: flags=8843 mtu 1500 - inet6 fe80::200:f8ff:fe55:7011%de0 prefixlen 64 scopeid 0x2 - inet 163.221.203.12 netmask 0xffffff00 broadcast 163.221.203.255 - inet6 3ffe:501:4819:2:200:f8ff:fe55:7011 prefixlen 64 - ether 00:00:f8:55:70:11 - media: 100baseTX status: active -# ndp -p -3ffe:501:4819:1::/64 if=de0 - flags=LA, vltime=2592000, pltime=604800, expire=Never, origin=RR - No advertising router -3ffe:501:4819:2::/64 if=de1 - flags=LA, vltime=2592000, pltime=604800, expire=Never, origin=RR - No advertising router - -See also "/etc/rc.network6" for actual examples. - - -<<>> - -If there is a router announcing Router Advertisement on a subnet, -you need not to add a default route for your host by hand -(Please refer to "sysctl" section to accept Router Advertisement). - -If you want to add a default route manually, do like: - -# route add -inet6 default fe80::200:a2ff:fe0e:7543%ed0 - -"default" means ::/0. In other cases, if "prefixlen" is omitted, 64 -is assumed for "prefixlen" to get along with the aggregatable address. - -Note that, in IPv6, a link-local address should be used as gateway -("fe80::200:a2ff:fe0e:7543%ed0" in the above). If you use global addresses, -ICMPv6 redirect will not work properly. Also note that we use a special form -of link-local address as gateway. See Section 1.3 of IMPLEMENTATION for -more details. -For ease of configuration we recommend you to avoid static routes and run -a routing daemon (route6d for example) instead. - - -<<>> - -Reachability can be checked by "ping6". This "ping6" allows multicast -for its argument. - -% ping6 -n -I ed0 ff02::1 - -PING6(56=40+8+8 bytes) fe80::5254:ff:feda:cb7d --> ff02::1%ed0 -56 bytes from fe80::5254:ff:feda:cb7d%lo0, icmp_seq=0 hlim=64 time=0.25 ms -56 bytes from fe80::2a0:c9ff:fe84:ed6c%ed0, icmp_seq=0 hlim=64 time=1.333 ms(DUP!) -56 bytes from fe80::5254:ff:feda:d161%ed0, icmp_seq=0 hlim=64 time=1.459 ms(DUP!) -56 bytes from fe80::260:97ff:fec2:80bf%ed0, icmp_seq=0 hlim=64 time=1.538 ms(DUP!) -56 bytes from 3ffe:501:4819:2000:5054:ff:fedb:aa46, icmp_seq=0 hlim=255 time=1.615 ms(DUP!) - - -<<>> - -Name resolution is possible by ICMPv6 node information query message. -This is very convenient for link-local addresses whose host name cannot be -resolved by DNS. Specify the "-w" option to "ping6". - -% ping6 -n -I ed0 -w ff02::1 - -64 bytes from fe80::5254:ff:feda:cb7d%lo0: fto.kame.net -67 bytes from fe80::5254:ff:feda:d161%ed0: banana.kame.net -69 bytes from fe80::2a0:c9ff:fe84:ebd9%ed0: paradise.kame.net -66 bytes from fe80::260:8ff:fe8b:447f%ed0: taroh.kame.net -66 bytes from fe80::2a0:c9ff:fe84:ed6c%ed0: ayame.kame.net - - -<<>> - -The route for a target host can be checked by "traceroute6". - -% traceroute6 tokyo.v6.wide.ad.jp - -traceroute to tokyo.v6.wide.ad.jp (3ffe:501:0:401:200:e8ff:fed5:8923), 30 hops max, 12 byte packets - 1 nr60.v6.kame.net 1.239 ms 0.924 ms 0.908 ms - 2 otemachi.v6.wide.ad.jp 28.953 ms 31.451 ms 26.567 ms - 3 tokyo.v6.wide.ad.jp 26.549 ms 26.58 ms 26.186 ms - -If the -l option is specified, both address and name are shown in each line. -% traceroute6 -l tokyo.v6.wide.ad.jp - -traceroute to tokyo.v6.wide.ad.jp (3ffe:501:0:401:200:e8ff:fed5:8923), 30 hops max, 12 byte packets - 1 nr60.v6.kame.net (3ffe:501:4819:2000:260:97ff:fec2:80bf) 1.23 ms 0.952 ms 0.92 ms - 2 otemachi.v6.wide.ad.jp (3ffe:501:0:1802:260:97ff:feb6:7ff0) 27.345 ms 26.706 ms 26.563 ms - 3 tokyo.v6.wide.ad.jp (3ffe:501:0:401:200:e8ff:fed5:8923) 26.329 ms 26.36 ms 28.63 ms - - -<<>> - -To display the current Neighbor cache, use "ndp": - -% ndp -a -Neighbor Linklayer Address Netif Expire St Flgs Prbs -nr60.v6.kame.net 0:60:97:c2:80:bf ed0 expired S R -3ffe:501:4819:2000:2c0:cff:fe 0:c0:c:10:3a:53 ed0 permanent R -paradise.v6.kame.net 52:54:0:dc:52:17 ed0 expired S R -fe80::200:eff:fe49:f929%ed0 0:0:e:49:f9:29 ed0 expired S R -fe80::200:86ff:fe05:80da%ed0 0:0:86:5:80:da ed0 expired S -fe80::200:86ff:fe05:c2d8%ed0 0:0:86:5:c2:d8 ed0 9s R - -To flush all of the NDP cache entries, execute the following as root. - -# ndp -c - -To display the prefix list: - -% ndp -p -3ffe:501:4819:2000::/64 if=ed0 - flags=LA, vltime=2592000, pltime=604800, expire=29d23h59m58s, origin=RA - advertised by - fe80::5254:ff:fedc:5217%ed0 (reachable) - fe80::260:97ff:fec2:80bf%ed0 (reachable) - fe80::200:eff:fe49:f929%ed0 (no neighbor state) - -To display the default router list: - -% ndp -r -fe80::260:97ff:fec2:80bf if=ed0, flags=, expire=29m55s -fe80::5254:ff:fedc:5217 if=ed0, flags=, expire=29m7s -fe80::200:eff:fe49:f929 if=ed0, flags=, expire=28m47s - - -<<>> - -To generate a Router Solicitation message right now to get global -addresses, use "rtsol". - -# ifconfig ef0 -ef0: flags=8863 - link type ether 0:a0:24:ab:83:9b mtu 1500 speed 10Mbps - media 10baseT status active - inet6 fe80::2a0:24ff:feab:839b%ef0 prefixlen 64 scopeid 0x2 -# rtsol ef0 -# ifconfig ef0 -ef0: flags=8863 - link type ether 0:a0:24:ab:83:9b mtu 1500 speed 10Mbps - media 10baseT status active - inet6 fe80::2a0:24ff:feab:839b%ef0 prefixlen 64 scopeid 0x2 - inet6 3ffe:501:4819:2000:2a0:24ff:feab:839b prefixlen 64 - - -<<>> - -rtsold is a daemon version of rtsol. If you run KAME IPv6 on a laptop -computer and frequently move with it, the daemon is useful since it watches -the interface and sends router solicitations when the status of the interface -changes. Note, however, that the feature is disabled by default. Please -add -m option when invocation of rtsold. - -rtsold also supports multiple interfaces. For example, you can -invoke the daemon as follows: - -# rtsold -m ep0 cnw0 - - -<<>> - -To see routing table: - -# netstat -nr -# netstat -nrl - long format with Ref and Use. Note that bsdi4 does not support the - -l option. You should use the -O option instead. - - -<<>> - -If "net.inet6.ip6.accept_rtadv" is 1, Router Advertisement is -accepted. This means that global addresses and default route are -automatically set up. Otherwise, the announcement is rejected. The -default value is 0. To set "net.inet6.ip6.accept_rtadv" to 1, execute -as follows: - -# sysctl net.inet6.ip6.accept_rtadv=1 - - -<<>> - -"gif" interface enables you to perform IPv{4,6} over IPv{4,6} -protocol tunneling. To use this interface, you must specify the -outer IPv{4,6} address by using gifconfig, like: - -# gifconfig gif0 163.221.198.61 163.221.11.21 - -"ifconfig gif0" will configure the address pair used for inner -IPv{4,6} header. - -It is not required to configure inner IPv{4,6} address pair. If -you do not configure inner IPv{4,6} address pair, tunnel link is -considered as un-numbered link and the source address of inner -IPv{4,6} address pair will be borrowed from other interfaces. - -The following example configures un-numbered IPv6-over-IPv4 tunnel: -# gifconfig gif0 10.0.0.1 10.0.0.1 netmask 255.255.255.0 - -The following example configures numbered IPv6-over-IPv4 tunnel: -# gifconfig gif0 10.0.0.1 10.0.0.1 netmask 255.255.255.0 -# ifconfig gif0 inet6 3ffe:501:808:5::1 3ffe:501:808:5::2 prefixlen 64 alias - -IPv6 spec allows you to use point-to-point link without global IPv6 -address assigned to the interface. Routing protocol (such as RIPng) -uses link-local addresses only. If you are to configure IPv6-over-IPv4 -tunnel, you need not to configure an address pair for inner IPv6 -header. We suggest you to use the former example (un-numbered -IPv6-over-IPv4 tunnel) to connect to 6bone for simplicity. - -Note that it is so easy to make an infinite routing loop using gif -interface, if you configure a tunnel using the same protocol family -for inner and outer header (i.e. IPv4-over-IPv4). - -Refer to gifconfig(8) for more details. - - -<<<6to4>>> - -WARNING: malicious party can abuse 6to4 relay routers/sites, read through -internet draft draft-itojun-ipv6-transition-abuse-xx.txt before configuring it. - -"stf" interface enables you to perform 6to4 IPv6-over-IPv4 encapsulation, -as documented in draft-ietf-ngtrans-6to4-06.txt. See stf(4) for details. - - -<<>> - -Inetd supports AF_INET and AF_INET6 sockets, with IPsec policy -configuration support. - -Refer to inetd(8) for more details. - - -<<>> - -IPsec requires fairly complex configuration, so here we show transport -mode only. https://www.kame.net/newsletter/ has more comprehensive -examples. - -Let us setup security association to deploy a secure channel between -HOST A (10.2.3.4) and HOST B (10.6.7.8). Here we show a little -complicated example. From HOST A to HOST B, only old AH is used. -From HOST B to HOST A, new AH and new ESP are combined. - -Now we should choose algorithm to be used corresponding to "AH"/"new -AH"/"ESP"/"new ESP". Please refer to the "setkey" man page to know -algorithm names. Our choice is MD5 for AH, new-HMAC-SHA1 for new AH, -and new-DES-expIV with 8 byte IV for new ESP. - -Key length highly depends on each algorithm. For example, key -length must be equal to 16 bytes for MD5, 20 for new-HMAC-SHA1, -and 8 for new-DES-expIV. Now we choose "MYSECRETMYSECRET", -"KAMEKAMEKAMEKAMEKAME", "PASSWORD", respectively. - -OK, let us assign SPI (Security Parameter Index) for each protocol. -Please note that we need 3 SPIs for this secure channel since three -security headers are produced (one for from HOST A to HOST B, two for -from HOST B to HOST A). Please also note that SPI MUST be greater -than or equal to 256. We choose, 1000, 2000, and 3000, respectively. - - - (1) - HOST A ------> HOST B - - (1)PROTO=AH - ALG=MD5(RFC1826) - KEY=MYSECRETMYSECRET - SPI=1000 - - (2.1) - HOST A <------ HOST B - <------ - (2.2) - - (2.1) - PROTO=AH - ALG=new-HMAC-SHA1(new AH) - KEY=KAMEKAMEKAMEKAMEKAME - SPI=2000 - - (2.2) - PROTO=ESP - ALG=new-DES-expIV(new ESP) - IV length = 8 - KEY=PASSWORD - SPI=3000 - -Now, let us setup security association. Execute "setkey" on both HOST -A and B: - -# setkey -c -add 10.2.3.4 10.6.7.8 ah 1000 -m transport -A keyed-md5 "MYSECRETMYSECRET" ; -add 10.6.7.8 10.2.3.4 ah 2000 -m transport -A hmac-sha1 "KAMEKAMEKAMEKAMEKAME" ; -add 10.6.7.8 10.2.3.4 esp 3000 -m transport -E des-cbc "PASSWORD" ; -^D - -Actually, IPsec communication doesn't process until security policy -entries will be defined. In this case, you must setup each host. - -At A: -# setkey -c -spdadd 10.2.3.4 10.6.7.8 any -P out ipsec - ah/transport/10.2.3.4-10.6.7.8/require ; -^D - -At B: -spdadd 10.6.7.8 10.2.3.4 any -P out ipsec - esp/transport//require - ah/transport//require ; -^D - -To utilize the security associations installed into the kernel, you -must set the socket security level by using setsockopt(). -This is per-application (or per-socket) security. For example, -the "ping" command has the -P option with parameter to enable AH and/or ESP. - -For example: -% ping -P "out ipsec \ - ah/transport//use \ - esp/tunnel/10.0.1.1-10.0.1.2/require" 10.0.2.2 - -If there are proper SAs, this policy specification causes ICMP packet -to be AH transport mode inner ESP tunnel mode like below. - - HOST C -----------> GATEWAY D ----------> HOST E - 10.0.1.1 10.0.1.2 10.0.2.1 10.0.2.2 - | | | | - | ======= ESP ======= | - ==================== AH ================== - - -<<>> - -EDNS0 is defined in RFC2671. With EDNS0, the resolver library can tell DNS -server of its receiving buffer size, and permit DNS server to transmit large -reply packet. EDNS0 is necessary to take advantage of larger minimum MTU -in IPv6. KAME libinet6 includes resolver side support for EDNS0. -Server side support for EDNS0 is included in ISC BIND9. - - query packet with EDNS0 - tells receive buffer size -KAME box -----------------------------> BIND9 DNS server -KAME box <----------------------------- BIND9 DNS server - can transmit jumbo reply, since DNS server - knows receive buffer size of KAME box - -How to play with it: -- prepare KAME box and BIND9 DNS server (can be a same node) -- add the following into /etc/resolv.conf on KAME box: - options edns0 <--- enables EDNS0 - nameserver -- run applications compiled with libinet6 (like /usr/local/v6/bin/telnet), - see EDNS0 packet fly on the wire by tcpdump or some other method. - -Caveats: -- BIND 4/8 DNS server will choke with EDNS0 packet, so you must not - turn the option on if you have BIND 4/8 DNS server. If you enable - "options edns0" against BIND 4/8 DNS server, you will never be able - to resolve names. -- If you use IPv6 UDP as DNS transport, path MTU discovery may - affect the traffic. KAME box tries to fragment packet to 1280 - bytes, however, BIND9 may not. -- Some of our platforms do not use our extended resolver code in libinet6. - See COVERAGE for detail. - - -<> - -http://www.netbsd.org/Documentation/network/ipv6/ - Even if you are on non-netbsd operating system, the URL should be - useful. -https://www.kame.net/ - - diff --git a/share/examples/Makefile b/share/examples/Makefile index 06d10a0bc149..504f3d7807dc 100644 --- a/share/examples/Makefile +++ b/share/examples/Makefile @@ -8,7 +8,6 @@ FILESDIR= ${SHAREDIR}/examples LDIRS= BSD_daemon \ FreeBSD_version \ - IPv6 \ bootforth \ csh \ drivers \ @@ -57,9 +56,6 @@ SE_FREEBSD_VERSION= \ Makefile \ README -SE_DIRS+= IPv6 -SE_IPV6= USAGE - SE_DIRS+= bootforth SE_BOOTFORTH= \ README \ From 36f0a34ca645d49ec79d60ea7e773374ef0991ea Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Fri, 2 Feb 2024 09:23:53 -0500 Subject: [PATCH 04/17] libthr: Force the thr_wake() symbol to be resolved during initialization Otherwise the lock upgrade performed by rtld's load_filtees() can result in infinite recursion, wherein: 1. _rtld_bind() acquires the bind read lock, 2. the source DSO's filtees haven't been loaded yet, so the lock upgrade in load_filtees() cause rtld to jump to _rtld_bind() and release the bind lock, 3. _thr_rtld_lock_release() calls _thr_ast(), which calls thr_wake(), which hasn't been resolved yet, 4. _rtld_bind() acquires the bind read lock in order to resolve thr_wake(), 5. ... See the linked pull request for an instance of this problem arising with libsys. That particular instance is also worked around by commit e7951d0b04e6. Reported by: brooks Reviewed by: kib Pull Request: https://github.com/freebsd/freebsd-src/pull/908 MFC after: 1 week Sponsored by: Innovate UK --- lib/libthr/thread/thr_rtld.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 9026abf941e2..767b4735e1fa 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -238,6 +238,7 @@ _thr_rtld_init(void) mprotect(NULL, 0, 0); _rtld_get_stack_prot(); + thr_wake(-1); li.rtli_version = RTLI_VERSION; li.lock_create = _thr_rtld_lock_create; From f4613af424cc93d42f35730fd9862f0c6f964cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mina=20Gali=C4=87?= Date: Fri, 2 Feb 2024 08:35:46 -0700 Subject: [PATCH 05/17] kldxref: Fix maketempfile function's way of finding the root dir Rather than assuming that the "root" is passed as directory and will be marked by a trailing slash, we just assume that the directory, which has been checked previously to be a directory, is a directory. This fixes an inconsistency between `kldxref /boot/modules`, which tries to create the temp file in `/boot/`, and `kldxref /boot/modules/`, which tries to create it in `/boot/modules/` itself. Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1093 --- usr.sbin/kldxref/kldxref.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c index 1f06ad811d91..969d07e5677a 100644 --- a/usr.sbin/kldxref/kldxref.c +++ b/usr.sbin/kldxref/kldxref.c @@ -717,12 +717,9 @@ read_kld(char *filename, char *kldname) static FILE * maketempfile(char *dest, const char *root) { - char *p; - int n, fd; + int fd; - p = strrchr(root, '/'); - n = p != NULL ? p - root + 1 : 0; - if (snprintf(dest, MAXPATHLEN, "%.*slhint.XXXXXX", n, root) >= + if (snprintf(dest, MAXPATHLEN, "%s/lhint.XXXXXX", root) >= MAXPATHLEN) { errno = ENAMETOOLONG; return (NULL); From 93a25ac9f4c0812c5d99fa0a34d436e46fae2094 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Fri, 2 Feb 2024 09:17:19 -0700 Subject: [PATCH 06/17] .gitignore: add sys/*/compile Files in sys/*/compile are created when compiling the kernel with config(8). They are never source files and should never be committed to source control, so list this entire directory in .gitignore. While not the official way to build the kernel, it's often useful to debug sys/conf/files* changes when adding new drivers, etc. Reviewed by: imp, meena Pull Request: https://github.com/freebsd/freebsd-src/pull/1082 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 785568271794..3ed711f301ac 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ tags .cache .clangd .ccls-cache +sys/*/compile From b8ef285f6cc6ae733e75488a6ff879e6fb23133d Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Thu, 1 Feb 2024 18:59:36 +0100 Subject: [PATCH 07/17] pf: ensure dummynet gets the correct direction after route-to If we apply a route-to to an inbound packet pf_route() may hand that packet over to dummynet. Dummynet may then delay the packet, and later re-inject it. This re-injection (in dummynet_send()) needs to know if the packet was inbound or outbound, to call the correct path for continued processing. That's done based on the pf_pdesc we pass along (through pf_dummynet_route() and pf_pdesc_to_dnflow()). In the case of pf_route() on inbound packets that may be wrong, because we're called in the input path, and didn't update pf_pdesc->dir. This can manifest in issues with fragmented packets. For example, a fragmented packet will be re-fragmented in pf_route(), and if dummynet makes different decisions for some of the fragments (that is, it delays some and allows others to pass through directly) this will break. The packets that pass through dummynet without delay will be transmitted correctly (through the ifp->if_output() call in pf_route()), but the delayed packets will be re-injected in the input path (and not the output path, as they should be). These packets will pass through pf_test(PF_IN) as they're tagged PF_MTAG_FLAG_DUMMYNET. However, this tag is then removed and the packet will be routed and enter pf_test(PF_OUT) where pf_reassemble() will hold them indefinitely (as some fragments have been transmitted directly, and will never hit pf_test(PF_OUT)). The fix is simple: we must update pf_pfdesc->dir to PF_OUT before we pass the packet to dummynet. See also: https://redmine.pfsense.org/issues/15156 Reviewed by: rcm Sponsored by: Rubicon Communications, LLC ("Netgate") --- sys/netpfil/pf/pf.c | 6 ++++ tests/sys/netpfil/pf/route_to.sh | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 36ff0eac16ad..ec7964a48e6d 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -7361,6 +7361,12 @@ pf_route(struct mbuf **m, struct pf_krule *r, struct ifnet *oifp, m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; } + /* + * Make sure dummynet gets the correct direction, in case it needs to + * re-inject later. + */ + pd->dir = PF_OUT; + /* * If small enough for interface, or the interface will take * care of the fragmentation for us, we can just send directly. diff --git a/tests/sys/netpfil/pf/route_to.sh b/tests/sys/netpfil/pf/route_to.sh index 7e8310bceb30..31a47e75c82e 100644 --- a/tests/sys/netpfil/pf/route_to.sh +++ b/tests/sys/netpfil/pf/route_to.sh @@ -407,6 +407,55 @@ ifbound_cleanup() pft_cleanup } +atf_test_case "dummynet_frag" "cleanup" +dummynet_frag_head() +{ + atf_set descr 'Test fragmentation with route-to and dummynet' + atf_set require.user root +} + +dummynet_frag_body() +{ + pft_init + dummynet_init + + epair_one=$(vnet_mkepair) + epair_two=$(vnet_mkepair) + + ifconfig ${epair_one}a 192.0.2.1/24 up + + vnet_mkjail alcatraz ${epair_one}b ${epair_two}a + jexec alcatraz ifconfig ${epair_one}b 192.0.2.2/24 up + jexec alcatraz ifconfig ${epair_two}a 198.51.100.1/24 up + jexec alcatraz sysctl net.inet.ip.forwarding=1 + + vnet_mkjail singsing ${epair_two}b + jexec singsing ifconfig ${epair_two}b 198.51.100.2/24 up + jexec singsing route add default 198.51.100.1 + + route add 198.51.100.0/24 192.0.2.2 + + jexec alcatraz dnctl pipe 1 config bw 1000Byte/s burst 4500 + jexec alcatraz dnctl pipe 2 config + # This second pipe ensures that the pf_test(PF_OUT) call in pf_route() doesn't + # delay packets in dummynet (by inheriting pipe 1 from the input rule). + + jexec alcatraz pfctl -e + pft_set_rules alcatraz \ + "set reassemble yes" \ + "pass in route-to (${epair_two}a 198.51.100.2) inet proto icmp all icmp-type echoreq dnpipe 1" \ + "pass out dnpipe 2" + + + atf_check -s exit:0 -o ignore ping -c 1 198.51.100.2 + atf_check -s exit:0 -o ignore ping -c 1 -s 4000 198.51.100.2 +} + +dummynet_frag_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4" @@ -416,4 +465,5 @@ atf_init_test_cases() atf_add_test_case "icmp_nat" atf_add_test_case "dummynet" atf_add_test_case "ifbound" + atf_add_test_case "dummynet_frag" } From 777a4702c591154c5a844d43c32f588f371ae80a Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Fri, 12 Jan 2024 11:54:18 +0100 Subject: [PATCH 08/17] pf: implement addrule via netlink Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 282 +++++++++++++++++++++++++++++++- lib/libpfctl/libpfctl.h | 3 + sbin/pfctl/pfctl.c | 4 +- sys/net/pfvar.h | 5 +- sys/netlink/netlink_snl.h | 12 ++ sys/netpfil/pf/pf_ioctl.c | 22 ++- sys/netpfil/pf/pf_nl.c | 312 ++++++++++++++++++++++++++++++++++++ sys/netpfil/pf/pf_nl.h | 14 ++ sys/netpfil/pf/pf_ruleset.c | 68 +++----- 9 files changed, 659 insertions(+), 63 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 2db3f0ede99f..cb9b377f7b6c 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1229,7 +1229,287 @@ pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor, anchor_call, false)); } -int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, +#define _OUT(_field) offsetof(struct pf_addr_wrap, _field) +static const struct snl_attr_parser ap_addr_wrap[] = { + { .type = PF_AT_ADDR, .off = _OUT(v.a.addr), .cb = snl_attr_get_in6_addr }, + { .type = PF_AT_MASK, .off = _OUT(v.a.mask), .cb = snl_attr_get_in6_addr }, + { .type = PF_AT_IFNAME, .off = _OUT(v.ifname), .arg = (void *)IFNAMSIZ,.cb = snl_attr_copy_string }, + { .type = PF_AT_TABLENAME, .off = _OUT(v.tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_AT_TYPE, .off = _OUT(type), .cb = snl_attr_get_uint8 }, + { .type = PF_AT_IFLAGS, .off = _OUT(iflags), .cb = snl_attr_get_uint8 }, + { .type = PF_AT_TBLCNT, .off = _OUT(p.tblcnt), .cb = snl_attr_get_uint32 }, + { .type = PF_AT_DYNCNT, .off = _OUT(p.dyncnt), .cb = snl_attr_get_uint32 }, +}; +SNL_DECLARE_ATTR_PARSER(addr_wrap_parser, ap_addr_wrap); +#undef _OUT + +#define _OUT(_field) offsetof(struct pf_rule_addr, _field) +static struct snl_attr_parser ap_rule_addr[] = { + { .type = PF_RAT_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = snl_attr_get_nested }, + { .type = PF_RAT_SRC_PORT, .off = _OUT(port[0]), .cb = snl_attr_get_uint16 }, + { .type = PF_RAT_DST_PORT, .off = _OUT(port[1]), .cb = snl_attr_get_uint16 }, + { .type = PF_RAT_NEG, .off = _OUT(neg), .cb = snl_attr_get_uint8 }, + { .type = PF_RAT_OP, .off = _OUT(port_op), .cb = snl_attr_get_uint8 }, +}; +#undef _OUT +SNL_DECLARE_ATTR_PARSER(rule_addr_parser, ap_rule_addr); + +struct snl_parsed_labels +{ + char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; + uint32_t i; +}; + +static bool +snl_attr_get_pf_rule_labels(struct snl_state *ss, struct nlattr *nla, + const void *arg __unused, void *target) +{ + struct snl_parsed_labels *l = (struct snl_parsed_labels *)target; + bool ret; + + if (l->i >= PF_RULE_MAX_LABEL_COUNT) + return (E2BIG); + + ret = snl_attr_copy_string(ss, nla, (void *)PF_RULE_LABEL_SIZE, + l->labels[l->i]); + if (ret) + l->i++; + + return (ret); +} + +#define _OUT(_field) offsetof(struct nl_parsed_labels, _field) +static const struct snl_attr_parser ap_labels[] = { + { .type = PF_LT_LABEL, .off = 0, .cb = snl_attr_get_pf_rule_labels }, +}; +SNL_DECLARE_ATTR_PARSER(rule_labels_parser, ap_labels); +#undef _OUT + +static bool +snl_attr_get_nested_pf_rule_labels(struct snl_state *ss, struct nlattr *nla, + const void *arg __unused, void *target) +{ + struct snl_parsed_labels parsed_labels = { }; + bool error; + + /* Assumes target points to the beginning of the structure */ + error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &rule_labels_parser, &parsed_labels); + if (! error) + return (error); + + memcpy(target, parsed_labels.labels, sizeof(parsed_labels)); + + return (true); +} + +#define _OUT(_field) offsetof(struct pf_mape_portset, _field) +static const struct snl_attr_parser ap_mape_portset[] = { + { .type = PF_MET_OFFSET, .off = _OUT(offset), .cb = snl_attr_get_uint8 }, + { .type = PF_MET_PSID_LEN, .off = _OUT(psidlen), .cb = snl_attr_get_uint8 }, + {. type = PF_MET_PSID, .off = _OUT(psid), .cb = snl_attr_get_uint16 }, +}; +SNL_DECLARE_ATTR_PARSER(mape_portset_parser, ap_mape_portset); +#undef _OUT + +#define _OUT(_field) offsetof(struct pfctl_pool, _field) +static const struct snl_attr_parser ap_pool[] = { + { .type = PF_PT_KEY, .off = _OUT(key), .arg = (void *)sizeof(struct pf_poolhashkey), .cb = snl_attr_get_bytes }, + { .type = PF_PT_COUNTER, .off = _OUT(counter), .cb = snl_attr_get_in6_addr }, + { .type = PF_PT_TBLIDX, .off = _OUT(tblidx), .cb = snl_attr_get_uint32 }, + { .type = PF_PT_PROXY_SRC_PORT, .off = _OUT(proxy_port[0]), .cb = snl_attr_get_uint16 }, + { .type = PF_PT_PROXY_DST_PORT, .off = _OUT(proxy_port[1]), .cb = snl_attr_get_uint16 }, + { .type = PF_PT_OPTS, .off = _OUT(opts), .cb = snl_attr_get_uint8 }, + { .type = PF_PT_MAPE, .off = _OUT(mape), .arg = &mape_portset_parser, .cb = snl_attr_get_nested }, +}; +SNL_DECLARE_ATTR_PARSER(pool_parser, ap_pool); +#undef _OUT + +struct nl_parsed_timeouts +{ + uint32_t timeouts[PFTM_MAX]; + uint32_t i; +}; + +static bool +snl_attr_get_pf_timeout(struct snl_state *ss, struct nlattr *nla, + const void *arg __unused, void *target) +{ + struct nl_parsed_timeouts *t = (struct nl_parsed_timeouts *)target; + bool ret; + + if (t->i >= PFTM_MAX) + return (E2BIG); + + ret = snl_attr_get_uint32(ss, nla, NULL, &t->timeouts[t->i]); + if (ret) + t->i++; + + return (ret); +} + +#define _OUT(_field) offsetof(struct nl_parsed_timeout, _field) +static const struct snl_attr_parser ap_timeouts[] = { + { .type = PF_TT_TIMEOUT, .off = 0, .cb = snl_attr_get_pf_timeout }, +}; +SNL_DECLARE_ATTR_PARSER(timeout_parser, ap_timeouts); +#undef _OUT + +static bool +snl_attr_get_nested_timeouts(struct snl_state *ss, struct nlattr *nla, + const void *arg __unused, void *target) +{ + struct nl_parsed_timeouts parsed_timeouts = { }; + bool error; + + /* Assumes target points to the beginning of the structure */ + error = snl_parse_header(ss, NLA_DATA(nla), NLA_DATA_LEN(nla), &timeout_parser, &parsed_timeouts); + if (! error) + return (error); + + memcpy(target, parsed_timeouts.timeouts, sizeof(parsed_timeouts.timeouts)); + + return (true); +} + +#define _OUT(_field) offsetof(struct pf_rule_uid, _field) +static const struct snl_attr_parser ap_rule_uid[] = { + { .type = PF_RUT_UID_LOW, .off = _OUT(uid[0]), .cb = snl_attr_get_uint32 }, + { .type = PF_RUT_UID_HIGH, .off = _OUT(uid[1]), .cb = snl_attr_get_uint32 }, + { .type = PF_RUT_OP, .off = _OUT(op), .cb = snl_attr_get_uint8 }, +}; +SNL_DECLARE_ATTR_PARSER(rule_uid_parser, ap_rule_uid); +#undef _OUT + +struct pfctl_nl_get_rule { + struct pfctl_rule r; + char anchor_call[MAXPATHLEN]; +}; +#define _OUT(_field) offsetof(struct pfctl_nl_get_rule, _field) +static struct snl_attr_parser ap_getrule[] = { + { .type = PF_RT_SRC, .off = _OUT(r.src), .arg = &rule_addr_parser,.cb = snl_attr_get_nested }, + { .type = PF_RT_DST, .off = _OUT(r.dst), .arg = &rule_addr_parser,.cb = snl_attr_get_nested }, + { .type = PF_RT_RIDENTIFIER, .off = _OUT(r.ridentifier), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_LABELS, .off = _OUT(r.label), .arg = &rule_labels_parser,.cb = snl_attr_get_nested_pf_rule_labels }, + { .type = PF_RT_IFNAME, .off = _OUT(r.ifname), .arg = (void *)IFNAMSIZ, .cb = snl_attr_copy_string }, + { .type = PF_RT_QNAME, .off = _OUT(r.qname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_RT_PQNAME, .off = _OUT(r.pqname), .arg = (void *)PF_QNAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_RT_TAGNAME, .off = _OUT(r.tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_RT_MATCH_TAGNAME, .off = _OUT(r.match_tagname), .arg = (void *)PF_TAG_NAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_RT_OVERLOAD_TBLNAME, .off = _OUT(r.overload_tblname), .arg = (void *)PF_TABLE_NAME_SIZE, .cb = snl_attr_copy_string }, + { .type = PF_RT_RPOOL, .off = _OUT(r.rpool), .arg = &pool_parser, .cb = snl_attr_get_nested }, + { .type = PF_RT_OS_FINGERPRINT, .off = _OUT(r.os_fingerprint), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_RTABLEID, .off = _OUT(r.rtableid), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_TIMEOUT, .off = _OUT(r.timeout), .arg = &timeout_parser, .cb = snl_attr_get_nested_timeouts }, + { .type = PF_RT_MAX_STATES, .off = _OUT(r.max_states), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_MAX_SRC_NODES, .off = _OUT(r.max_src_nodes), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_MAX_SRC_STATES, .off = _OUT(r.max_src_states), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_MAX_SRC_CONN_RATE_LIMIT, .off = _OUT(r.max_src_conn_rate.limit), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_MAX_SRC_CONN_RATE_SECS, .off = _OUT(r.max_src_conn_rate.seconds), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_DNPIPE, .off = _OUT(r.dnpipe), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_DNRPIPE, .off = _OUT(r.dnrpipe), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_DNFLAGS, .off = _OUT(r.free_flags), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_NR, .off = _OUT(r.nr), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_PROB, .off = _OUT(r.prob), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_CUID, .off = _OUT(r.cuid), .cb = snl_attr_get_uint32 }, + {. type = PF_RT_CPID, .off = _OUT(r.cpid), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_RETURN_ICMP, .off = _OUT(r.return_icmp), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_RETURN_ICMP6, .off = _OUT(r.return_icmp6), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_MAX_MSS, .off = _OUT(r.max_mss), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_SCRUB_FLAGS, .off = _OUT(r.scrub_flags), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_UID, .off = _OUT(r.uid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested }, + { .type = PF_RT_GID, .off = _OUT(r.gid), .arg = &rule_uid_parser, .cb = snl_attr_get_nested }, + { .type = PF_RT_RULE_FLAG, .off = _OUT(r.rule_flag), .cb = snl_attr_get_uint32 }, + { .type = PF_RT_ACTION, .off = _OUT(r.action), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_DIRECTION, .off = _OUT(r.direction), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_LOG, .off = _OUT(r.log), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_LOGIF, .off = _OUT(r.logif), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_QUICK, .off = _OUT(r.quick), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_IF_NOT, .off = _OUT(r.ifnot), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_MATCH_TAG_NOT, .off = _OUT(r.match_tag_not), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_NATPASS, .off = _OUT(r.natpass), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_KEEP_STATE, .off = _OUT(r.keep_state), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_AF, .off = _OUT(r.af), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_PROTO, .off = _OUT(r.proto), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_TYPE, .off = _OUT(r.type), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_CODE, .off = _OUT(r.code), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_FLAGS, .off = _OUT(r.flags), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_FLAGSET, .off = _OUT(r.flagset), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_MIN_TTL, .off = _OUT(r.min_ttl), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_ALLOW_OPTS, .off = _OUT(r.allow_opts), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_RT, .off = _OUT(r.rt), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_RETURN_TTL, .off = _OUT(r.return_ttl), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_TOS, .off = _OUT(r.tos), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_SET_TOS, .off = _OUT(r.set_tos), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_ANCHOR_RELATIVE, .off = _OUT(r.anchor_relative), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_ANCHOR_WILDCARD, .off = _OUT(r.anchor_wildcard), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_FLUSH, .off = _OUT(r.flush), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_PRIO, .off = _OUT(r.prio), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_SET_PRIO, .off = _OUT(r.set_prio[0]), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_SET_PRIO_REPLY, .off = _OUT(r.set_prio[1]), .cb = snl_attr_get_uint8 }, + { .type = PF_RT_DIVERT_ADDRESS, .off = _OUT(r.divert.addr), .cb = snl_attr_get_in6_addr }, + { .type = PF_RT_DIVERT_PORT, .off = _OUT(r.divert.port), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_PACKETS_IN, .off = _OUT(r.packets[0]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_PACKETS_OUT, .off = _OUT(r.packets[1]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_BYTES_IN, .off = _OUT(r.bytes[0]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_BYTES_OUT, .off = _OUT(r.bytes[1]), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_EVALUATIONS, .off = _OUT(r.evaluations), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_TIMESTAMP, .off = _OUT(r.last_active_timestamp), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_STATES_CUR, .off = _OUT(r.states_cur), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_STATES_TOTAL, .off = _OUT(r.states_tot), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_SRC_NODES, .off = _OUT(r.src_nodes), .cb = snl_attr_get_uint64 }, + { .type = PF_RT_ANCHOR_CALL, .off = _OUT(anchor_call), .arg = (void*)MAXPATHLEN, .cb = snl_attr_copy_string }, +}; +static struct snl_field_parser fp_getrule[] = {}; +#undef _OUT +SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, fp_getrule, ap_getrule); + +int +pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, + const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, + char *anchor_call, bool clear) +{ + struct pfctl_nl_get_rule attrs = {}; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + struct snl_writer nw; + uint32_t seq_id; + int family_id; + + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); + + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULE); + hdr->nlmsg_flags |= NLM_F_DUMP; + + snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, anchor); + snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset); + snl_add_msg_attr_u32(&nw, PF_GR_NR, nr); + snl_add_msg_attr_u32(&nw, PF_GR_TICKET, ticket); + snl_add_msg_attr_u8(&nw, PF_GR_CLEAR, clear); + + hdr = snl_finalize_msg(&nw); + if (hdr == NULL) + return (ENOMEM); + + seq_id = hdr->nlmsg_seq; + if (! snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (! snl_parse_nlmsg(&h->ss, hdr, &getrule_parser, &attrs)) + continue; + } + + memcpy(rule, &attrs.r, sizeof(attrs.r)); + strlcpy(anchor_call, attrs.anchor_call, MAXPATHLEN); + + return (e.error); +} + +int +pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call, bool clear) { diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index cd72d04d6715..f05044a9a985 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -418,6 +418,9 @@ int pfctl_get_rule(int dev, uint32_t nr, uint32_t ticket, int pfctl_get_clear_rule(int dev, uint32_t nr, uint32_t ticket, const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, char *anchor_call, bool clear); +int pfctl_get_clear_rule_h(struct pfctl_handle *h, uint32_t nr, uint32_t ticket, + const char *anchor, uint32_t ruleset, struct pfctl_rule *rule, + char *anchor_call, bool clear); int pfctl_add_rule(int dev, const struct pfctl_rule *r, const char *anchor, const char *anchor_call, uint32_t ticket, uint32_t pool_ticket); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 217bf31b3301..c583279750f1 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -1303,7 +1303,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, } for (nr = 0; nr < ri.nr; ++nr) { - if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_SCRUB, + if (pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_SCRUB, &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) { warn("DIOCGETRULENV"); goto error; @@ -1334,7 +1334,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, goto error; } for (nr = 0; nr < ri.nr; ++nr) { - if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_PASS, + if (pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_PASS, &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) { warn("DIOCGETRULE"); goto error; diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index ff3370bc105e..f3a808f8ad26 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2470,10 +2470,10 @@ void pf_init_kruleset(struct pf_kruleset *); void pf_init_keth(struct pf_keth_ruleset *); int pf_kanchor_setup(struct pf_krule *, const struct pf_kruleset *, const char *); +int pf_kanchor_copyout(const struct pf_kruleset *, + const struct pf_krule *, char *); int pf_kanchor_nvcopyout(const struct pf_kruleset *, const struct pf_krule *, nvlist_t *); -int pf_kanchor_copyout(const struct pf_kruleset *, - const struct pf_krule *, struct pfioc_rule *); void pf_kanchor_remove(struct pf_krule *); void pf_remove_if_empty_kruleset(struct pf_kruleset *); struct pf_kruleset *pf_find_kruleset(const char *); @@ -2501,6 +2501,7 @@ int pf_ioctl_addrule(struct pf_krule *, uint32_t, pid_t); void pf_krule_free(struct pf_krule *); +void pf_krule_clear_counters(struct pf_krule *); #endif /* The fingerprint functions can be linked into userland programs (tcpdump) */ diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h index 7bdf5424ddf3..6636d53f2353 100644 --- a/sys/netlink/netlink_snl.h +++ b/sys/netlink/netlink_snl.h @@ -513,6 +513,18 @@ snl_attr_get_flag(struct snl_state *ss __unused, struct nlattr *nla, const void return (false); } +static inline bool +snl_attr_get_bytes(struct snl_state *ss __unused, struct nlattr *nla, const void *arg, + void *target) +{ + if ((size_t)NLA_DATA_LEN(nla) != (size_t)arg) + return (false); + + memcpy(target, NLA_DATA_CONST(nla), (size_t)arg); + + return (true); +} + static inline bool snl_attr_get_uint8(struct snl_state *ss __unused, struct nlattr *nla, const void *arg __unused, void *target) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 7f70321ea560..d83933cd293f 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -1867,6 +1867,17 @@ pf_krule_free(struct pf_krule *rule) free(rule, M_PFRULE); } +void +pf_krule_clear_counters(struct pf_krule *rule) +{ + pf_counter_u64_zero(&rule->evaluations); + for (int i = 0; i < 2; i++) { + pf_counter_u64_zero(&rule->packets[i]); + pf_counter_u64_zero(&rule->bytes[i]); + } + counter_u64_zero(rule->states_tot); +} + static void pf_kpooladdr_to_pooladdr(const struct pf_kpooladdr *kpool, struct pf_pooladdr *pool) @@ -3266,14 +3277,9 @@ DIOCADDRULENV_error: ERROUT(ENOSPC); } - if (clear_counter) { - pf_counter_u64_zero(&rule->evaluations); - for (int i = 0; i < 2; i++) { - pf_counter_u64_zero(&rule->packets[i]); - pf_counter_u64_zero(&rule->bytes[i]); - } - counter_u64_zero(rule->states_tot); - } + if (clear_counter) + pf_krule_clear_counters(rule); + PF_RULES_WUNLOCK(); error = copyout(nvlpacked, nv->data, nv->len); diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index e74d4773b1e7..120ce88f8720 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -401,6 +401,42 @@ static const struct nlattr_parser nla_p_addr_wrap[] = { NL_DECLARE_ATTR_PARSER(addr_wrap_parser, nla_p_addr_wrap); #undef _OUT +static bool +nlattr_add_addr_wrap(struct nl_writer *nw, int attrtype, struct pf_addr_wrap *a) +{ + int off = nlattr_add_nested(nw, attrtype); + int num; + + nlattr_add_in6_addr(nw, PF_AT_ADDR, &a->v.a.addr.v6); + nlattr_add_in6_addr(nw, PF_AT_MASK, &a->v.a.mask.v6); + nlattr_add_u8(nw, PF_AT_TYPE, a->type); + nlattr_add_u8(nw, PF_AT_IFLAGS, a->iflags); + + if (a->type == PF_ADDR_DYNIFTL) { + nlattr_add_string(nw, PF_AT_IFNAME, a->v.ifname); + num = 0; + if (a->p.dyn != NULL) + num = a->p.dyn->pfid_acnt4 + a->p.dyn->pfid_acnt6; + nlattr_add_u32(nw, PF_AT_DYNCNT, num); + } else if (a->type == PF_ADDR_TABLE) { + struct pfr_ktable *kt; + + nlattr_add_string(nw, PF_AT_TABLENAME, a->v.tblname); + num = -1; + kt = a->p.tbl; + if ((kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && + kt->pfrkt_root != NULL) + kt = kt->pfrkt_root; + if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) + num = kt->pfrkt_cnt; + nlattr_add_u32(nw, PF_AT_TBLCNT, num); + } + + nlattr_set_len(nw, off); + + return (true); +} + #define _OUT(_field) offsetof(struct pf_rule_addr, _field) static const struct nlattr_parser nla_p_ruleaddr[] = { { .type = PF_RAT_ADDR, .off = _OUT(addr), .arg = &addr_wrap_parser, .cb = nlattr_get_nested }, @@ -412,6 +448,22 @@ static const struct nlattr_parser nla_p_ruleaddr[] = { NL_DECLARE_ATTR_PARSER(rule_addr_parser, nla_p_ruleaddr); #undef _OUT +static bool +nlattr_add_rule_addr(struct nl_writer *nw, int attrtype, struct pf_rule_addr *r) +{ + int off = nlattr_add_nested(nw, attrtype); + + nlattr_add_addr_wrap(nw, PF_RAT_ADDR, &r->addr); + nlattr_add_u16(nw, PF_RAT_SRC_PORT, r->port[0]); + nlattr_add_u16(nw, PF_RAT_DST_PORT, r->port[1]); + nlattr_add_u8(nw, PF_RAT_NEG, r->neg); + nlattr_add_u8(nw, PF_RAT_OP, r->port_op); + + nlattr_set_len(nw, off); + + return (true); +} + #define _OUT(_field) offsetof(struct pf_mape_portset, _field) static const struct nlattr_parser nla_p_mape_portset[] = { { .type = PF_MET_OFFSET, .off = _OUT(offset), .cb = nlattr_get_uint8 }, @@ -421,6 +473,20 @@ static const struct nlattr_parser nla_p_mape_portset[] = { NL_DECLARE_ATTR_PARSER(mape_portset_parser, nla_p_mape_portset); #undef _OUT +static bool +nlattr_add_mape_portset(struct nl_writer *nw, int attrtype, const struct pf_mape_portset *m) +{ + int off = nlattr_add_nested(nw, attrtype); + + nlattr_add_u8(nw, PF_MET_OFFSET, m->offset); + nlattr_add_u8(nw, PF_MET_PSID_LEN, m->psidlen); + nlattr_add_u16(nw, PF_MET_PSID, m->psid); + + nlattr_set_len(nw, off); + + return (true); +} + struct nl_parsed_labels { char labels[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE]; @@ -468,6 +534,23 @@ nlattr_get_nested_pf_rule_labels(struct nlattr *nla, struct nl_pstate *npt, cons return (0); } +static bool +nlattr_add_labels(struct nl_writer *nw, int attrtype, const struct pf_krule *r) +{ + int off = nlattr_add_nested(nw, attrtype); + int i = 0; + + while (r->label[i][0] != 0 + && i < PF_RULE_MAX_LABEL_COUNT) { + nlattr_add_string(nw, PF_LT_LABEL, r->label[i]); + i++; + } + + nlattr_set_len(nw, off); + + return (true); +} + #define _OUT(_field) offsetof(struct pf_kpool, _field) static const struct nlattr_parser nla_p_pool[] = { { .type = PF_PT_KEY, .off = _OUT(key), .arg = (void *)sizeof(struct pf_poolhashkey), .cb = nlattr_get_bytes }, @@ -481,6 +564,24 @@ static const struct nlattr_parser nla_p_pool[] = { NL_DECLARE_ATTR_PARSER(pool_parser, nla_p_pool); #undef _OUT +static bool +nlattr_add_pool(struct nl_writer *nw, int attrtype, const struct pf_kpool *pool) +{ + int off = nlattr_add_nested(nw, attrtype); + + nlattr_add(nw, PF_PT_KEY, sizeof(struct pf_poolhashkey), &pool->key); + nlattr_add_in6_addr(nw, PF_PT_COUNTER, (const struct in6_addr *)&pool->counter); + nlattr_add_u32(nw, PF_PT_TBLIDX, pool->tblidx); + nlattr_add_u16(nw, PF_PT_PROXY_SRC_PORT, pool->proxy_port[0]); + nlattr_add_u16(nw, PF_PT_PROXY_DST_PORT, pool->proxy_port[1]); + nlattr_add_u8(nw, PF_PT_OPTS, pool->opts); + nlattr_add_mape_portset(nw, PF_PT_MAPE, &pool->mape); + + nlattr_set_len(nw, off); + + return (true); +} + #define _OUT(_field) offsetof(struct pf_rule_uid, _field) static const struct nlattr_parser nla_p_rule_uid[] = { { .type = PF_RUT_UID_LOW, .off = _OUT(uid[0]), .cb = nlattr_get_uint32 }, @@ -490,6 +591,20 @@ static const struct nlattr_parser nla_p_rule_uid[] = { NL_DECLARE_ATTR_PARSER(rule_uid_parser, nla_p_rule_uid); #undef _OUT +static bool +nlattr_add_rule_uid(struct nl_writer *nw, int attrtype, const struct pf_rule_uid *u) +{ + int off = nlattr_add_nested(nw, attrtype); + + nlattr_add_u32(nw, PF_RUT_UID_LOW, u->uid[0]); + nlattr_add_u32(nw, PF_RUT_UID_HIGH, u->uid[1]); + nlattr_add_u8(nw, PF_RUT_OP, u->op); + + nlattr_set_len(nw, off); + + return (true); +} + struct nl_parsed_timeouts { uint32_t timeouts[PFTM_MAX]; @@ -536,6 +651,19 @@ nlattr_get_nested_timeouts(struct nlattr *nla, struct nl_pstate *npt, const void return (0); } +static bool +nlattr_add_timeout(struct nl_writer *nw, int attrtype, uint32_t *timeout) +{ + int off = nlattr_add_nested(nw, attrtype); + + for (int i = 0; i < PFTM_MAX; i++) + nlattr_add_u32(nw, PF_RT_TIMEOUT, timeout[i]); + + nlattr_set_len(nw, off); + + return (true); +} + #define _OUT(_field) offsetof(struct pf_krule, _field) static const struct nlattr_parser nla_p_rule[] = { { .type = PF_RT_SRC, .off = _OUT(src), .arg = &rule_addr_parser,.cb = nlattr_get_nested }, @@ -654,6 +782,7 @@ static const struct nlattr_parser nla_p_getrules[] = { }; static const struct nlfield_parser nlf_p_getrules[] = { }; +#undef _OUT NL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, nlf_p_getrules, nla_p_getrules); static int @@ -695,6 +824,182 @@ out: return (error); } +struct nl_parsed_get_rule { + char anchor[MAXPATHLEN]; + uint8_t action; + uint32_t nr; + uint32_t ticket; + uint8_t clear; +}; +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct nl_parsed_get_rule, _field) +static const struct nlattr_parser nla_p_getrule[] = { + { .type = PF_GR_ANCHOR, .off = _OUT(anchor), .arg = (void *)MAXPATHLEN, .cb = nlattr_get_chara }, + { .type = PF_GR_ACTION, .off = _OUT(action), .cb = nlattr_get_uint8 }, + { .type = PF_GR_NR, .off = _OUT(nr), .cb = nlattr_get_uint32 }, + { .type = PF_GR_TICKET, .off = _OUT(ticket), .cb = nlattr_get_uint32 }, + { .type = PF_GR_CLEAR, .off = _OUT(clear), .cb = nlattr_get_uint8 }, +}; +static const struct nlfield_parser nlf_p_getrule[] = { +}; +NL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, nlf_p_getrule, nla_p_getrule); + +static int +pf_handle_getrule(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + char anchor_call[MAXPATHLEN]; + struct nl_parsed_get_rule attrs = {}; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + struct pf_kruleset *ruleset; + struct pf_krule *rule; + int rs_num; + int error; + + error = nl_parse_nlmsg(hdr, &getrule_parser, npt, &attrs); + if (error != 0) + return (error); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_GETRULE; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + PF_RULES_WLOCK(); + ruleset = pf_find_kruleset(attrs.anchor); + if (ruleset == NULL) { + PF_RULES_WUNLOCK(); + error = ENOENT; + goto out; + } + + rs_num = pf_get_ruleset_number(attrs.action); + if (rs_num >= PF_RULESET_MAX) { + PF_RULES_WUNLOCK(); + error = EINVAL; + goto out; + } + + if (attrs.ticket != ruleset->rules[rs_num].active.ticket) { + PF_RULES_WUNLOCK(); + error = EBUSY; + goto out; + } + + rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); + while ((rule != NULL) && (rule->nr != attrs.nr)) + rule = TAILQ_NEXT(rule, entries); + if (rule == NULL) { + PF_RULES_WUNLOCK(); + error = EBUSY; + goto out; + } + + nlattr_add_rule_addr(nw, PF_RT_SRC, &rule->src); + nlattr_add_rule_addr(nw, PF_RT_DST, &rule->dst); + nlattr_add_u32(nw, PF_RT_RIDENTIFIER, rule->ridentifier); + nlattr_add_labels(nw, PF_RT_LABELS, rule); + nlattr_add_string(nw, PF_RT_IFNAME, rule->ifname); + nlattr_add_string(nw, PF_RT_QNAME, rule->qname); + nlattr_add_string(nw, PF_RT_PQNAME, rule->pqname); + nlattr_add_string(nw, PF_RT_TAGNAME, rule->tagname); + nlattr_add_string(nw, PF_RT_MATCH_TAGNAME, rule->match_tagname); + nlattr_add_string(nw, PF_RT_OVERLOAD_TBLNAME, rule->overload_tblname); + nlattr_add_pool(nw, PF_RT_RPOOL, &rule->rpool); + nlattr_add_u32(nw, PF_RT_OS_FINGERPRINT, rule->os_fingerprint); + nlattr_add_u32(nw, PF_RT_RTABLEID, rule->rtableid); + nlattr_add_timeout(nw, PF_RT_TIMEOUT, rule->timeout); + nlattr_add_u32(nw, PF_RT_MAX_STATES, rule->max_states); + nlattr_add_u32(nw, PF_RT_MAX_SRC_NODES, rule->max_src_nodes); + nlattr_add_u32(nw, PF_RT_MAX_SRC_STATES, rule->max_src_states); + nlattr_add_u32(nw, PF_RT_MAX_SRC_CONN_RATE_LIMIT, rule->max_src_conn_rate.limit); + nlattr_add_u32(nw, PF_RT_MAX_SRC_CONN_RATE_SECS, rule->max_src_conn_rate.seconds); + + nlattr_add_u16(nw, PF_RT_DNPIPE, rule->dnpipe); + nlattr_add_u16(nw, PF_RT_DNRPIPE, rule->dnrpipe); + nlattr_add_u32(nw, PF_RT_DNFLAGS, rule->free_flags); + + nlattr_add_u32(nw, PF_RT_NR, rule->nr); + nlattr_add_u32(nw, PF_RT_PROB, rule->prob); + nlattr_add_u32(nw, PF_RT_CUID, rule->cuid); + nlattr_add_u32(nw, PF_RT_CPID, rule->cpid); + + nlattr_add_u16(nw, PF_RT_RETURN_ICMP, rule->return_icmp); + nlattr_add_u16(nw, PF_RT_RETURN_ICMP6, rule->return_icmp6); + nlattr_add_u16(nw, PF_RT_RETURN_ICMP6, rule->return_icmp6); + nlattr_add_u16(nw, PF_RT_MAX_MSS, rule->max_mss); + nlattr_add_u16(nw, PF_RT_SCRUB_FLAGS, rule->scrub_flags); + + nlattr_add_rule_uid(nw, PF_RT_UID, &rule->uid); + nlattr_add_rule_uid(nw, PF_RT_GID, (const struct pf_rule_uid *)&rule->gid); + + nlattr_add_u32(nw, PF_RT_RULE_FLAG, rule->rule_flag); + nlattr_add_u8(nw, PF_RT_ACTION, rule->action); + nlattr_add_u8(nw, PF_RT_DIRECTION, rule->direction); + nlattr_add_u8(nw, PF_RT_LOG, rule->log); + nlattr_add_u8(nw, PF_RT_LOGIF, rule->logif); + nlattr_add_u8(nw, PF_RT_QUICK, rule->quick); + nlattr_add_u8(nw, PF_RT_IF_NOT, rule->ifnot); + nlattr_add_u8(nw, PF_RT_MATCH_TAG_NOT, rule->match_tag_not); + nlattr_add_u8(nw, PF_RT_NATPASS, rule->natpass); + nlattr_add_u8(nw, PF_RT_KEEP_STATE, rule->keep_state); + + nlattr_add_u8(nw, PF_RT_AF, rule->af); + nlattr_add_u8(nw, PF_RT_PROTO, rule->proto); + nlattr_add_u8(nw, PF_RT_TYPE, rule->type); + nlattr_add_u8(nw, PF_RT_CODE, rule->code); + nlattr_add_u8(nw, PF_RT_FLAGS, rule->flags); + nlattr_add_u8(nw, PF_RT_FLAGSET, rule->flagset); + nlattr_add_u8(nw, PF_RT_MIN_TTL, rule->min_ttl); + nlattr_add_u8(nw, PF_RT_ALLOW_OPTS, rule->allow_opts); + nlattr_add_u8(nw, PF_RT_RT, rule->rt); + nlattr_add_u8(nw, PF_RT_RETURN_TTL, rule->return_ttl); + nlattr_add_u8(nw, PF_RT_TOS, rule->tos); + nlattr_add_u8(nw, PF_RT_SET_TOS, rule->set_tos); + nlattr_add_u8(nw, PF_RT_ANCHOR_RELATIVE, rule->anchor_relative); + nlattr_add_u8(nw, PF_RT_ANCHOR_WILDCARD, rule->anchor_wildcard); + nlattr_add_u8(nw, PF_RT_FLUSH, rule->flush); + nlattr_add_u8(nw, PF_RT_PRIO, rule->prio); + nlattr_add_u8(nw, PF_RT_SET_PRIO, rule->set_prio[0]); + nlattr_add_u8(nw, PF_RT_SET_PRIO_REPLY, rule->set_prio[1]); + + nlattr_add_in6_addr(nw, PF_RT_DIVERT_ADDRESS, &rule->divert.addr.v6); + nlattr_add_u16(nw, PF_RT_DIVERT_PORT, rule->divert.port); + + nlattr_add_u64(nw, PF_RT_PACKETS_IN, pf_counter_u64_fetch(&rule->packets[0])); + nlattr_add_u64(nw, PF_RT_PACKETS_OUT, pf_counter_u64_fetch(&rule->packets[1])); + nlattr_add_u64(nw, PF_RT_BYTES_IN, pf_counter_u64_fetch(&rule->bytes[0])); + nlattr_add_u64(nw, PF_RT_BYTES_OUT, pf_counter_u64_fetch(&rule->bytes[1])); + nlattr_add_u64(nw, PF_RT_EVALUATIONS, pf_counter_u64_fetch(&rule->evaluations)); + nlattr_add_u64(nw, PF_RT_TIMESTAMP, pf_get_timestamp(rule)); + nlattr_add_u64(nw, PF_RT_STATES_CUR, counter_u64_fetch(rule->states_cur)); + nlattr_add_u64(nw, PF_RT_STATES_TOTAL, counter_u64_fetch(rule->states_tot)); + nlattr_add_u64(nw, PF_RT_SRC_NODES, counter_u64_fetch(rule->src_nodes)); + + error = pf_kanchor_copyout(ruleset, rule, anchor_call); + MPASS(error == 0); + + nlattr_add_string(nw, PF_RT_ANCHOR_CALL, anchor_call); + + if (attrs.clear) + pf_krule_clear_counters(rule); + + PF_RULES_WUNLOCK(); + + if (!nlmsg_end(nw)) { + error = ENOMEM; + goto out; + } + + return (0); +out: + nlmsg_abort(nw); + return (error); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser, &addrule_parser, @@ -746,6 +1051,13 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_GETRULE, + .cmd_name = "GETRULE", + .cmd_cb = pf_handle_getrule, + .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index d8b494a54cf7..51df8b7aece9 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -42,6 +42,7 @@ enum { PFNL_CMD_STOP = 4, PFNL_CMD_ADDRULE = 5, PFNL_CMD_GETRULES = 6, + PFNL_CMD_GETRULE = 7, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -117,6 +118,8 @@ enum pf_addr_type_t { PF_AT_TABLENAME = 4, /* string */ PF_AT_TYPE = 5, /* u8 */ PF_AT_IFLAGS = 6, /* u8 */ + PF_AT_TBLCNT = 7, /* u32 */ + PF_AT_DYNCNT = 8, /* u32 */ }; enum pfrule_addr_type_t { @@ -229,6 +232,16 @@ enum pf_rule_type_t { PF_RT_SET_PRIO_REPLY = 60, /* u8 */ PF_RT_DIVERT_ADDRESS = 61, /* in6_addr */ PF_RT_DIVERT_PORT = 62, /* u16 */ + PF_RT_PACKETS_IN = 63, /* u64 */ + PF_RT_PACKETS_OUT = 64, /* u64 */ + PF_RT_BYTES_IN = 65, /* u64 */ + PF_RT_BYTES_OUT = 66, /* u64 */ + PF_RT_EVALUATIONS = 67, /* u64 */ + PF_RT_TIMESTAMP = 68, /* u64 */ + PF_RT_STATES_CUR = 69, /* u64 */ + PF_RT_STATES_TOTAL = 70, /* u64 */ + PF_RT_SRC_NODES = 71, /* u64 */ + PF_RT_ANCHOR_CALL = 72, /* string */ }; enum pf_addrule_type_t { @@ -246,6 +259,7 @@ enum pf_getrules_type_t { PF_GR_ACTION = 2, /* u8 */ PF_GR_NR = 3, /* u32 */ PF_GR_TICKET = 4, /* u32 */ + PF_GR_CLEAR = 5, /* u8 */ }; #ifdef _KERNEL diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c index bdc205785bd4..38cc1eae419f 100644 --- a/sys/netpfil/pf/pf_ruleset.c +++ b/sys/netpfil/pf/pf_ruleset.c @@ -367,10 +367,10 @@ pf_kanchor_setup(struct pf_krule *r, const struct pf_kruleset *s, } int -pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r, - nvlist_t *nvl) +pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, + char *anchor_call) { - char anchor_call[MAXPATHLEN] = { 0 }; + anchor_call[0] = 0; if (r->anchor == NULL) goto done; @@ -408,11 +408,25 @@ pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r, sizeof(anchor_call)); done: - nvlist_add_string(nvl, "anchor_call", anchor_call); return (0); } +int +pf_kanchor_nvcopyout(const struct pf_kruleset *rs, const struct pf_krule *r, + nvlist_t *nvl) +{ + char anchor_call[MAXPATHLEN] = { 0 }; + int ret; + + ret = pf_kanchor_copyout(rs, r, anchor_call); + MPASS(ret == 0); + + nvlist_add_string(nvl, "anchor_call", anchor_call); + + return (ret); +} + int pf_keth_anchor_nvcopyout(const struct pf_keth_ruleset *rs, const struct pf_keth_rule *r, nvlist_t *nvl) @@ -460,52 +474,6 @@ done: return (0); } -int -pf_kanchor_copyout(const struct pf_kruleset *rs, const struct pf_krule *r, - struct pfioc_rule *pr) -{ - pr->anchor_call[0] = 0; - if (r->anchor == NULL) - return (0); - if (!r->anchor_relative) { - strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call)); - strlcat(pr->anchor_call, r->anchor->path, - sizeof(pr->anchor_call)); - } else { - char *a, *p; - int i; - - a = (char *)rs_malloc(MAXPATHLEN); - if (a == NULL) - return (1); - if (rs->anchor == NULL) - a[0] = 0; - else - strlcpy(a, rs->anchor->path, MAXPATHLEN); - for (i = 1; i < r->anchor_relative; ++i) { - if ((p = strrchr(a, '/')) == NULL) - p = a; - *p = 0; - strlcat(pr->anchor_call, "../", - sizeof(pr->anchor_call)); - } - if (strncmp(a, r->anchor->path, strlen(a))) { - printf("pf_anchor_copyout: '%s' '%s'\n", a, - r->anchor->path); - rs_free(a); - return (1); - } - if (strlen(r->anchor->path) > strlen(a)) - strlcat(pr->anchor_call, r->anchor->path + (a[0] ? - strlen(a) + 1 : 0), sizeof(pr->anchor_call)); - rs_free(a); - } - if (r->anchor_wildcard) - strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*", - sizeof(pr->anchor_call)); - return (0); -} - void pf_kanchor_remove(struct pf_krule *r) { From 306d3fb23d7ccbc327b6038df2088629daff87b4 Mon Sep 17 00:00:00 2001 From: Kristof Provost Date: Thu, 1 Feb 2024 22:32:32 +0100 Subject: [PATCH 09/17] libpfct: fix incorrect array check Reported by: Coverity Scan CID: 1523771 Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index cb9b377f7b6c..71546c4709c2 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -965,8 +965,8 @@ snl_add_msg_attr_rule_labels(struct snl_writer *nw, uint32_t type, const char la off = snl_add_msg_attr_nested(nw, type); - while (labels[i][0] != 0 && - i < PF_RULE_MAX_LABEL_COUNT) { + while (i < PF_RULE_MAX_LABEL_COUNT && + labels[i][0] != 0) { snl_add_msg_attr_string(nw, PF_LT_LABEL, labels[i]); i++; } From 0e867a49115687398fd486b3af67fbb41f48b8a8 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Fri, 2 Feb 2024 17:08:55 +0000 Subject: [PATCH 10/17] aarch/SYS.h: implement _SYSCALL_BODY() macro Add _SYSCALL_BODY() macro which invokes the syscall via _SYCALL() and calls cerror as required. Use to implement PSEUDO() and RSYSCALL(). Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D43058 --- lib/libc/aarch64/SYS.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/libc/aarch64/SYS.h b/lib/libc/aarch64/SYS.h index af7f0200a0c7..07d14ab1bb44 100644 --- a/lib/libc/aarch64/SYS.h +++ b/lib/libc/aarch64/SYS.h @@ -40,21 +40,21 @@ * to jump around to use more capable unconditional branch * instruction. */ -#define PSEUDO(name) \ -ENTRY(__sys_##name); \ - WEAK_REFERENCE(__sys_##name, _##name); \ +#define _SYSCALL_BODY(name) \ _SYSCALL(name); \ b.cs 1f; \ ret; \ -1: b cerror; \ +1: b cerror + +#define PSEUDO(name) \ +ENTRY(__sys_##name); \ + WEAK_REFERENCE(__sys_##name, _##name); \ + _SYSCALL_BODY(name); \ END(__sys_##name) #define RSYSCALL(name) \ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, name); \ WEAK_REFERENCE(__sys_##name, _##name); \ - _SYSCALL(name); \ - b.cs 1f; \ - ret; \ -1: b cerror; \ + _SYSCALL_BODY(name); \ END(__sys_##name) From 02b0d4b688cc4deb14cb6e7534a2a4958e48b753 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Fri, 2 Feb 2024 09:41:40 -0700 Subject: [PATCH 11/17] sys/cdefs.h: add __noexcept and __noexcept_if These macros provide the C++11 noexcept and noexcept(...) keywords if we're compiling in a C++11 environment. Otherwise, they expand to an empty string. This will be used to add the required noexcept specifier to several libc functions as required in C++11. MFC after: 2 weeks Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1085 --- sys/sys/cdefs.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h index fcc90b4d8aee..206cc569c55a 100644 --- a/sys/sys/cdefs.h +++ b/sys/sys/cdefs.h @@ -358,6 +358,17 @@ #endif #endif +/* + * noexcept keyword added in C++11. + */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#define __noexcept noexcept +#define __noexcept_if(__c) noexcept(__c) +#else +#define __noexcept +#define __noexcept_if(__c) +#endif + /* * We use `__restrict' as a way to define the `restrict' type qualifier * without disturbing older software that is unaware of C99 keywords. From c27a89971805b176dcfa5a234f2ea6f6109d0a70 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Fri, 2 Feb 2024 09:41:40 -0700 Subject: [PATCH 12/17] stdlib.h: add __noexcept to prototypes The noexcept specifier is required on these functions in C++: _Exit(), atexit(), quick_exit(), at_quick_exit(), abort(). MFC after: 2 weeks Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1085 --- include/stdlib.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index ff8991d1fa94..f0687f01e6c7 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -84,9 +84,9 @@ extern int __mb_cur_max; extern int ___mb_cur_max(void); #define MB_CUR_MAX ((size_t)___mb_cur_max()) -_Noreturn void abort(void); +_Noreturn void abort(void) __noexcept; int abs(int) __pure2; -int atexit(void (* _Nonnull)(void)); +int atexit(void (* _Nonnull)(void)) __noexcept; double atof(const char *); int atoi(const char *); long atol(const char *); @@ -154,7 +154,7 @@ unsigned long long strtoull(const char * __restrict, char ** __restrict, int); #endif /* __LONG_LONG_SUPPORTED */ -_Noreturn void _Exit(int); +_Noreturn void _Exit(int) __noexcept; #endif /* __ISO_C_VISIBLE >= 1999 */ /* @@ -163,9 +163,9 @@ _Noreturn void _Exit(int); #if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) __alloc_size(2); -int at_quick_exit(void (*)(void)); +int at_quick_exit(void (*)(void)) __noexcept; _Noreturn void - quick_exit(int); + quick_exit(int) __noexcept; #endif /* __ISO_C_VISIBLE >= 2011 */ /* * Extensions made by POSIX relative to C. From 4b1d3a30914e176e9fd2c363db81c26124a8ee30 Mon Sep 17 00:00:00 2001 From: Lexi Winter Date: Fri, 2 Feb 2024 11:18:54 -0700 Subject: [PATCH 13/17] daily/223.backup-zfs: improve daily_backup_zfs_verbose behaviour - 223.backup-zfs would previously honour the daily_backup_zfs_verbose flag for zfs/zpool list, but not for the properties list. fix it to show a diff for both of these if requested. - if daily_backup_zfs_verbose was disabled, 223.backup-zfs would still set rc=1 if the backup files changed, which caused periodic(8) to send a useless email even if daily_show_success=NO was set. change this so that it only sets rc=1 if diff output is enabled, i.e. the output is actually useful to the admin. MFC after: 2 weeks Reviewed by: imp Pull Request: https://github.com/freebsd/freebsd-src/pull/1091 --- usr.sbin/periodic/etc/daily/223.backup-zfs | 26 ++++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/usr.sbin/periodic/etc/daily/223.backup-zfs b/usr.sbin/periodic/etc/daily/223.backup-zfs index a49bbb2eaa04..e76421220a0b 100755 --- a/usr.sbin/periodic/etc/daily/223.backup-zfs +++ b/usr.sbin/periodic/etc/daily/223.backup-zfs @@ -13,6 +13,7 @@ then fi bak_dir=/var/backups +rc=0 rotate() { base_name=$1 @@ -20,12 +21,13 @@ rotate() { file="$bak_dir/$base_name" if [ -f "${file}.bak" ] ; then - rc=0 if cmp -s "${file}.bak" "${file}.tmp"; then rm "${file}.tmp" else - rc=1 - [ -n "$show_diff" ] && diff ${daily_diff_flags} "${file}.bak" "${file}.tmp" + if [ -n "$show_diff" ]; then + rc=1 + diff ${daily_diff_flags} "${file}.bak" "${file}.tmp" + fi mv "${file}.bak" "${file}.bak2" || rc=3 mv "${file}.tmp" "${file}.bak" || rc=3 fi @@ -36,6 +38,7 @@ rotate() { fi } +show="" case "$daily_backup_zfs_verbose" in [Yy][Ee][Ss]) show="YES" esac @@ -43,9 +46,9 @@ esac case "$daily_backup_zfs_enable" in [Yy][Ee][Ss]) - zpools=$(zpool list $daily_backup_zpool_list_flags) + zpools=$(zpool list $daily_backup_zpool_list_flags) - if [ -z "$zpools" ]; then + if [ -z "$zpools" ]; then echo 'daily_backup_zfs_enable is set to YES but no zpools found.' rc=2 else @@ -59,18 +62,17 @@ case "$daily_backup_zfs_enable" in rotate "zfs_list" $show fi ;; - *) rc=0;; esac case "$daily_backup_zfs_props_enable" in - [Yy][Ee][Ss]) + [Yy][Ee][Ss]) - zfs get $daily_backup_zfs_get_flags > "$bak_dir/zfs_props.tmp" - rotate "zfs_props" + zfs get $daily_backup_zfs_get_flags > "$bak_dir/zfs_props.tmp" + rotate "zfs_props" $show - zpool get $daily_backup_zpool_get_flags > "$bak_dir/zpool_props.tmp" - rotate "zpool_props" - ;; + zpool get $daily_backup_zpool_get_flags > "$bak_dir/zpool_props.tmp" + rotate "zpool_props" $show + ;; esac exit $rc From 619f455b8fc9d05b50822387d3203f74c86fcb5c Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 2 Feb 2024 11:30:39 -0700 Subject: [PATCH 14/17] regex: fix freeing g->charjump in low memory condition computejumps() moves g->charjump to a position relativ to the value of CHAR_MIN. As such, g->charjump doesn't necessarily point to the address actually allocated. While regfree() takes that into account, the low memory handling in regcomp_internal() doesn't. Fix that by free'ing the actually allocated address, as in regfree(). MFC After: 2 weeks Reviewed by: imp,jrtc27 Pull Request: https://github.com/freebsd/freebsd-src/pull/692 --- lib/libc/regex/regcomp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c index 89b96b00fefb..7481d3ecf240 100644 --- a/lib/libc/regex/regcomp.c +++ b/lib/libc/regex/regcomp.c @@ -321,7 +321,7 @@ regcomp_internal(regex_t * __restrict preg, computejumps(p, g); computematchjumps(p, g); if(g->matchjump == NULL && g->charjump != NULL) { - free(g->charjump); + free(&g->charjump[CHAR_MIN]); g->charjump = NULL; } } From 754cac4b283eb024a3a6a194130199c860e32ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Rochoy?= Date: Thu, 4 May 2023 09:23:47 +0200 Subject: [PATCH 15/17] stand/lua: per-product conf if requested via product_vars If product_vars is set, it must be a space separated list of environment variable names to walk through to guess the product. Each time a product can be guessed (i.e., the corresponding variable is defined), prepend /boot/loader.conf.d/PRODUCT/ to loader_conf_dirs. It can be typically used as follow: smbios.system.planar.maker="PLANAR_MAKER" smbios.system.planar.product="PLANAR_PRODUCT" smbios.system.product="PRODUCT" uboot.m_product="M_PRODUCT" product_vars="smbios.system.planar.maker smbios.system.planar.product smbios.system.product uboot.m_product" to read files found in the following directories, in that order: /boot/loader.conf.d/PLANAR_MAKER /boot/loader.conf.d/PLANAR_PRODUCT /boot/loader.conf.d/PRODUCT /boot/loader.conf.d/M_PRODUCT --- stand/defaults/loader.conf.5 | 34 +++++++++++++++++++++++++++++++++- stand/lua/config.lua | 25 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5 index 42e5712d93b8..0d82a3dac9b3 100644 --- a/stand/defaults/loader.conf.5 +++ b/stand/defaults/loader.conf.5 @@ -21,7 +21,7 @@ .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. -.Dd January 10, 2024 +.Dd February 2, 2024 .Dt LOADER.CONF 5 .Os .Sh NAME @@ -138,6 +138,38 @@ present file. should be treated as write-only. One cannot depend on any value remaining in the loader environment or carried over into the kernel environment. +.It Ar product_vars +When set, must be a space separated list of environment variable names to walk +through to guess product information. +The order matters as reading a config file override the previously defined +values. +Undefined variables are silently ignored. +.Pp +When product information can be guessed, for each product information found, +append +.Pa /boot/loader.conf.d/PRODUCT +to +.Ar loader_conf_dirs . +It can be typically used as follow: +.Bd -literal +smbios.system.planar.maker="PLANAR_MAKER" +smbios.system.planar.product="PLANAR_PRODUCT" +smbios.system.product="PRODUCT" +uboot.m_product="M_PRODUCT" +product_vars="smbios.system.planar.maker smbios.system.planar.product smbios.system.product uboot.m_product" +.Ed +.Pp +to read files found in the following directories, in that order: +.Bl -bullet -compact +.It +.Pa /boot/loader.conf.d/PLANAR_MAKER +.It +.Pa /boot/loader.conf.d/PLANAR_PRODUCT +.It +.Pa /boot/loader.conf.d/PRODUCT +.It +.Pa /boot/loader.conf.d/M_PRODUCT +.El .It Ar kernel Name of the kernel to be loaded. If no kernel name is set, no additional diff --git a/stand/lua/config.lua b/stand/lua/config.lua index 8fdc805ee983..210bb9338783 100644 --- a/stand/lua/config.lua +++ b/stand/lua/config.lua @@ -658,12 +658,37 @@ function config.readConf(file, loaded_files) if load_conf_dirs then local loader_conf_dirs = getEnv("loader_conf_dirs") + + -- If product_vars is set, it must be a list of environment variable names + -- to walk through to guess product information. The order matters as + -- reading a config files override the previously defined values. + -- + -- If product information can be guessed, for each product information + -- found, also read config files found in /boot/loader.conf.d/PRODUCT/. + local product_vars = getEnv("product_vars") + if product_vars then + local product_conf_dirs = "" + for var in product_vars:gmatch("%S+") do + local product = getEnv(var) + if product then + product_conf_dirs = product_conf_dirs .. " /boot/loader.conf.d/" .. product + end + end + + if loader_conf_dirs then + loader_conf_dirs = loader_conf_dirs .. product_conf_dirs + else + loader_conf_dirs = product_conf_dirs + end + end + if loader_conf_dirs ~= nil then for name in loader_conf_dirs:gmatch("[%w%p]+") do if lfs.attributes(name, "mode") ~= "directory" then print(MSG_FAILDIR:format(name)) goto nextdir end + for cfile in lfs.dir(name) do if cfile:match(".conf$") then local fpath = name .. "/" .. cfile From d3d0b735571d9562812ce5b343a6e91f7a795dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Rochoy?= Date: Thu, 21 Dec 2023 15:05:58 +0100 Subject: [PATCH 16/17] stand/lua: always allow overriding with local config files Loader now also read configuration files listed in local_loader_conf_files. Files listed here are the last ones read. And /boot/loader.conf.local was moved from loader_conf_files to local_loader_conf_files leaving only loader.conf and device.hints in loader_conf_files by default. The idea is to ensure local_loader_conf_files, i.e., /boot/loader.conf.local, can always be used to override other user defined settings. So the sequencing is now as follow: 1. Bootstrap: /boot/defaults/loader.conf 2. Read loader_conf_files files: /boot/device.hints /boot/loader.conf 3. Read loader_conf_dirs files: /boot/loader.conf.d/*.conf 4. And finally, rread local_loader_conf_files files: /boot/loader.conf.local --- UPDATING | 21 +++++++++++++++++++++ stand/defaults/loader.conf | 3 ++- stand/defaults/loader.conf.5 | 32 ++++++++++++++++++++++++++++---- stand/lua/config.lua | 15 ++++++++++++--- stand/lua/config.lua.8 | 8 ++++++-- 5 files changed, 69 insertions(+), 10 deletions(-) diff --git a/UPDATING b/UPDATING index 14fae1eb0656..33bae2a42b9d 100644 --- a/UPDATING +++ b/UPDATING @@ -27,6 +27,27 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.x IS SLOW: world, or to merely disable the most expensive debugging functionality at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20240202: + Loader now also read configuration files listed in local_loader_conf_files. + Files listed here are the last ones read. And /boot/loader.conf.local was + moved from loader_conf_files to local_loader_conf_files leaving only + loader.conf and device.hints in loader_conf_files by default. + + The following sequencing is applied: + + 1. Bootstrap: + /boot/defaults/loader.conf + + 2. Read loader_conf_files files: + /boot/device.hints + /boot/loader.conf + + 3. Read loader_conf_dirs files: + /boot/loader.conf.d/*.conf + + 4. And finally, rread local_loader_conf_files files: + /boot/loader.conf.local + 20240201: sendmail 8.18.1 has been imported and merged. This version enforces stricter RFC compliance by default, especially with respect to line diff --git a/stand/defaults/loader.conf b/stand/defaults/loader.conf index e0062bbc8149..a5d27b96b6ba 100644 --- a/stand/defaults/loader.conf +++ b/stand/defaults/loader.conf @@ -13,8 +13,9 @@ exec="echo Loading /boot/defaults/loader.conf" kernel="kernel" # /boot sub-directory containing kernel and modules bootfile="kernel" # Kernel name (possibly absolute path) kernel_options="" # Flags to be passed to the kernel -loader_conf_files="/boot/device.hints /boot/loader.conf /boot/loader.conf.local" +loader_conf_files="/boot/device.hints /boot/loader.conf" loader_conf_dirs="/boot/loader.conf.d" +local_loader_conf_files="/boot/loader.conf.local" nextboot_conf="/boot/nextboot.conf" verbose_loading="NO" # Set to YES for verbose loader output diff --git a/stand/defaults/loader.conf.5 b/stand/defaults/loader.conf.5 index 0d82a3dac9b3..e38ad865c288 100644 --- a/stand/defaults/loader.conf.5 +++ b/stand/defaults/loader.conf.5 @@ -131,6 +131,10 @@ Space separated list of directories to process for configuration files. The lua-based loader will process files with a .Dq .conf suffix that are placed in these directories. +Files found here are processed after the ones listed in +.Va loader_conf_files +but before the ones found in +.Va local_loader_conf_files . .It Ar loader_conf_files Defines additional configuration files to be processed right after the present file. @@ -138,6 +142,13 @@ present file. should be treated as write-only. One cannot depend on any value remaining in the loader environment or carried over into the kernel environment. +.It Ar local_loader_conf_files +Space separated list of additional configuration files to be processed at last, +i.e., after +.Va loader_conf_files +and +.Va loader_conf_dirs +are processed. .It Ar product_vars When set, must be a space separated list of environment variable names to walk through to guess product information. @@ -274,6 +285,14 @@ default settings can be ignored. The few of them which are important or useful are: .Bl -tag -width bootfile -offset indent +.It Va local_loader_conf_files +.Pq Dq /boot/loader.conf.local +Ensure +.Va loader.conf.local +can always be used to override settings from files found in +.Va loader_conf_files +and +.Va loader_conf_dirs . .It Va bitmap_load .Pq Dq NO If set to @@ -455,13 +474,18 @@ It is not available in the default Forth-based loader. .Sh FILES .Bl -tag -width /boot/defaults/loader.conf -compact .It Pa /boot/defaults/loader.conf -default settings \(em do not change this file. +Default settings \(em do not change this file. .It Pa /boot/loader.conf -user defined settings. +User defined settings. .It Pa /boot/loader.conf.lua -user defined settings written in lua. +User defined settings written in lua. +.It Pa /boot/loader.conf.d/*.conf +User defined settings split in separate files. +.It Pa /boot/loader.conf.d/*.lua +User defined settings written in lua and split in separate files. .It Pa /boot/loader.conf.local -machine-specific settings for sites with a common loader.conf. +Machine-specific settings for sites with a common loader.conf. Allow to override +settings defined in other files. .El .Sh SEE ALSO .Xr kenv 1 , diff --git a/stand/lua/config.lua b/stand/lua/config.lua index 210bb9338783..86f5ef6174a2 100644 --- a/stand/lua/config.lua +++ b/stand/lua/config.lua @@ -630,8 +630,7 @@ function config.readConf(file, loaded_files) return end - -- We'll process loader_conf_dirs at the top-level readConf - local load_conf_dirs = next(loaded_files) == nil + local top_level = next(loaded_files) == nil -- Are we the top-level readConf? print("Loading " .. file) -- The final value of loader_conf_files is not important, so just @@ -656,7 +655,7 @@ function config.readConf(file, loaded_files) end end - if load_conf_dirs then + if top_level then local loader_conf_dirs = getEnv("loader_conf_dirs") -- If product_vars is set, it must be a list of environment variable names @@ -682,6 +681,7 @@ function config.readConf(file, loaded_files) end end + -- Process "loader_conf_dirs" extra-directories if loader_conf_dirs ~= nil then for name in loader_conf_dirs:gmatch("[%w%p]+") do if lfs.attributes(name, "mode") ~= "directory" then @@ -700,6 +700,15 @@ function config.readConf(file, loaded_files) ::nextdir:: end end + + -- Always allow overriding with local config files, e.g., + -- /boot/loader.conf.local. + local local_loader_conf_files = getEnv("local_loader_conf_files") + if local_loader_conf_files then + for name in local_loader_conf_files:gmatch("[%w%p]+") do + config.readConf(name, loaded_files) + end + end end end diff --git a/stand/lua/config.lua.8 b/stand/lua/config.lua.8 index f9896f2aa420..b2b1122285eb 100644 --- a/stand/lua/config.lua.8 +++ b/stand/lua/config.lua.8 @@ -64,9 +64,13 @@ as a configuration file .Po e.g., as .Pa loader.conf .Pc -and then processing files listed in +and then process files listed in the .Ev loader_conf_files -variable +variable. Additionnaly, the top-level call to readConf will process files listed in the +.Ev loader_conf_dirs +and +.Ev local_loader_conf_files +variables .Po see .Xr loader.conf 5 .Pc . From 30f8cb812e27d8ab40a2c0669ac20a8ee45a7c56 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Fri, 2 Feb 2024 13:58:37 -0500 Subject: [PATCH 17/17] socket: Don't assume m0 != NULL in sbappendcontrol_locked() Some callers (e.g., ktls_decrypt()) violate this assumption and thus could trigger a NULL pointer dereference in KMSAN kernels. Reported by: glebius Fixes: ec45f952a232 ("sockbuf: Add KMSAN checks to sbappend*()") MFC after: 1 week --- sys/kern/uipc_sockbuf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 2732ee8199ee..6d3050596f23 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -1326,7 +1326,8 @@ sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, { struct mbuf *m, *mlast; - kmsan_check_mbuf(m0, "sbappend"); + if (m0 != NULL) + kmsan_check_mbuf(m0, "sbappend"); kmsan_check_mbuf(control, "sbappend"); sbm_clrprotoflags(m0, flags);