riscv64: Move pcb out of kstack into a new UMA zone
Similar to arm64, riscv's pcb embeds a copy of the floating point
registers and is too large to store directly in struct mdthread as is
done on amd64. Instead, use a separate UMA zone for pcbs. riscv's
floating point state is not as large as arm64's, so its pcb is also
somewhat smaller and a single 4k page can hold 6 pcbs.
Reviewed by: kib, jrtc27
Sponsored by: AFRL, DARPA
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
sys: Add td_kstack_top inline helper function
This function returns a pointer to the top of the kstack.
Reviewed by: kib, andrew (arm changes)
Sponsored by: AFRL, DARPA
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
arm64: Move pcb out of kstack into a new UMA zone
This is similar to commit 5e921ff49ea8bb70506248a4675894729cdad8c2
which moved the pcb for amd64, but a bit different. arm64's pcb is
much larger (over 1KB!) than amd64's since it still embeds FP
registers. Moving the pcb out of the kstack frees up that much
additional kstack space. Unlike amd64 however, embedding the pcb in
struct mdthread is not practical as the resulting struct thread would
grow such that UMA would now store 1 thread per 4k page instead of 2
threads per page. By using a separate UMA zone for pcbs, 2 struct
threads can continue to fit in a single 4k page, and 3 pcbs can fit in
another 4k page.
Reviewed by: kib, jrtc27, andrew
Sponsored by: AFRL, DARPA
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
cpu_thread_new_kstack: Introduce new MD callback
Previously, the cpu_thread_alloc callback was invoked each time a
kernel stack was allocated for a thread. This included thread
creation, but it was also invoked if a recycled thread had to allocate
a new kstack. This means that cpu_thread_alloc could be called
multiple times for a single thread, but cpu_thread_free is only called
once. Not only that, but the cpu_thread_alloc callback can't tell if
it is being invoked on a new thread object, or a recycled thread.
Calling *_alloc multiple times on an object is also atypical for
kernel APIs.
As a result of this confusion, amd64 was potentially leaking an XSAVE
buffer each time a new kstack was allocated for an existing thread,
since cpu_thread_alloc for amd64 always allocated a new XSAVE buffer.
In practice, this edge case is probably rare. A process object needs
to be recycled where either the new or old process is a kernel process
with a non-default kernel stack size.
[11 lines not shown]
amd64/i386: Remove dead code to clear XSAVE header
If XSAVE is being used, the XSAVE header will be overwritten either by
copying it from the parent thread in copy_thread for user threads, or
by a fresh copy from fpu/npx_initialstate on the first use of the FPU
for kernel threads.
Reviewed by: kib
Sponsored by: AFRL, DARPA
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
amd64: Don't set an initial FPU state save size
This used to be needed to initialize the pcb pointer when the pcb was
allocated on the kstack.
Reviewed by: kib
Sponsored by: AFRL, DARPA
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
arm64: Adjust the kernel stack pointer at the end of fork_trampoline
All other paths that return from the kernel to userspace pop the user
trapframe off of the kernel stack pointer before returning to
userspace in restore_registers. fork_trampoline was missing this, so
all of the user faults after fork pushed another trapframe leaving a
trapframe's worth of wasted space on the kstack.
This would be fatal after a future change to remove duplicate
initialization of td_frame in cpu_fork() as without this fix each time
a thread was recycled it would "lose" another trapframe's worth of
space.
Reviewed by: kib, andrew
Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/23
ipfilter: Fix NULL dereferences in ipf_checkicmp6matchingstate()
Add NULL checks for ic6 (the ICMPv6 header pointer from fin->fin_dp)
and oic (the inner ICMPv6 header from ofin.fin_dp after ipf_makefrip).
These pointers can be NULL when processing malformed ICMPv6 error
packets with extension headers.
Also fix the length validation: the original check (fin->fin_plen <
sizeof(ip6_t)) could never trigger because an earlier check already
ensures fin->fin_plen >= ICMP6ERR_MINPKTLEN (48). Replace with a proper
check that fin->fin_dlen contains at least ICMPERR_ICMPHLEN +
sizeof(ip6_t) bytes to ensure sufficient data exists for both the
ICMPv6 error header and the embedded IPv6 header.
PR: 288333
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit c028080749c09e68c555155df0e9f681ba63c6ae)
ipfilter: Validate length before checksum
Validate the length of the packet listed in the mbuf is the same as
the calculated packet length. If not reject the packet and bump the
bad packet stat.
PR: 295198
Differential Revision: https://reviews.freebsd.org/D57095
(cherry picked from commit 8dfb0805fc31cd78940429ab0560dae7e8ab6536)
ipfilter: Add NULL check for fin_dp in ICMP packet handlers
Add NULL checks for fin->fin_dp in ipf_pr_icmp6() and ipf_pr_icmp()
before dereferencing. When processing packets with IPv6 extension
headers, ipf_pr_pullup() can succeed but fin->fin_dp may still be NULL
due to extension header processing leaving insufficient data for the
protocol header.
PR: 288333
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit 68ed81631afa20c07883f7f60343f6da8397ee41)
ipfilter: Add NULL check for fin_m in ipf_pr_icmp6()
Add NULL check for fin->fin_m before calling M_LEN() in the ICMPv6
error handling code path. When ipf_checkicmp6matchingstate() calls
ipf_makefrip() with a synthesized fr_info_t that has fin_m set to
NULL, the subsequent call to ipf_pr_ipv6hdr() can reach ipf_pr_icmp6()
which would crash when trying to access the mbuf via M_LEN().
PR: 288333
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit cdc40489a7a617b742e295cf9005b3569b45e823)
ipfilter: Fix NULL dereferences in ipf_checkicmp6matchingstate()
Add NULL checks for ic6 (the ICMPv6 header pointer from fin->fin_dp)
and oic (the inner ICMPv6 header from ofin.fin_dp after ipf_makefrip).
These pointers can be NULL when processing malformed ICMPv6 error
packets with extension headers.
Also fix the length validation: the original check (fin->fin_plen <
sizeof(ip6_t)) could never trigger because an earlier check already
ensures fin->fin_plen >= ICMP6ERR_MINPKTLEN (48). Replace with a proper
check that fin->fin_dlen contains at least ICMPERR_ICMPHLEN +
sizeof(ip6_t) bytes to ensure sufficient data exists for both the
ICMPv6 error header and the embedded IPv6 header.
PR: 288333
MFC after: 1 week
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit c028080749c09e68c555155df0e9f681ba63c6ae)
ipfilter: Validate length before checksum
Validate the length of the packet listed in the mbuf is the same as
the calculated packet length. If not reject the packet and bump the
bad packet stat.
PR: 295198
Differential Revision: https://reviews.freebsd.org/D57095
(cherry picked from commit 8dfb0805fc31cd78940429ab0560dae7e8ab6536)
ipfilter: Add NULL check for fin_m in ipf_pr_icmp6()
Add NULL check for fin->fin_m before calling M_LEN() in the ICMPv6
error handling code path. When ipf_checkicmp6matchingstate() calls
ipf_makefrip() with a synthesized fr_info_t that has fin_m set to
NULL, the subsequent call to ipf_pr_ipv6hdr() can reach ipf_pr_icmp6()
which would crash when trying to access the mbuf via M_LEN().
PR: 288333
MFC after: 1 week
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit cdc40489a7a617b742e295cf9005b3569b45e823)
ipfilter: Add NULL check for fin_dp in ICMP packet handlers
Add NULL checks for fin->fin_dp in ipf_pr_icmp6() and ipf_pr_icmp()
before dereferencing. When processing packets with IPv6 extension
headers, ipf_pr_pullup() can succeed but fin->fin_dp may still be NULL
due to extension header processing leaving insufficient data for the
protocol header.
PR: 288333
Pull Request: https://github.com/freebsd/freebsd-src/pull/2214
Signed-off-by: Teddy Engel <engel.teddy at gmail.com>
(cherry picked from commit 68ed81631afa20c07883f7f60343f6da8397ee41)