packet to ensure it is not malformed. Call this function in "points of
interest", that are the IPv4/IPv6/IPsec entry points. There could be more.
We use M_VERIFY_PACKET(m), declared under DIAGNOSTIC only.
This function should not be called everywhere, especially not in places
that temporarily manipulate (and clobber) the mbuf structure; once they're
done they put the mbuf back in a correct format.
we are not guaranteed to have enough room for another struct ip, and we
may crash here. Triggerable remotely, but after authentication, by sending
an AH packet that has a one-byte-sized IPIP payload.
that they don't have a 'length' field. It is therefore incorrect to
read ip6e.ip6e_len, it contains garbage.
I'm not sure whether this an exploitable vulnerability. Because of this
bug you could theoretically craft 'protoff', which means that you can
have the kernel patch the nxt value at the wrong place once the packet
is decrypted. Perhaps it can be used in some unusual MITM - a router that
happens to be between two IPsec hosts adds a frag6 option in the outer
IPv6 header to trigger the bug in the receiver -, but I couldn't come up
with anything worrying.
to prevent use-after-free.
In fact, the m_pullup call is never reached: it is impossible for 'skip'
to be zero in this function, so add an XXX for now.
It seems that PACKET_TAG_IPSEC_IN_CRYPTO_DONE is for network adapters
that have IPsec accelerators; a driver sets the mtag to a packet
when its device has already encrypted the packet.
Unfortunately no driver implements such offload features for long
years and seems unlikely to implement them soon. (Note that neither
FreeBSD nor Linux doesn't have such drivers.) Let's remove related
(unused) codes and simplify the IPsec code.
No functional changes (except for a debug printf).
Note that there remain some __FreeBSD__ for sysctl knobs which counerparts
to NetBSD don't exist. And ipsec_osdep.h isn't touched yet; tidying it up
requires actual code changes.
- Include "opt_*.h" only if _KERNEL_OPT is defined
- Allow encapinit to be called twice (by ifinit and ipe4_attach)
- ifinit didn't call encapinit if IPSEC is enabled (ipe4_attach called
it instead), however, on a rump kernel ipe4_attach may not be called
even if IPSEC is enabled. So we need to allow ifinit to call it anyway
- Setup sysctls in ipsec_attach explicitly instead of using SYSCTL_SETUP
- Call ip6flow_invalidate_all in key_spdadd only if in6_present
- It's possible that a rump kernel loads the ipsec library but not
the inet6 library
Having a pointer of an interface in a mbuf isn't safe if we remove big
kernel locks; an interface object (ifnet) can be destroyed anytime in any
packet processing and accessing such object via a pointer is racy. Instead
we have to get an object from the interface collection (ifindex2ifnet) via
an interface index (if_index) that is stored to a mbuf instead of an
pointer.
The change provides two APIs: m_{get,put}_rcvif_psref that use psref(9)
for sleep-able critical sections and m_{get,put}_rcvif that use
pserialize(9) for other critical sections. The change also adds another
API called m_get_rcvif_NOMPSAFE, that is NOT MP-safe and for transition
moratorium, i.e., it is intended to be used for places where are not
planned to be MP-ified soon.
The change adds some overhead due to psref to performance sensitive paths,
however the overhead is not serious, 2% down at worst.
Proposed on tech-kern and tech-net.
outdated pointers and pass ESP data to UPD-sockets.
While here, simplify the code and remove the IPSEC_NAT_T option; always
compile nat-traversal in so that it does not bitrot.
to upper layers through the IP protosw, as done for IPv6.
Before it was reinjected into the IP netisr queue which caused more
overhead and caused artefacts like double IP option processing.
Works well for me, should get more testing and review.
sys/stdarg.h and expect compiler to provide proper builtins, defaulting
to the GCC interface. lint still has a special fallback.
Reduce abuse of _BSD_VA_LIST_ by defining __va_list by default and
derive va_list as required by standards.
into account that the extension header type is not in the extension
header itself but in the previous one -- this makes a difference
because (a) the length field is different for AH than for all others
and (b) the offset of the "next type" field isn't the same in primary
and extension headers.
(I didn't manage to trigger the bug in my tests, no extension headers
besides AH made it to that point. Didn't try hard enough -- the fix
is still valid.)