From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-bn3nam01on0139.outbound.protection.outlook.com ([104.47.33.139]:52931 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727480AbeH3WHE (ORCPT ); Thu, 30 Aug 2018 18:07:04 -0400 From: Sasha Levin To: "stable@vger.kernel.org" CC: Florian Westphal , Pablo Neira Ayuso , Sasha Levin Subject: [PATCH AUTOSEL 4.18 043/113] netfilter: fix memory leaks on netlink_dump_start error Date: Thu, 30 Aug 2018 18:03:01 +0000 Message-ID: <20180830180050.35735-43-alexander.levin@microsoft.com> References: <20180830180050.35735-1-alexander.levin@microsoft.com> In-Reply-To: <20180830180050.35735-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Florian Westphal [ Upstream commit 3e673b23b541b8e7f773b2d378d6eb99831741cd ] 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 90fd131afc565159c9e0ea742f082b337e10f8c6 ("netfilter: nf_tables: move dumper state allocation into ->start"). Reported-by: shaochun chen Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nf_conntrack_netlink.c | 26 ++++++++++++++++--------- net/netfilter/nfnetlink_acct.c | 29 +++++++++++++--------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntr= ack_netlink.c index 20a2e37c76d1..e952eedf44b4 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -821,6 +821,21 @@ ctnetlink_alloc_filter(const struct nlattr * const cda= []) #endif } =20 +static int ctnetlink_start(struct netlink_callback *cb) +{ + const struct nlattr * const *cda =3D cb->data; + struct ctnetlink_filter *filter =3D NULL; + + if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) { + filter =3D ctnetlink_alloc_filter(cda); + if (IS_ERR(filter)) + return PTR_ERR(filter); + } + + cb->data =3D filter; + return 0; +} + static int ctnetlink_filter_match(struct nf_conn *ct, void *data) { struct ctnetlink_filter *filter =3D data; @@ -1240,19 +1255,12 @@ static int ctnetlink_get_conntrack(struct net *net,= struct sock *ctnl, =20 if (nlh->nlmsg_flags & NLM_F_DUMP) { struct netlink_dump_control c =3D { + .start =3D ctnetlink_start, .dump =3D ctnetlink_dump_table, .done =3D ctnetlink_done, + .data =3D (void *)cda, }; =20 - if (cda[CTA_MARK] && cda[CTA_MARK_MASK]) { - struct ctnetlink_filter *filter; - - filter =3D ctnetlink_alloc_filter(cda); - if (IS_ERR(filter)) - return PTR_ERR(filter); - - c.data =3D filter; - } return netlink_dump_start(ctnl, skb, nlh, &c); } =20 diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.= c index a0e5adf0b3b6..8fa8bf7c48e6 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -238,29 +238,33 @@ static const struct nla_policy filter_policy[NFACCT_F= ILTER_MAX + 1] =3D { [NFACCT_FILTER_VALUE] =3D { .type =3D NLA_U32 }, }; =20 -static struct nfacct_filter * -nfacct_filter_alloc(const struct nlattr * const attr) +static int nfnl_acct_start(struct netlink_callback *cb) { - struct nfacct_filter *filter; + const struct nlattr *const attr =3D cb->data; struct nlattr *tb[NFACCT_FILTER_MAX + 1]; + struct nfacct_filter *filter; int err; =20 + if (!attr) + return 0; + err =3D nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy, NULL); if (err < 0) - return ERR_PTR(err); + return err; =20 if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE]) - return ERR_PTR(-EINVAL); + return -EINVAL; =20 filter =3D kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL); if (!filter) - return ERR_PTR(-ENOMEM); + return -ENOMEM; =20 filter->mask =3D ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK])); filter->value =3D ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE])); + cb->data =3D filter; =20 - return filter; + return 0; } =20 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) { struct netlink_dump_control c =3D { .dump =3D nfnl_acct_dump, + .start =3D nfnl_acct_start, .done =3D nfnl_acct_done, + .data =3D (void *)tb[NFACCT_FILTER], }; =20 - if (tb[NFACCT_FILTER]) { - struct nfacct_filter *filter; - - filter =3D nfacct_filter_alloc(tb[NFACCT_FILTER]); - if (IS_ERR(filter)) - return PTR_ERR(filter); - - c.data =3D filter; - } return netlink_dump_start(nfnl, skb, nlh, &c); } =20 --=20 2.17.1