ipsec-2023-10-17
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmUuRZ4ACgkQrB3Eaf9P W7e7eg//fgQux/sJoq2Qf7T8cvVt3NSpOLXB43NRsIb9nUyMNN/cYTtypYM/+0FM f0zxmwtUkj9Mx/IL2nNzK/h8lMtJeKfy14tt8lAX2ux5oJltCcTiLgdp3C4HWxOh 9DrXMGIryr0apedkcStSzhRoJBd8giFViAQZE8NwO5EKG8WLJNVvw0YzlNgM0WOk 5y/sN1uXeUmUCYDkOGcdt6yIyV+GIo/nEg/XOY8LkaQDzKveDypydj0dPGL/Dj8U MhczTCf1WdbTHh0dmITIdX/yZ8/bPNfV3EzAtAaYgceVh1DSq8/F9buRXz2oxxvh r8Igv+640+SoWEtIsVoXHx7KIZ7LckasrJv1IoKRXGVV25LjnR+bxGVQNyUjdd6+ Cb11Q/m66fp/k7B+++b6eFVlKvr9O4jBogb3kfGpqMiwm6LNM+CJicdAfM8/GEgM ejnVNSEaChhdgGvrXVbKhI2ACatwbPrt6d4PN0d9fpUbZJnuBZl4QHElLNSBznjO xJUF8LvPjFGx6vj3YFnBg5f3uNH35nR2jQxPsx+yWdBEFqbxBt7yKr/pftwP1gxD ZLHF8JbOT4J+96ClDRFnlWFdY+Phq0fg5S5WhPhNGQ4rj9rsjAS8ZMcHWZeA7iZ2 0w5P/DlFmmnw6CC+Xr+wQJlgB1tZ2sdC8nAK6gxQJ3eFVv4wnhk= =yHtO -----END PGP SIGNATURE----- Merge tag 'ipsec-2023-10-17' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec Steffen Klassert says: ==================== pull request (net): ipsec 2023-10-17 1) Fix a slab-use-after-free in xfrm_policy_inexact_list_reinsert. From Dong Chenchen. 2) Fix data-races in the xfrm interfaces dev->stats fields. From Eric Dumazet. 3) Fix a data-race in xfrm_gen_index. From Eric Dumazet. 4) Fix an inet6_dev refcount underflow. From Zhang Changzhong. 5) Check the return value of pskb_trim in esp_remove_trailer for esp4 and esp6. From Ma Ke. 6) Fix a data-race in xfrm_lookup_with_ifid. From Eric Dumazet. * tag 'ipsec-2023-10-17' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: fix a data-race in xfrm_lookup_with_ifid() net: ipv4: fix return value check in esp_remove_trailer net: ipv6: fix return value check in esp_remove_trailer xfrm6: fix inet6_dev refcount underflow problem xfrm: fix a data-race in xfrm_gen_index() xfrm: interface: use DEV_STATS_INC() net: xfrm: skip policies marked as dead while reinserting policies ==================== Link: https://lore.kernel.org/r/20231017083723.1364940-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
f6c7b42243
|
@ -50,6 +50,7 @@ struct netns_xfrm {
|
|||
struct list_head policy_all;
|
||||
struct hlist_head *policy_byidx;
|
||||
unsigned int policy_idx_hmask;
|
||||
unsigned int idx_generator;
|
||||
struct hlist_head policy_inexact[XFRM_POLICY_MAX];
|
||||
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX];
|
||||
unsigned int policy_count[XFRM_POLICY_MAX * 2];
|
||||
|
|
|
@ -732,7 +732,9 @@ static inline int esp_remove_trailer(struct sk_buff *skb)
|
|||
skb->csum = csum_block_sub(skb->csum, csumdiff,
|
||||
skb->len - trimlen);
|
||||
}
|
||||
pskb_trim(skb, skb->len - trimlen);
|
||||
ret = pskb_trim(skb, skb->len - trimlen);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ret = nexthdr[1];
|
||||
|
||||
|
|
|
@ -770,7 +770,9 @@ static inline int esp_remove_trailer(struct sk_buff *skb)
|
|||
skb->csum = csum_block_sub(skb->csum, csumdiff,
|
||||
skb->len - trimlen);
|
||||
}
|
||||
pskb_trim(skb, skb->len - trimlen);
|
||||
ret = pskb_trim(skb, skb->len - trimlen);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
ret = nexthdr[1];
|
||||
|
||||
|
|
|
@ -117,10 +117,10 @@ static void xfrm6_dst_destroy(struct dst_entry *dst)
|
|||
{
|
||||
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
|
||||
|
||||
if (likely(xdst->u.rt6.rt6i_idev))
|
||||
in6_dev_put(xdst->u.rt6.rt6i_idev);
|
||||
dst_destroy_metrics_generic(dst);
|
||||
rt6_uncached_list_del(&xdst->u.rt6);
|
||||
if (likely(xdst->u.rt6.rt6i_idev))
|
||||
in6_dev_put(xdst->u.rt6.rt6i_idev);
|
||||
xfrm_dst_destroy(xdst);
|
||||
}
|
||||
|
||||
|
|
|
@ -380,8 +380,8 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
|
|||
skb->dev = dev;
|
||||
|
||||
if (err) {
|
||||
dev->stats.rx_errors++;
|
||||
dev->stats.rx_dropped++;
|
||||
DEV_STATS_INC(dev, rx_errors);
|
||||
DEV_STATS_INC(dev, rx_dropped);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -426,7 +426,6 @@ static int
|
|||
xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
||||
{
|
||||
struct xfrm_if *xi = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &xi->dev->stats;
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
unsigned int length = skb->len;
|
||||
struct net_device *tdev;
|
||||
|
@ -473,7 +472,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
|
|||
tdev = dst->dev;
|
||||
|
||||
if (tdev == dev) {
|
||||
stats->collisions++;
|
||||
DEV_STATS_INC(dev, collisions);
|
||||
net_warn_ratelimited("%s: Local routing loop detected!\n",
|
||||
dev->name);
|
||||
goto tx_err_dst_release;
|
||||
|
@ -512,13 +511,13 @@ xmit:
|
|||
if (net_xmit_eval(err) == 0) {
|
||||
dev_sw_netstats_tx_add(dev, 1, length);
|
||||
} else {
|
||||
stats->tx_errors++;
|
||||
stats->tx_aborted_errors++;
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
DEV_STATS_INC(dev, tx_aborted_errors);
|
||||
}
|
||||
|
||||
return 0;
|
||||
tx_err_link_failure:
|
||||
stats->tx_carrier_errors++;
|
||||
DEV_STATS_INC(dev, tx_carrier_errors);
|
||||
dst_link_failure(skb);
|
||||
tx_err_dst_release:
|
||||
dst_release(dst);
|
||||
|
@ -528,7 +527,6 @@ tx_err_dst_release:
|
|||
static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct xfrm_if *xi = netdev_priv(dev);
|
||||
struct net_device_stats *stats = &xi->dev->stats;
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct flowi fl;
|
||||
int ret;
|
||||
|
@ -545,7 +543,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6);
|
||||
if (dst->error) {
|
||||
dst_release(dst);
|
||||
stats->tx_carrier_errors++;
|
||||
DEV_STATS_INC(dev, tx_carrier_errors);
|
||||
goto tx_err;
|
||||
}
|
||||
skb_dst_set(skb, dst);
|
||||
|
@ -561,7 +559,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
|
||||
rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4);
|
||||
if (IS_ERR(rt)) {
|
||||
stats->tx_carrier_errors++;
|
||||
DEV_STATS_INC(dev, tx_carrier_errors);
|
||||
goto tx_err;
|
||||
}
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
|
@ -580,8 +578,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
return NETDEV_TX_OK;
|
||||
|
||||
tx_err:
|
||||
stats->tx_errors++;
|
||||
stats->tx_dropped++;
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
DEV_STATS_INC(dev, tx_dropped);
|
||||
kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
|
|
@ -851,7 +851,7 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
|
|||
struct hlist_node *newpos = NULL;
|
||||
bool matches_s, matches_d;
|
||||
|
||||
if (!policy->bydst_reinsert)
|
||||
if (policy->walk.dead || !policy->bydst_reinsert)
|
||||
continue;
|
||||
|
||||
WARN_ON_ONCE(policy->family != family);
|
||||
|
@ -1256,8 +1256,11 @@ static void xfrm_hash_rebuild(struct work_struct *work)
|
|||
struct xfrm_pol_inexact_bin *bin;
|
||||
u8 dbits, sbits;
|
||||
|
||||
if (policy->walk.dead)
|
||||
continue;
|
||||
|
||||
dir = xfrm_policy_id2dir(policy->index);
|
||||
if (policy->walk.dead || dir >= XFRM_POLICY_MAX)
|
||||
if (dir >= XFRM_POLICY_MAX)
|
||||
continue;
|
||||
|
||||
if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) {
|
||||
|
@ -1372,8 +1375,6 @@ EXPORT_SYMBOL(xfrm_policy_hash_rebuild);
|
|||
* of an absolute inpredictability of ordering of rules. This will not pass. */
|
||||
static u32 xfrm_gen_index(struct net *net, int dir, u32 index)
|
||||
{
|
||||
static u32 idx_generator;
|
||||
|
||||
for (;;) {
|
||||
struct hlist_head *list;
|
||||
struct xfrm_policy *p;
|
||||
|
@ -1381,8 +1382,8 @@ static u32 xfrm_gen_index(struct net *net, int dir, u32 index)
|
|||
int found;
|
||||
|
||||
if (!index) {
|
||||
idx = (idx_generator | dir);
|
||||
idx_generator += 8;
|
||||
idx = (net->xfrm.idx_generator | dir);
|
||||
net->xfrm.idx_generator += 8;
|
||||
} else {
|
||||
idx = index;
|
||||
index = 0;
|
||||
|
@ -1823,9 +1824,11 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
|
|||
|
||||
again:
|
||||
list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
|
||||
if (pol->walk.dead)
|
||||
continue;
|
||||
|
||||
dir = xfrm_policy_id2dir(pol->index);
|
||||
if (pol->walk.dead ||
|
||||
dir >= XFRM_POLICY_MAX ||
|
||||
if (dir >= XFRM_POLICY_MAX ||
|
||||
pol->type != type)
|
||||
continue;
|
||||
|
||||
|
@ -1862,9 +1865,11 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
|
|||
|
||||
again:
|
||||
list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
|
||||
if (pol->walk.dead)
|
||||
continue;
|
||||
|
||||
dir = xfrm_policy_id2dir(pol->index);
|
||||
if (pol->walk.dead ||
|
||||
dir >= XFRM_POLICY_MAX ||
|
||||
if (dir >= XFRM_POLICY_MAX ||
|
||||
pol->xdo.dev != dev)
|
||||
continue;
|
||||
|
||||
|
@ -3215,7 +3220,7 @@ no_transform:
|
|||
}
|
||||
|
||||
for (i = 0; i < num_pols; i++)
|
||||
pols[i]->curlft.use_time = ktime_get_real_seconds();
|
||||
WRITE_ONCE(pols[i]->curlft.use_time, ktime_get_real_seconds());
|
||||
|
||||
if (num_xfrms < 0) {
|
||||
/* Prohibit the flow */
|
||||
|
|
Loading…
Reference in New Issue