Skip to content

Commit dbb2483

Browse files
congwangklassert
authored andcommitted
xfrm: clean up xfrm protocol checks
In commit 6a53b75 ("xfrm: check id proto in validate_tmpl()") I introduced a check for xfrm protocol, but according to Herbert IPSEC_PROTO_ANY should only be used as a wildcard for lookup, so it should be removed from validate_tmpl(). And, IPSEC_PROTO_ANY is expected to only match 3 IPSec-specific protocols, this is why xfrm_state_flush() could still miss IPPROTO_ROUTING, which leads that those entries are left in net->xfrm.state_all before exit net. Fix this by replacing IPSEC_PROTO_ANY with zero. This patch also extracts the check from validate_tmpl() to xfrm_id_proto_valid() and uses it in parse_ipsecrequest(). With this, no other protocols should be added into xfrm. Fixes: 6a53b75 ("xfrm: check id proto in validate_tmpl()") Reported-by: [email protected] Cc: Steffen Klassert <[email protected]> Cc: Herbert Xu <[email protected]> Signed-off-by: Cong Wang <[email protected]> Acked-by: Herbert Xu <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 01ce31c commit dbb2483

File tree

5 files changed

+23
-16
lines changed

5 files changed

+23
-16
lines changed

include/net/xfrm.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,23 @@ static inline int xfrm_state_kern(const struct xfrm_state *x)
14041404
return atomic_read(&x->tunnel_users);
14051405
}
14061406

1407+
static inline bool xfrm_id_proto_valid(u8 proto)
1408+
{
1409+
switch (proto) {
1410+
case IPPROTO_AH:
1411+
case IPPROTO_ESP:
1412+
case IPPROTO_COMP:
1413+
#if IS_ENABLED(CONFIG_IPV6)
1414+
case IPPROTO_ROUTING:
1415+
case IPPROTO_DSTOPTS:
1416+
#endif
1417+
return true;
1418+
default:
1419+
return false;
1420+
}
1421+
}
1422+
1423+
/* IPSEC_PROTO_ANY only matches 3 IPsec protocols, 0 could match all. */
14071424
static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
14081425
{
14091426
return (!userproto || proto == userproto ||

net/ipv6/xfrm6_tunnel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
345345
unsigned int i;
346346

347347
xfrm_flush_gc();
348-
xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true);
348+
xfrm_state_flush(net, 0, false, true);
349349

350350
for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
351351
WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));

net/key/af_key.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1951,8 +1951,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
19511951

19521952
if (rq->sadb_x_ipsecrequest_mode == 0)
19531953
return -EINVAL;
1954+
if (!xfrm_id_proto_valid(rq->sadb_x_ipsecrequest_proto))
1955+
return -EINVAL;
19541956

1955-
t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */
1957+
t->id.proto = rq->sadb_x_ipsecrequest_proto;
19561958
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
19571959
return -EINVAL;
19581960
t->mode = mode;

net/xfrm/xfrm_state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,7 @@ void xfrm_state_fini(struct net *net)
23842384

23852385
flush_work(&net->xfrm.state_hash_work);
23862386
flush_work(&xfrm_state_gc_work);
2387-
xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true);
2387+
xfrm_state_flush(net, 0, false, true);
23882388

23892389
WARN_ON(!list_empty(&net->xfrm.state_all));
23902390

net/xfrm/xfrm_user.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,20 +1513,8 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
15131513
return -EINVAL;
15141514
}
15151515

1516-
switch (ut[i].id.proto) {
1517-
case IPPROTO_AH:
1518-
case IPPROTO_ESP:
1519-
case IPPROTO_COMP:
1520-
#if IS_ENABLED(CONFIG_IPV6)
1521-
case IPPROTO_ROUTING:
1522-
case IPPROTO_DSTOPTS:
1523-
#endif
1524-
case IPSEC_PROTO_ANY:
1525-
break;
1526-
default:
1516+
if (!xfrm_id_proto_valid(ut[i].id.proto))
15271517
return -EINVAL;
1528-
}
1529-
15301518
}
15311519

15321520
return 0;

0 commit comments

Comments
 (0)