From: netdev-bot+sashiko@kernel.org
To: edumazet@google.com
Cc: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com,
horms@kernel.org, netdev@vger.kernel.org, eric.dumazet@gmail.com,
mitch@sfgoth.com, 3chas3@gmail.com, qingfang.deng@linux.dev
Subject: Re: [PATCH v2 net] pppoatm: ensure a writable skb header and linear data
Date: Sun, 13 Sep 2026 23:32:54 +0000 [thread overview]
Message-ID: <178934237420.22033.12474248772012953233@kernel.org> (raw)
In-Reply-To: <20260912233048.3977192-1-edumazet@google.com>
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 · Low: 0 (1)
- [High] pppoatm_send() does not make the frame linear, although the
commit subject claims to "ensure a writable skb header and linear…
Pre-existing issues:
- [Low] net/atm/pppoatm.c never initialises pvcc->chan.hdrlen although
the channel requires LLC_LEN (4) bytes of headroom for e_llc…
--
pppoatm: ensure a writable skb header and linear data
pppoatm_send() now uses skb_cow_head() to get a writable header with room
for the LLC header, adds a pskb_may_pull(skb, 1) before looking at
skb->data[0], and defers the SC_COMP_PROT pull plus the LLC push until
after pppoatm_may_send() has succeeded, dropping the old "undo" heuristic.
A couple of questions about the linearity claim and about the channel
headroom hint.
> diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
> index 6da52d12df68e..5214786e61d11 100644
> --- a/net/atm/pppoatm.c
> +++ b/net/atm/pppoatm.c
> @@ -292,10 +292,13 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
> struct atm_vcc *vcc;
> int ret;
>
> + if (!pskb_may_pull(skb, 1)) {
> + kfree_skb(skb);
> + return DROP_PACKET;
> + }
> +
[Severity: High]
The subject says "linear data" and the changelog says this pull is there
"to prevent out-of-bounds reads on zero-length or non-linear frames
(e.g. from bridging)", but does this pull actually make the frame linear?
pskb_may_pull(skb, 1) only guarantees the single byte read as
skb->data[0]; skb_cow_head() -> __skb_cow() -> pskb_expand_head()
unshares and grows the head but leaves the paged fragments in place.
So a frame with skb->len > skb_headlen(skb) still reaches the device
send op further down this function:
ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
? DROP_PACKET : 1;
vcc->send is the device op (net/atm/raw.c does
vcc->send = vcc->dev->ops->send), and nothing under drivers/atm/
references nr_frags, skb_headlen or skb_linearize. For example
solos-pci psend() takes pktlen = skb->len and fpga_tx() then does:
memcpy_toio(TX_BUF(card, port), skb->data, skb->len);
or, in the DMA case:
dma_map_single(..., data, skb->len, DMA_TO_DEVICE);
For a paged skb, can this read past the end of the linear head buffer
and put unrelated heap bytes on the wire (and map a length larger than
the mapped object)?
The bridging path the changelog cites is the one that can deliver such a
frame: ppp_input() calls ppp_channel_bridge_input() before any
normalization, and the bridge hands the received skb to the peer channel
verbatim:
drivers/net/ppp/ppp_generic.c:ppp_channel_bridge_input() {
...
skb_scrub_packet(skb, !net_eq(pch->chan_net, pchb->chan_net));
if (!pchb->chan->ops->start_xmit(pchb->chan, skb))
...
}
The source channels do not linearize either (pppoe_rcv() only does
pskb_may_pull(skb, sizeof(struct pppoe_hdr)) before ppp_input(), and
l2tp_ppp.c is similar), while the normal ppp_start_xmit() path is linear
because the ppp netdev has no SG offload. Would skb_linearize() (or
pskb_may_pull(skb, skb->len)) here be the intended fix, or should the
subject and changelog be reworded so that backporters do not conclude
non-linear bridged frames are now handled?
> @@ -317,23 +320,13 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
>
> switch (pvcc->encaps) { /* LLC encapsulation needed */
> case e_llc:
> - if (skb_headroom(skb) < LLC_LEN) {
> - struct sk_buff *n;
> - n = skb_realloc_headroom(skb, LLC_LEN);
> - if (n != NULL &&
> - !pppoatm_may_send(pvcc, n->truesize)) {
> - kfree_skb(n);
> - goto nospace;
> - }
> - consume_skb(skb);
> - skb = n;
> - if (skb == NULL) {
> - bh_unlock_sock(sk_atm(vcc));
> - return DROP_PACKET;
> - }
> - } else if (!pppoatm_may_send(pvcc, skb->truesize))
> + if (skb_cow_head(skb, LLC_LEN)) {
> + bh_unlock_sock(sk_atm(vcc));
> + kfree_skb(skb);
> + return DROP_PACKET;
> + }
> + if (!pppoatm_may_send(pvcc, skb->truesize))
> goto nospace;
> - memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
> break;
[Severity: Low]
This isn't a bug introduced by this patch, since the previous code did the
same reallocation via skb_realloc_headroom() and dropped on failure, but
would it be worth setting pvcc->chan.hdrlen while touching this?
pppoatm_assign_vcc() sets chan.private, chan.ops and chan.mtu, and even
subtracts LLC_LEN from the MTU, but leaves chan.hdrlen at 0 (pvcc is
kzalloc'ed):
pvcc->chan.private = pvcc;
pvcc->chan.ops = &pppoatm_ops;
pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
(be.encaps == e_vc ? 0 : LLC_LEN);
include/linux/ppp_channel.h documents the field as:
int hdrlen; /* amount of headroom channel needs */
and ppp_generic honours it, e.g. in ppp_write():
skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
if (!skb)
goto out;
skb_reserve(skb, pf->hdrlen);
With hdrlen left at 0, frames written directly to the channel fd and
multilink fragments arrive with no headroom, so the new
skb_cow_head(skb, LLC_LEN) has to run a full pskb_expand_head() with
GFP_ATOMIC inside the bh_lock_sock() section for every such frame, and
drops the packet if that allocation fails. Setting
pvcc->chan.hdrlen = LLC_LEN for the non-e_vc encapsulations would make
the common case a no-op.
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260912233048.3977192-1-edumazet%40google.com
next prev parent reply other threads:[~2026-09-13 23:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-12 23:30 [PATCH v2 net] pppoatm: ensure a writable skb header and linear data Eric Dumazet
2026-09-13 23:32 ` netdev-bot+sashiko [this message]
2026-09-13 23:49 ` Eric Dumazet
2026-09-13 23:58 ` Eric Dumazet
2026-09-14 10:33 ` Simon Horman
2026-09-16 0:10 ` patchwork-bot+netdevbpf
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=178934237420.22033.12474248772012953233@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=3chas3@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=mitch@sfgoth.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=qingfang.deng@linux.dev \
/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