From: Johannes Berg Date: Fri, 16 Jan 2015 10:37:13 +0000 (+0100) Subject: genetlink: disallow subscribing to unknown mcast groups X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=5ad6300524c0332ac67e912c20d6e5cf262ba58f;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git genetlink: disallow subscribing to unknown mcast groups Jeff Layton reported that he could trigger the multicast unbind warning in generic netlink using trinity. I originally thought it was a race condition between unregistering the generic netlink family and closing the socket, but there's a far simpler explanation: genetlink currently allows subscribing to groups that don't (yet) exist, and the warning is triggered when unsubscribing again while the group still doesn't exist. Originally, I had a warning in the subscribe case and accepted it out of userspace API concerns, but the warning was of course wrong and removed later. However, I now think that allowing userspace to subscribe to groups that don't exist is wrong and could possibly become a security problem: Consider a (new) genetlink family implementing a permission check in the mcast_bind() function similar to the like the audit code does today; it would be possible to bypass the permission check by guessing the ID and subscribing to the group it exists. This is only possible in case a family like that would be dynamically loaded, but it doesn't seem like a huge stretch, for example wireless may be loaded when you plug in a USB device. To avoid this reject such subscription attempts. If this ends up causing userspace issues we may need to add a workaround in af_netlink to deny such requests but not return an error. Reported-by: Jeff Layton Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 2e11061ef885..c18d3f5624b2 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -985,7 +985,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = { static int genl_bind(struct net *net, int group) { - int i, err = 0; + int i, err = -ENOENT; down_read(&cb_lock); for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {