diff options
author | Kuniyuki Iwashima <kuniyu@google.com> | 2025-07-04 06:23:52 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-07-17 18:37:06 +0200 |
commit | 9f771816f14da6d6157a8c30069091abf6b566fb (patch) | |
tree | 7a4cd58a56c15fee5cdcf96d2b78e1253578b9f8 | |
parent | 36caab990b69ef4eec1d81c52a19f080b7daa059 (diff) |
atm: clip: Fix memory leak of struct clip_vcc.
[ Upstream commit 62dba28275a9a3104d4e33595c7b3328d4032d8d ]
ioctl(ATMARP_MKIP) allocates struct clip_vcc and set it to
vcc->user_back.
The code assumes that vcc_destroy_socket() passes NULL skb
to vcc->push() when the socket is close()d, and then clip_push()
frees clip_vcc.
However, ioctl(ATMARPD_CTRL) sets NULL to vcc->push() in
atm_init_atmarp(), resulting in memory leak.
Let's serialise two ioctl() by lock_sock() and check vcc->push()
in atm_init_atmarp() to prevent memleak.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250704062416.1613927-3-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | net/atm/clip.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c index 59bd67aac168..1fcf2f99c4c7 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -645,6 +645,9 @@ static struct atm_dev atmarpd_dev = { static int atm_init_atmarp(struct atm_vcc *vcc) { + if (vcc->push == clip_push) + return -EINVAL; + mutex_lock(&atmarpd_lock); if (atmarpd) { mutex_unlock(&atmarpd_lock); @@ -669,6 +672,7 @@ static int atm_init_atmarp(struct atm_vcc *vcc) static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct atm_vcc *vcc = ATM_SD(sock); + struct sock *sk = sock->sk; int err = 0; switch (cmd) { @@ -689,14 +693,18 @@ static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) err = clip_create(arg); break; case ATMARPD_CTRL: + lock_sock(sk); err = atm_init_atmarp(vcc); if (!err) { sock->state = SS_CONNECTED; __module_get(THIS_MODULE); } + release_sock(sk); break; case ATMARP_MKIP: + lock_sock(sk); err = clip_mkip(vcc, arg); + release_sock(sk); break; case ATMARP_SETENTRY: err = clip_setentry(vcc, (__force __be32)arg); |