mirror of
https://github.com/torvalds/linux.git
synced 2026-03-07 23:04:33 +01:00
atm: lec: fix null-ptr-deref in lec_arp_clear_vccs
syzkaller reported a null-ptr-deref in lec_arp_clear_vccs(). This issue can be easily reproduced using the syzkaller reproducer. In the ATM LANE (LAN Emulation) module, the same atm_vcc can be shared by multiple lec_arp_table entries (e.g., via entry->vcc or entry->recv_vcc). When the underlying VCC is closed, lec_vcc_close() iterates over all ARP entries and calls lec_arp_clear_vccs() for each matched entry. For example, when lec_vcc_close() iterates through the hlists in priv->lec_arp_empty_ones or other ARP tables: 1. In the first iteration, for the first matched ARP entry sharing the VCC, lec_arp_clear_vccs() frees the associated vpriv (which is vcc->user_back) and sets vcc->user_back to NULL. 2. In the second iteration, for the next matched ARP entry sharing the same VCC, lec_arp_clear_vccs() is called again. It obtains a NULL vpriv from vcc->user_back (via LEC_VCC_PRIV(vcc)) and then attempts to dereference it via `vcc->pop = vpriv->old_pop`, leading to a null-ptr-deref crash. Fix this by adding a null check for vpriv before dereferencing it. If vpriv is already NULL, it means the VCC has been cleared by a previous call, so we can safely skip the cleanup and just clear the entry's vcc/recv_vcc pointers. The entire cleanup block (including vcc_release_async()) is placed inside the vpriv guard because a NULL vpriv indicates the VCC has already been fully released by a prior iteration — repeating the teardown would redundantly set flags and trigger callbacks on an already-closing socket. The Fixes tag points to the initial commit because the entry->vcc path has been vulnerable since the original code. The entry->recv_vcc path was later added by commit8d9f73c0ad("atm: fix a memory leak of vcc->user_back") with the same pattern, and both paths are fixed here. Reported-by: syzbot+72e3ea390c305de0e259@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/68c95a83.050a0220.3c6139.0e5c.GAE@google.com/T/ Fixes:1da177e4c3("Linux-2.6.12-rc2") Suggested-by: Dan Carpenter <dan.carpenter@linaro.org> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com> Link: https://patch.msgid.link/20260225123250.189289-1-jiayuan.chen@linux.dev Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
74badb9c20
commit
101bacb303
1 changed files with 15 additions and 11 deletions
|
|
@ -1260,24 +1260,28 @@ static void lec_arp_clear_vccs(struct lec_arp_table *entry)
|
|||
struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
|
||||
struct net_device *dev = (struct net_device *)vcc->proto_data;
|
||||
|
||||
vcc->pop = vpriv->old_pop;
|
||||
if (vpriv->xoff)
|
||||
netif_wake_queue(dev);
|
||||
kfree(vpriv);
|
||||
vcc->user_back = NULL;
|
||||
vcc->push = entry->old_push;
|
||||
vcc_release_async(vcc, -EPIPE);
|
||||
if (vpriv) {
|
||||
vcc->pop = vpriv->old_pop;
|
||||
if (vpriv->xoff)
|
||||
netif_wake_queue(dev);
|
||||
kfree(vpriv);
|
||||
vcc->user_back = NULL;
|
||||
vcc->push = entry->old_push;
|
||||
vcc_release_async(vcc, -EPIPE);
|
||||
}
|
||||
entry->vcc = NULL;
|
||||
}
|
||||
if (entry->recv_vcc) {
|
||||
struct atm_vcc *vcc = entry->recv_vcc;
|
||||
struct lec_vcc_priv *vpriv = LEC_VCC_PRIV(vcc);
|
||||
|
||||
kfree(vpriv);
|
||||
vcc->user_back = NULL;
|
||||
if (vpriv) {
|
||||
kfree(vpriv);
|
||||
vcc->user_back = NULL;
|
||||
|
||||
entry->recv_vcc->push = entry->old_recv_push;
|
||||
vcc_release_async(entry->recv_vcc, -EPIPE);
|
||||
entry->recv_vcc->push = entry->old_recv_push;
|
||||
vcc_release_async(entry->recv_vcc, -EPIPE);
|
||||
}
|
||||
entry->recv_vcc = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue