summaryrefslogtreecommitdiff
path: root/backport
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2017-10-26 10:22:53 +0200
committerJohannes Berg <johannes.berg@intel.com>2017-10-26 10:22:53 +0200
commit75fadbc1381e4aef826177591a02968998f5ebe7 (patch)
tree239ac55d3d6093ef261d76c934b9ad0fa217bc2b /backport
parent0d4503988a997e6414d1bf074c9a6fc62a7b339c (diff)
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 <johannes.berg@intel.com>
Diffstat (limited to 'backport')
-rw-r--r--backport/compat/backport-4.12.c38
1 files changed, 28 insertions, 10 deletions
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(&copy->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(&copy->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(&copy->list);
+ mutex_unlock(&copies_mutex);
+
if (!copy)
return -ENOENT;