Skip to contentSkip to conversation

memory leak in netlink user->kernel processing

PATCH In review Denis V. Lunev 4 participants 5 messages Oct 1, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 memory leak in netlink user->kernel processing

netlink_kernel_create can be called with NULL as an input callback in several places, f.e. in kobject_uevent_init. This means that if one sends packet from user to kernel for such a socket, the packet will be leaked in the socket queue forever.

This patch adds a simple generic cleanup callback for these sockets.

net/netlink/af_netlink.c renamed from net/netlink/af_netlink.c.nlk4 +8 -2
@@ -1301,6 +1301,13 @@ out:
 	return err ? : copied;
 }
 
+static void netlink_rcv_drop(struct sock *sk, int len)
+{
+	struct sk_buff *skb;
+	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
+		kfree_skb(skb);
+}
+
 static void netlink_data_ready(struct sock *sk, int len)
 {
 	struct netlink_sock *nlk = nlk_sk(sk);
@@ -1346,8 +1353,7 @@ netlink_kernel_create(struct net *net, i
 
 	sk = sock->sk;
 	sk->sk_data_ready = netlink_data_ready;
-	if (input)
-		nlk_sk(sk)->data_ready = input;
+	nlk_sk(sk)->data_ready = input != NULL ? input : netlink_rcv_drop;
 
 	if (netlink_insert(sk, net, 0))
 		goto out_sock_release;
#1 lore raw
Quoted 6 lines · Denis V. Lunev

netlink_kernel_create can be called with NULL as an input callback in several places, f.e. in kobject_uevent_init. This means that if one sends packet from user to kernel for such a socket, the packet will be leaked in the socket queue forever.

This patch adds a simple generic cleanup callback for these sockets.

This should already be handled by netlink_getsockbypid:

        /* Don't bother queuing skb if kernel socket has no input
function */
        nlk = nlk_sk(sock);
        if ((nlk->pid == 0 && !nlk->data_ready) ||
            (sock->sk_state == NETLINK_CONNECTED &&
             nlk->dst_pid != nlk_sk(ssk)->pid)) {
                sock_put(sock);
                return ERR_PTR(-ECONNREFUSED);
        }
#2 lore raw
Quoted 20 lines · Patrick McHardy
Quoted 6 lines · Denis V. Lunev

netlink_kernel_create can be called with NULL as an input callback in several places, f.e. in kobject_uevent_init. This means that if one sends packet from user to kernel for such a socket, the packet will be leaked in the socket queue forever.

This patch adds a simple generic cleanup callback for these sockets.

This should already be handled by netlink_getsockbypid:

        /* Don't bother queuing skb if kernel socket has no input
function */
        nlk = nlk_sk(sock);
        if ((nlk->pid == 0 && !nlk->data_ready) ||
            (sock->sk_state == NETLINK_CONNECTED &&
             nlk->dst_pid != nlk_sk(ssk)->pid)) {
                sock_put(sock);
                return ERR_PTR(-ECONNREFUSED);
        }
Quoted 5 lines

-
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Looks so...

By the way, Patrick, this looks like nlk->pid == 0 if and only if this is a kernel socket. Right?

I have told with Alexey Kuznetsov and we have discrovered a way to get rid of

        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);

in netlink_sendskb/etc for kernel sockets and make user->kernel packets processing truly synchronous.

The idea is simple, we should queue/wakeup in kernel->user direction and simply call nlk->data_ready for user->kernel direction. This will remove all the crap we have now. But we need a mark to determine the direction. Which one will be better? (nlk->data_ready) or (nlk->pid == 0)

Regards,
Den

#3 lore raw
Quoted 3 lines · Denis V. Lunev

By the way, Patrick, this looks like nlk->pid == 0 if and only if this is a kernel socket. Right?

Thats correct.

Quoted 11 lines

I have told with Alexey Kuznetsov and we have discrovered a way to get rid of

        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);

in netlink_sendskb/etc for kernel sockets and make user->kernel packets processing truly synchronous.

The idea is simple, we should queue/wakeup in kernel->user direction and simply call nlk->data_ready for user->kernel direction. This will remove all the crap we have now. But we need a mark to determine the direction. Which one will be better? (nlk->data_ready) or (nlk->pid == 0)

Both would work fine, but I think nlk->pid is better since its actually the "address".

#4 lore raw
Quoted 14 lines · Patrick McHardy
Quoted 3 lines · Denis V. Lunev

By the way, Patrick, this looks like nlk->pid == 0 if and only if this is a kernel socket. Right?

Thats correct.

Quoted 7 lines

I have told with Alexey Kuznetsov and we have discrovered a way to get rid of

        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);

in netlink_sendskb/etc for kernel sockets and make user->kernel packets processing truly synchronous.

Quoted 8 lines
Quoted 4 lines

The idea is simple, we should queue/wakeup in kernel->user direction and simply call nlk->data_ready for user->kernel direction. This will remove all the crap we have now. But we need a mark to determine the direction. Which one will be better? (nlk->data_ready) or (nlk->pid == 0)

Both would work fine, but I think nlk->pid is better since its actually the "address".

Maybe. nlk->pid is also 0, before the socket is bound so it does not serve as a reliable indicator that you have a kernel socket.

My gut feel says the best test is:
(nlk->flags & NETLINK_KERNEL_SOCKET)

There is no confusion in that and it is dead obvious what we are testing for. Although we do still need to properly handle the case when netlink_kernel_create is called with a NULL input method. As long as get the proper -ECONNREFUSED the code path doesn't look like it matters.

Eric