From: Paolo Abeni <pabeni@redhat.com>
To: ouster@cs.stanford.edu
Cc: horms@kernel.org, netdev@vger.kernel.org, kuba@kernel.org,
pabeni@redhat.com, edumazet@google.com
Subject: Re: [net-next,v17,11/14] net: homa: create homa_incoming.c
Date: Wed, 18 Mar 2026 08:21:44 +0100 [thread overview]
Message-ID: <20260318072144.269088-1-pabeni@redhat.com> (raw)
In-Reply-To: <20260316223228.2611-12-ouster@cs.stanford.edu>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
For local reproduction steps see https://netdev-ai.bots.linux.dev/ai-local.html
---
net: homa: create homa_incoming.c
This file contains most of the code for handling incoming packets,
including top-level dispatching code plus specific handlers for each
pack type. It also contains code for dispatching fully-received
messages to waiting application threads.
> diff --git a/net/homa/homa_impl.h b/net/homa/homa_impl.h
> index 4726762b688f..779abd7bb1b7 100644
> --- a/net/homa/homa_impl.h
> +++ b/net/homa/homa_impl.h
[ ... ]
> diff --git a/net/homa/homa_incoming.c b/net/homa/homa_incoming.c
> new file mode 100644
> index 000000000000..f083784921f4
> --- /dev/null
> +++ b/net/homa/homa_incoming.c
[ ... ]
> @@ -0,0 +1,887 @@
[ ... ]
> +/**
> + * homa_add_packet() - Add an incoming packet to the contents of a
> + * partially received message.
> + * @rpc: Add the packet to the msgin for this RPC.
> + * @skb: The new packet. This function takes ownership of the packet
> + * (the packet will either be freed or added to rpc->msgin.packets).
> + */
> +void homa_add_packet(struct homa_rpc *rpc, struct sk_buff *skb)
> + __must_hold(rpc->bucket->lock)
> +{
> + struct homa_data_hdr *h = (struct homa_data_hdr *)skb->data;
> + struct homa_gap *gap, *dummy, *gap2;
> + int start = ntohl(h->seg.offset);
> + int length = homa_data_len(skb);
> + enum skb_drop_reason reason;
> + int end = start + length;
> +
> + if ((start + length) > rpc->msgin.length) {
> + reason = SKB_DROP_REASON_PKT_TOO_BIG;
> + goto discard;
> + }
> +
> + if (start == rpc->msgin.recv_end) {
> + /* Common case: packet is sequential. */
> + rpc->msgin.recv_end += length;
> + goto keep;
> + }
> +
> + if (start > rpc->msgin.recv_end) {
> + /* Packet creates a new gap. */
> + if (!homa_gap_alloc(&rpc->msgin.gaps,
> + rpc->msgin.recv_end, start)) {
> + reason = SKB_DROP_REASON_NOMEM;
> + goto discard;
> + }
> + rpc->msgin.recv_end = end;
> + goto keep;
> + }
> +
> + /* Must now check to see if the packet fills in part or all of
> + * an existing gap.
> + */
> + list_for_each_entry_safe(gap, dummy, &rpc->msgin.gaps, links) {
> + /* Is packet at the start of this gap? */
> + if (start <= gap->start) {
> + if (end <= gap->start)
> + continue;
> + if (start < gap->start) {
> + reason = SKB_DROP_REASON_DUP_FRAG;
> + goto discard;
> + }
> + if (end > gap->end) {
> + reason = SKB_DROP_REASON_DUP_FRAG;
> + goto discard;
> + }
> + gap->start = end;
> + if (gap->start >= gap->end) {
> + list_del(&gap->links);
> + kfree(gap);
> + }
> + goto keep;
> + }
> +
> + /* Is packet at the end of this gap? BTW, at this point we know
> + * the packet can't cover the entire gap.
> + */
> + if (end >= gap->end) {
> + if (start >= gap->end)
> + continue;
> + if (end > gap->end) {
> + reason = SKB_DROP_REASON_DUP_FRAG;
> + goto discard;
> + }
> + gap->end = start;
> + goto keep;
> + }
> +
> + /* Packet is in the middle of the gap; must split the gap. */
> + gap2 = homa_gap_alloc(&gap->links, gap->start, start);
> + if (!gap2) {
> + reason = SKB_DROP_REASON_NOMEM;
> + goto discard;
> + }
> + gap2->time = gap->time;
> + gap->start = end;
> + goto keep;
> + }
> +
> +discard:
> + kfree_skb_reason(skb, reason);
^^^^^^
Can the 'reason' variable be used uninitialized here? When data has been
received sequentially (no gaps), a retransmitted duplicate packet with an
offset below recv_end won't match any of the early conditions (it doesn't
equal recv_end, it isn't greater than recv_end), so it falls through to the
gap traversal loop. With an empty gap list, the loop body never executes and
execution continues to the discard label where kfree_skb_reason() is called
with an uninitialized reason.
[ ... ]
> +/**
> + * homa_copy_to_user() - Copy as much data as possible from incoming
> + * packet buffers to buffers in user space.
> + * @rpc: RPC for which data should be copied. Must be locked by caller.
> + * Return: Zero for success or a negative errno if there is an error.
> + * It is possible for the RPC to be freed while this function
> + * executes (it releases and reacquires the RPC lock). If that
> + * happens, -EINVAL will be returned and the state of @rpc
> + * will be RPC_DEAD. Clears the RPC_PKTS_READY bit in @rpc->flags
> + * if all available packets have been copied out.
> + */
> +int homa_copy_to_user(struct homa_rpc *rpc)
> + __must_hold(rpc->bucket->lock)
> +{
[ ... ]
> +/**
> + * homa_dispatch_pkts() - Top-level function that processes a batch of packets,
> + * all related to the same RPC.
> + * @skb: First packet in the batch, linked through skb->next.
> + */
> +void homa_dispatch_pkts(struct sk_buff *skb)
> +{
[ ... ]
> + switch (h->common.type) {
> + case DATA:
> + homa_data_pkt(skb, rpc);
> + break;
> + case RESEND:
> + homa_resend_pkt(skb, rpc, hsk);
> + break;
> + case RPC_UNKNOWN:
> + homa_rpc_unknown_pkt(skb, rpc);
> + break;
> + case BUSY:
> + /* Nothing to do for these packets except reset
> + * silent_ticks, which happened above.
> + */
> + goto discard;
> + case NEED_ACK:
> + homa_need_ack_pkt(skb, hsk, rpc);
> + break;
> + case ACK:
> + homa_ack_pkt(skb, hsk, rpc);
> + break;
> + goto discard;
^^^^^^^^^^^^
This goto is unreachable because it follows the break statement above.
More critically, the switch has no default case. Looking at the validation
in homa_softirq (which checks 'h->type >= DATA && h->type <= MAX_OP'),
the header_lengths array (defined in homa_plumbing.c) has zero entries
for types 0x11, 0x15, and 0x16. Packets with these type values pass
validation since 'skb->len < 0' is always false.
When such a packet reaches homa_dispatch_pkts, no case matches, execution
falls through to 'continue', and the SKB is never freed. Can this leak
memory?
[ ... ]
> +/**
> + * homa_ack_pkt() - Handler for incoming ACK packets
> + * @skb: Incoming packet; size already verified large enough for header.
> + * This function now owns the packet.
> + * @hsk: Socket on which the packet was received.
> + * @rpc: The RPC named in the packet header, or NULL if no such
> + * RPC exists. The RPC lock will be dead on return.
> + */
> +void homa_ack_pkt(struct sk_buff *skb, struct homa_sock *hsk,
> + struct homa_rpc *rpc)
> + __must_hold(rpc->bucket->lock)
> +{
> + const struct in6_addr saddr = skb_canonical_ipv6_saddr(skb);
> + struct homa_ack_hdr *h = (struct homa_ack_hdr *)skb->data;
> + int i, count;
> +
> + if (rpc)
> + homa_rpc_end(rpc);
> +
> + count = ntohs(h->num_acks);
> + if (count > 0) {
> + if (rpc) {
> + /* Must temporarily release rpc's lock because
> + * homa_rpc_acked needs to acquire RPC locks.
> + */
> + homa_rpc_unlock(rpc);
> + for (i = 0; i < count; i++)
> + homa_rpc_acked(hsk, &saddr, &h->acks[i]);
^^^^^^^^^^^
Is 'count' validated before accessing h->acks[i] in this loop? The
num_acks field comes from the network via ntohs() and can be any value
from 0 to 65535. The acks array in struct homa_ack_hdr is declared as
'struct homa_ack acks[HOMA_MAX_ACKS_PER_PKT]' where HOMA_MAX_ACKS_PER_PKT
is 5 in net/homa/homa_wire.h.
If a peer sends an ACK packet with num_acks > 5, this code reads beyond
the acks[] array boundary in the skb data. The out-of-bounds data is
passed to homa_rpc_acked() which dereferences it (reading ack->server_port
and ack->client_id). Can this cause protocol state corruption or a kernel
crash if the read extends beyond the skb's allocated linear data region?
next prev parent reply other threads:[~2026-03-18 7:21 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-16 22:32 [PATCH net-next v17 00/14] Begin upstreaming Homa transport protocol John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 01/14] net: homa: define user-visible API for Homa John Ousterhout
2026-03-17 10:10 ` kernel test robot
2026-03-17 18:40 ` kernel test robot
2026-03-16 22:32 ` [PATCH net-next v17 02/14] net: homa: create homa_wire.h John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 03/14] net: homa: create shared Homa header files John Ousterhout
2026-03-18 7:20 ` [net-next,v17,03/14] " Paolo Abeni
2026-03-19 20:37 ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 04/14] net: homa: create homa_pool.h and homa_pool.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 05/14] net: homa: create homa_peer.h and homa_peer.c John Ousterhout
2026-03-18 7:21 ` [net-next,v17,05/14] " Paolo Abeni
2026-03-20 17:13 ` John Ousterhout
2026-03-20 17:20 ` Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 06/14] net: homa: create homa_sock.h and homa_sock.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 07/14] net: homa: create homa_interest.h and homa_interest.c John Ousterhout
2026-03-18 7:21 ` [net-next,v17,07/14] " Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 08/14] net: homa: create homa_rpc.h and homa_rpc.c John Ousterhout
2026-03-18 7:21 ` [net-next,v17,08/14] " Paolo Abeni
2026-03-23 22:43 ` John Ousterhout
2026-03-24 8:55 ` Paolo Abeni
2026-03-16 22:32 ` [PATCH net-next v17 09/14] net: homa: create homa_outgoing.c John Ousterhout
2026-03-18 7:21 ` [net-next,v17,09/14] " Paolo Abeni
2026-03-20 18:21 ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 10/14] net: homa: create homa_utils.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 11/14] net: homa: create homa_incoming.c John Ousterhout
2026-03-18 7:21 ` Paolo Abeni [this message]
2026-03-20 20:51 ` [net-next,v17,11/14] " John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 12/14] net: homa: create homa_timer.c John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 13/14] net: homa: create homa_plumbing.c John Ousterhout
2026-03-18 7:21 ` [net-next,v17,13/14] " Paolo Abeni
2026-03-20 21:49 ` John Ousterhout
2026-03-16 22:32 ` [PATCH net-next v17 14/14] net: homa: create Makefile and Kconfig John Ousterhout
2026-03-17 18:51 ` kernel test robot
2026-03-17 19:26 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260318072144.269088-1-pabeni@redhat.com \
--to=pabeni@redhat.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=ouster@cs.stanford.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox