Skip to content

Commit ec38fb4

Browse files
ummakynesgregkh
authored andcommitted
netfilter: nfnl_cthelper: fix runtime expectation policy updates
[ Upstream commit 2c42225 ] We only allow runtime updates of expectation policies for timeout and maximum number of expectations, otherwise reject the update. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Acked-by: Liping Zhang <zlpnobody@gmail.com> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 02197d8 commit ec38fb4

1 file changed

Lines changed: 84 additions & 2 deletions

File tree

net/netfilter/nfnetlink_cthelper.c

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,89 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
255255
return ret;
256256
}
257257

258+
static int
259+
nfnl_cthelper_update_policy_one(const struct nf_conntrack_expect_policy *policy,
260+
struct nf_conntrack_expect_policy *new_policy,
261+
const struct nlattr *attr)
262+
{
263+
struct nlattr *tb[NFCTH_POLICY_MAX + 1];
264+
int err;
265+
266+
err = nla_parse_nested(tb, NFCTH_POLICY_MAX, attr,
267+
nfnl_cthelper_expect_pol);
268+
if (err < 0)
269+
return err;
270+
271+
if (!tb[NFCTH_POLICY_NAME] ||
272+
!tb[NFCTH_POLICY_EXPECT_MAX] ||
273+
!tb[NFCTH_POLICY_EXPECT_TIMEOUT])
274+
return -EINVAL;
275+
276+
if (nla_strcmp(tb[NFCTH_POLICY_NAME], policy->name))
277+
return -EBUSY;
278+
279+
new_policy->max_expected =
280+
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
281+
new_policy->timeout =
282+
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
283+
284+
return 0;
285+
}
286+
287+
static int nfnl_cthelper_update_policy_all(struct nlattr *tb[],
288+
struct nf_conntrack_helper *helper)
289+
{
290+
struct nf_conntrack_expect_policy new_policy[helper->expect_class_max + 1];
291+
struct nf_conntrack_expect_policy *policy;
292+
int i, err;
293+
294+
/* Check first that all policy attributes are well-formed, so we don't
295+
* leave things in inconsistent state on errors.
296+
*/
297+
for (i = 0; i < helper->expect_class_max + 1; i++) {
298+
299+
if (!tb[NFCTH_POLICY_SET + i])
300+
return -EINVAL;
301+
302+
err = nfnl_cthelper_update_policy_one(&helper->expect_policy[i],
303+
&new_policy[i],
304+
tb[NFCTH_POLICY_SET + i]);
305+
if (err < 0)
306+
return err;
307+
}
308+
/* Now we can safely update them. */
309+
for (i = 0; i < helper->expect_class_max + 1; i++) {
310+
policy = (struct nf_conntrack_expect_policy *)
311+
&helper->expect_policy[i];
312+
policy->max_expected = new_policy->max_expected;
313+
policy->timeout = new_policy->timeout;
314+
}
315+
316+
return 0;
317+
}
318+
319+
static int nfnl_cthelper_update_policy(struct nf_conntrack_helper *helper,
320+
const struct nlattr *attr)
321+
{
322+
struct nlattr *tb[NFCTH_POLICY_SET_MAX + 1];
323+
unsigned int class_max;
324+
int err;
325+
326+
err = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr,
327+
nfnl_cthelper_expect_policy_set);
328+
if (err < 0)
329+
return err;
330+
331+
if (!tb[NFCTH_POLICY_SET_NUM])
332+
return -EINVAL;
333+
334+
class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM]));
335+
if (helper->expect_class_max + 1 != class_max)
336+
return -EBUSY;
337+
338+
return nfnl_cthelper_update_policy_all(tb, helper);
339+
}
340+
258341
static int
259342
nfnl_cthelper_update(const struct nlattr * const tb[],
260343
struct nf_conntrack_helper *helper)
@@ -265,8 +348,7 @@ nfnl_cthelper_update(const struct nlattr * const tb[],
265348
return -EBUSY;
266349

267350
if (tb[NFCTH_POLICY]) {
268-
ret = nfnl_cthelper_parse_expect_policy(helper,
269-
tb[NFCTH_POLICY]);
351+
ret = nfnl_cthelper_update_policy(helper, tb[NFCTH_POLICY]);
270352
if (ret < 0)
271353
return ret;
272354
}

0 commit comments

Comments
 (0)