Subject: [1/1] netlink: fix broadcasting to the wrong group.

From: Evgeniy Polyakov <[email-masked]>
Date: Mon, 17 Apr 2006 13:36:33 +0400

When application is bound to group N and it is less than 32
and has first bit set (I tested with 1, 3, 5) and kernel broadcasts
events to group number 1, application will receive messages, even if
1. it was not subscribed to that group
2. it was bound to different group

Attached trivial test module and userspace program.
make
insmod nltest.ko
./nluser -g5

see the dmesg.
Test module sends data to group number 1, but application is bound and
subscribed to group 5, but still receives messages.

This issue happens due to the following check in do_one_broadcast():

if (nlk->pid == p->pid || p->group - 1 >= nlk->ngroups ||
	    !test_bit(p->group - 1, nlk->groups))

nlk->groups is set at bind time to the userspace provided bind group.
So in above case it will be 5.
But above test_bit() is supposed to check subscribed groups, which are
set using set_bit(users_group - 1, nlk->groups).
So when kernelspace broadcasts to group 1 above test_bit() returns true
and message is delivered to the wrong socket.

Attached patch removes nlk->groups[0] assignment at bind time since it
is completely meaningless due to subscription introduction.
nltest.c - simple test module which broadcasts events to group 1.
nluser.c - userspace application which receives data from socket bound
to specified group.

Tested with different groups (less than 32 though).
With patch applied it is required to subscribe to any group one wants to
listen to.
Patch is against 2.6.16

Signed-off-by: Evgeniy Polyakov <[email-masked]>

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 59dc7d1..895958b 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -588,7 +588,6 @@ static int netlink_bind(struct socket *s
 	netlink_update_subscriptions(sk, nlk->subscriptions +
 	                                 hweight32(nladdr->nl_groups) -
 	                                 hweight32(nlk->groups[0]));
-	nlk->groups[0] = (nlk->groups[0] & ~0xffffffffUL) | nladdr->nl_groups; 
 	netlink_table_ungrab();
 
 	return 0;

-- 
	Evgeniy Polyakov