summaryrefslogtreecommitdiff
path: root/net/netlink/policy.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2020-10-02 09:46:04 +0200
committerDavid S. Miller <davem@davemloft.net>2020-10-02 13:07:42 -0700
commit949ca6b82e43b342dba153a9fd643fb1b5e9f034 (patch)
tree2c6e4b48a50f0cbed8cc9600fa40c4146e9b52c3 /net/netlink/policy.c
parent360f89874635b08057757376b8cc4faa221862e2 (diff)
netlink: fix policy dump leak
[ Upstream commit a95bc734e60449e7b073ff7ff70c35083b290ae9 ] If userspace doesn't complete the policy dump, we leak the allocated state. Fix this. Fixes: d07dcf9aadd6 ("netlink: add infrastructure to expose policies to userspace") Signed-off-by: Johannes Berg <johannes.berg@intel.com> Reviewed-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/policy.c')
-rw-r--r--net/netlink/policy.c24
1 files changed, 10 insertions, 14 deletions
diff --git a/net/netlink/policy.c b/net/netlink/policy.c
index 62f977fa645a..7a9792442578 100644
--- a/net/netlink/policy.c
+++ b/net/netlink/policy.c
@@ -84,7 +84,6 @@ int netlink_policy_dump_start(const struct nla_policy *policy,
unsigned int policy_idx;
int err;
- /* also returns 0 if "*_state" is our ERR_PTR() end marker */
if (*_state)
return 0;
@@ -140,21 +139,11 @@ static bool netlink_policy_dump_finished(struct nl_policy_dump *state)
!state->policies[state->policy_idx].policy;
}
-bool netlink_policy_dump_loop(unsigned long *_state)
+bool netlink_policy_dump_loop(unsigned long _state)
{
- struct nl_policy_dump *state = (void *)*_state;
-
- if (IS_ERR(state))
- return false;
-
- if (netlink_policy_dump_finished(state)) {
- kfree(state);
- /* store end marker instead of freed state */
- *_state = (unsigned long)ERR_PTR(-ENOENT);
- return false;
- }
+ struct nl_policy_dump *state = (void *)_state;
- return true;
+ return !netlink_policy_dump_finished(state);
}
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
@@ -316,3 +305,10 @@ nla_put_failure:
nla_nest_cancel(skb, policy);
return -ENOBUFS;
}
+
+void netlink_policy_dump_free(unsigned long _state)
+{
+ struct nl_policy_dump *state = (void *)_state;
+
+ kfree(state);
+}