Skip to content

Commit

Permalink
netlink: fix policy dump leak
Browse files Browse the repository at this point in the history
[ Upstream commit a95bc73 ]

If userspace doesn't complete the policy dump, we leak the
allocated state. Fix this.

Fixes: d07dcf9 ("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>
  • Loading branch information
Johannes Berg authored and David S. Miller committed Oct 2, 2020
1 parent 360f898 commit 949ca6b
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 16 deletions.
3 changes: 2 additions & 1 deletion include/net/netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,8 @@ void nla_get_range_signed(const struct nla_policy *pt,
int netlink_policy_dump_start(const struct nla_policy *policy,
unsigned int maxtype,
unsigned long *state);
bool netlink_policy_dump_loop(unsigned long *state);
bool netlink_policy_dump_loop(unsigned long state);
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long state);
void netlink_policy_dump_free(unsigned long state);

#endif
9 changes: 8 additions & 1 deletion net/netlink/genetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,7 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
if (err)
return err;

while (netlink_policy_dump_loop(&cb->args[1])) {
while (netlink_policy_dump_loop(cb->args[1])) {
void *hdr;
struct nlattr *nest;

Expand Down Expand Up @@ -1113,6 +1113,12 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}

static int ctrl_dumppolicy_done(struct netlink_callback *cb)
{
netlink_policy_dump_free(cb->args[1]);
return 0;
}

static const struct genl_ops genl_ctrl_ops[] = {
{
.cmd = CTRL_CMD_GETFAMILY,
Expand All @@ -1123,6 +1129,7 @@ static const struct genl_ops genl_ctrl_ops[] = {
{
.cmd = CTRL_CMD_GETPOLICY,
.dumpit = ctrl_dumppolicy,
.done = ctrl_dumppolicy_done,
},
};

Expand Down
24 changes: 10 additions & 14 deletions net/netlink/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -316,3 +305,10 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
nla_nest_cancel(skb, policy);
return -ENOBUFS;
}

void netlink_policy_dump_free(unsigned long _state)
{
struct nl_policy_dump *state = (void *)_state;

kfree(state);
}

0 comments on commit 949ca6b

Please sign in to comment.