mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 22:05:08 +00:00
ipsec-2023-02-08
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmPjhfIACgkQrB3Eaf9P W7c5cg//b8Kpjp9AVOHzQ2UfZ5YbFNC3F+goJRWtCVIfXTft2N+1gn80uXk5q1r1 GjSAlOxh2lQcNAZR4pWAXXqDq8vQuSmuNn7H6YZg8n6a9oFBi3fX5m1tNdu+G0wu Hv28M1jZgmnwJXcUQax3N59NHe1dv/CdtDd9qg6stvFDW3lcD96EbJUkKNsPwpin RZ/CqZX8UBpc+JRQmPPHw7dRSlvUh0hmr2m4HD63RJiYDrgOG9SO/Xx/GW6t/i9u XbuXezJxaulOvbB77uhevPkJqyDGy7IT3Ou0s5GGswiYZ6+ctcZZTayRsKcPWjnk n+OS7jk0yEApN1ZAo+wZD9inYKZuYOFNs2hkSetbca9NJ7ZpnXUoqvFxbZKl8biR v/ecf2yd31T+Vk0mhwBlgmcVfKNQzmRZA45UnOnxuYEXWNok89uQMqHmLdbSBrpR T0LptPzP5Vd7N33zRIiZS7t9vrlw9Xjfbm9O/sSHh0LuRED2gfHHp85MwBhcNfYA AKuxpj8Q9vEf1VW0OYhXyz8Te2+6oB2JJhqNdFsjea64zEoXFeJuSMYq/9DBzIDu glToJME9CV9BCN+r/q96zXBJao2UU4BhSGUVActKOktCnLJOE+XRsR7tpm2hHzr1 wY1PHvCvbpvNXPTGsAf6nijwSFSAcrErfD3ZmyvWvkmopdEajW0= =Bkiy -----END PGP SIGNATURE----- Merge tag 'ipsec-2023-02-08' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec Steffen Klassert says: ==================== ipsec 2023-02-08 1) Fix policy checks for nested IPsec tunnels when using xfrm interfaces. From Benedict Wong. 2) Fix netlink message expression on 32=>64-bit messages translators. From Anastasia Belova. 3) Prevent potential spectre v1 gadget in xfrm_xlate32_attr. From Eric Dumazet. 4) Always consistently use time64_t in xfrm_timer_handler. From Eric Dumazet. 5) Fix KCSAN reported bug: Multiple cpus can update use_time at the same time. From Eric Dumazet. 6) Fix SCP copy from IPv4 to IPv6 on interfamily tunnel. From Christian Hopps. * tag 'ipsec-2023-02-08' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: fix bug with DSCP copy to v6 from v4 tunnel xfrm: annotate data-race around use_time xfrm: consistently use time64_t in xfrm_timer_handler() xfrm/compat: prevent potential spectre v1 gadget in xfrm_xlate32_attr() xfrm: compat: change expression for switch in xfrm_xlate64 Fix XFRM-I support for nested ESP tunnels ==================== Link: https://lore.kernel.org/r/20230208114322.266510-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
646be03ec4
@ -5,6 +5,7 @@
|
||||
* Based on code and translator idea by: Florian Westphal <fw@strlen.de>
|
||||
*/
|
||||
#include <linux/compat.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/xfrm.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
@ -302,7 +303,7 @@ static int xfrm_xlate64(struct sk_buff *dst, const struct nlmsghdr *nlh_src)
|
||||
nla_for_each_attr(nla, attrs, len, remaining) {
|
||||
int err;
|
||||
|
||||
switch (type) {
|
||||
switch (nlh_src->nlmsg_type) {
|
||||
case XFRM_MSG_NEWSPDINFO:
|
||||
err = xfrm_nla_cpy(dst, nla, nla_len(nla));
|
||||
break;
|
||||
@ -437,6 +438,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla,
|
||||
NL_SET_ERR_MSG(extack, "Bad attribute");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
type = array_index_nospec(type, XFRMA_MAX + 1);
|
||||
if (nla_len(nla) < compat_policy[type].len) {
|
||||
NL_SET_ERR_MSG(extack, "Attribute bad length");
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -279,8 +279,7 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
|
||||
goto out;
|
||||
|
||||
if (x->props.flags & XFRM_STATE_DECAP_DSCP)
|
||||
ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)),
|
||||
ipipv6_hdr(skb));
|
||||
ipv6_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipipv6_hdr(skb));
|
||||
if (!(x->props.flags & XFRM_STATE_NOECN))
|
||||
ipip6_ecn_decapsulate(skb);
|
||||
|
||||
|
@ -310,6 +310,52 @@ 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;
|
||||
@ -945,8 +991,8 @@ static struct pernet_operations xfrmi_net_ops = {
|
||||
};
|
||||
|
||||
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
|
||||
.handler = xfrm6_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.handler = xfrmi6_rcv,
|
||||
.input_handler = xfrmi6_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi6_err,
|
||||
.priority = 10,
|
||||
@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
|
||||
#endif
|
||||
|
||||
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
|
||||
.handler = xfrm4_rcv,
|
||||
.input_handler = xfrm_input,
|
||||
.handler = xfrmi4_rcv,
|
||||
.input_handler = xfrmi4_input,
|
||||
.cb_handler = xfrmi_rcv_cb,
|
||||
.err_handler = xfrmi4_err,
|
||||
.priority = 10,
|
||||
|
@ -336,7 +336,7 @@ static void xfrm_policy_timer(struct timer_list *t)
|
||||
}
|
||||
if (xp->lft.hard_use_expires_seconds) {
|
||||
time64_t tmo = xp->lft.hard_use_expires_seconds +
|
||||
(xp->curlft.use_time ? : xp->curlft.add_time) - now;
|
||||
(READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now;
|
||||
if (tmo <= 0)
|
||||
goto expired;
|
||||
if (tmo < next)
|
||||
@ -354,7 +354,7 @@ static void xfrm_policy_timer(struct timer_list *t)
|
||||
}
|
||||
if (xp->lft.soft_use_expires_seconds) {
|
||||
time64_t tmo = xp->lft.soft_use_expires_seconds +
|
||||
(xp->curlft.use_time ? : xp->curlft.add_time) - now;
|
||||
(READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now;
|
||||
if (tmo <= 0) {
|
||||
warn = 1;
|
||||
tmo = XFRM_KM_TIMEOUT;
|
||||
@ -3661,7 +3661,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
||||
return 1;
|
||||
}
|
||||
|
||||
pol->curlft.use_time = ktime_get_real_seconds();
|
||||
/* This lockless write can happen from different cpus. */
|
||||
WRITE_ONCE(pol->curlft.use_time, ktime_get_real_seconds());
|
||||
|
||||
pols[0] = pol;
|
||||
npols++;
|
||||
@ -3676,7 +3677,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
||||
xfrm_pol_put(pols[0]);
|
||||
return 0;
|
||||
}
|
||||
pols[1]->curlft.use_time = ktime_get_real_seconds();
|
||||
/* This write can happen from different cpus. */
|
||||
WRITE_ONCE(pols[1]->curlft.use_time,
|
||||
ktime_get_real_seconds());
|
||||
npols++;
|
||||
}
|
||||
}
|
||||
@ -3742,6 +3745,9 @@ 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;
|
||||
}
|
||||
|
@ -577,7 +577,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
||||
if (x->km.state == XFRM_STATE_EXPIRED)
|
||||
goto expired;
|
||||
if (x->lft.hard_add_expires_seconds) {
|
||||
long tmo = x->lft.hard_add_expires_seconds +
|
||||
time64_t tmo = x->lft.hard_add_expires_seconds +
|
||||
x->curlft.add_time - now;
|
||||
if (tmo <= 0) {
|
||||
if (x->xflags & XFRM_SOFT_EXPIRE) {
|
||||
@ -594,8 +594,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
||||
next = tmo;
|
||||
}
|
||||
if (x->lft.hard_use_expires_seconds) {
|
||||
long tmo = x->lft.hard_use_expires_seconds +
|
||||
(x->curlft.use_time ? : now) - now;
|
||||
time64_t tmo = x->lft.hard_use_expires_seconds +
|
||||
(READ_ONCE(x->curlft.use_time) ? : now) - now;
|
||||
if (tmo <= 0)
|
||||
goto expired;
|
||||
if (tmo < next)
|
||||
@ -604,7 +604,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
||||
if (x->km.dying)
|
||||
goto resched;
|
||||
if (x->lft.soft_add_expires_seconds) {
|
||||
long tmo = x->lft.soft_add_expires_seconds +
|
||||
time64_t tmo = x->lft.soft_add_expires_seconds +
|
||||
x->curlft.add_time - now;
|
||||
if (tmo <= 0) {
|
||||
warn = 1;
|
||||
@ -616,8 +616,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
|
||||
}
|
||||
}
|
||||
if (x->lft.soft_use_expires_seconds) {
|
||||
long tmo = x->lft.soft_use_expires_seconds +
|
||||
(x->curlft.use_time ? : now) - now;
|
||||
time64_t tmo = x->lft.soft_use_expires_seconds +
|
||||
(READ_ONCE(x->curlft.use_time) ? : now) - now;
|
||||
if (tmo <= 0)
|
||||
warn = 1;
|
||||
else if (tmo < next)
|
||||
@ -1906,7 +1906,7 @@ out:
|
||||
|
||||
hrtimer_start(&x1->mtimer, ktime_set(1, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
if (x1->curlft.use_time)
|
||||
if (READ_ONCE(x1->curlft.use_time))
|
||||
xfrm_state_check_expire(x1);
|
||||
|
||||
if (x->props.smark.m || x->props.smark.v || x->if_id) {
|
||||
@ -1940,8 +1940,8 @@ int xfrm_state_check_expire(struct xfrm_state *x)
|
||||
{
|
||||
xfrm_dev_state_update_curlft(x);
|
||||
|
||||
if (!x->curlft.use_time)
|
||||
x->curlft.use_time = ktime_get_real_seconds();
|
||||
if (!READ_ONCE(x->curlft.use_time))
|
||||
WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds());
|
||||
|
||||
if (x->curlft.bytes >= x->lft.hard_byte_limit ||
|
||||
x->curlft.packets >= x->lft.hard_packet_limit) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user