From 75fadbc1381e4aef826177591a02968998f5ebe7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 26 Oct 2017 10:22:53 +0200 Subject: backports: fix the extack backport for dumps I also never seem to have really tested unload after dumps, and using the family->attrbuf was causing memory corruption in the copied family. Fix this by keeping track of the family copies separately and actually copying the attrbuf over so the family can use it from there. Signed-off-by: Johannes Berg --- backport/compat/backport-4.12.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'backport') diff --git a/backport/compat/backport-4.12.c b/backport/compat/backport-4.12.c index 382a3af4..767ecb98 100644 --- a/backport/compat/backport-4.12.c +++ b/backport/compat/backport-4.12.c @@ -19,10 +19,14 @@ enum nlmsgerr_attrs { struct bp_extack_genl_family { struct genl_family family; struct genl_family *real_family; + struct list_head list; struct genl_ops ops[]; }; +static LIST_HEAD(copies_list); +static DEFINE_MUTEX(copies_mutex); + static const struct nla_policy extack_dummy_policy[1] = {}; static struct bp_extack_genl_family *get_copy(__genl_const struct genl_ops *op) @@ -212,25 +216,39 @@ int bp_extack_genl_register_family(struct genl_family *family) copy->family.pre_doit = extack_pre_doit; copy->family.post_doit = extack_post_doit; - /* - * store in attrbuf, so that even if we re-register the family - * the data will be overwritten and we don't overwrite data - * that's used again later... - */ - family->attrbuf = (void *)copy; - err = __real_bp_extack_genl_register_family(©->family); - if (err) + if (err) { kfree(copy); - return err; + return err; + } + + /* copy this since the family might access it directly */ + family->attrbuf = copy->family.attrbuf; + + mutex_lock(&copies_mutex); + list_add_tail(©->list, &copies_list); + mutex_unlock(&copies_mutex); + + return 0; } EXPORT_SYMBOL_GPL(bp_extack_genl_register_family); int bp_extack_genl_unregister_family(struct genl_family *family) { - struct bp_extack_genl_family *copy = (void *)family->attrbuf; + struct bp_extack_genl_family *tmp, *copy = NULL; int err; + mutex_lock(&copies_mutex); + list_for_each_entry(tmp, &copies_list, list) { + if (tmp->real_family == family) { + copy = tmp; + break; + } + } + if (copy) + list_del(©->list); + mutex_unlock(&copies_mutex); + if (!copy) return -ENOENT; -- cgit v1.2.3