All of lore.kernel.org
 help / color / mirror / Atom feed
* Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum")
@ 2026-10-19  8:43 Pranjal Kumar Singh
  2026-10-19  8:50 ` Michael S. Tsirkin
  2026-10-19  8:54 ` Greg KH
  0 siblings, 2 replies; 4+ messages in thread
From: Pranjal Kumar Singh @ 2026-10-19  8:43 UTC (permalink / raw)
  To: cve, netdev, Pablo Neira Ayuso, Jozsef Kadlecsik, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Michael S. Tsirkin,
	Willem de Bruijn, Paulos Yibelo, openvswitch, stable,
	fw@strlen.de


[-- Attachment #1.1: Type: text/plain, Size: 5512 bytes --]

Hello Security Team,

The IPv4 part of this was fixed some time ago in commit 6785011f8b16
("ipv4: validate checksum_start before completing checksum"): a packet
whose virtio_net_hdr csum metadata points its checksum start inside the
IP header makes skb_checksum_help() (the deferred csum completion)
rewrite the header the stack has already validated (fixed checksum
offset-width write at csum_start + csum_offset).  The IPv6 paths were
not covered, and they still are not: a 2-patch series mirroring that
commit for IPv4->IPv6, including its remaining not-yet-IPv6-guarded
sinks, is reproduced below and attached as patches/0001 and 0002.

Why this is reachable today
---------------------------
include/linux/virtio_net.h's __virtio_net_hdr_to_skb() only enforces
skb_transport_offset() >= sizeof(struct iphdr) (nh_min_len) for
NEEDS_CSUM -- i.e., for IPv6 packets any csum_start in
[20, sizeof(struct ipv6hdr)) passes admission, sitting inside the fixed
40-byte IPv6 header that the stack has just validated.  With TUN (tun
device using IFF_VNET_HDR) or AF_PACKET csum -- the same admission the
virtio/vhost setup uses for guests, and reachable unprivileged --
skb_checksum_help() can then write an attacker-chosen 16-bit value into
the outgoing IPv6 header of a forwarded frame.  The write value is
csum_fold over an attacker-built payload and is fully deterministic
(pre-computed in userspace in the reproducer).

Sinks on master (line numbers from c03c1a14507d, "Linux 7.3", checked
2026-10-19):

  net/ipv6/ip6_output.c:945           ip6_fragment()      unguarded
  net/ipv6/netfilter.c:147            br_ip6_fragment()   unguarded
                                      (reachable by bridge
                                      refrag in
                                      net/bridge/netfilter/
                                      nf_conntrack_bridge.c:358 and
                                      by Open vSwitch
                                      ovs_fragment()'s IPv6 branch
                                      which calls ip6_fragment())
  net/netfilter/xt_CHECKSUM.c:30      checksum_tg()       guard is
                                      NFPROTO_IPV4-only, IPv6 falls
                                      through; helper return also
                                      ignored (patch 2)
  net/netfilter/nfnetlink_queue.c:678 nf_queue_checksum_help()
                                      checked for ETH_P_IP only,
                                      IPv6 falls through
  net/xfrm/xfrm_output.c:826          xfrm_output()       same
                                      ETH_P_IP-only gate

The ip6_fragment() side-drop is the direct sibling of the IPv4
ip_do_fragment() check that commit added; xt_CHECKSUM's IPv6 case is
reachable for a v6-only netns since ingress-side -- for instance via
`ip6tables -t mangle POSTROUTING -j CHECKSUM --checksum-fill`, which
finalizes the partial checksum at the sink.

Bug report and evidence
-----------------------
Dear attachments, all under ipv6-csum-start-submission.zip:

  - report.txt: detailed writeup with the full admission-gap audit and
    the sink table above, impact, and the reproducer output below;
  - patches/0000-cover-letter.txt, 0001, 0002: the proposed git-series
    (2 patches, drafted against c03c1a14507d);
  - poc/poc_ipv6_csum_start.c: a single-file reproducer (as PID 1 in an
    initramfs VM it needs no external tools -- netns + veth + tun via
    raw netlink, TUN,VNET_HDR, ip6tables via the bundled
    ip6tables-legacy, and a packet-over-TUN/AF_PACKET sender); csum
    geometry (csum_start=24 = inside the IPv6 fixed header) with a
    csum_start=64 falsification control variant;
  - poc/build_vm.sh, logs/run-*.log: the two runs, verbatim, from a
    QEMU initramfs VM against a real 6.12.38 kernel (no KVM required):

  -- control (csum_start=64, past the header) --
  [*] emitted frame #1 len=1478 daddr intact: fd:00:00:0c hop_limit=63
  [+] control OK: 1 frames, headers intact
      Ip6OutForwDatagrams             1

  -- evil (csum_start=24, inside the header) --
  [!] MUTATED OUTPUT FRAME #1: daddr bits now 4a:32:00:0c
      (wire-validated value was fd00:c::= 0c:0c:0c:0c); written
      16-bit=4a32 len=1478
  [+] BUG CONFIRMED: csum_start=24 < sizeof(struct ipv6hdr)=40:
      deferred skb_checksum_help() rewrote the previously VALIDATED
      IPv6 header in an EMITTED packet.
      Ip6OutForwDatagrams             1

The 4a:32 written into the emitted frame's destination address is the
folded checksum the reproducer predicted before sending; the control
run shows the same code path intact, ruling out ordinary corruption.
Likewise, no CVE for this IPv6 path is known to me as of 2026-10-19;
there is no harm in restoring parity with the IPv4 fix, and following
up with cve@kernel.org after this lands, if you agree.

The proposed fix mirrors commit 6785011f8b16 one sink at a time; the
input-side admission is still the "more work forthcoming" item from
that commit's changelog (its IPv4 work precedes it), and this series
does not attempt to change it -- it only documents that gap in
report.txt for whoever picks it up.

Happy to rework the split (netfilter-only first, or one patch per
sink), or to paste the patches inline if inline is preferred over the
attachment.  Testing status: the reproducer was exercised end to end
against the 6.12.38 kernel named above; patches are hand-crafted and
not yet boot-tested as a series.

Let me know if it is eligible for CVE

Thanks,
PRNJL

[-- Attachment #1.2: Type: text/html, Size: 6293 bytes --]

[-- Attachment #2: ipv6-csum-PRNJL.zip --]
[-- Type: application/x-zip-compressed, Size: 26367 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum")
  2026-10-19  8:43 Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum") Pranjal Kumar Singh
@ 2026-10-19  8:50 ` Michael S. Tsirkin
       [not found]   ` <CA+UYBZCEe3C2HuqgZSZ9Xa7MUxCNy=9ckBmA1Kyjmt882ZRQBA@mail.gmail.com>
  2026-10-19  8:54 ` Greg KH
  1 sibling, 1 reply; 4+ messages in thread
From: Michael S. Tsirkin @ 2026-10-19  8:50 UTC (permalink / raw)
  To: Pranjal Kumar Singh
  Cc: cve, netdev, Pablo Neira Ayuso, Jozsef Kadlecsik, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Willem de Bruijn,
	Paulos Yibelo, openvswitch, stable, fw@strlen.de

On Mon, Oct 19, 2026 at 02:13:04PM +0530, Pranjal Kumar Singh wrote:
> Hello Security Team,
> 
> The IPv4 part of this was fixed some time ago in commit 6785011f8b16
> ("ipv4: validate checksum_start before completing checksum"): a packet
> whose virtio_net_hdr csum metadata points its checksum start inside the
> IP header makes skb_checksum_help() (the deferred csum completion)
> rewrite the header the stack has already validated (fixed checksum
> offset-width write at csum_start + csum_offset).  The IPv6 paths were
> not covered, and they still are not: a 2-patch series mirroring that
> commit for IPv4->IPv6, including its remaining not-yet-IPv6-guarded
> sinks, is reproduced below and attached as patches/0001 and 0002.

Thanks, I think this has been reported already. Just to clarify, the effect
is just packet header corruption past validation, right?

See [PATCH net-next v2 0/7] more virtio-net csum hardening
for WIP fixes.

-- 
MST


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum")
  2026-10-19  8:43 Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum") Pranjal Kumar Singh
  2026-10-19  8:50 ` Michael S. Tsirkin
@ 2026-10-19  8:54 ` Greg KH
  1 sibling, 0 replies; 4+ messages in thread
From: Greg KH @ 2026-10-19  8:54 UTC (permalink / raw)
  To: Pranjal Kumar Singh
  Cc: cve, netdev, Pablo Neira Ayuso, Jozsef Kadlecsik, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Michael S. Tsirkin,
	Willem de Bruijn, Paulos Yibelo, openvswitch, stable,
	fw@strlen.de

On Mon, Oct 19, 2026 at 02:13:04PM +0530, Pranjal Kumar Singh wrote:
> Bug report and evidence
> -----------------------
> Dear attachments, all under ipv6-csum-start-submission.zip:

For obvious reasons, you don't want us opening binary attachments.
Always submit everything in plain text, as our documentation kindly asks
you to.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum")
       [not found]   ` <CA+UYBZCEe3C2HuqgZSZ9Xa7MUxCNy=9ckBmA1Kyjmt882ZRQBA@mail.gmail.com>
@ 2026-10-19 10:09     ` Michael S. Tsirkin
  0 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2026-10-19 10:09 UTC (permalink / raw)
  To: Pranjal Kumar Singh
  Cc: cve, netdev, Pablo Neira Ayuso, Jozsef Kadlecsik, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Willem de Bruijn,
	Paulos Yibelo, openvswitch, stable, fw@strlen.de

On Mon, Oct 19, 2026 at 02:36:14PM +0530, Pranjal Kumar Singh wrote:
> Yes. One 16-bit csum_fold() write at
> csum_start + csum_offset, always within the packet's own linear data
> (admission's pskb_may_pull(needed) bounds it), so no OOB, no memory
> safety issue and no crash; just a previously-validated header field
> changed after the stack committed to it.  With the IPv6 geometry I
> reported (csum_start in [20, 40) slipping past nh_min_len == 20), the
> write lands in the fixed IPv6 header only -- dst/src bytes; version,
> payload length, nexthdr and hop limit (bytes 0-7) are unreachable from
> that geometry -- and the written value is attacker-derivable
> (precomputed csum_fold in the reproducer; wire value matched byte for
> byte, control run intact).
> 
> I went through the full v2 series: with 4/7 my geometry is resolved at
> ingress via the mismatch path (Routing-header parse -> csum_start !=
> thoff -> completed before protocol processing), so the observed window
> is closed on the virtio-hdr-tested flows and my sink-side patches are
> superseded for that case.  I'll repost them (or thin them further out)
> as a net-next follow-up to your v3 only for the sysctl opt-out case in
> 5/7 (knob off = my geometry is admitted fully intact with
> CHECKSUM_PARTIAL retained and the deferred write happens as before),
> plus the xt_CHECKSUM v6 / nf_queue / xfrm_output family gates, which
> 0/7 doesn't touch.
> 

I don't get what this all means What sink side patches? 0/7 of the
patches I posted touches what code? I don't think it makes sense to look
at that sysctl deep in the net stack, if that is what you are saying.


> On Mon, Oct 19, 2026 at 2:20 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     On Mon, Oct 19, 2026 at 02:13:04PM +0530, Pranjal Kumar Singh wrote:
>     > Hello Security Team,
>     >
>     > The IPv4 part of this was fixed some time ago in commit 6785011f8b16
>     > ("ipv4: validate checksum_start before completing checksum"): a packet
>     > whose virtio_net_hdr csum metadata points its checksum start inside the
>     > IP header makes skb_checksum_help() (the deferred csum completion)
>     > rewrite the header the stack has already validated (fixed checksum
>     > offset-width write at csum_start + csum_offset).  The IPv6 paths were
>     > not covered, and they still are not: a 2-patch series mirroring that
>     > commit for IPv4->IPv6, including its remaining not-yet-IPv6-guarded
>     > sinks, is reproduced below and attached as patches/0001 and 0002.
> 
>     Thanks, I think this has been reported already. Just to clarify, the effect
>     is just packet header corruption past validation, right?
> 
>     See [PATCH net-next v2 0/7] more virtio-net csum hardening
>     for WIP fixes.
> 
>     --
>     MST
> 
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-19 10:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-19  8:43 Kernel bug report: unguarded deferred skb_checksum_help() writes corrupt the previously-validated IPv6 fixed header (IPv6 counterpart of commit 6785011f8b16, "ipv4: validate checksum_start before completing checksum") Pranjal Kumar Singh
2026-10-19  8:50 ` Michael S. Tsirkin
     [not found]   ` <CA+UYBZCEe3C2HuqgZSZ9Xa7MUxCNy=9ckBmA1Kyjmt882ZRQBA@mail.gmail.com>
2026-10-19 10:09     ` Michael S. Tsirkin
2026-10-19  8:54 ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.