diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0da39eaed255..41d37442f186 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1513,6 +1513,7 @@ struct ctrl_dump_policy_ctx { struct netlink_policy_dump_state *state; const struct genl_family *rt; struct genl_op_iter *op_iter; + struct module *owner; u32 op; u16 fam_id; u8 dump_map:1, @@ -1555,6 +1556,9 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) return -ENOENT; ctx->rt = rt; + ctx->owner = rt->module; + if (!try_module_get(ctx->owner)) + return -ENOENT; if (tb[CTRL_ATTR_OP]) { struct genl_split_ops doit, dump; @@ -1565,7 +1569,7 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) err = genl_get_cmd_both(ctx->op, rt, &doit, &dump); if (err) { NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]); - return err; + goto err_put_owner; } if (doit.policy) { @@ -1583,16 +1587,20 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) goto err_free_state; } - if (!ctx->state) - return -ENODATA; + if (!ctx->state) { + err = -ENODATA; + goto err_put_owner; + } ctx->dump_map = 1; return 0; } ctx->op_iter = kmalloc_obj(*ctx->op_iter); - if (!ctx->op_iter) - return -ENOMEM; + if (!ctx->op_iter) { + err = -ENOMEM; + goto err_put_owner; + } genl_op_iter_init(rt, ctx->op_iter); ctx->dump_map = genl_op_iter_next(ctx->op_iter); @@ -1624,6 +1632,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) netlink_policy_dump_free(ctx->state); err_free_op_iter: kfree(ctx->op_iter); +err_put_owner: + module_put(ctx->owner); return err; } @@ -1760,6 +1770,7 @@ static int ctrl_dumppolicy_done(struct netlink_callback *cb) kfree(ctx->op_iter); netlink_policy_dump_free(ctx->state); + module_put(ctx->owner); return 0; }