Skip to content

Commit 6ad85ed

Browse files
committed
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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 47d55c6 + 8680407 commit 6ad85ed

File tree

5 files changed

+29
-74
lines changed

5 files changed

+29
-74
lines changed

net/key/af_key.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,8 @@ static u32 gen_reqid(struct net *net)
19401940
}
19411941

19421942
static int
1943-
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
1943+
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol,
1944+
struct sadb_x_ipsecrequest *rq)
19441945
{
19451946
struct net *net = xp_net(xp);
19461947
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)
19581959
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
19591960
return -EINVAL;
19601961
t->mode = mode;
1961-
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
1962+
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) {
1963+
if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) &&
1964+
pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
1965+
return -EINVAL;
19621966
t->optional = 1;
1963-
else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
1967+
} else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
19641968
t->reqid = rq->sadb_x_ipsecrequest_reqid;
19651969
if (t->reqid > IPSEC_MANUAL_REQID_MAX)
19661970
t->reqid = 0;
@@ -2002,7 +2006,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
20022006
rq->sadb_x_ipsecrequest_len < sizeof(*rq))
20032007
return -EINVAL;
20042008

2005-
if ((err = parse_ipsecrequest(xp, rq)) < 0)
2009+
if ((err = parse_ipsecrequest(xp, pol, rq)) < 0)
20062010
return err;
20072011
len -= rq->sadb_x_ipsecrequest_len;
20082012
rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);

net/xfrm/xfrm_device.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ int xfrm_dev_policy_add(struct net *net, struct xfrm_policy *xp,
378378
break;
379379
default:
380380
xdo->dev = NULL;
381-
dev_put(dev);
381+
netdev_put(dev, &xdo->dev_tracker);
382382
NL_SET_ERR_MSG(extack, "Unrecognized offload direction");
383383
return -EINVAL;
384384
}

net/xfrm/xfrm_interface_core.c

Lines changed: 4 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -310,52 +310,6 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
310310
skb->mark = 0;
311311
}
312312

313-
static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
314-
int encap_type, unsigned short family)
315-
{
316-
struct sec_path *sp;
317-
318-
sp = skb_sec_path(skb);
319-
if (sp && (sp->len || sp->olen) &&
320-
!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
321-
goto discard;
322-
323-
XFRM_SPI_SKB_CB(skb)->family = family;
324-
if (family == AF_INET) {
325-
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
326-
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
327-
} else {
328-
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
329-
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
330-
}
331-
332-
return xfrm_input(skb, nexthdr, spi, encap_type);
333-
discard:
334-
kfree_skb(skb);
335-
return 0;
336-
}
337-
338-
static int xfrmi4_rcv(struct sk_buff *skb)
339-
{
340-
return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
341-
}
342-
343-
static int xfrmi6_rcv(struct sk_buff *skb)
344-
{
345-
return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
346-
0, 0, AF_INET6);
347-
}
348-
349-
static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
350-
{
351-
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
352-
}
353-
354-
static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
355-
{
356-
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
357-
}
358-
359313
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
360314
{
361315
const struct xfrm_mode *inner_mode;
@@ -991,8 +945,8 @@ static struct pernet_operations xfrmi_net_ops = {
991945
};
992946

993947
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
994-
.handler = xfrmi6_rcv,
995-
.input_handler = xfrmi6_input,
948+
.handler = xfrm6_rcv,
949+
.input_handler = xfrm_input,
996950
.cb_handler = xfrmi_rcv_cb,
997951
.err_handler = xfrmi6_err,
998952
.priority = 10,
@@ -1042,8 +996,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
1042996
#endif
1043997

1044998
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
1045-
.handler = xfrmi4_rcv,
1046-
.input_handler = xfrmi4_input,
999+
.handler = xfrm4_rcv,
1000+
.input_handler = xfrm_input,
10471001
.cb_handler = xfrmi_rcv_cb,
10481002
.err_handler = xfrmi4_err,
10491003
.priority = 10,

net/xfrm/xfrm_policy.c

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,7 +3312,7 @@ xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
33123312

33133313
static inline int
33143314
xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
3315-
unsigned short family)
3315+
unsigned short family, u32 if_id)
33163316
{
33173317
if (xfrm_state_kern(x))
33183318
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,
33233323
(tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
33243324
!(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
33253325
!(x->props.mode != XFRM_MODE_TRANSPORT &&
3326-
xfrm_state_addr_cmp(tmpl, x, family));
3326+
xfrm_state_addr_cmp(tmpl, x, family)) &&
3327+
(if_id == 0 || if_id == x->if_id);
33273328
}
33283329

33293330
/*
@@ -3335,7 +3336,7 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
33353336
*/
33363337
static inline int
33373338
xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
3338-
unsigned short family)
3339+
unsigned short family, u32 if_id)
33393340
{
33403341
int idx = start;
33413342

@@ -3345,7 +3346,7 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
33453346
} else
33463347
start = -1;
33473348
for (; idx < sp->len; idx++) {
3348-
if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
3349+
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
33493350
return ++idx;
33503351
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
33513352
if (start == -1)
@@ -3712,12 +3713,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37123713
}
37133714
xfrm_nr = ti;
37143715

3715-
if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK &&
3716-
!xfrm_nr) {
3717-
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);
3718-
goto reject;
3719-
}
3720-
37213716
if (npols > 1) {
37223717
xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
37233718
tpp = stp;
@@ -3730,7 +3725,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37303725
* are implied between each two transformations.
37313726
*/
37323727
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
3733-
k = xfrm_policy_ok(tpp[i], sp, k, family);
3728+
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
37343729
if (k < 0) {
37353730
if (k < -1)
37363731
/* "-2 - errored_index" returned */
@@ -3745,9 +3740,6 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37453740
goto reject;
37463741
}
37473742

3748-
if (if_id)
3749-
secpath_reset(skb);
3750-
37513743
xfrm_pols_put(pols, npols);
37523744
return 1;
37533745
}

net/xfrm/xfrm_user.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
17701770
}
17711771

17721772
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
1773-
struct netlink_ext_ack *extack)
1773+
int dir, struct netlink_ext_ack *extack)
17741774
{
17751775
u16 prev_family;
17761776
int i;
@@ -1796,6 +1796,10 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
17961796
switch (ut[i].mode) {
17971797
case XFRM_MODE_TUNNEL:
17981798
case XFRM_MODE_BEET:
1799+
if (ut[i].optional && dir == XFRM_POLICY_OUT) {
1800+
NL_SET_ERR_MSG(extack, "Mode in optional template not allowed in outbound policy");
1801+
return -EINVAL;
1802+
}
17991803
break;
18001804
default:
18011805
if (ut[i].family != prev_family) {
@@ -1833,7 +1837,7 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family,
18331837
}
18341838

18351839
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
1836-
struct netlink_ext_ack *extack)
1840+
int dir, struct netlink_ext_ack *extack)
18371841
{
18381842
struct nlattr *rt = attrs[XFRMA_TMPL];
18391843

@@ -1844,7 +1848,7 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs,
18441848
int nr = nla_len(rt) / sizeof(*utmpl);
18451849
int err;
18461850

1847-
err = validate_tmpl(nr, utmpl, pol->family, extack);
1851+
err = validate_tmpl(nr, utmpl, pol->family, dir, extack);
18481852
if (err)
18491853
return err;
18501854

@@ -1921,7 +1925,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct net *net,
19211925
if (err)
19221926
goto error;
19231927

1924-
if (!(err = copy_from_user_tmpl(xp, attrs, extack)))
1928+
if (!(err = copy_from_user_tmpl(xp, attrs, p->dir, extack)))
19251929
err = copy_from_user_sec_ctx(xp, attrs);
19261930
if (err)
19271931
goto error;
@@ -1980,6 +1984,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
19801984

19811985
if (err) {
19821986
xfrm_dev_policy_delete(xp);
1987+
xfrm_dev_policy_free(xp);
19831988
security_xfrm_policy_free(xp->security);
19841989
kfree(xp);
19851990
return err;
@@ -3499,7 +3504,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
34993504
return NULL;
35003505

35013506
nr = ((len - sizeof(*p)) / sizeof(*ut));
3502-
if (validate_tmpl(nr, ut, p->sel.family, NULL))
3507+
if (validate_tmpl(nr, ut, p->sel.family, p->dir, NULL))
35033508
return NULL;
35043509

35053510
if (p->dir > XFRM_POLICY_OUT)

0 commit comments

Comments
 (0)