| Age | Commit message (Collapse) | Author |
|
Pull late 9p updates from Dominique Martinet:
"This is mostly a huge wave of LLM-driven fixes. At least the LLM fixes
sort of slowed down recently? Or maybe it's just the time of the cycle
and/or I got used to it, time will tell...
A few exceptions:
- a new vsock transport was added, since it's a variant of the
existing fd/tcp transport there is little harm in taking it in
- there's an incomplete fix for when file actual size doesn't match
the size attribute (e.g. exports of sysfs).
The fix addresses when st_size > actual size with cache=none but
just about everything else is still broken (st_size=0 with actual
data regardless of cache, or with data cache st_size > actual is
still wrong and so are symlinks with 0 size)...
Maybe at some point I'll find time to understand how netfs works
and address these :|
- some fixes for the usbg transport by its author, thank you!"
* tag '9p-for-7.4-rc2' of https://github.com/martinetd/linux: (39 commits)
9p: optimize p9_fcall struct
9p: reject RERROR/RLERROR with zero errcode
9p: do not store the create fid on special files
9p: fall back to the normal open path for non-regular files
9p: don't decrement a server-owned zero nlink
9p: fix kernel-doc warning for enum p9_session_flags
9p: treat read return values of 0 as EOF
9p/xen: validate the response size from the backend
9p: fix typo in file header comments
9p: remove duplicated assignment in v9fs_fill_super()
9p: fix typos and wrong parameter docs in vfs_inode.c
9p: fix header guard comment in acl.h
net/9p/usbg: clear stale client pointer on close
net/9p/usbg: remove bogus context initialization in alloc_requests
net/9p/usbg: fix out_req buffer leak in disable_usb9pfs
net/9p/usbg: call disable_usb9pfs() from usb9pfs_disable()
net/9p/usbg: always reset completion when disconnecting
net/9p/usbg: set client to Disconnected on usb9pfs_disable
net/9p/usbg: also disable endpoints on p9_usbg_close
net/9p/usbg: Fix use-after-free in disable_usb9pfs()
...
|
|
Pull bpf fixes from Alexei Starovoitov:
"Fix various bugs in bpf core and bpf-lwt. Looks like the speed of us
fixing bugs is higher than the number of new bugs found. Not out of
the woods yet. sockmap fixes will come later.
- Various fixes (Alexei Starovoitov):
- Use one may_goto time slice per prog invocation instead of one
per stack frame to fix a soft lockup in loops that nest across
calls
- Fix use-after-free in btf__add_type() in libbpf
- Invalidate a dynptr slice when its stack buffer is written or
when the frame of the buffer returns
- Fix the tracking of pointers to the stack in SCEV
- Keep the valid bytes of a packet pointer in SCEV
- Fix bpf_throw() in a prog with a private stack in x86 JIT
- Compare the arguments of an extension prog with those of its
target
- Don't accept memory of the prog for struct arguments of
KF_ACQUIRE kfuncs and for arguments of an empty struct type
- Fix mmap() of an arena: refuse address 0 and a length above
max_entries pages, etc.
- Don't let bpf_skb_adjust_room() raise gso_size to GSO_BY_FRAGS
- Fix lwt progs: reset skb->cb and don't leave a stale MAC header
after a prog pushes an IP header, require BPF_LWT_REROUTE when
an lwt_in prog changes the protocol, don't call into IPv6 when
it is disabled, don't look for the SRH again in the End.BPF
helpers, and set a dst for test runs of lwt_in progs
- Fix bpf_dynptr_copy() for overlapping ranges in one packet
(Ayushman Rout)
- Various fixes (Chris Mason):
- Reject memory of the prog for kfunc projection type arguments
- Require prog fd or capability for cgroup prog detach
- Keep the skb network offset signed in cgroup skb progs
- Reject non-IPv6 packets in BPF_LWT_ENCAP_SEG6
- Limit the SRH length and move the MAC header in
bpf_lwt_seg6_adjust_srh()
- Move the transport header together with the headers that
bpf_skb_adjust_room() and bpf_lwt_seg6_adjust_srh() move, and
use the inner transport header after a decap
- Check the offset in bpf_skb_generic_{push,pop}()
- Mark jmp mode of ftrace direct trampolines on x86 by clearing bit
63 of the address instead of setting bit 0, since an ftrace
callback can start at an odd address (Daniel Borkmann)
- Fix psock update-side data races on sk->sk_prot and progs in
sockmap (Jakub Sitnicki)
- Fix skb_pull() BUG in __bpf_redirect_neigh(): make sure that the
MAC and IP headers are there and are linear (Jamal Hadi Salim)
- Fix jited line info that is off by the CFI preamble on x86-64,
arm64 and riscv64 (Jose Fernandez)
- Clamp the trace length in __bpf_get_stack() to fix a write after
the end of the buffer (Josef Bacik)
- Drop percpu_counter from the htab element count, since its lock can
deadlock with NMI and tracing progs that update the same map
(Puranjay Mohan)
- Propagate scalar precision through stack arguments (Xu Yunxiang)
- Fix callback recursion selftest with llvm24 (Yonghong Song)
- Free the skb when bpf_xmit() fails to expand the headroom (Yuqiang
Sun)"
* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: (61 commits)
libbpf: Fix use-after-free in btf__add_type
selftests/bpf: Exercise stack argument precision on state reuse
bpf: Propagate scalar precision through stack arguments
selftests/bpf: Fix callback recursion test with noipa global func
selftests/bpf: Test one may_goto time slice per prog invocation
bpf: End bpf_loop() when the time of may_goto is up
bpf: One may_goto time slice per prog invocation
bpf: Pass a pointer to arch_bpf_timed_may_goto()
s390/bpf: Support internal-only MOV instruction to resolve per-CPU addrs
selftests/bpf: End the loop of parallel_test_bitmap after 50 ms
selftests/bpf: Give the first loop of cond_break5 an end
selftests/bpf: Don't cast a pointer to .bss in arena_htab_asm
bpf: Emit timed may_goto for JITed progs only
selftests/bpf: Test writes to the buffer of bpf_dynptr_slice_rdwr()
bpf: Invalidate a dynptr slice when its stack buffer is written
selftests/bpf: Test a callee that overwrites a spilled pointer of its caller
bpf: Don't trust pointers spilled in slots that a callee can write
selftests/bpf: Test the join of fp+0 with a value that is not a pointer to stack
bpf: Fix the join of fp+0 with a value that is not a pointer to stack
selftests/bpf: Run arena_mmap serially and test MAP_FIXED addresses
...
|
|
When an LWT xmit program returns BPF_OK, bpf_xmit() makes sure that
the skb still has room for the link layer header. If
pskb_expand_head() fails there, bpf_xmit() returns -ENOMEM without
freeing the skb. Its callers, lwtunnel_xmit() and then
ip_finish_output2() or ip6_finish_output2(), take any return value
other than LWTUNNEL_XMIT_CONTINUE to mean that the skb has been
consumed, so nothing frees it.
Each such failure leaks the skb, together with what it holds: its dst
and its charge to the sending socket, so the socket is never freed
either. The other error paths of bpf_xmit() (BPF_DROP, an illegal
return code, a changed protocol, a failed reroute) all free the skb.
Free it here too.
The leak was found with kbound, a static analysis prototype for
ownership mismatches at kernel interfaces, on v7.2.12; it is present in
mainline.
Build-tested with x86_64 and arm64 allmodconfig (W=1, sparse): no new
warnings. Run-tested on QEMU (x86_64, KVM) with KASAN: a route through a
dummy device with an LWT xmit program that pushes one byte with
bpf_skb_change_head(), so the headroom check has to expand the head, and
failslab limited to allocations under bpf_xmit(). Each of 10 pings then
fails with ENOMEM. Without this patch each leaves a raw socket behind
(RAW slab objects 6 -> 16); with it none does (6 -> 6), and nothing else
is reported. Without injection both kernels go from 6 to 6.
Fixes: 3a0af8fd61f9 ("bpf: BPF for lightweight tunnel infrastructure")
Signed-off-by: Yuqiang Sun <izaiahsun@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101182343.17991-1-izaiahsun@gmail.com
|
|
To make room for len bytes at offset off, bpf_skb_generic_push() moves the
first off bytes and clears len bytes after them. It assumes that the first
off bytes are in the linear part. But in bpf_skb_adjust_room() off can be
the end of the IP header, and this header can be in a frag. Then the
function reads and writes after skb->tail, and can damage skb_shared_info.
bpf_skb_generic_pop() checks off + len, but this u32 sum can wrap to a
small value. bpf_skb_adjust_room() and bpf_skb_change_proto() calculate off
from skb_mac_header_len(). This length is a very large u32 when
network_header < mac_header. Then the check can pass, and memmove() reads
and writes far outside the skb.
Return -ENOMEM from both functions, like the present check, when
off > skb->len. Thus the sum cannot wrap. In bpf_skb_generic_push() also
pull the first off bytes into the linear part. Now bpf_skb_adjust_room()
fails when a prog grows an skb that ends before off. network_header stays
wrong.
Fixes: 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper")
Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-28-alexei.starovoitov@gmail.com
|
|
If skb->encapsulation is set, qdisc_pkt_len_segs_init() reads the TCP
header of a GSO packet at skb->inner_transport_header. Otherwise it uses
skb->transport_header. A decap with BPF_F_ADJ_ROOM_DECAP_L4_{GRE,UDP}
removes the outer transport header. It clears skb->encapsulation if no
tunnel flag remains in gso_type. The result in BPF_ADJ_ROOM_MAC mode is:
before | MAC | outer IP | GRE | inner IP | TCP | payload
transport_header ^ ^ inner_transport_header
after | MAC | inner IP | TCP | payload
transport_header ^ ^ inner_transport_header
Then qdisc_pkt_len_segs_init() reads the inner IP header as a TCP header.
Thus the kernel can drop a valid packet with SKB_DROP_REASON_SKB_BAD_GSO.
Copy skb->inner_transport_header to skb->transport_header when a decap
clears skb->encapsulation. Keep skb->transport_header if it is larger. This
occurs if nothing sets the inner field. At tc ingress nothing changes for
IPIP or GRO packets. Both fields are at the TCP header there.
Fixes: ec20dee2f2c4 ("bpf: Clear decap state on skb_adjust_room shrink path")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-27-alexei.starovoitov@gmail.com
|
|
bpf_skb_net_hdr_pop() removes len bytes at offset off.
bpf_skb_net_hdr_push() does the opposite.
skb->data off
before | A | removed | B |
after | A | B |
skb->data off
mac_header and network_header move with A. transport_header moves only when
it is equal to network_header. inner_transport_header never moves. This is
correct only for a header in B. In bpf_lwt_seg6_adjust_srh()
transport_header is in A. bpf_skb_adjust_room() can remove both transport
headers. With an incorrect header offset, the stack can drop the skb or
read outside of it.
Also move transport_header with A when it is in A. Set it to offset off
when it is in the removed bytes. In BPF_ADJ_ROOM_MAC mode it is then equal
to network_header. Do not unset it, because skb_gso_validate_mac_len() uses
it without a check. After a removal, set inner_transport_header to off when
it is not in B and skb->encapsulation is set. A has only outer headers.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Fixes: 868d523535c2 ("bpf: add bpf_skb_adjust_room encap flags")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-26-alexei.starovoitov@gmail.com
|
|
With ipv6.disable=1, inet6_init() returns before it registers any pernet
subsystem. Thus net->ipv6.devconf_all and net->ipv6.seg6_data stay NULL.
IS_ENABLED(CONFIG_IPV6) only says that the code is built in.
bpf_lwt_input_reroute() and bpf_push_seg6_encap() call into IPv6, but do
not test ipv6_mod_enabled(). An lwt_in prog also runs with ipv6.disable=1,
and skb->protocol == htons(ETH_P_IPV6) does not prove that IPv6 is enabled.
Thus the kernel dereferences NULL and crashes.
Return -EAFNOSUPPORT before these calls if ipv6_mod_enabled() is false.
BPF_LWT_REROUTE then drops an IPv6 skb. With IPv6 enabled nothing changes.
The first Fixes tag is for bpf_push_seg6_encap(), which never had this
test. The second tag is for bpf_lwt_input_reroute(). Until that commit it
used ipv6_stub, which returned -EAFNOSUPPORT with ipv6.disable=1.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Fixes: ad84b1eefe28 ("bpf: remove ipv6_bpf_stub completely and use direct function calls")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-25-alexei.starovoitov@gmail.com
|
|
When an lwt_in prog returns BPF_OK, bpf_input() calls orig_input(), the
input handler of the route. This handler is for one IP version and needs a
dst of the same family. But BPF_LWT_ENCAP_IP lets the prog push a header of
the other IP version and thus change skb->protocol. Then the handler reads
and changes a header of the other IP version. The push of an SRH also
replaces the dst, because seg6_lookup_nexthop() puts an rt6_info into the
skb. Then ip_forward() uses the rt6_info as a struct rtable.
Drop the skb with -EINVAL when skb->protocol changes, as bpf_xmit() does.
Drop it also when the family of the dst changes, because skb->protocol does
not always show this change. Today no such skb leaves as the prog made it.
A prog works as before if it returns BPF_LWT_REROUTE, or if it pushes an
SRH on an IPv6 route.
The commit in the first Fixes tag lets a prog change skb->protocol. The
commit in the second tag adds the check to bpf_xmit() only.
Fixes: 52f278774e79 ("bpf: implement BPF_LWT_ENCAP_IP mode in bpf_lwt_push_encap")
Fixes: 3bd0b15281af ("bpf: add handling of BPF_LWT_REROUTE to lwt_bpf.c")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-24-alexei.starovoitov@gmail.com
|
|
IPCB(skb)->opt holds the offsets from the network header to the IPv4
options. But bpf_lwt_push_ip_encap() moves the network header and does not
change IPCB(skb). Then ip_forward_options() and __ip_options_echo() use the
old offsets on the pushed header. Thus the kernel corrupts the skb and the
stack. If the family changes, the kernel also reads IP6CB(skb) as
IPCB(skb), or the reverse. With CONFIG_IPV6_MIP6, it reads IPSKB_FORWARDED
as frag_max_size and adds a needless fragment header.
Reset skb->cb after the prog. bpf_lwt_push_ip_encap() cannot do it, because
bpf_prog_run_save_cb() can restore skb->cb. For IPv4 in IPv4, clear
IPCB(skb)->opt as ip_tunnel_xmit() does. If the family changes, clear the
cb of the new family but keep iif, because ip6_forward() gets the input
device from it. Behind a VRF, skb->skb_iif is the VRF device and cannot
replace iif. Do nothing for IPv6 in IPv6, as in seg6_do_srh_encap().
Do the reset in bpf_input() only after a push. Without a push,
ip_forward_options() needs the offsets. Do it in bpf_xmit() before each
reroute, because an lwt_xmit prog can also change the options. Thus after a
reroute without a push, ip_options_fragment() leaves the options in all
fragments, and ICMP errors echo none. After BPF_OK or BPF_REDIRECT the skb
goes to a device, thus bpf_xmit() does no reset. The inner IPv4 checksum
can still be wrong after ip_rcv_options() changes an option.
Fixes: 52f278774e79 ("bpf: implement BPF_LWT_ENCAP_IP mode in bpf_lwt_push_encap")
Reported-by: Xiang Mei <xmei5@asu.edu>
Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-23-alexei.starovoitov@gmail.com
|
|
With BPF_LWT_ENCAP_IP, bpf_lwt_push_encap() pushes a new IP header. The new
header overwrites the MAC header of a received skb. But skb->mac_header
continues to point to the same bytes. Code that reads the MAC header after
the push, for example netfilter, gets bytes of the new header.
before the push | MAC header | old IP | payload
^ mac_header ^ network_header
today | new header | old IP | payload
network_header ^ ^ mac_header
this patch, lwt_in | MAC header | new header | old IP | payload
^ mac_header ^ network_header
this patch, lwt_xmit | new header | old IP | payload
network_header ^ mac_header is not set
For lwt_in, move the MAC header in front of the new header before the
memcpy(), as __seg6_do_srh_encap() does. skb_cow_head() already reserves
len + skb->mac_len bytes.
For lwt_xmit, the output path makes a new MAC header. Thus mark
skb->mac_header as not set. This is the state of a locally generated skb.
Fixes: 52f278774e79 ("bpf: implement BPF_LWT_ENCAP_IP mode in bpf_lwt_push_encap")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-22-alexei.starovoitov@gmail.com
|
|
bpf_skb_net_hdr_push() and bpf_skb_net_hdr_pop() change skb->data and
skb->mac_header by len. That is correct in a tc prog, where skb->data is
the MAC header. But bpf_lwt_seg6_adjust_srh() calls them in an End.BPF
prog, where skb->data is the network header. The MAC header does not move:
before push | free | MAC header | IPv6 | SRH | payload
^ head ^ mac_header ^ data
today | free | MAC h| IPv6 | SRH + len | payload
^ head ^ mac_header ^ data
this patch | free | MAC header | IPv6 | SRH + len | payload
^ head ^ mac_header ^ data
Users of skb_mac_header() get incorrect bytes until __dev_queue_xmit() sets
skb->mac_header again. skb_cow_head() reserves only len bytes. Thus the
16-bit offset skb->mac_header can wrap. A push also changes the "not set"
value. In both cases skb_mac_header() points after the skb.
Move the MAC header too. Pass len + skb->mac_len to skb_cow_head(). Keep
the "not set" value. The second Fixes tag is for this case. Since that
commit an End.BPF prog can get an skb with skb->mac_header not set.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Fixes: 20a081b7984c ("seg6: add VRF support for SRv6 End.DT6 behavior")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-21-alexei.starovoitov@gmail.com
|
|
A packet can have two SRHs. Thus input_action_end_bpf() uses
IP6_FH_F_SKIP_RH to skip routing headers with segments_left 0. The helpers
bpf_lwt_seg6_store_bytes() and bpf_lwt_seg6_adjust_srh() can reallocate the
head of the skb. Thus they look for the SRH again, but without this flag.
+------------------------+ <- the helpers: srh_state->srh
| SRH 1, segments_left 0 |
+------------------------+ <- input_action_end_bpf(): srh_state->srh
| SRH 2 | and srh_state->hdrlen
+------------------------+
Then the helpers check offset against the wrong limits. If a helper changes
TLVs, seg6_bpf_has_valid_srh() writes the length of SRH 2 to SRH 1.
Neither helper changes the offset of the SRH from skb->data. Calculate the
new address from this offset. To add IP6_FH_F_SKIP_RH is not sufficient,
because advance_nextseg() can set segments_left of SRH 2 to 0. The helper
bpf_lwt_seg6_action() can change the headers and still looks for the SRH.
Fixes: fbbc5bc2ab8c ("seg6: ignore routing header with segments left equal to 0")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-20-alexei.starovoitov@gmail.com
|
|
bpf_lwt_seg6_adjust_srh() lets an End.BPF prog change the size of the TLVs
in the SRH. The helper keeps the SRH length in srh_state->hdrlen, in bytes
and without the first 8 bytes. Later seg6_bpf_has_valid_srh() writes it to
srh->hdrlen, an 8-bit field in units of 8 bytes. But srh_state->hdrlen has
no upper limit, and the cast to u8 can truncate it. After that,
seg6_validate_srh() gets the SRH length from srh->hdrlen, and thus it can
accept the SRH. Then srh->hdrlen is too small, and a parser reads TLVs as
the subsequent header.
Return -EFAULT when the new srh_state->hdrlen is larger than 2040, the
largest length that srh->hdrlen can hold. To replace a TLV in the largest
SRH, a prog can no longer add bytes first. It must remove bytes first.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-19-alexei.starovoitov@gmail.com
|
|
When an lwt prog runs on a route, the skb always has a dst. To push an SRH,
bpf_lwt_push_encap() reads the device from this dst. But
bpf_prog_test_run_skb() sets a dst for lwt_xmit progs only. Thus the helper
dereferences a NULL dst in a test run of an lwt_in prog.
Set the same dst, ip6_null_entry, for lwt_in progs. When IPv6 is disabled
or not built, their test run now fails with -EOPNOTSUPP too. An lwt_out
prog cannot call this helper.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-18-alexei.starovoitov@gmail.com
|
|
The mode BPF_LWT_ENCAP_SEG6 of bpf_lwt_push_encap() pushes an IPv6 header
and an SRH, and it replaces the dst. The SRH says that IPv6 follows, and
skb->protocol does not change. Thus the mode assumes an IPv6 packet, but an
lwt_in prog also runs for IPv4 packets. After the prog, bpf_input() calls
orig_input() of the old dst. This IPv4 handler reads the pushed headers as
IPv4. It can write after the packet data, and the kernel crashes.
after the push orig_input() expects
--------------------- --------------------
skb->protocol ETH_P_IP ETH_P_IP
dst rt6_info rtable
packet | IPv6 | SRH | IPv4 | | IPv4 |
The mode BPF_LWT_ENCAP_SEG6_INLINE returns -EBADMSG for non-IPv6 packets.
Apply this check to both modes. End.BPF does not change, because
seg6_local_input() drops non-IPv6 packets.
Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-17-alexei.starovoitov@gmail.com
|
|
When bpf_skb_adjust_room() shrinks a TCP GSO skb, it adds the number of
removed bytes to gso_size. gso_size has 16 bits, and nothing checks the
sum. Thus gso_size can wrap to 0 or to a small size, or it can be
GSO_BY_FRAGS. GSO_BY_FRAGS is not a size. It tells skb_segment() to read
the length of each segment from the frag_list. If the TCP GSO skb has no
frag_list, skb_segment() dereferences a NULL pointer.
Return -ENOTSUPP and do not change the skb if the sum is GSO_BY_FRAGS or
larger. With BPF_F_ADJ_ROOM_FIXED_GSO the helper does not change gso_size,
so it shrinks the skb as before.
Fixes: 2be7e212d541 ("bpf: add bpf_skb_adjust_room helper")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-16-alexei.starovoitov@gmail.com
|
|
The update side of the sockmap psock lifecycle has several unsynchronized
accesses to sk->sk_prot and psock prog state that KCSAN flags when the
new update-vs-delete race selftest runs. The fix comes from Alexei [1]:
* sock_map_link() installed psock programs and called sock_map_init_proto()
before taking sk->sk_callback_lock, racing a concurrent teardown's
tcp_bpf_update_proto() write of sk->sk_prot. Take the write_lock early,
before psock_set_prog() and sock_map_init_proto(), and drop the
psock->saved_data_ready gating from prog detection (it is re-checked
under the lock before stopping progs).
* sock_map_del_link() read psock->saved_data_ready outside the lock. Move
the saved_data_ready check under write_lock_bh(&sk->sk_callback_lock)
so prog teardown is serialized against the proto restore.
* sock_map_psock_get_checked() and sock_map_sk_is_suitable() did plain
sk->sk_prot reads. Convert to READ_ONCE() to mark the intentional racy
read against the WRITE_ONCE() swap in sock_replace_proto().
With these changes the sock_map_link/psock_set_prog side of the reported
KCSAN splats is silenced; the remaining teardown-vs-core-TCP pairings
are the separate read-side annotation problem.
[1] https://lore.kernel.org/bpf/DMBHB0TQOV1L.38MECMYFGUS5B@gmail.com
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261030-bpf-next-v1-2-035eabf8eae7@cloudflare.com
|
|
The issue:
This is a follow-up to the short link-layer header fixes from Eric.
After vlan pop_eth, a privileged SCHED_ACT BPF program can call
bpf_skb_change_head(skb, 1, 0) and then bpf_redirect_neigh().
__bpf_redirect_neigh() calls skb_pull(skb, sizeof(*ethh)) after checking
only that mac_header < network_header. Nothing verifies that the MAC
header is long enough, that it is linear, or that the IP header the
redirect goes on to read is linear either.
A SCHED_ACT BPF program can do:
bpf_skb_change_head(skb, 1, 0);
bpf_redirect_neigh(lo, NULL, 0, 0);
after vlan pop_eth. The skb then has mac_len == 1 and only one byte of
linear data; skb_pull(ETH_HLEN) trips the skb->len < skb->data_len BUG in
__skb_pull():
kernel BUG at ./include/linux/skbuff.h:2839!
RIP: skb_pull+0x40/0x50
Call Trace: skb_do_redirect -> packet_xmit -> packet_sendmsg
Kernel panic - not syncing: Fatal exception in interrupt
The v4 and v6 paths read ip_hdr() and ipv6_hdr() as soon as the MAC
header is gone. On the AF_PACKET frame below that leaves headlen == 0
after the pull, so the network header sits at skb->tail and the route
lookup reads ip4h->protocol, ip4h->saddr and ip4h->daddr past the linear
area.
The Fix:
Use skb_network_offset(), which is the MAC header span, instead of
skb->mac_len. mac_len is zero for locally generated tc egress and netkit
packets, while the span still rejects the one-byte header produced by
pop_eth + bpf_skb_change_head(skb, 1, 0). The single check also covers
the mac_header >= network_header test it replaces.
Use pskb_may_pull() to make the Ethernet header linear before it is read
or pulled, and to make the IP header linear in both the v4 and the v6
path before ip_hdr()/ipv6_hdr() is read. The header pointers are taken
after the pull, since pskb_may_pull() may reallocate skb->head.
Conditions to recreate the bug:
On x86-64 with 4 KiB pages, enable CONFIG_PACKET, CONFIG_BPF_SYSCALL,
CONFIG_NET_SCH_INGRESS, CONFIG_NET_CLS_MATCHALL, CONFIG_NET_ACT_VLAN and
CONFIG_NET_ACT_BPF. Run as root with BPF loading, network administration
and raw-packet privileges. Bring lo up and attach a SCHED_ACT program
that calls bpf_skb_change_head(skb, 1, 0), then returns
bpf_redirect_neigh(skb->ifindex, NULL, 0, 0):
ip link set lo up
tc qdisc add dev lo clsact
tc filter add dev lo egress matchall action vlan pop_eth pipe \
action bpf object-file neigh_chghead.o section action
Send an untagged ETH_P_IP frame of ETH_HLEN + 8192 bytes through an
AF_PACKET/SOCK_RAW socket bound to lo, without PACKET_VNET_HDR or
PACKET_QDISC_BYPASS. Use a unicast destination MAC. The sender's skb
has a 14-byte linear Ethernet prefix and a fragmented payload; pop_eth
removes that prefix and change_head restores only one linear byte.
The unfixed neighbor redirect then tries to pull 14 bytes and BUGs.
Sending the same frame without pop_eth and change_head leaves the IP
header in the frags, which is the route lookup reading past skb->tail.
Fixes: b4ab31414970 ("bpf: Add redirect_neigh helper as redirect drop-in")
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/netdev/20261027082604.1485903-1-edumazet@kernel.org/
Link: https://lore.kernel.org/all/2a0f5ff1d8db81b07fc4b344b8e68e3505fcbf36f72a471d1678b2f1cecd881b@mail.kernel.org/
Link: https://lore.kernel.org/netdev/DMII4JGTEUEG.2WRJPT6ODT6J0@gmail.com/
Link: https://patch.msgid.link/bpf_redirect_neigh_short_linear.v3.r0.20261031153053-1@mojatatu.com
|
|
Two fixes for the same Write chunk payload corruption meet in
linux-next. In the nfs tree, commit a0db57fee35e ("xprtrdma: Fix Write
chunk payload corruption on a short reply header") trims
head[0].iov_len in rpcrdma_decode_msg(). In the nfs-anna tree,
commit 9ee534a75912 ("xprtrdma: trim head iovec when the payload
arrives via a Write chunk") trims it in rpcrdma_inline_fixup() and
reduces buflen by the same amount.
The merge resolution keeps the caller-side trim. By the time
rpcrdma_inline_fixup() runs, head[0].iov_len already equals copy_len,
so the block added by the nfs-anna commit never runs and its buflen
reduction in rq_rcv_buf and rq_private_buf is lost. The helper is also
still passed xdr_pad_size(writelist), while its kernel-doc now
describes @writelist as the number of bytes conveyed by the Write
chunk.
Drop the caller-side trim and pass the full Write chunk length, so
that rpcrdma_inline_fixup() is the only place that trims head[0] and
reduces buflen. Compute the pad with xdr_pad_size() in the helper, so
the padding from the nfs commit stays correct for lengths that are not
a multiple of four. Its rpclen calculation and empty reply check stay
in rpcrdma_decode_msg().
Fixes: 53ab189bdc14 ("Merge branch 'linux-next' of git://git.linux-nfs.org/projects/anna/linux-nfs.git")
Link: https://lore.kernel.org/all/as4aacUf2Q78FMvY@sirena.org.uk/
Signed-off-by: Sasha Levin <sashal@kernel.org>
Tested-by: Tim Menninger <tmenninger@everpuredata.com>
Reviewed-by: Tim Menninger <tmenninger@everpuredata.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Pull ceph updates from Ilya Dryomov:
"The two things of note here are the disablement of inline data support
and a new lazyio mount option to enable LAZYIO behavior globally
(instead of via an ioctl on a per-file basis), both from Xiubo.
Despite being over a decade old, the inline data feature never lost
its experimental status -- it has always been off by default and
required passing --yes-i-really-mean-it flag to be turned on. It was
officially deprecated in 2020 and is now in the process of being
removed on the MDS side. For now it's still possible to re-enable it
in Kconfig, but the code will eventually be dropped from the kernel
client entirely.
Outside of that we have a number of bug fixes, a series from Tal to
help phase out older page APIs, some cleanups from Max and a large
pile of LLM-based hardening patches.
Xiubo is also back in a maintainer role, replacing Slava"
* tag 'ceph-for-7.4-rc1' of https://github.com/ceph/ceph-client: (66 commits)
ceph: fix uninitialized err in ceph_netfs_issue_read()
MAINTAINERS: update ceph and libceph maintainers
ceph: validate encoded xattr name lengths
ceph: validate MDS reply fragtree split array length
ceph: bound name skips in ceph_mdsmap_decode() by the message end
ceph: validate fscrypt auth blob length
ceph: check the caps of a closed file after caps_wanted_delay_min
ceph: don't fail write_begin with -EAGAIN after flushing old snapc
ceph: fail readdir when the MDS reply carries no dirfrag
ceph: clamp MDS reply result code to the errno range
libceph: initialize CRUSH choose argument weights
libceph: fix out-of-bounds reads from repeated CRUSH bucket entries
ceph: fix 32-bit overflow in readdir reply count check
libceph: reject bad connect_seq in msgr1 READY reply
ceph: Fix mds session leak in __open_export_target_session()
ceph: Fix xattr buffer leak in __send_cap()
ceph: fix integer overflow in the snap trace bounds check
libceph: bound mon_command ack decode to front len
ceph: use alloc_page() in fill_fscrypt_truncate()
libceph: use alloc_page() in ceph_alloc_page_vector()
...
|
|
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner:
- writeback:
- Update dirtied_when instead of dirtied_time_when when a wb switch
puts an inode at the newest end of the target b_dirty list. The
list was left out of order so move_expired_inodes() could stop
before older inodes, and the lazytime expiration timestamp was
reset
- Clear the old wb's dirty-I/O state and bandwidth contribution when
a batch of inode switches leaves its dirty lists empty. An empty
wb stayed scheduled for periodic writeback and inflated
bdi->tot_write_bandwidth
- Take wb_switch_rwsem across the inode scan of
cleanup_offline_cgwb(). The v7.3-rc5 fix that rotates scanned
inodes let a scan racing a sync()'s queue_io() move lazytime
inodes past the sync's cutoff, so sync() returned without
persisting their timestamps
- Don't kick writeback for an IOCB_DONTCACHE write on an inode that
has no wb yet. With cgroup writeback an O_DIRECT RWF_DONTCACHE
write to a block device dereferenced NULL
- statmount/listmount/listns:
- Refuse statmount() string requests with a buffer that isn't larger
than struct statmount
- Don't wrap around with a U64_MAX cursor in listmount() and
listns()
- Don't end listns() at an inactive namespace
- Only add init_ipc_ns and init_net to the namespace trees if
CONFIG_IPC_NS and CONFIG_NET_NS are enabled
- iomap:
- Only mark blocks uptodate in __iomap_write_begin() after reading
them and let __iomap_write_end() mark the zeroed blocks uptodate
once the copy from userspace succeeded
- Check a chunk against max_integrity_io_size() on its own before
the bio size check
- Only enforce block alignment for direct I/O into holes and
unwritten extents if IOMAP_DIO_FSBLOCK_ALIGNED is set
- backing-file:
- Check S_APPEND and S_IMMUTABLE on the backing inode. FUSE
passthrough opens the backing file with vfs_open() which skips
may_open(), so anyone who may open the FUSE file for writing could
overwrite an append-only backing file anywhere or write to an
immutable one. Open, mmap and writes now check the backing inode
the way may_open() and do_mmap() do
- Always call kiocb_end_write() for a queued write
- Let backing files inherit FMODE_NONOTIFY from the user file. The
event fds fanotify creates for permission events on a stacked
filesystem raised FS_OPEN_PERM on the real path from inside the
listener's read() and deadlocked listeners with marks on both
layers
- pidfs:
- Look the task up before checking for exit information in
PIDFD_GET_INFO and start over if the task no longer owns the pid
once all fields have been read. A caller racing release_task() got
neither PIDFD_INFO_PID nor PIDFD_INFO_EXIT or ESRCH although the
exit information was available, and a caller racing a sub-thread's
exec reported that thread's tid as the pid
- Clear the mask bits of fields that lie beyond the struct size the
caller passed. The uapi header promises that the mask names no
such field but a caller passing PIDFD_INFO_SIZE_VER0 got the
coredump and supported mask bits set for fields that were never
written
- aio:
- Give the aio ring a ->read_folio that fails with EIO so a fault on
a ring whose file was truncated gets SIGBUS instead of jumping to
NULL
- Check nr_events against the ring size before doubling it in
ioctx_alloc()
- splice:
- Only write back an implicit file position in do_splice() when the
splice helper succeeded. splice doesn't take f_pos_lock so a
failed splice restored a stale snapshot over a position that a
concurrent getdents() had moved. On ext2 the next readdir then
trusted an offset inside a directory entry
- Retry tee() when the input pipe was emptied or the output pipe
filled between the prep steps and link_pipe() instead of returning
0 while the input pipe still has writers, as splice_pipe_to_pipe()
does
- ucount:
- Take the reference that pins a ucounts level on the 0 -> 1
transition before checking the rlimit
- Read the parent ucounts before dropping the rlimit count in
do_dec_rlimit_put_ucounts()
- inode:
- Rotate inodes whose page cache couldn't be dropped to the tail of
the LRU
- Skip inodes that another LRU walker is isolating
- setns:
- Set nsset->flags before anything in prepare_nsset() can fail so
the error path drops the cred prepared for CLONE_NEWUSER. A
failing setns() with CLONE_NEWUSER and CLONE_NEWNS leaked it
together with its user namespace
- Refuse setns(CLONE_NEWNS) for a task that shares its fs_struct
again when more namespaces are requested
- minix:
- Restore uptodate on the pinned bitmap buffers before redirtying
them after a failed writeback instead of tripping the warning in
mark_buffer_dirty(), as ext2 and ext4 do for their superblock
buffers
- Reject rmdir() of a directory with a corrupted link count with
EFSCORRUPTED instead of hitting the drop_nlink() warning
- userns: Keep the exec securebits and their locks when creating or
joining a user namespace. set_cred_user_ns() reset all securebits to
SECUREBITS_DEFAULT so anyone who may create a user namespace could
shed SECBIT_EXEC_RESTRICT_FILE and SECBIT_EXEC_DENY_INTERACTIVE with
a single unshare(CLONE_NEWUSER)
- fs: Honor FOP_UNSIGNED_OFFSET in sys_llseek() and in the pread64(),
pwrite64(), preadv() and pwritev() wrappers
- proc/kcore: Advance the vmalloc retry in read_kcore_iter() by the
last vread_iter() copy instead of the running total
- eventpoll: Return the error when the wakeup source for EPOLLWAKEUP
can't be created in EPOLL_CTL_MOD instead of reporting success
without suspend protection
- coredump: Mark do_coredump() noinline_for_stack
- nsfs: Check the trailing bytes of a namespace file handle in bytes
instead of words
- netfs: Restore the per-level and per-point decoding of the debug mask
- exportfs: Release the directory file get_name() opened with
__fput_sync(). From nfsd's kernel threads the deferred fputs arrived
faster than delayed_fput retired them and each pinned the directory's
readdir state, growing unreclaimable slab by about 90 MB per second
under a parallel tree walk
- fs: Call ramfs_kill_sb() for a ramfs rootfs. Since rootfs can be
unmounted as of v7.0 its struct ramfs_fs_info was leaked
- signal: Check the blocked mask for every entry
dequeue_synchronous_signal() looks at. The scan could select a
blocked synchronous signal and deliver it while blocked
- super: Convert the superblock device table from an rhltable to a
plain hashtable under a spinlock. This fixes a bug from v7.3 where
fs_bdev_freeze() froze a btrfs filesystem through a stale member that
open_ctree() had already released while the freeze was waiting for
SB_BORN
- fork: Leave rcu_users at zero until copy_process() can't fail
anymore. bpf_task_acquire() handed out trusted references to the new
task from the task_alloc LSM hook and sched_ext's ops.init_task() and
a failing fork freed the task behind them
- xattr: Always run cap_convert_nscap() for a security.capability
write. A zero-length setxattr() skipped it and let an unprivileged
caller without CAP_SETFCAP or write permission on the file plant an
empty security.capability xattr that made every execve() of the
binary fail with EINVAL
- namei: Skip the S_ISDIR assertion in
- proc: Refuse to mount on entries below /proc/<pid>/net like fd/,
fdinfo/ and map_files/. proc_net_d_revalidate() always fails so the
first lookup by anyone with search permission ran d_invalidate() on
the dentry and detached every mount on it, locked mounts included
- libfs: Hold one mount reference for all pins instead of one per pin.
The pin count is what keeps the mount alive, so the per-pin reference
only cost a mntget() and a mntput() through
mntput_no_expire_slowpath() for every debugfs, tracefs, securityfs or
configfs file that comes and goes
- iov_iter: Return 0 from iov_iter_alignment() for an empty iterator of
any type
- watch_queue: Give info_id its own storage instead of overlaying it
with rcu_head
- filelock: Take an active superblock reference while waiting for a
delegation break. After a lazy umount closing the delegation holder
could shut down the superblock under the waiter whose final iput()
then ran shmem_evict_inode() on freed state
- fs: Skip the copy_file_range() write limit checks when there is no
data to copy
- bpf: Allow bpf_d_path() from fentry on filp_close_sync(). Since
close_range() became synchronous this cycle close(), close_range()
and the closes on exec and exit no longer go through filp_close().
fexit stays rejected since the file may be gone by then
- fs_pin: Dequeue the wait entry unconditionally in pin_kill(). A
spuriously woken waiter kept its on-stack entry queued, took that as
proof that the pin was alive and used the freed acct structure when
umount() of the accounting file raced acct(2)
- dcache: Don't fail __d_obtain_alias() for an inode without links and
aliases. The ESTALE check added this cycle broke open_by_handle_at()
and nfsd file handle decoding on NFS and FUSE where i_nlink is just
what the server last reported and the handle may well still be valid
- selftests/ovl: Fix the mountinfo expectations of the detached layer
test which has failed since it was added
* tag 'vfs-7.4-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (60 commits)
fs: don't fail __d_obtain_alias() for unlinked inodes
ns: don't add init_ipc_ns and init_net without namespace support
aio: avoid request count overflow in ioctx_alloc()
selftests/ovl: fix detached layer mountinfo expectations
bpf: Allow bpf_d_path() from filp_close_sync()
fs: skip copy_file_range write limits when there is no data
minix: reject rmdir of a directory with a corrupted link count
fs_pin: do not trust the pin after a spurious wakeup in pin_kill()
ucount: read the parent ucounts before dropping the rlimit count
splice: retry tee() instead of returning 0 when it races
selftests/pidfd: test that fields beyond the struct size are not reported
pidfs: do not report fields that do not fit into the caller's struct
fs: let backing files inherit FMODE_NONOTIFY from the user file
splice: avoid stale f_pos writeback on error
backing-file: always end a queued write
filelock: keep superblock active through delegation wait
watch_queue: keep info_id separate from rcu_head
iomap: only follow dio alignment requirement if specified
iov_iter: fix NULL deref in iov_iter_alignment()
backing-file: enforce append-only and immutable backing inodes
...
|
|
When CONFIG_IPC_NS or CONFIG_NET_NS are turned off we still add the
initial ipc and network namespace to the namespace trees. ipc_ns_init()
calls ns_tree_add(&init_ipc_ns) whenever CONFIG_SYSVIPC is set and
setup_net() calls ns_tree_add_raw() on init_net whenever CONFIG_NET is
set.
But without CONFIG_IPC_NS and CONFIG_NET_NS these aren't namespaces
userspace can do anything with. They don't have proc_ns_operations so
there's no /proc/<pid>/ns/{ipc,net} for them, nsfs_fh_to_dentry()
refuses them with -EOPNOTSUPP, and since ns->ops is NULL
__ns_tree_add_raw() doesn't add them to the owner list of init_user_ns
either. So they end up half registered. That's also not how we treat
any of the other namespace types. Without CONFIG_UTS_NS, CONFIG_PID_NS,
CONFIG_TIME_NS or CONFIG_USER_NS the initial namespace is never added
to the tree.
listns() walks the unified tree and calls is_current_namespace() for
every namespace it finds via may_list_ns(). But is_current_namespace()
only knows about CLONE_NEWIPC and CLONE_NEWNET if CONFIG_IPC_NS and
CONFIG_NET_NS are set. Otherwise we end up in the default case and its
VFS_WARN_ON_ONCE(). Any unprivileged caller can trigger that with a
plain listns() call:
WARNING: CPU: 0 PID: 526 at fs/nsfs.c:508 is_current_namespace+0x12f/0x440
Call Trace:
legitimize_ns+0x25f/0x4c0
do_listns+0x185/0x5c0
__do_sys_listns+0x13b/0x300
Instead of teaching is_current_namespace() about namespaces that can't
be opened, only add the initial namespaces to the tree if their
namespace type is enabled. Move the registration of init_ipc_ns into
ipc/namespace.c which is only built with CONFIG_IPC_NS. That also fixes
CONFIG_SYSVIPC=n, CONFIG_POSIX_MQUEUE=y, CONFIG_IPC_NS=y where
ipc/shm.c isn't built and init_ipc_ns was never added at all. For the
network namespace only call ns_tree_add_raw() if CONFIG_NET_NS is set.
Without CONFIG_NET_NS cleanup_net() isn't built and init_net is never
removed so there's nothing to balance.
Fixes: 74b24a582e1f ("ipc: support ns lookup")
Fixes: 195f7422298d ("net: support ns lookup")
Reported-by: kernel test robot <yi1.lai@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202610260917.6248e316-lkp@intel.com
Cc: stable@vger.kernel.org # v6.18+
Link: https://patch.msgid.link/20261030-work-nsfs-init_ns_tree-v1-1-7ec0adb47c54@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
|
|
git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Jakub Kicinski:
"Current release - new code bugs:
- mctp: usblib: fix assertion breaking esoteric builds
Previous releases - regressions:
- Revert advertising the TCP MSS from the configured MTU
- netlink: check sk_rcvbuf before charging the dump skb
- eth:
- ti: am65-cpts: fix support for PTP_EXTTS_REQUEST2 ioctl
- mlx4: always create the eth and ib auxiliary devices
- tg3: invert restart quirk logic to restrict SNP power-down bypass
- bnxt: recycle agg buffers when Rx head buffer allocation fails
Previous releases - always broken:
- net: fix frag_list leak in skb_segment_list() error path
- sctp: reject forged cookie peer_addr with unknown address family
- vxlan: keep reserved_bits across changelink
- net: limit priority VLAN untag depth
- inet: frags: prevent acceptance of partially authenticated reassembly
- gro: do not GRO GSO packets with inconsistent payload
- tcp: avoid double destroy in tcp_abort() of an unaccepted child"
* tag 'net-7.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (137 commits)
tun: drop batched packets while the device is down
selftests: net: netlink-dumps: start a dump with a notification queued
netlink: check sk_rcvbuf before charging the dump skb
net/sched: act_ife: do not consume the inner header on egress
openvswitch: use eth_type_trans_careful() in internal_dev_recv()
net: use eth_type_trans_careful() in __dev_forward_skb2()
loopback: use eth_type_trans_careful()
net: add eth_type_trans_careful()
tcp: initialize mapped children before route lookup
tcp: fix reordering addition overflow in MTU probing
tcp: avoid double destroy in tcp_abort() of an unaccepted child
net: bgmac: fix TX DMA unmapping and slot cleanup
gro: do not GRO GSO packets with inconsistent payload
net/packet: check TX_RING fragments before memory accounting
eth: bnxt: hand XDP frags over to the copybreak skb
eth: bnxt: free XDP frags when xdp_do_redirect() fails
eth: bnxt: don't leak buffers when XDP agg buffer allocation fails
eth: bnxt: resize Rx head buffers when rx-copybreak changes
eth: bnxt: recycle agg buffers when Rx head buffer allocation fails
netdev-genl: ignore NETDEV_UNREGISTER rebroadcasts
...
|
|
Pull bpf fixes from Alexei Starovoitov:
- Remove BPF_F_ARENA_SCALAR flag and .arena.data section in libbpf that
were added for rust-bpf in this merge window. We found a cleaner
approach that does it on compiler side instead of kernel/libbpf. No
released kernel has them (Alexei Starovoitov)
- Fix bpf_send_signal_task() returning -EPERM when it is called from a
kernel thread (Aditya Sharma)
- Various fixes (Alexei Starovoitov):
- Use emit_rsb_call() to call bpf_unwind_target() in x86 JIT to fix
objtool warning during the build
- Fix scalar evolution: clear delta of a widened register, don't
widen a pointer to a buffer, don't clamp a register whose type
changed in the loop, and reset the range of a clamped packet
pointer
- Finish the insn in the state that maybe_fork_scalars() splits
off, so that pruning doesn't drop it at the head of a counted
loop
- Preserve the registers that carry stack arguments across
arch_bpf_timed_may_goto() on x86-64, arm64 and riscv64
- Don't re-sort subprog_info[] for every new subprogram
- Fix flaky map_kptr and rcu_reentry selftests
- Use memmove() in bpf_skb_load_bytes(), bpf_skb_load_bytes_relative()
and bpf_xdp_load_bytes(), since the destination can be a slice of the
same packet (Ayushman Rout)
- Fixes and follow-ups for scalar evolution: reject pointer operands in
32-bit recurrences and latches, don't intersect with the current
register range on clamp to avoid a false 'verifier bug', avoid false
infinite loop reports, and recognize a 32-bit copy of the induction
variable (Eduard Zingerman)
- Fix out-of-bounds write to btf->types[] for split BTF and propagate
btf_add_type() errors in btf_check_all_metas() (Feng Yang)
- Fix use-after-free in bpf_timer callback that fires after its inner
map was freed (Mani Tofigh)
- Fix x86 JIT stopping before jumps converge: size backward jumps by
the insns they jump over (Mykyta Yatsenko)
- Fix use-after-free of struct_ops trampoline: dissociate struct_ops
progs before the grace period of the map (Qiliang Yuan)
- Validate stack argument reads against the caller state to fix
out-of-bounds read in the verifier, and reject callbacks with stack
arguments (Weiming Shi)
- Tie borrowed iterator results and pointers loaded from trusted fields
to the lifetime of their source, so that iterator next, destroy and
reference release invalidate them (Xu Yunxiang)
* tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: (48 commits)
bpf: Don't re-sort subprog_info[] for every new subprogram
bpf: Fix out-of-bounds btf->types write for split BTF
selftests/bpf: Test stack arguments across may_goto
bpf: Keep stack arguments in arch_bpf_timed_may_goto()
selftests/bpf: Test maybe_fork_scalars() at the head of a counted loop
bpf: Finish the insn in the state that maybe_fork_scalars() splits off
selftests/bpf: Test the clamp of pointers in scalar evolution
bpf: Reset the range of a packet pointer that scalar evolution clamps
bpf: Don't clamp a register whose type changed in the loop
selftests/bpf: Test a loop that moves a pointer to a buffer
bpf: Don't widen a pointer to a buffer in scalar evolution
selftests/bpf: Avoid a page fault in rcu_reentry while the handler is armed
selftests/bpf: Wait for the last maps of map_kptr to be freed
selftests/bpf: Test that a widened register is not linked
bpf: Clear delta of a register that scalar evolution widens
bpf, x86: Remove r0_on_stack from fetching atomics in arena
bpf: Remove BPF_F_ARENA_SCALAR
selftests/bpf: Remove tests for arena access through numbers
libbpf: Keep format strings of bpf_printk() in .rodata
libbpf: Remove .arena.data
...
|
|
Since commit ae8f160e7eb2 ("netlink: Fix wraparounds of
sk->sk_rmem_alloc."), netlink_dump() charges the dump skb first and
queues it only if sk_rmem_alloc is still below sk_rcvbuf. Commit
a215b5723922 ("netlink: make sure we allow at least one dump skb")
added an exception for an empty socket.
A dump that starts while something else is still charged to a socket
with a small receive buffer fails with ENOBUFS and stays running.
Every recvmsg() retries it, fails again and sets sk_err, so a reader
that peeks before reading, as libnl does, gets ENOBUFS on the read
after each peek, never consumes the message at the head of the queue
and spins forever.
I hit this with "iw dev wlan0 scan" hanging at 100% CPU on an arm64
board with a 6.6 based kernel (iw 5.19 sets SO_RCVBUF to 8KiB). A
kprobe trace showed the scan dump starting while the NEW_SCAN_RESULTS
notification iw had just read was still charged to its socket,
because iw had preempted the sender before netlink_broadcast()
returned.
Check the limit before charging, as before ae8f160e7eb2, which also
covers the empty socket. netlink_recvmsg() continues a dump only at
or below half of sk_rcvbuf, so the skb is then always queued, and a
dump goes over the limit by at most one skb. Refuse a skb that would
take sk_rmem_alloc past INT_MAX, so the wraparound stays fixed.
Reproduced on net in a KVM guest with a userspace reproducer and the
selftest in the next patch; both pass with this fix.
Fixes: ae8f160e7eb2 ("netlink: Fix wraparounds of sk->sk_rmem_alloc.")
Signed-off-by: Jhonata Poma-Hansen <jhonata.poma@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Link: https://patch.msgid.link/20261027-netlink-dump-livelock-v2-1-c4bb05352a33@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
The issue:
tcf_ife_decode() unconditionally calls eth_type_trans(), which pulls
ETH_HLEN. On egress this consumes the inner Ethernet header, and the
device receives an skb whose data points to the L3 header:
- loopback_xmit() parses L3 data as Ethernet: the "ethertype" comes
from the inner IPv4 source address, and the decapsulated packet is
dropped or misparsed.
- a real NIC transmits the frame without its Ethernet header.
(The __skb_pull() BUG this used to trigger in loopback_xmit() when the
remaining linear area was short is handled by "loopback: use
eth_type_trans_careful()".)
The Fix:
Parse the inner Ethernet header with eth_type_trans() in both directions,
then restore the egress data position and MAC length. On ingress the
existing behavior is unchanged. On egress, push the inner Ethernet header
back after parsing so the xmit path sees the original frame and later
actions see a consistent network header.
Conditions to recreate the bug:
- egress tc filter on lo: action ife decode pipe;
- AF_PACKET SOCK_RAW frame: outer Ethernet with ETH_P_IFE, IFE metadata,
inner Ethernet + a valid IPv4 ICMP echo request to a local address;
- before this patch, no echo is received; after it, the echo is
delivered and answered.
Fixes: ef6980b6becb ("introduce IFE action")
Cc: stable@vger.kernel.org
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
[edumazet: reworded changelog, the crash is now handled in loopback]
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261028122703.2093730-6-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
OVS actions like pop_eth followed by pop_mpls(ETH_P_TEB) or pop_nsh
can expose an inner Ethernet header which is not in the linear part
of the skb. Output to an internal port then crashes in eth_type_trans():
flow: in_port(0),eth(),eth_type(0x8847),mpls(lse=0x00010140)
actions: pop_eth,pop_mpls(0x6558),0
# AF_PACKET SOCK_RAW on dp0: eth / mpls / eth / 4096 bytes of payload
kernel BUG at include/linux/skbuff.h:2839!
RIP: 0010:eth_type_trans (include/linux/etherdevice.h:635 net/ethernet/eth.c:163)
Call Trace:
internal_dev_recv (net/openvswitch/vport-internal_dev.c:202) openvswitch
do_execute_actions (net/openvswitch/actions.c:1296) openvswitch
ovs_execute_actions (net/openvswitch/actions.c:1606) openvswitch
ovs_dp_process_packet (net/openvswitch/datapath.c:310) openvswitch
ovs_vport_receive (net/openvswitch/vport.c:448) openvswitch
internal_dev_xmit (net/openvswitch/vport-internal_dev.c:42) openvswitch
dev_hard_start_xmit (include/linux/netdevice.h:5455 include/linux/netdevice.h:5464 net/core/dev.c:4057 net/core/dev.c:4073)
__dev_queue_xmit (net/core/dev.c:5066)
packet_sendmsg (net/packet/af_packet.c:3157 net/packet/af_packet.c:3189)
Use eth_type_trans_careful(), and drop the packet if the Ethernet
header can not be pulled. This covers all OVS actions at the consumer,
instead of fixing each producer.
Fixes: b2d0f5d5dc53 ("openvswitch: enable NSH support")
Fixes: f66b53fdbb22 ("openvswitch: New MPLS actions for layer 2 tunnelling")
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Aaron Conole <aconole@redhat.com>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20261028122703.2093730-5-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
A tc egress BPF program can push a tiny link-layer header with
bpf_skb_change_head() on an skb whose head is almost empty, then
redirect it to an Ethernet device ingress. __bpf_redirect_common()
only checks mac_header < network_header, and __dev_forward_skb2()
crashes in eth_type_trans():
tc filter add dev lo egress pref 1 matchall action vlan pop_eth continue
tc filter add dev lo egress pref 2 bpf da obj prog.o
# prog: bpf_skb_change_head(skb, 1, 0);
# return bpf_redirect(veth1_ifindex, BPF_F_INGRESS);
# AF_PACKET SOCK_RAW on lo: eth / eth / 8192 bytes of payload
kernel BUG at include/linux/skbuff.h:2839!
RIP: 0010:eth_type_trans (include/linux/etherdevice.h:635 net/ethernet/eth.c:163)
Call Trace:
__dev_forward_skb2 (net/core/dev.c:2507)
dev_forward_skb_nomtu (net/core/dev.c:2546)
__dev_queue_xmit (net/core/dev.c:4738 net/core/dev.c:4998)
packet_sendmsg (net/packet/af_packet.c:3157 net/packet/af_packet.c:3189)
Use eth_type_trans_careful(), and drop the packet if the Ethernet
header can not be pulled. This also covers other dev_forward_skb()
users (veth, macvlan, ipvlan, netdevsim, l2tp_eth).
Update the empty_skb BPF selftest: at lwt_xmit, BPF_PROG_TEST_RUN
strips the Ethernet header, so the "veth ETH_HLEN+1" packet is a 1-byte
skb. Redirecting it to veth ingress used to read the Ethernet header
past skb->tail and deliver a 1-byte frame; it is now dropped with
NET_RX_DROP, as veth_xmit() already does at egress.
Fixes: 3a0af8fd61f9 ("bpf: BPF for lightweight tunnel infrastructure")
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20261028122703.2093730-4-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
IPv4 passive opens on a dual-stack listener go through
tcp_v4_syn_recv_sock() with tcp_v6_mapped_child_init() as the optional
initializer. The callback currently runs after the output route lookup.
If that lookup fails, tcp_done() destroys a clone whose pinet6 and
ipv6_fl_list still refer to the listener's state.
With the flowlabel list head in inet_sock, fl6_free_socklist() walks
the clone's list and RCU-frees its nodes without unlinking them from the
live listener. Subsequent flowlabel operations can use or free the nodes
again. Commit 858d2a4f67ff ("tcp: fix potential race in
tcp_v6_syn_recv_sock()") moved the initializer before ehash insertion,
but did not cover this error path.
Invoke the existing initializer after the IPv4 fields it consumes have
been set, but before route lookup can fail. It needs neither the
destination nor sk_setup_caps(), and all later disposal paths remain
covered.
Fixes: 1c17f4373d4d ("ipv6: Move ipv6_fl_list from ipv6_pinfo to inet_sock.")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20261028154101.2153360-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
Commit efb8763d7bbb ("net: ipv4: bound TCP reordering sysctl writes and
MTU probe sizes") widened size_needed and the MSS multiplication, but
tp->reordering + 1 is still evaluated as u32. RTAX_REORDERING accepts
an unrestricted u32, and tcp_init_metrics() can install U32_MAX.
In that case the extra-data requirement becomes zero. A write queue
with probe_size - 1 data bytes and a FIN satisfies the sequence-space
check. The coalescing walk can pass the queue head to
tcp_skb_can_collapse(), and tcp_clone_payload() can produce an skb
whose advertised payload exceeds the data in its fragments. Local
delivery followed by TCP_ZEROCOPY_RECEIVE can then walk beyond the
fragment array. KASAN reports a slab-out-of-bounds read in
can_map_frag().
Cast reordering before incrementing it so the arithmetic handles the
entire u32 metric range. For U32_MAX, the required size exceeds the
32-bit queue and window limits, so the existing checks skip the probe.
The calculation is unchanged for all other reordering values.
Fixes: efb8763d7bbb ("net: ipv4: bound TCP reordering sysctl writes and MTU probe sizes")
Cc: stable@vger.kernel.org
Cc: Wyatt Feng <bronzed_45_vested@icloud.com>
Cc: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Neal Cardwell <ncardwell@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/20261028160226.2170244-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
tcp_abort() checks for TCP_CLOSE while only owning the socket lock,
then grabs the BH lock before calling tcp_done_with_error().
For a child still sitting in a listener accept queue (which can be
reached via SOCK_DESTROY or bpf_sock_destroy()), inet_csk_listen_stop()
can run in this window: it only holds the child BH lock, and calls
inet_child_forget(), which disconnects, orphans and destroys the child.
tcp_abort() then calls tcp_done_with_error() -> tcp_done(), which sees
SOCK_DEAD and calls inet_csk_destroy_sock() a second time, leading to
a double sock_put() and a use-after-free.
Recheck TCP_CLOSE after acquiring the BH lock, unless we just closed
a listener ourselves, in which case tcp_done_with_error() must still
run to report the error.
Note that the WARN_ON(sock_owned_by_user(child)) in
inet_csk_listen_stop() can still trigger in this window.
Fixes: bac76cf89816 ("tcp: fix forever orphan socket caused by tcp_abort")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
[edumazet: recheck TCP_CLOSE under the BH lock instead of moving the test, smaller diff]
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20261028160847.2170959-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
tcp_gro_receive() excludes empty non-GSO packets with the unsigned
len - 1 check, but its GSO branch only checks that gso_size matches
the held packet's MSS. A trusted TCP GSO skb can reach GRO again with
no payload after TC pedit increases its TCP data offset.
If the skb is fully linear, skb_gro_receive() then enters its fragment
transfer path with nr_frags == 0. The do-while loop copies skb_frag_t
entries backwards beyond both fragment arrays. An unprivileged process
using its own user and network namespaces can trigger a KASAN
slab-out-of-bounds write and panic through veth, pedit and GRE.
More generally, the payload of such a packet can be shrunk to any
value, making it inconsistent with its gso_segs, and a GSO packet
with gso_segs == 0 contributes no segment to the GRO packet.
Do not aggregate GSO packets with gso_segs == 0, and require the
payload of GSO packets to be consistent with gso_segs and gso_size,
the last segment being allowed to be short. This rejects the empty
skb before either TCP merge helper, and covers both IPv4 and IPv6.
Fixes: 5eddb24901ee ("gro: add support of (hw)gro packets to gro stack")
Signed-off-by: Kyle Zeng <kylebot@openai.com>
[edumazet: check payload against gso_segs, refuse gso_segs == 0]
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20261028171350.2205175-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
tpacket_fill_skb() adds the full non-linear payload length to
skb->truesize and sk_wmem_alloc before checking MAX_SKB_FRAGS. With
PACKET_VNET_HDR, userspace can submit a ring-sized frame even when it
greatly exceeds the device MTU.
A near-INT_MAX frame can saturate sk_wmem_alloc before the fragment
loop rejects it. A subsequent refcount_add(0x40000001) can temporarily
turn REFCOUNT_SATURATED into 1. A concurrent TX completion can then
drop that apparent last reference and free the still-live packet
socket before refcount_warn_saturate() restores the counter.
Check that the remaining payload fits in MAX_SKB_FRAGS pages before
accounting it. Include the initial page offset in the calculation,
and move the existing -EFAULT handling out of the fragment loop.
This preserves the accepted packet sizes and error code while
preventing an invalid frame from injecting an oversized byte charge.
Fixes: 69e3c75f4d54 ("net: TX_RING and packet mmap")
Cc: stable@vger.kernel.org
Cc: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Signed-off-by: Kyle Zeng <kylebot@openai.com>
[edumazet: use net_warn_ratelimited() instead of pr_err(), add a Fixes: tag]
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20261028181450.2221013-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
netdev_wait_allrefs_any() re-sends NETDEV_UNREGISTER every second while
it waits for the last references on a device to be dropped. By then
netdev_run_todo() has already marked the device NETREG_UNREGISTERED and
RTNL has been dropped at least once since the initial notification sent
by unregister_netdevice_many_notify().
netdev_genl_netdevice_event() does not tell these rebroadcasts apart
from the initial notification and sends a NETDEV_CMD_DEV_DEL_NTF
multicast for each of them. At best this spams NETDEV_NLGRP_MGMT
listeners with duplicate notifications; at worst the pernet state of
the netns the device belongs to is already gone and the handler
dereferences a NULL pointer.
default_device_exit_batch() only unregisters the devices still listed
in the exiting netns; it does not wait for in-flight unregistrations of
devices that were already unlisted (the barrier doing that was removed
by commit 8a4fc54b07d7 ("net: get rid of rtnl_lock_unregistering()")).
So when a device is unregistered by something other than the
cleanup_net() of its own netns while references on it are still held,
e.g. a veth whose peer in another netns gets deleted, and that netns
exits while the device is stuck in netdev_wait_allrefs_any(), the
remaining pernet exit handlers run and genl_pernet_exit() sets
net->genl_sock to NULL. The next rebroadcast then crashes in
genl_has_listeners():
BUG: KASAN: null-ptr-deref in netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388
Read of size 8 at addr 0000000000000578 by task syz.0.0/5325
Call Trace:
<TASK>
netlink_has_listeners+0x3d/0x3f0 net/netlink/af_netlink.c:1388
genl_has_listeners include/net/genetlink.h:644 [inline]
netdev_genl_dev_notify+0x161/0x450 net/core/netdev-genl.c:93
netdev_genl_netdevice_event+0x98/0x3c0 net/core/netdev-genl.c:1491
notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
netdev_wait_allrefs_any net/core/dev.c:11690 [inline]
netdev_run_todo+0x731/0x1060 net/core/dev.c:11808
rtnl_unlock net/core/rtnetlink.c:157 [inline]
rtnl_dellink+0x68f/0x810 net/core/rtnetlink.c:3707
syzbot hit this by moving one end of a veth pair into a short-lived
netns while netdevsim's deferred FIB event processing still held a
reference on it, and then deleting the other end (repro [1]). While the
source of this bug is netdevsim deferring FIB processing for and holding
onto the device reference for O(seconds) which is being fixed
separately [2], any driver may introduce such a delay and trigger the
null-ptr-deref.
Skip the rebroadcasts, which are the only NETDEV_UNREGISTER events
delivered with reg_state == NETREG_UNREGISTERED. The notifications sent
by unregister_netdevice_many_notify() and, for a device leaving a netns,
by __dev_change_net_namespace() are issued under RTNL in the same
critical section that unlists the device, before its netns can be torn
down, and keep being handled. This mirrors what ip6_route_dev_notify()
already does to cope with the rebroadcasts.
This change should not break the UAPI spec as it defines dev-del-ntf as
a "Notification about device disappearing." which is a single event. The
rebroadcast in netdev_wait_allrefs_any() exists to re-kick in-kernel
subsystems holding references; netdev-genl happens to be on the notifier
chain and forwards it.
[1] https://gist.github.com/NamanGulati/2d1b49b8757f9a88b0bd6e55018c02ae
[2] https://lore.kernel.org/r/20261023191517.607834-1-kuniyu@google.com
Fixes: d3d854fd6a1d ("netdev-genl: create a simple family for netdev stuff")
Reported-by: syzbot+1269fe6cc2016008124e@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6adf9f64.6200f071.51519.0ed1.GAE@google.com/
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Naman Gulati <namangulati@google.com>
Link: https://patch.msgid.link/20261026221306.3151025-1-namangulati@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
tcp_set_default_congestion_control() takes a reference to an algorithm
before checking whether a non-init network namespace may select it. A
rejected request returns -EPERM without dropping the reference.
This affects module-backed algorithms too; BPF is not required. For
example, after root loads tcp_bbr, a user with CAP_NET_ADMIN in a
non-init network namespace can repeatedly request it as the default
although it is not in tcp_allowed_congestion_control. Each rejected
write leaks a module reference. Since module->refcnt is an atomic_t,
2^31 such writes can make it negative; later module_put() calls warn,
and rmmod can hit the BUG_ON() in try_release_module_ref().
Check the namespace restriction before acquiring the reference, as
tcp_set_congestion_control() already does.
Fixes: 8d432592f30f ("net: Only allow init netns to set default tcp cong to a restricted algo")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Suggested-by: Eric Dumazet <edumazet@kernel.org>
Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/71c142b2d45af6a2fe7fc6cd4a5ca52c53afbe23.1793075984.git.zhilinz@nebusec.ai
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
The issue: teql_master_xmit() tests the slave's ndo_start_xmit() return
value against NETDEV_TX_OK alone. A slave that consumes the skb but
returns an error code (rc < NET_XMIT_MASK, e.g. NET_XMIT_DROP) is treated
as if the skb were still owned, so the loop restores skb->dev and calls
__skb_pull() on it. A VLAN slave returns the result of dev_queue_xmit()
from its ndo_start_xmit() (propagated since cbbef5e18307), and when the
lower qdisc drops the packet that value is NET_XMIT_DROP after the skb
has been freed, giving a use-after-free in teql_master_xmit().
The Fix: test for consumption with dev_xmit_complete(), which accepts
NETDEV_TX_OK and every rc < NET_XMIT_MASK, matching other callers that
need to distinguish consumed results from busy. Only NETDEV_TX_OK keeps
the packet counted in tx_packets/tx_bytes and advances the slave; a
consumed result that is neither a success nor NET_XMIT_CN ends the
attempt and is charged to tx_dropped, so lower-qdisc drops are no longer
reported as good transmits. NET_XMIT_CN is counted like success because
it can accompany acceptance of the current packet: pfifo_head_drop drops
the old head, enqueues the current skb and returns NET_XMIT_CN.
Conditions to recreate the bug:
With CONFIG_NET_SCH_TEQL,
CONFIG_VLAN_8021Q and CONFIG_DUMMY enabled, add lkrdummy0 (dummy) and
lkrvlan0 (VLAN id 37 on lkrdummy0); set a pfifo limit 0 root on lkrdummy0
and a teql0 root on lkrvlan0; bring teql0 up with an address and send one
UDP packet to it. The VLAN xmit returns NET_XMIT_DROP from the lower
qdisc while holding a freed skb.
Fixes: 572a9d7b6fc7 ("net: allow to propagate errors through ->ndo_hard_start_xmit()")
Link: https://lore.kernel.org/netdev/179248763469.3135.1739559328868319628@kernel.org/
Link: https://lore.kernel.org/netdev/20261023162821.GN708417@horms.kernel.org/
Cc: stable@vger.kernel.org
Signed-off-by: owen kwan <owen@verialabs.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/QDISC-Y0BY.v2.r0.20261024060625-2@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
This is a followup of commit e5b811fe7931 ("net/sched: sch_teql:
Introduce slaves_lock to avoid race condition and UAF") as reported by
Sashiko.
The issue: master->slaves_lock serializes the master's ring of slave
qdiscs. The control paths -- teql_dequeue(), teql_destroy() and
teql_qdisc_init() -- take it with spin_lock_bh(), while
teql_master_xmit() (the master's ndo_start_xmit) takes it with plain
spin_lock().
netpoll_send_skb() wraps the transmit in local_irq_save(), and
__netpoll_send_skb() asserts lockdep_assert_irqs_disabled(), so
teql_master_xmit() reached from netconsole always acquires slaves_lock
with hard IRQs disabled. On PREEMPT_RT spinlock_t is an rtmutex, and
Documentation/locking/locktypes.rst names
local_irq_disable();
spin_lock(&lock);
as a sequence that breaks there because the rtmutex requires a fully
preemptible context. This is reachable without any panic: the nbcon
printer thread calls netconsole's write_thread() callback on every
message. The usual remedy -- folding the IRQ disable into the lock with
spin_lock_irqsave() -- is unavailable because the local_irq_save() is
netpoll's, not ours.
On non-RT the same asymmetry leaves slaves_lock acquirable with hard IRQs
disabled on one path and held with hard IRQs enabled on another. That is
only exploitable during the panic console flush (netconsole is
CON_NBCON_ATOMIC_UNSAFE, so console_is_usable() admits its write_atomic()
only from nbcon_atomic_flush_unsafe(), which panic() alone calls), and
even then an IRQ-saving lock does not help if the holder oopsed inside the
section or was stopped by panic_other_cpus_shutdown(). So the non-RT half
is hardening; the PREEMPT_RT half is the bug.
The Fix: take slaves_lock as a raw spinlock with IRQs saved at every
site. Since skb_queue_purge() takes the queue's spinlock_t and may not
nest inside a raw lock on PREEMPT_RT, move its call in teql_destroy()
outside the raw section; dat->q is the dying qdisc's own queue and was
never serialized by slaves_lock, so the move is behaviour-neutral.
The new critical sections contain only RCU pointer assignments and
netdev_get_tx_queue(); skb_queue_purge(), netif_wake_queue() and
dev_reset_queue() are all outside them. teql_destroy()'s ring walk is
O(slaves), two pointer loads and a compare per iteration, so even a large
ring is microseconds with IRQs off. Keeping the purge conditional rather
than dropping it outright is the conservative call for a backport.
Some context: commit 6301f6a34ed8 ("net/sched: sch_teql: move
rcu_read_lock()/spin_lock() from _bh variants") hardened the parent
fix; together they addressed the master->slaves resurrection
use-after-free and the xmit-side BH warning but left the reverse
direction -- a hard IRQ re-entering xmit while a control path holds the
lock -- unaddressed.
Conditions to recreate the bug:
- CONFIG_PREEMPT_RT, CONFIG_NET_SCH_TEQL, CONFIG_DUMMY and
CONFIG_NETCONSOLE.
- Run `ip link add dev teqlslave0 type dummy`, bring teqlslave0 up, attach
it with `tc qdisc add dev teqlslave0 root teql0`, and bring teql0 up.
- Configure a netconsole target on teql0 with explicit local and remote
IP addresses and a remote MAC address, then emit a console message.
The nbcon printer thread reaches teql_master_xmit() with hard IRQs
disabled by netpoll; taking slaves_lock as a spinlock_t is invalid on
PREEMPT_RT. No panic or concurrent qdisc change is required.
- Reachable by an admin with CAP_NET_ADMIN; teql devices exist only in the
initial netns (no per-netns ops), so a user namespace does not suffice.
Fixes: e5b811fe7931 ("net/sched: sch_teql: Introduce slaves_lock to avoid race condition and UAF")
Reported-by: Sashiko (gemini) <sashiko-bot@kernel.org>
Closes: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260630150922.238714-1-jhs%40mojatatu.com
Link: https://lore.kernel.org/netdev/20260630150922.238714-1-jhs@mojatatu.com/
Cc: stable@vger.kernel.org
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/QDISC-Y0BY.v2.r0.20261024060625-1@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
When a start-of-message fragment creates a new reassembly key on the
broadcast/bind path, mctp_frag_queue() stores the skb as
key->reasm_head before the key is made observable with mctp_key_add().
If mctp_key_add() fails (a race with another SOM packet for the same
source/dest/tag, or the receiving socket going away), the error path
only drops the key reference via mctp_key_unref(). The final key
destructor frees the key itself but not key->reasm_head, and since the
key was never added to any list, neither the expiry worker nor socket
teardown can reach it to release the queued fragment. The skb is
leaked.
Free key->reasm_head on the key_add failure path before releasing the
key. Other teardown paths (__mctp_key_done_in(), EOM delivery) already
clear reasm_head before the final unref, so this only affects the
failure path.
Fixes: 4a992bbd3650 ("mctp: Implement message fragmentation & reassembly")
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Reported-by: Guikun Yang <yangguikun19@qq.com>
Closes: https://lore.kernel.org/all/tencent_43A65D51143E18518EA968DF9323694EFD08@qq.com/
Acked-by: Jeremy Kerr <jk@codeconstruct.com.au>
Link: https://patch.msgid.link/179287946888.17431.11219154409333681184@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
|
In p9_check_errors() (net/9p/client.c), a malicious or buggy 9p server
returning P9_RERROR or P9_RLERROR with ecode == 0 causes
p9_check_errors() to return 0 (success) while leaving the unparsed
response payload as if the expected reply message type succeeded.
Map ecode == 0 on RERROR / RLERROR to -EPROTO.
Link: https://lore.kernel.org/all/20260919221734.3708000-1-benquike@gmail.com/
Signed-off-by: Hui Peng <benquike@gmail.com>
Message-ID: <20261029055801.3-1-asmadeus@codewreck.org>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
|
|
p9_xen_response() takes the length of an incoming response from the ring
-- the first field of the 9p header, which the Xen transport reuses as
its framing header -- and uses it to advance the consumer index, but
never checks that it is at least the header size or no larger than the
number of bytes the backend has actually produced.
A malicious or buggy backend can post a response whose size is smaller
than the header (for example 0). The consumer index then never advances,
so the response work re-reads the same ring contents instead of making
progress. In testing this raced with the teardown that the malformed
reply triggers and dereferenced a freed p9_client:
9pfs 9pfs-0: Wrong req tag=ffff
BUG: kernel NULL pointer dereference, address: 0000000000000060
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: Oops: 0000 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 7.2.0-rc5 #6 PREEMPT(lazy)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
Workqueue: events p9_xen_response
RIP: 0010:idr_find+0x4/0x10
RSP: 0018:ffffbf5d80063de8 EFLAGS: 00010202
RAX: 0000000000000001 RBX: ffffa229c21195a0 RCX: ffffa229c2400000
RDX: ffffa229c11c2200 RSI: 000000000000ffff RDI: 0000000000000050
RBP: 000000000000ffff R08: 3fffffffffffdfff R09: ffffffffffffffff
R10: 3fffffffffffdfff R11: ffffffff87a60e80 R12: 0000000000000050
R13: 0000000000000000 R14: 000000000000ffff R15: 0000000000100000
FS: 0000000000000000(0000) GS:ffffa22a7661c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000060 CR3: 000000003ac34002 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
p9_tag_lookup+0x2b/0x90
p9_xen_response+0x17c/0x2e0
process_one_work+0x16a/0x3a0
worker_thread+0x172/0x2e0
kthread+0xdd/0x110
ret_from_fork+0x18b/0x240
ret_from_fork_asm+0x1a/0x30
</TASK>
Modules linked in:
CR2: 0000000000000060
---[ end trace 0000000000000000 ]---
Reject a response whose size is outside [sizeof(header), queued] before
using it, matching the validation the backend already applies to
incoming requests.
Fixes: f66c72bea129 ("xen/9pfs: receive responses")
Cc: stable@vger.kernel.org
Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
Reviewed-by: Juergen Gross <jgross@suse.com>
Message-ID: <20261005125640.274054-1-yhlee@isslab.korea.ac.kr>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
|
|
br_fill_ifinfo() assigns the result of br_fill_vlan_tunnel_info() over
the result of br_fill_ifvlaninfo() or br_fill_ifvlaninfo_compressed()
instead of only running the second helper when the first one succeeded.
When the vlan information no longer fits in the skb but the port has no
vlan mapped to a tunnel dst, br_fill_vlan_tunnel_info() walks the vlan
list and returns 0 without touching the skb. The -EMSGSIZE is lost,
br_fill_ifinfo() completes a message whose IFLA_AF_SPEC is truncated,
and the dump carries on to the next interface instead of stopping, so
userspace silently sees an incomplete vlan list.
Only fill the tunnel information when the vlan information was filled
successfully.
This was flagged as a pre-existing issue in the Sashiko review of the
net-next series, which noted that the VLAN fill result is overwritten
before it is tested (see the Link tag below). Not triggered or tested.
Fixes: efa5356b0d97 ("bridge: per vlan dst_metadata netlink support")
Link: https://lore.kernel.org/bridge/ed1de95e-e112-4076-93f0-6f7668e657ad@blackwall.org/T/#u#5
Signed-off-by: Linkui Xiao <xiaolinkui@kylinos.cn>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20261027085200.1501599-1-xiaolinkui@126.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
syzbot reported the warning below. [0]
While call_fib6_multipath_entry_notifiers() is called locklessly,
fib6_siblings could be changed concurrently, leading to the
warning (and later null-ptr-deref).
Let's protect multiple routes insertion with tb6_lock.
Along with that, __ip6_ins_rt() and ip6_route_del() are changed
to fib6_add() and fib6_del().
Note that fib6_del() finally calls rt6_multipath_rebalance(),
which requires rcu_read_lock().
[0]:
i != fen6_info->nsiblings
WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib6_event_init drivers/net/netdevsim/fib.c:831 [inline], CPU#0: syz.0.157/6279
WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib6_prepare_event drivers/net/netdevsim/fib.c:947 [inline], CPU#0: syz.0.157/6279
WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1003 [inline], CPU#0: syz.0.157/6279
WARNING: drivers/net/netdevsim/fib.c:831 at nsim_fib_event_nb+0x1029/0x11d0 drivers/net/netdevsim/fib.c:1043, CPU#0: syz.0.157/6279
Modules linked in:
CPU: 0 UID: 0 PID: 6279 Comm: syz.0.157 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/24/2026
RIP: 0010:nsim_fib6_event_init drivers/net/netdevsim/fib.c:831 [inline]
RIP: 0010:nsim_fib6_prepare_event drivers/net/netdevsim/fib.c:947 [inline]
RIP: 0010:nsim_fib_event_schedule_work drivers/net/netdevsim/fib.c:1003 [inline]
RIP: 0010:nsim_fib_event_nb+0x1029/0x11d0 drivers/net/netdevsim/fib.c:1043
Code: eb 0d 4d 89 fd e8 b7 c5 6c fa be 01 00 00 00 48 89 df e8 5a 38 85 fd 4d 89 ef 4c 8b 6c 24 20 e9 4a f3 ff ff e8 98 c5 6c fa 90 <0f> 0b 90 e9 db fa ff ff 89 e9 80 e1 07 80 c1 03 38 c1 0f 8c df f0
RSP: 0018:ffffc900047bef10 EFLAGS: 00010293
RAX: ffffffff875b59a8 RBX: 0000000000000002 RCX: ffff888079770000
RDX: 0000000000000000 RSI: 0000000000000002 RDI: 0000000000000001
RBP: ffffc900047bf0a0 R08: ffff88805c0bb02f R09: 1ffff1100b817605
R10: dffffc0000000000 R11: ffffed100b817606 R12: dffffc0000000000
R13: 0000000000000000 R14: 0000000000000001 R15: ffff88802c792000
FS: 00007f334ba076c0(0000) GS:ffff888123ad0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f334ba06ff8 CR3: 000000007a5b2000 CR4: 00000000003526f0
Call Trace:
<TASK>
notifier_call_chain+0x1a5/0x3d0 kernel/notifier.c:85
atomic_notifier_call_chain+0xda/0x180 kernel/notifier.c:223
call_fib_notifiers+0x31/0x60 net/core/fib_notifier.c:36
call_fib6_multipath_entry_notifiers+0xf5/0x160 net/ipv6/ip6_fib.c:428
ip6_route_multipath_add net/ipv6/route.c:5542 [inline]
inet6_rtm_newroute+0x14f5/0x1a30 net/ipv6/route.c:5664
rtnetlink_rcv_msg+0x802/0xc00 net/core/rtnetlink.c:7163
netlink_rcv_skb+0x226/0x4a0 net/netlink/af_netlink.c:2572
netlink_unicast_kernel net/netlink/af_netlink.c:1335 [inline]
netlink_unicast+0x7bd/0x940 net/netlink/af_netlink.c:1361
netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1916
sock_sendmsg_nosec+0x14e/0x190 net/socket.c:800
__sock_sendmsg net/socket.c:818 [inline]
____sys_sendmsg+0x54e/0x850 net/socket.c:2715
___sys_sendmsg+0x2a5/0x360 net/socket.c:2769
__sys_sendmmsg+0x273/0x4d0 net/socket.c:2858
__do_sys_sendmmsg net/socket.c:2885 [inline]
__se_sys_sendmmsg net/socket.c:2882 [inline]
__x64_sys_sendmmsg+0xa0/0xc0 net/socket.c:2882
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f334ab9e1d9
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f334ba07028 EFLAGS: 00000246 ORIG_RAX: 0000000000000133
RAX: ffffffffffffffda RBX: 00007f334ae26090 RCX: 00007f334ab9e1d9
RDX: 04000000000001f2 RSI: 0000200000000000 RDI: 0000000000000004
RBP: 00007f334ac35888 R08: 0000000000000000 R09: 0000000000000000
R10: 00000000000000fc R11: 0000000000000246 R12: 0000000000000000
R13: 00007f334ae26128 R14: 00007f334ae26090 R15: 00007ffd96688aa8
</TASK>
Fixes: 169fd62799e8 ("ipv6: Get rid of RTNL for SIOCADDRT and RTM_NEWROUTE.")
Reported-by: syzbot+751b587577d0ebca10f2@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6adbaed6.67317f00.38c4bc.001b.GAE@google.com/T/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20261027065247.2871134-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
tls_sw_splice_read() takes its blocking behavior from
SPLICE_F_NONBLOCK alone. When splicing from a socket to a pipe,
do_splice() sets that flag from the pipe's O_NONBLOCK, not the
socket's. On a nonblocking socket, a splice(2) call without
SPLICE_F_NONBLOCK therefore sleeps in tls_rx_rec_wait() until a
record arrives. tcp_splice_read() instead reads sock->file->f_flags
and returns -EAGAIN.
Polling first does not avoid the sleep once tls_sw_splice_read()
consumes zero-length records, as it does after a later patch in this
series. tls_sw_sock_is_readable() reports the socket readable while
any record sits on rx_list, including a zero-length record that
delivers no bytes to the pipe. For TLS 1.3 the strparser announces a
record before decryption, when its plaintext length is still unknown,
so the readiness test cannot screen such a record out. A splice that
consumes the record and waits for the next stalls every connection
an event loop multiplexes.
An LLM audit of the TLS read paths found this defect.
Treat the socket's O_NONBLOCK as nonblocking too. A caller that
sets O_NONBLOCK on the socket and splices without SPLICE_F_NONBLOCK
now gets -EAGAIN where the splice blocked before. sendfile(2) from
a TLS socket changes the same way, because do_sendfile() leaves the
input file's O_NONBLOCK out of the splice flags. Both now behave as
they do on a plain TCP socket.
Fixes: c46234ebb4d1 ("tls: RX path for ktls")
Signed-off-by: Chuck Lever <cel@kernel.org>
Link: https://patch.msgid.link/20261027015215.605919-2-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
dev_requeue_skb() appends requeued skbs to the tail of q->gso_skb, while
dequeue_skb() takes them back one at a time from the head. If the driver
returns NETDEV_TX_BUSY again for the first of them, it moves behind the
skbs still parked there and is sent after them.
This showed up as heavy TCP reordering while benchmarking over veth,
which returns NETDEV_TX_BUSY whenever its ring is full since
commit dc82a33297fc ("veth: apply qdisc backpressure on full ptr_ring to reduce TX drops").
Requeue the skbs at the head of gso_skb, keeping their order. With 4 TCP
streams over a veth pair with a pfifo qdisc, this removes about 1.3M
out-of-order segments and 15-37k retransmits per 15 seconds, and raises
throughput from about 40 to 76 Gbit/s.
Fixes: a53851e2c321 ("net: sched: explicit locking in gso_cpu fallback")
Fixes: 9540d977618c ("net: sched: fix skb leak in dev_requeue_skb()")
Cc: stable@vger.kernel.org
Signed-off-by: Antonio Quartulli <antonio@mandelbit.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
Link: https://patch.msgid.link/20261026153113.3275494-1-antonio@mandelbit.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
dcbnl_getpfccfg() and dcbnl_cee_fill() pass the address of an
uninitialized stack u8 to the driver's getpfccfg() op and then put it
into the netlink reply unconditionally. The op returns void, so the
core cannot tell whether the driver wrote the value.
i40e_dcbnl_get_pfc_cfg() and ice_dcbnl_get_pfc_cfg() return without
writing *setting unless the DCBX agent is host managed and in CEE mode.
Both drivers normally run with firmware managed DCBX
(DCB_CAP_DCBX_LLD_MANAGED), and i40e with FW LLDP disabled runs host
managed in IEEE mode, so on a DCB capable i40e/ice port the PFC values
in DCB_CMD_PFC_GCFG and DCB_CMD_CEE_GET replies, and in the CEE part of
RTNLGRP_DCB notifications, come from uninitialized stack. The same u8
is reused for all eight priorities, so this is one byte per reply.
dcb_doit() only requires CAP_NET_ADMIN for RTM_SETDCB, so the GET
commands are available to unprivileged users.
Set the value to 0 before each call, like the PG config path already
presets its outputs to DCB_ATTR_VALUE_UNDEFINED. 0 is also what the
reply contains today on kernels built with CONFIG_INIT_STACK_ALL_ZERO,
so nothing changes for those.
Found by code inspection, compile-tested only (W=1). I don't have
i40e/ice hardware to check the reply.
Fixes: b94b013eb626 ("ice: Implement DCBNL support")
Fixes: 5effa78e7c94 ("i40e: Add netlink callbacks support for software based DCB")
Signed-off-by: Joas Antonio dos Santos <joasantonio108@gmail.com>
Link: https://patch.msgid.link/179289284460.50470.572724041164324949@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
This reverts commit 2640e6419594 ("net: advertise TCP MSS from the
configured MTU, not the learned PMTU").
That commit stopped the learned PMTU from lowering the MSS we advertise
in SYN and SYN-ACK. For symmetric paths it argued that "the peer runs
its own PMTU discovery and usually already knows the real path MTU".
That only holds if ICMP "fragmentation needed" can reach the peer. When
the peer sits behind a firewall that drops inbound ICMP, its PMTU
discovery is a black hole (RFC 2923, section 2.1), and the smaller MSS
we advertised was the only thing keeping its full-size segments off the
narrow hop.
Inbound ICMP filtering is very common in enterprise and carrier
networks, and it is pervasive in mainland China. We hit this in
production after the commit was backported to 6.12.111: TCP connections
that reach a server through a relay with a smaller-MTU hop complete the
handshake, then stall as soon as the client sends full-size segments.
Clients on networks that let ICMP through, and connections that bypass
the relay, are unaffected, which made it hard to trace back to the
kernel.
Reproducer, network namespaces on a single host:
cli --(1500)-- r1 --(1456)-- r2 --(1500)-- srv
r1 drops ICMP frag-needed towards cli. srv has already learned PMTU
1456 towards cli, then cli uploads 1 MB to srv:
kernel SYN-ACK MSS 1 MB upload
6.12.107 1416 OK
6.12.111 1460 stalls, times out
7.3-rc7 1460 stalls, times out
7.3-rc7 + this revert 1416 OK
The asymmetric case the commit was written for does not need a new
default: the advertised MSS can already be set per route with the
advmss metric, which takes precedence over default_advmss(). With this
revert applied, on an asymmetric path where srv learned PMTU 1456
towards cli while cli->srv is 1500 end to end:
srv route to cli SYN-ACK MSS largest cli->srv segment
default 1416 1404
advmss 1460 1460 1448
So DSR-style setups can opt in with "ip route ... advmss <mss>", while
hosts whose peers cannot complete PMTU discovery keep working by
default.
Fixes: 2640e6419594 ("net: advertise TCP MSS from the configured MTU, not the learned PMTU")
Closes: https://lore.kernel.org/regressions/4F0FAEB6-A13B-47F3-BFF1-C706686C6F64@gmail.com/
Cc: stable@vger.kernel.org
Signed-off-by: Yongjian Wang <echoowall@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/20261026-advmss-revert-v1-2-272fa4b7ecb6@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
|
em_ipt_change() accepts the user-provided TCA_EM_IPT_HOOK value
without validating its range.
The value is later used in check_match() as "1 << im->hook". A hook
value of 32 or greater causes undefined behavior and may undermine the
xt match hook-mask validation. The value is also passed to
nf_hook_state_init() as a hook index.
Reject hook values outside the supported IPv4/IPv6 Netfilter hook
range after checking the required attributes, before loading the xt
match or allocating the match state.
Reviewed-by: Weibin Liu <liuwb@xiaopeng.com>
Signed-off-by: Fang Xieyan <fangxy@xiaopeng.com>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
|
|
TAPRIO can schedule a deactivated qdisc after some_qdisc_is_busy() has
reported it idle.
Commit 47e8dbb6e763 ("net/sched: do not reset queues in graft operations")
made graft deactivation skip queue reset, leaving TAPRIO's timer armed.
A late callback schedules NET_TX softirq work, whose dequeue path can
race the unlocked child-queue reset in taprio_reset(). The same skb can
be queued for deferred freeing by RTNL and dequeued for transmission.
In the reproducer, the TAP reader frees it before __rtnl_unlock() reads
its next pointer. KASAN reports a slab-use-after-free in
__rtnl_unlock+0xa3/0xd0, with a read of size 8 from the freed skb.
Reject deactivated qdiscs in __netif_schedule(). Callers' RCU protection
lets the existing grace period join earlier scheduling calls before the
busy check. Restart nonempty transmit queues on reactivation so suppressed
scheduling does not strand packets.
Fixes: 47e8dbb6e763 ("net/sched: do not reset queues in graft operations")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/netdev/20260805102514.740834-1-david.lee@trailofbits.com/
Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Co-developed-by: David Lee <david.lee@trailofbits.com>
Signed-off-by: David Lee <david.lee@trailofbits.com>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
|
|
A reassembled skb retains the secpath from its first fragment, which
makes it possible for the final policy check to accept bytes that were
not covered by the transform recorded on the skb. This can affect IPsec
tunnel traffic, including AH and ESP, and allow a packet to be accepted
even though only part of its payload was authenticated.
Reject a fragment when its secpath differs from the fragments already
in the queue, and keep overlap statistics limited to actual overlaps.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
|
|
After TX is offloaded on device A, a route change, or a change in the
usable-slave set of an 802.3ad or balance-xor (layer3+4) bond, can make
RX setup program device B. tls_device_attach() sees the existing TLS
destructor and keeps ctx->netdev pointing at A. The RX driver state on B
is then untracked: tls_dev_resync() and tls_dev_del() are invoked on A
for a context it never created, and neither socket close nor
NETDEV_DOWN on B calls tls_dev_del() for B, so the driver context leaks.
The reverse setup order has the same problem.
Check the shared device binding under device_offload_lock before each
tls_dev_add(). Permit the first attachment and a second direction on the
same device. Reject a different device, including when the old binding
was cleared by NETDEV_DOWN: the TLS destructor remains installed and
tls_device_attach() cannot establish a new binding. Setup then falls
back to software for the requested direction.
The RX check precedes allocation and software setup. TX uses its existing
resource unwind path without calling the driver. Document the shared
binding and clarify that fallback is per direction.
This issue was discovered during code review and subsequently
reproduced on hardware using mlx5 and TLS 1.2 AES-GCM-128.
Changing the route between TX and RX setup installed the second
direction on a different device. Driver traces showed successful adds
on both devices, but both deletes at socket close targeted the first
device, leaving an orphaned context on the second. Both setup orders
reproduced the leak, even though all current core TLS context counters
returned to zero. No crash was observed.
With the fix, the same tests correctly fall back to software for the
second direction and leave no orphaned hardware context.
Fixes: 4799ac81e52a ("tls: Add rx inline crypto offload")
Signed-off-by: Rishikesh Jethwani <rjethwani@purestorage.com>
Signed-off-by: Dave Miller <davem@davem-thinkpadp1gen8.ibmlond.csb>
|