mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-01 11:54:10 +00:00
netfilter: fix memory leaks on netlink_dump_start error
Shaochun Chen points out we leak dumper filter state allocations
stored in dump_control->data in case there is an error before netlink sets
cb_running (after which ->done will be called at some point).
In order to fix this, add .start functions and move allocations there.
Same pattern as used in commit 90fd131afc
("netfilter: nf_tables: move dumper state allocation into ->start").
Reported-by: shaochun chen <cscnull@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
4ef360dd6a
commit
3e673b23b5
2 changed files with 30 additions and 25 deletions
|
@ -846,6 +846,21 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[])
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ctnetlink_start(struct netlink_callback *cb)
|
||||||
|
{
|
||||||
|
const struct nlattr * const *cda = cb->data;
|
||||||
|
struct ctnetlink_filter *filter = NULL;
|
||||||
|
|
||||||
|
if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
|
||||||
|
filter = ctnetlink_alloc_filter(cda);
|
||||||
|
if (IS_ERR(filter))
|
||||||
|
return PTR_ERR(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb->data = filter;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
|
static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
|
||||||
{
|
{
|
||||||
struct ctnetlink_filter *filter = data;
|
struct ctnetlink_filter *filter = data;
|
||||||
|
@ -1290,19 +1305,12 @@ static int ctnetlink_get_conntrack(struct net *net, struct sock *ctnl,
|
||||||
|
|
||||||
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||||
struct netlink_dump_control c = {
|
struct netlink_dump_control c = {
|
||||||
|
.start = ctnetlink_start,
|
||||||
.dump = ctnetlink_dump_table,
|
.dump = ctnetlink_dump_table,
|
||||||
.done = ctnetlink_done,
|
.done = ctnetlink_done,
|
||||||
|
.data = (void *)cda,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) {
|
|
||||||
struct ctnetlink_filter *filter;
|
|
||||||
|
|
||||||
filter = ctnetlink_alloc_filter(cda);
|
|
||||||
if (IS_ERR(filter))
|
|
||||||
return PTR_ERR(filter);
|
|
||||||
|
|
||||||
c.data = filter;
|
|
||||||
}
|
|
||||||
return netlink_dump_start(ctnl, skb, nlh, &c);
|
return netlink_dump_start(ctnl, skb, nlh, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,29 +238,33 @@ static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = {
|
||||||
[NFACCT_FILTER_VALUE] = { .type = NLA_U32 },
|
[NFACCT_FILTER_VALUE] = { .type = NLA_U32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nfacct_filter *
|
static int nfnl_acct_start(struct netlink_callback *cb)
|
||||||
nfacct_filter_alloc(const struct nlattr * const attr)
|
|
||||||
{
|
{
|
||||||
struct nfacct_filter *filter;
|
const struct nlattr *const attr = cb->data;
|
||||||
struct nlattr *tb[NFACCT_FILTER_MAX + 1];
|
struct nlattr *tb[NFACCT_FILTER_MAX + 1];
|
||||||
|
struct nfacct_filter *filter;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!attr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy,
|
err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy,
|
||||||
NULL);
|
NULL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return ERR_PTR(err);
|
return err;
|
||||||
|
|
||||||
if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
|
if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
|
||||||
return ERR_PTR(-EINVAL);
|
return -EINVAL;
|
||||||
|
|
||||||
filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
|
filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
|
||||||
if (!filter)
|
if (!filter)
|
||||||
return ERR_PTR(-ENOMEM);
|
return -ENOMEM;
|
||||||
|
|
||||||
filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
|
filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
|
||||||
filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
|
filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
|
||||||
|
cb->data = filter;
|
||||||
|
|
||||||
return filter;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfnl_acct_get(struct net *net, struct sock *nfnl,
|
static int nfnl_acct_get(struct net *net, struct sock *nfnl,
|
||||||
|
@ -275,18 +279,11 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
|
||||||
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||||
struct netlink_dump_control c = {
|
struct netlink_dump_control c = {
|
||||||
.dump = nfnl_acct_dump,
|
.dump = nfnl_acct_dump,
|
||||||
|
.start = nfnl_acct_start,
|
||||||
.done = nfnl_acct_done,
|
.done = nfnl_acct_done,
|
||||||
|
.data = (void *)tb[NFACCT_FILTER],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tb[NFACCT_FILTER]) {
|
|
||||||
struct nfacct_filter *filter;
|
|
||||||
|
|
||||||
filter = nfacct_filter_alloc(tb[NFACCT_FILTER]);
|
|
||||||
if (IS_ERR(filter))
|
|
||||||
return PTR_ERR(filter);
|
|
||||||
|
|
||||||
c.data = filter;
|
|
||||||
}
|
|
||||||
return netlink_dump_start(nfnl, skb, nlh, &c);
|
return netlink_dump_start(nfnl, skb, nlh, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue