ax25_rx_fragment() accumulates fragment lengths into ax25_cb->fraglen, which is an unsigned short. When the total exceeds 65535, fraglen wraps around to a small value. The subsequent alloc_skb(fraglen) allocates a too-small buffer, and skb_put() in the copy loop triggers skb_over_panic(). Add pskb_may_pull(skb, 1) at function entry to ensure the segmentation header byte is in the linear data area before dereferencing skb->data. This also rejects zero-length skbs, which the original code did not check for. Three issues in the overflow error path are also fixed: First, the current skb, after skb_pull(skb, 1), is neither enqueued nor freed before returning 1, leaking it. Add kfree_skb(skb) before the return. Second, ax25->fraglen is not reset after skb_queue_purge(). Add ax25->fraglen = 0 to restore a consistent state. Third, the explicit (unsigned int) cast on fraglen is unnecessary: the addition with skb->len (unsigned int) promotes fraglen automatically. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Mashiro Chen --- net/ax25/ax25_in.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 68202c19b19e3f..e1834e11bb0b6a 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c @@ -35,15 +35,20 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb) { struct sk_buff *skbn, *skbo; + if (!pskb_may_pull(skb, 1)) + return 0; + if (ax25->fragno != 0) { if (!(*skb->data & AX25_SEG_FIRST)) { if ((ax25->fragno - 1) == (*skb->data & AX25_SEG_REM)) { /* Enqueue fragment */ ax25->fragno = *skb->data & AX25_SEG_REM; skb_pull(skb, 1); /* skip fragno */ - if ((unsigned int)ax25->fraglen + skb->len > USHRT_MAX) { + if (ax25->fraglen + skb->len > USHRT_MAX) { + kfree_skb(skb); skb_queue_purge(&ax25->frag_queue); ax25->fragno = 0; + ax25->fraglen = 0; return 1; } ax25->fraglen += skb->len; -- 2.53.0