atm: clip: Fix memory leak of struct clip_vcc.
authorKuniyuki Iwashima <kuniyu@google.com>
Fri, 4 Jul 2025 06:23:52 +0000 (06:23 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 10 Jul 2025 00:52:26 +0000 (17:52 -0700)
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>
net/atm/clip.c

index f36f2c7d871463cba089c6bbfcf296ac7984f9d2..9c9c6c3d988610b00548c96a8119aed2c69226c7 100644 (file)
@@ -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);