aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-12-23 15:00:06 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-27 03:07:50 -0500
commit023e2cfa36c31b0ad28c159a1bb0d61ff57334c8 (patch)
treefb696a81e6c2246cec25cfa35741de31c090ed7a /net/netlink/genetlink.c
parenteb69c5bf8273edbe1c5c748fa299b5e5a08f35d6 (diff)
netlink/genetlink: pass network namespace to bind/unbind
Netlink families can exist in multiple namespaces, and for the most part multicast subscriptions are per network namespace. Thus it only makes sense to have bind/unbind notifications per network namespace. To achieve this, pass the network namespace of a given client socket to the bind/unbind functions. Also do this in generic netlink, and there also make sure that any bind for multicast groups that only exist in init_net is rejected. This isn't really a problem if it is accepted since a client in a different namespace will never receive any notifications from such a group, but it can confuse the family if not rejected (it's also possible to silently (without telling the family) accept it, but it would also have to be ignored on unbind so families that take any kind of action on bind/unbind won't do unnecessary work for invalid clients like that. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 05bf40bbd189..91566ed36c43 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -983,7 +983,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
983 { .name = "notify", }, 983 { .name = "notify", },
984}; 984};
985 985
986static int genl_bind(int group) 986static int genl_bind(struct net *net, int group)
987{ 987{
988 int i, err; 988 int i, err;
989 bool found = false; 989 bool found = false;
@@ -997,8 +997,10 @@ static int genl_bind(int group)
997 group < f->mcgrp_offset + f->n_mcgrps) { 997 group < f->mcgrp_offset + f->n_mcgrps) {
998 int fam_grp = group - f->mcgrp_offset; 998 int fam_grp = group - f->mcgrp_offset;
999 999
1000 if (f->mcast_bind) 1000 if (!f->netnsok && net != &init_net)
1001 err = f->mcast_bind(fam_grp); 1001 err = -ENOENT;
1002 else if (f->mcast_bind)
1003 err = f->mcast_bind(net, fam_grp);
1002 else 1004 else
1003 err = 0; 1005 err = 0;
1004 found = true; 1006 found = true;
@@ -1014,7 +1016,7 @@ static int genl_bind(int group)
1014 return err; 1016 return err;
1015} 1017}
1016 1018
1017static void genl_unbind(int group) 1019static void genl_unbind(struct net *net, int group)
1018{ 1020{
1019 int i; 1021 int i;
1020 bool found = false; 1022 bool found = false;
@@ -1029,7 +1031,7 @@ static void genl_unbind(int group)
1029 int fam_grp = group - f->mcgrp_offset; 1031 int fam_grp = group - f->mcgrp_offset;
1030 1032
1031 if (f->mcast_unbind) 1033 if (f->mcast_unbind)
1032 f->mcast_unbind(fam_grp); 1034 f->mcast_unbind(net, fam_grp);
1033 found = true; 1035 found = true;
1034 break; 1036 break;
1035 } 1037 }