Skip to content

Commit 3d776e3

Browse files
tobiasbrunnerklassert
authored andcommitted
xfrm: Reject optional tunnel/BEET mode templates in outbound policies
xfrm_state_find() uses `encap_family` of the current template with the passed local and remote addresses to find a matching state. If an optional tunnel or BEET mode template is skipped in a mixed-family scenario, there could be a mismatch causing an out-of-bounds read as the addresses were not replaced to match the family of the next template. While there are theoretical use cases for optional templates in outbound policies, the only practical one is to skip IPComp states in inbound policies if uncompressed packets are received that are handled by an implicitly created IPIP state instead. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Tobias Brunner <[email protected]> Acked-by: Herbert Xu <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 5fc46f9 commit 3d776e3

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

net/xfrm/xfrm_user.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
17681768
}
17691769

17701770
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
1771-
struct netlink_ext_ack *extack)
1771+
int dir, struct netlink_ext_ack *extack)
17721772
{
17731773
u16 prev_family;
17741774
int i;
@@ -1794,6 +1794,10 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
17941794
switch (ut[i].mode) {
17951795
case XFRM_MODE_TUNNEL:
17961796
case XFRM_MODE_BEET:
1797+
if (ut[i].optional && dir == XFRM_POLICY_OUT) {
1798+
NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy");
1799+
return -EINVAL;
1800+
}
17971801
break;
17981802
default:
17991803
if (ut[i].family != prev_family) {
@@ -1831,7 +1835,7 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
18311835
}
18321836

18331837
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
1834-
struct netlink_ext_ack *extack)
1838+
int dir, struct netlink_ext_ack *extack)
18351839
{
18361840
struct nlattr *rt = attrs[XFRMA_TMPL];
18371841

@@ -1842,7 +1846,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
18421846
int nr = nla_len(rt) / sizeof(*utmpl);
18431847
int err;
18441848

1845-
err = validate_tmpl(nr, utmpl, pol->family, extack);
1849+
err = validate_tmpl(nr, utmpl, pol->family, dir, extack);
18461850
if (err)
18471851
return err;
18481852

@@ -1919,7 +1923,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net,
19191923
if (err)
19201924
goto error;
19211925

1922-
if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
1926+
if (!(err = copy_from_user_tmpl(xp, attrs, p->dir, extack)))
19231927
err = copy_from_user_sec_ctx(xp, attrs);
19241928
if (err)
19251929
goto error;
@@ -3498,7 +3502,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
34983502
return NULL;
34993503

35003504
nr = ((len - sizeof(*p)) / sizeof(*ut));
3501-
if (validate_tmpl(nr, ut, p->sel.family, NULL))
3505+
if (validate_tmpl(nr, ut, p->sel.family, p->dir, NULL))
35023506
return NULL;
35033507

35043508
if (p->dir > XFRM_POLICY_OUT)

0 commit comments

Comments
 (0)