From e80ce97d57f9da38f99fe94dd23d1e8229df824b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 22 Jul 2020 17:50:56 +0200 Subject: [PATCH] Revert "genetlink: remove genl_bind" This reverts commit 0845447d9c783a502bd3e13af0f38aa4c7655a77 which is commit 1e82a62fec613844da9e558f3493540a5b7a7b67 upstream. It breaks the API and isn't something we should really have to worry about in android devices. Cc: Sean Tranchetti Change-Id: I4ec83063705a9f0fe449ff46803f6594b69efd08 Signed-off-by: Greg Kroah-Hartman Signed-off-by: Will McVicker --- include/net/genetlink.h | 8 +++++++ net/netlink/genetlink.c | 49 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 3e3a1a38884a..decf6012a401 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -34,6 +34,12 @@ struct genl_info; * do additional, common, filtering and return an error * @post_doit: called after an operation's doit callback, it may * undo operations done by pre_doit, for example release locks + * @mcast_bind: a socket bound to the given multicast group (which + * is given as the offset into the groups array) + * @mcast_unbind: a socket was unbound from the given multicast group. + * Note that unbind() will not be called symmetrically if the + * generic netlink family is removed while there are still open + * sockets. * @attrbuf: buffer to store parsed attributes (private) * @mcgrps: multicast groups used by this family * @n_mcgrps: number of multicast groups @@ -56,6 +62,8 @@ struct genl_family { void (*post_doit)(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info); + int (*mcast_bind)(struct net *net, int group); + void (*mcast_unbind)(struct net *net, int group); struct nlattr ** attrbuf; /* private */ const struct genl_ops * ops; const struct genl_multicast_group *mcgrps; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index ede73ecfb1f5..cec2caaf34f0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -961,11 +961,60 @@ static struct genl_family genl_ctrl __ro_after_init = { .netnsok = true, }; +static int genl_bind(struct net *net, int group) +{ + struct genl_family *f; + int err = 0; + unsigned int id; + + down_read(&cb_lock); + + idr_for_each_entry(&genl_fam_idr, f, id) { + if (group >= f->mcgrp_offset && + group < f->mcgrp_offset + f->n_mcgrps) { + int fam_grp = group - f->mcgrp_offset; + + if (!f->netnsok && net != &init_net) + err = -ENOENT; + else if (f->mcast_bind) + err = f->mcast_bind(net, fam_grp); + else + err = 0; + break; + } + } + up_read(&cb_lock); + + return err; +} + +static void genl_unbind(struct net *net, int group) +{ + struct genl_family *f; + unsigned int id; + + down_read(&cb_lock); + + idr_for_each_entry(&genl_fam_idr, f, id) { + if (group >= f->mcgrp_offset && + group < f->mcgrp_offset + f->n_mcgrps) { + int fam_grp = group - f->mcgrp_offset; + + if (f->mcast_unbind) + f->mcast_unbind(net, fam_grp); + break; + } + } + up_read(&cb_lock); +} + static int __net_init genl_pernet_init(struct net *net) { struct netlink_kernel_cfg cfg = { .input = genl_rcv, .flags = NL_CFG_F_NONROOT_RECV, + .bind = genl_bind, + .unbind = genl_unbind, }; /* we'll bump the group number right afterwards */