ipsec-2023-05-16
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmRjDy4ACgkQrB3Eaf9P W7fTYQ/+J1Vic3YQI3xzrpeDWQInX0t/0vsNx0aTkoYZ+jP7F+0ybjb7TK+8yfmb N0Ov0l1NM3LCXlTaRRMAMO3KBtPnqQsHYYJpin1zSRr4zI/KE6R+u+DExIHB2p/z ArgNzahC2r8zKulJkrcGVm3LniQbv5NcSjAgAj/Y85flknQMghpOX5Y3qamtoc5s y9H2kcBxeAdAR+z8mphpD5lDmk6idQQP3VUg+YB9OmvKmrVT2FSO4p1KK+nxf3+5 9zxwaFLyEqY7IZsify5rRy2p9OXNReHt9lgDEmVdF4SRV49nLE7EMqa5cYxC1bfx TUcUqc8pZ0yNsqkkTqs33y45m/ogU+Uf3lF/uIpdZZBYyLmhTkw39hupvK31UfWv lDRQ7hj9pcUSTNBHadjnPsFmytBE3mKDyya1BWvNbWWSKpwxLDww88vAXmDqE1H0 SiElDIdojf4O8xQ31nAtNXIVDqcZfLROcEFHq6yqxd4i0HIe1wqeg/s+leibDkYG jA1wf98BPjuyX0iXxVLsGMATyXyeyZTDgEbiRIXnzDzrgWODeRmm2nYBEHLuyQTD MQEiMjoEtJJ5RBKC6pvsSewH4Zjjx80ahYAIBQmTO4Yt5fAgniz0fDRYvzlMTtK+ ZlwN2q+s+BB3DxA9VXp9ajEib60BNmykZi32GetlQtQLM+cvDlY= =/LPA -----END PGP SIGNATURE----- Merge tag 'ipsec-2023-05-16' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec Steffen Klassert says: ==================== pull request (net): ipsec 2023-05-16 1) Don't check the policy default if we have an allow policy. Fix from Sabrina Dubroca. 2) Fix netdevice refount usage on offload. From Leon Romanovsky. 3) Use netdev_put instead of dev_puti to correctly release the netdev on failure in xfrm_dev_policy_add. From Leon Romanovsky. 4) Revert "Fix XFRM-I support for nested ESP tunnels" This broke Netfilter policy matching. From Martin Willi. 5) Reject optional tunnel/BEET mode templates in outbound policies on netlink and pfkey sockets. From Tobias Brunner. 6) Check if_id in inbound policy/secpath match to make it symetric to the outbound codepath. From Benedict Wong. * tag 'ipsec-2023-05-16' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: Check if_id in inbound policy/secpath match af_key: Reject optional tunnel/BEET mode templates in outbound policies xfrm: Reject optional tunnel/BEET mode templates in outbound policies Revert "Fix XFRM-I support for nested ESP tunnels" xfrm: Fix leak of dev tracker xfrm: release all offloaded policy memory xfrm: don't check the default policy if the policy allows the packet ==================== Link: https://lore.kernel.org/r/20230516052405.2677554-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
6ad85ed0eb
|
@ -1940,7 +1940,8 @@ static u32 gen_reqid(struct net *net)
|
|||
}
|
||||
|
||||
static int
|
||||
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
|
||||
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol,
|
||||
struct sadb_x_ipsecrequest *rq)
|
||||
{
|
||||
struct net *net = xp_net(xp);
|
||||
struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
|
||||
|
@ -1958,9 +1959,12 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
|
|||
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
|
||||
return -EINVAL;
|
||||
t->mode = mode;
|
||||
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
|
||||
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) {
|
||||
if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) &&
|
||||
pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
|
||||
return -EINVAL;
|
||||
t->optional = 1;
|
||||
else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
|
||||
} else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
|
||||
t->reqid = rq->sadb_x_ipsecrequest_reqid;
|
||||
if (t->reqid > IPSEC_MANUAL_REQID_MAX)
|
||||
t->reqid = 0;
|
||||
|
@ -2002,7 +2006,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
|
|||
rq->sadb_x_ipsecrequest_len < sizeof(*rq))
|
||||
return -EINVAL;
|
||||
|
||||
if ((err = parse_ipsecrequest(xp, rq)) < 0)
|
||||
if ((err = parse_ipsecrequest(xp, pol, rq)) < 0)
|
||||
return err;
|
||||
len -= rq->sadb_x_ipsecrequest_len;
|
||||
rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
|
||||
|
|
|
@ -378,7 +378,7 @@ int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp,
|
|||
break;
|
||||
default:
|
||||
xdo->dev = NULL;
|
||||
dev_put(dev);
|
||||
netdev_put(dev, &xdo->dev_tracker);
|
||||
NL_SET_ERR_MSG(extack, "Unrecognized offload direction");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -310,52 +310,6 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
|
|||
skb->mark = 0;
|
||||
}
|
||||
|
||||
static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
|
||||
int encap_type, unsigned short family)
|
||||
{
|
||||
struct sec_path *sp;
|
||||
|
||||
sp = skb_sec_path(skb);
|
||||
if (sp && (sp->len || sp->olen) &&
|
||||
!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
|
||||
goto discard;
|
||||
|
||||
XFRM_SPI_SKB_CB(skb)->family = family;
|
||||
if (family == AF_INET) {
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
|
||||
} else {
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
|
||||
}
|
||||
|
||||
return xfrm_input(skb, nexthdr, spi, encap_type);
|
||||
discard:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xfrmi4_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
|
||||
}
|
||||
|
||||
static int xfrmi6_rcv(struct sk_buff *skb)
|
||||
{
|
||||
return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
|
||||
0, 0, AF_INET6);
|
||||
}
|
||||
|
||||
static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
{
|
||||
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
|
||||
}
|
||||
|
||||
static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
{
|
||||
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
|
||||
}
|
||||
|
||||
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode;
|
||||
|
@ -991,8 +945,8 @@ static struct pernet_operations xfrmi_net_ops = {
|
|||
};
|
||||
|
||||
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
|
||||
.handler = xfrmi6_rcv,
|
||||
.input_handler = xfrmi6_input,
|
||||
.handler = xfrm6_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi6_err,
|
||||
.priority = 10,
|
||||
|
@ -1042,8 +996,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
|
|||
#endif
|
||||
|
||||
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
||||
.handler = xfrmi4_rcv,
|
||||
.input_handler = xfrmi4_input,
|
||||
.handler = xfrm4_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi4_err,
|
||||
.priority = 10,
|
||||
|
|
|
@ -3312,7 +3312,7 @@ xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
|
|||
|
||||
static inline int
|
||||
xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
|
||||
unsigned short family)
|
||||
unsigned short family, u32 if_id)
|
||||
{
|
||||
if (xfrm_state_kern(x))
|
||||
return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family);
|
||||
|
@ -3323,7 +3323,8 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
|
|||
(tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
|
||||
!(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
|
||||
!(x->props.mode != XFRM_MODE_TRANSPORT &&
|
||||
xfrm_state_addr_cmp(tmpl, x, family));
|
||||
xfrm_state_addr_cmp(tmpl, x, family)) &&
|
||||
(if_id == 0 || if_id == x->if_id);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3335,7 +3336,7 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
|
|||
*/
|
||||
static inline int
|
||||
xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
|
||||
unsigned short family)
|
||||
unsigned short family, u32 if_id)
|
||||
{
|
||||
int idx = start;
|
||||
|
||||
|
@ -3345,7 +3346,7 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
|
|||
} else
|
||||
start = -1;
|
||||
for (; idx < sp->len; idx++) {
|
||||
if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
|
||||
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
|
||||
return ++idx;
|
||||
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
|
||||
if (start == -1)
|
||||
|
@ -3712,12 +3713,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
|||
}
|
||||
xfrm_nr = ti;
|
||||
|
||||
if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK &&
|
||||
!xfrm_nr) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if (npols > 1) {
|
||||
xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
|
||||
tpp = stp;
|
||||
|
@ -3730,7 +3725,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
|||
* are implied between each two transformations.
|
||||
*/
|
||||
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
|
||||
k = xfrm_policy_ok(tpp[i], sp, k, family);
|
||||
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
|
||||
if (k < 0) {
|
||||
if (k < -1)
|
||||
/* "-2 - errored_index" returned */
|
||||
|
@ -3745,9 +3740,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
|||
goto reject;
|
||||
}
|
||||
|
||||
if (if_id)
|
||||
secpath_reset(skb);
|
||||
|
||||
xfrm_pols_put(pols, npols);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1770,7 +1770,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
|
|||
}
|
||||
|
||||
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
|
||||
struct netlink_ext_ack *extack)
|
||||
int dir, struct netlink_ext_ack *extack)
|
||||
{
|
||||
u16 prev_family;
|
||||
int i;
|
||||
|
@ -1796,6 +1796,10 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
|
|||
switch (ut[i].mode) {
|
||||
case XFRM_MODE_TUNNEL:
|
||||
case XFRM_MODE_BEET:
|
||||
if (ut[i].optional && dir == XFRM_POLICY_OUT) {
|
||||
NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (ut[i].family != prev_family) {
|
||||
|
@ -1833,7 +1837,7 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
|
|||
}
|
||||
|
||||
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
|
||||
struct netlink_ext_ack *extack)
|
||||
int dir, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nlattr *rt = attrs[XFRMA_TMPL];
|
||||
|
||||
|
@ -1844,7 +1848,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
|
|||
int nr = nla_len(rt) / sizeof(*utmpl);
|
||||
int err;
|
||||
|
||||
err = validate_tmpl(nr, utmpl, pol->family, extack);
|
||||
err = validate_tmpl(nr, utmpl, pol->family, dir, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -1921,7 +1925,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net,
|
|||
if (err)
|
||||
goto error;
|
||||
|
||||
if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
|
||||
if (!(err = copy_from_user_tmpl(xp, attrs, p->dir, extack)))
|
||||
err = copy_from_user_sec_ctx(xp, attrs);
|
||||
if (err)
|
||||
goto error;
|
||||
|
@ -1980,6 +1984,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
|
||||
if (err) {
|
||||
xfrm_dev_policy_delete(xp);
|
||||
xfrm_dev_policy_free(xp);
|
||||
security_xfrm_policy_free(xp->security);
|
||||
kfree(xp);
|
||||
return err;
|
||||
|
@ -3499,7 +3504,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
|
|||
return NULL;
|
||||
|
||||
nr = ((len - sizeof(*p)) / sizeof(*ut));
|
||||
if (validate_tmpl(nr, ut, p->sel.family, NULL))
|
||||
if (validate_tmpl(nr, ut, p->sel.family, p->dir, NULL))
|
||||
return NULL;
|
||||
|
||||
if (p->dir > XFRM_POLICY_OUT)
|
||||
|
|
Loading…
Reference in New Issue