Skip to content

Commit a95bc73

Browse files
jmberg-inteldavem330
authored andcommitted
netlink: fix policy dump leak
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>
1 parent ef9da46 commit a95bc73

3 files changed

Lines changed: 20 additions & 16 deletions

File tree

include/net/netlink.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,8 @@ void nla_get_range_signed(const struct nla_policy *pt,
19341934
int netlink_policy_dump_start(const struct nla_policy *policy,
19351935
unsigned int maxtype,
19361936
unsigned long *state);
1937-
bool netlink_policy_dump_loop(unsigned long *state);
1937+
bool netlink_policy_dump_loop(unsigned long state);
19381938
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long state);
1939+
void netlink_policy_dump_free(unsigned long state);
19391940

19401941
#endif

net/netlink/genetlink.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
10791079
if (err)
10801080
return err;
10811081

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

@@ -1113,6 +1113,12 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb)
11131113
return skb->len;
11141114
}
11151115

1116+
static int ctrl_dumppolicy_done(struct netlink_callback *cb)
1117+
{
1118+
netlink_policy_dump_free(cb->args[1]);
1119+
return 0;
1120+
}
1121+
11161122
static const struct genl_ops genl_ctrl_ops[] = {
11171123
{
11181124
.cmd = CTRL_CMD_GETFAMILY,
@@ -1123,6 +1129,7 @@ static const struct genl_ops genl_ctrl_ops[] = {
11231129
{
11241130
.cmd = CTRL_CMD_GETPOLICY,
11251131
.dumpit = ctrl_dumppolicy,
1132+
.done = ctrl_dumppolicy_done,
11261133
},
11271134
};
11281135

net/netlink/policy.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ int netlink_policy_dump_start(const struct nla_policy *policy,
8484
unsigned int policy_idx;
8585
int err;
8686

87-
/* also returns 0 if "*_state" is our ERR_PTR() end marker */
8887
if (*_state)
8988
return 0;
9089

@@ -140,21 +139,11 @@ static bool netlink_policy_dump_finished(struct nl_policy_dump *state)
140139
!state->policies[state->policy_idx].policy;
141140
}
142141

143-
bool netlink_policy_dump_loop(unsigned long *_state)
142+
bool netlink_policy_dump_loop(unsigned long _state)
144143
{
145-
struct nl_policy_dump *state = (void *)*_state;
146-
147-
if (IS_ERR(state))
148-
return false;
149-
150-
if (netlink_policy_dump_finished(state)) {
151-
kfree(state);
152-
/* store end marker instead of freed state */
153-
*_state = (unsigned long)ERR_PTR(-ENOENT);
154-
return false;
155-
}
144+
struct nl_policy_dump *state = (void *)_state;
156145

157-
return true;
146+
return !netlink_policy_dump_finished(state);
158147
}
159148

160149
int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
@@ -309,3 +298,10 @@ int netlink_policy_dump_write(struct sk_buff *skb, unsigned long _state)
309298
nla_nest_cancel(skb, policy);
310299
return -ENOBUFS;
311300
}
301+
302+
void netlink_policy_dump_free(unsigned long _state)
303+
{
304+
struct nl_policy_dump *state = (void *)_state;
305+
306+
kfree(state);
307+
}

0 commit comments

Comments
 (0)