The protosw KPI historically has implemented two quite orthogonal
things: protocols that implement a certain kind of socket, and
protocols that are IPv4/IPv6 protocol. These two things do not
make one-to-one correspondence. The pr_input and pr_ctlinput methods
were utilized only in IP protocols. This strange duality required
IP protocols that doesn't have a socket to declare protosw, e.g.
carp(4). On the other hand developers of socket protocols thought
that they need to define pr_input/pr_ctlinput always, which lead to
strange dead code, e.g. div_input() or sdp_ctlinput().
With this change pr_input and pr_ctlinput as part of protosw disappear
and IPv4/IPv6 get their private single level protocol switch table
ip_protox[] and ip6_protox[] respectively, pointing at array of
ipproto_input_t functions. The pr_ctlinput that was used for
control input coming from the network (ICMP, ICMPv6) is now represented
by ip_ctlprotox[] and ip6_ctlprotox[].
ipproto_register() becomes the only official way to register in the
table. Those protocols that were always static and unlikely anybody
is interested in making them loadable, are now registered by ip_init(),
ip6_init(). An IP protocol that considers itself unloadable shall
register itself within its own private SYSINIT().
Reviewed by: tuexen, melifaro
Differential revision: https://reviews.freebsd.org/D36157
This makes key socket implementation self contained and removes one
of the last dependencies on the raw socket code and pr_output method.
There are very subtle API visible changes:
- now key socket would return EOPNOTSUPP instead of EINVAL on
syscalls that are not supposed to be called on a key socket.
- key socket buffer sizes are now controlled by net.key sysctls instead
of net.raw. The latter were not documented anywhere, and even Internet
search doesn't find any references or discussions related to them.
Reviewed by: melifaro
Differential revision: https://reviews.freebsd.org/D36123
Currently there is no upper bound on the PMTU value that is accepted.
Update hostcache only if the new pmtu is smaller than the current entry
and the link MTU.
Approved by: mw(mentor)
Sponsored by: Stormshield
Obtained from: Semihalf
Differential Revision: https://reviews.freebsd.org/D35872
With clang 15, the following -Werror warning is produced:
sys/netipsec/key_debug.c:923:9: error: variable 'j' set but not used [-Werror,-Wunused-but-set-variable]
int i, j;
^
The 'j' variable was in key_debug.c when it was first added, but it
appears to have been a debugging aid that has never been used, so remove
it.
MFC after: 3 days
With clang 15, the following -Werror warnings are produced:
sys/netipsec/key.c:6432:15: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
key_getcomb_ah()
^
void
sys/netipsec/key.c:6489:19: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
key_getcomb_ipcomp()
^
void
This is because key_getcomb_ah() and key_getcomb_ipcomp() are declared
with (void) argument lists, but defined with empty argument lists. Make
the definitions match the declarations.
MFC after: 3 days
With clang 15, the following -Werror warning is produced:
sys/netipsec/ipsec_mbuf.c:93:24: error: variable 'alloc' set but not used [-Werror,-Wunused-but-set-variable]
int todo, len, done, alloc;
^
The 'alloc' variable appears to have been a debugging aid that has never
been used for anything, so remove it.
MFC after: 3 days
This mutex is a significant point of contention in the ipsec code, and
can be relatively trivially replaced by a read-mostly lock.
It does require a separate lock for the replay protection, which we do
here by adding a separate mutex.
This improves throughput (without replay protection) by 10-15%.
MFC after: 3 weeks
Sponsored by: Orange Business Services
Differential Revision: https://reviews.freebsd.org/D35763
key_delsav used to conditionally dereference vnet, leading to panics as
it was getting unset too early.
While the particular condition was removed, it makes sense to handle all
operations of the sort with correct vnet set so change it.
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D34313
When TCP_MD5SIG is set on a socket, all packets are dropped that don't
contain an MD5 signature. Relax this behavior to accept a non-signed
packet when a security association doesn't exist with the peer.
This is useful when a listen socket set with TCP_MD5SIG wants to handle
connections protected with and without MD5 signatures.
Reviewed by: bz (previous version)
Sponsored by: nepustil.net
Sponsored by: Klara Inc.
Differential Revision: https://reviews.freebsd.org/D33227
Return ENOENT from tcp_ipsec_input() when a security association is not
found. This allows callers of TCP_MD5_INPUT() to differentiate between a
security association not found and receiving a bad signature.
Also return ENOENT from tcp_ipsec_output() for consistency.
Reviewed by: ae
Sponsored by: nepustil.net
Sponsored by: Klara Inc.
Differential Revision: https://reviews.freebsd.org/D33226
The historical BSD network stack loop that rolls over domains and
over protocols has no advantages over more modern SYSINIT(9).
While doing the sweep, split global and per-VNET initializers.
Getting rid of pr_init allows to achieve several things:
o Get rid of ifdef's that protect against double foo_init() when
both INET and INET6 are compiled in.
o Isolate initializers statically to the module they init.
o Makes code easier to understand and maintain.
Reviewed by: melifaro
Differential revision: https://reviews.freebsd.org/D33537
When adding an SPD entry that already exists, a refcount wraparound
panic is encountered. This was caused from dropping a reference on the
wrong security policy.
Fixes: 4920e38fec ("ipsec: fix race condition in key.c")
Reviewed by: wma
Sponsored by: Klara Inc.
Differential Revision: https://reviews.freebsd.org/D33100
Same comparison problem as in key_do_getnewspi.
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D32827
SPIs get allocated and inserted in separate steps. Prior to the change
there was nothing preventing 2 differnet threads from ending up with the
same one.
PR: 258849
Reported by: Herbie.Robinson@stratus.com
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D32826
The 'count' variable would end up being -1 post loop, while the
following condition would check for 0 instead.
PR: 258849
Reported by: Herbie.Robinson@stratus.com
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D32826
Discard and send ICMPv6 Packet Too Big to sender when we try to encapsulate
and forward a packet which total length exceeds the PMTU.
Logic is based on the IPv4 implementation.
Common code was moved to a separate function.
Differential revision: https://reviews.freebsd.org/D31771
Obtained from: Semihalf
Sponsored by: Stormshield
If we fail to find to PMTU in hostcache, we assume it's equal
to link's MTU.
This patch prevents packets larger then link's MTU to be dropped
silently if there is no PMTU in hostcache.
Differential revision: https://reviews.freebsd.org/D31770
Obtained from: Semihalf
Sponsored by: Stormshield
pfil_run_hooks which eventually can get called asserts on it.
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D32007
key_allocsa() expects to handle only IPSec protocols and has an
assertion to this effect. However, ipsec4_ctlinput() has to handle
messages from ICMP unreachable packets and was not validating the
protocol number. In practice such a packet would simply fail to match
any SADB entries and would thus be ignored.
Reported by: syzbot+6a9ef6fcfadb9f3877fe@syzkaller.appspotmail.com
Reviewed by: ae
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31890
If we matched SP to a packet, but no associated SA was found
ipsec4_allocsa will return NULL while setting error=0.
This resulted in use after free and potential kernel panic.
Return EINPROGRESS if the case described above instead.
Obtained from: Semihalf
Sponsored by: Stormshield
Differential revision: https://reviews.freebsd.org/D30994
If an encapsulated frame is going to have DF bit set check its desitnitions'
PMTU and if it won't fit drop it and:
Generate ICMP 3/4 message if the packet was to be forwarded.
Return EMSGSIZE error otherwise.
Obtained from: Semihalf
Sponsored by: Stormshield
Differential revision: https://reviews.freebsd.org/D30993
SO_RERROR indicates that receive buffer overflows should be handled as
errors. Historically receive buffer overflows have been ignored and
programs could not tell if they missed messages or messages had been
truncated because of overflows. Since programs historically do not
expect to get receive overflow errors, this behavior is not the
default.
This is really really important for programs that use route(4) to keep
in sync with the system. If we loose a message then we need to reload
the full system state, otherwise the behaviour from that point is
undefined and can lead to chasing bogus bug reports.
Reviewed by: philip (network), kbowling (transport), gbe (manpages)
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D26652
Creation of a zone is expensive and there is no need to have one for
every vnet. Moreover, this wastes memory as these separate zones
cannot use the same per-cpu caches. Finally, this is a step towards
replacing the custom zone with pcpu-16.
Two counter_u64_zero calls induce back-to-back IPIs to zero everything
out. Instead, pass the M_ZERO flag to let uma just iterate all buffers.
The counter(9) API abstraction is already violated by not using
counter_u64_alloc.
Reviewed by: ae
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D30916
Several protocol methods take a sockaddr as input. In some cases the
sockaddr lengths were not being validated, or were validated after some
out-of-bounds accesses could occur. Add requisite checking to various
protocol entry points, and convert some existing checks to assertions
where appropriate.
Reported by: syzkaller+KASAN
Reviewed by: tuexen, melifaro
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D29519
Historically receive buffer overflows have been ignored and programs
could not tell if they missed messages or messages had been truncated
because of overflows. Since programs historically do not expect to get
receive overflow errors, this behavior is not the default.
This is really really important for programs that use route(4) to keep in sync
with the system. If we loose a message then we need to reload the full system
state, otherwise the behaviour from that point is undefined and can lead
to chasing bogus bug reports.
Currently, OpenCrypto consumers can request asynchronous dispatch by
setting a flag in the cryptop. (Currently only IPSec may do this.) I
think this is a bit confusing: we (conditionally) set cryptop flags to
request async dispatch, and then crypto_dispatch() immediately examines
those flags to see if the consumer wants async dispatch. The flag names
are also confusing since they don't specify what "async" applies to:
dispatch or completion.
Add a new KPI, crypto_dispatch_async(), rather than encoding the
requested dispatch type in each cryptop. crypto_dispatch_async() falls
back to crypto_dispatch() if the session's driver provides asynchronous
dispatch. Get rid of CRYPTOP_ASYNC() and CRYPTOP_ASYNC_KEEPORDER().
Similarly, add crypto_dispatch_batch() to request processing of a tailq
of cryptops, rather than encoding the scheduling policy using cryptop
flags. Convert GELI, the only user of this interface (disabled by
default) to use the new interface.
Add CRYPTO_SESS_SYNC(), which can be used by consumers to determine
whether crypto requests will be dispatched synchronously. This is just
a helper macro. Use it instead of looking at cap flags directly.
Fix style in crypto_done(). Also get rid of CRYPTO_RETW_EMPTY() and
just check the relevant queues directly. This could result in some
unnecessary wakeups but I think it's very uncommon to be using more than
one queue per worker in a given workload, so checking all three queues
is a waste of cycles.
Reviewed by: jhb
Sponsored by: Ampere Computing
Submitted by: Klara, Inc.
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D28194
This is similar to the logic used in ip_output() to convert mbufs
prior to computing checksums. Unmapped mbufs can be sent when using
sendfile() over IPsec or using KTLS over IPsec.
Reported by: Sony Arpita Das @ Chelsio QA
Reviewed by: np
Sponsored by: Chelsio
Differential Revision: https://reviews.freebsd.org/D28187
This patch adds 80% of UINT32_MAX limit on sequence number.
When sequence number reaches limit kernel sends SADB_EXPIRE message to
IKE daemon which is responsible to perform rekeying.
Submitted by: Patryk Duda <pdk@semihalf.com>
Reviewed by: ae
Differential revision: https://reviews.freebsd.org/D22370
Obtained from: Semihalf
Sponsored by: Stormshield
Implement support for including IPsec ESN (Extended Sequence Number) to
both encrypt and authenticate mode (eg. AES-CBC and SHA256) and combined
mode (eg. AES-GCM). Both ESP and AH protocols are updated. Additionally
pass relevant information about ESN to crypto layer.
For the ETA mode the ESN is stored in separate crp_esn buffer because
the high-order 32 bits of the sequence number are appended after the
Next Header (RFC 4303).
For the AEAD modes the high-order 32 bits of the sequence number
[e.g. RFC 4106, Chapter 5 AAD Construction] are included as part of
crp_aad (SPI + ESN (32 high order bits) + Seq nr (32 low order bits)).
Submitted by: Grzegorz Jaszczyk <jaz@semihalf.com>
Patryk Duda <pdk@semihalf.com>
Reviewed by: jhb, gnn
Differential revision: https://reviews.freebsd.org/D22369
Obtained from: Semihalf
Sponsored by: Stormshield
As RFC 4304 describes there is anti-replay algorithm responsibility
to provide appropriate value of Extended Sequence Number.
This patch introduces anti-replay algorithm with ESN support based on
RFC 4304, however to avoid performance regressions window implementation
was based on RFC 6479, which was already implemented in FreeBSD.
To keep things clean and improve code readability, implementation of window
is kept in seperate functions.
Submitted by: Grzegorz Jaszczyk <jaz@semihalf.com>
Patryk Duda <pdk@semihalf.com>
Reviewed by: jhb
Differential revision: https://reviews.freebsd.org/D22367
Obtained from: Semihalf
Sponsored by: Stormshield