Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2021-08-04

1) Fix a sysbot reported memory leak in xfrm_user_rcv_msg.
From Pavel Skripkin.

2) Revert "xfrm: policy: Read seqcount outside of rcu-read side
in xfrm_policy_lookup_bytype". This commit tried to fix a
lockin bug, but only cured some of the symptoms. A proper
fix is applied on top of this revert.

3) Fix a locking bug on xfrm state hash resize. A recent change
on sequence counters accidentally repaced a spinlock by a mutex.
Fix from Frederic Weisbecker.

4) Fix possible user-memory-access in xfrm_user_rcv_msg_compat().
From Dmitry Safonov.

5) Add initialiation sefltest fot xfrm_spdattr_type_t.
From Dmitry Safonov.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+231 -28
+1
include/net/netns/xfrm.h
··· 75 75 #endif 76 76 spinlock_t xfrm_state_lock; 77 77 seqcount_spinlock_t xfrm_state_hash_generation; 78 + seqcount_spinlock_t xfrm_policy_hash_generation; 78 79 79 80 spinlock_t xfrm_policy_lock; 80 81 struct mutex xfrm_cfg_mutex;
+44 -5
net/xfrm/xfrm_compat.c
··· 298 298 len = nlmsg_attrlen(nlh_src, xfrm_msg_min[type]); 299 299 300 300 nla_for_each_attr(nla, attrs, len, remaining) { 301 - int err = xfrm_xlate64_attr(dst, nla); 301 + int err; 302 302 303 + switch (type) { 304 + case XFRM_MSG_NEWSPDINFO: 305 + err = xfrm_nla_cpy(dst, nla, nla_len(nla)); 306 + break; 307 + default: 308 + err = xfrm_xlate64_attr(dst, nla); 309 + break; 310 + } 303 311 if (err) 304 312 return err; 305 313 } ··· 349 341 350 342 /* Calculates len of translated 64-bit message. */ 351 343 static size_t xfrm_user_rcv_calculate_len64(const struct nlmsghdr *src, 352 - struct nlattr *attrs[XFRMA_MAX+1]) 344 + struct nlattr *attrs[XFRMA_MAX + 1], 345 + int maxtype) 353 346 { 354 347 size_t len = nlmsg_len(src); 355 348 ··· 367 358 case XFRM_MSG_POLEXPIRE: 368 359 len += 8; 369 360 break; 361 + case XFRM_MSG_NEWSPDINFO: 362 + /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */ 363 + return len; 370 364 default: 371 365 break; 372 366 } 367 + 368 + /* Unexpected for anything, but XFRM_MSG_NEWSPDINFO, please 369 + * correct both 64=>32-bit and 32=>64-bit translators to copy 370 + * new attributes. 371 + */ 372 + if (WARN_ON_ONCE(maxtype)) 373 + return len; 373 374 374 375 if (attrs[XFRMA_SA]) 375 376 len += 4; ··· 459 440 460 441 static int xfrm_xlate32(struct nlmsghdr *dst, const struct nlmsghdr *src, 461 442 struct nlattr *attrs[XFRMA_MAX+1], 462 - size_t size, u8 type, struct netlink_ext_ack *extack) 443 + size_t size, u8 type, int maxtype, 444 + struct netlink_ext_ack *extack) 463 445 { 464 446 size_t pos; 465 447 int i; ··· 540 520 } 541 521 pos = dst->nlmsg_len; 542 522 523 + if (maxtype) { 524 + /* attirbutes are xfrm_spdattr_type_t, not xfrm_attr_type_t */ 525 + WARN_ON_ONCE(src->nlmsg_type != XFRM_MSG_NEWSPDINFO); 526 + 527 + for (i = 1; i <= maxtype; i++) { 528 + int err; 529 + 530 + if (!attrs[i]) 531 + continue; 532 + 533 + /* just copy - no need for translation */ 534 + err = xfrm_attr_cpy32(dst, &pos, attrs[i], size, 535 + nla_len(attrs[i]), nla_len(attrs[i])); 536 + if (err) 537 + return err; 538 + } 539 + return 0; 540 + } 541 + 543 542 for (i = 1; i < XFRMA_MAX + 1; i++) { 544 543 int err; 545 544 ··· 603 564 if (err < 0) 604 565 return ERR_PTR(err); 605 566 606 - len = xfrm_user_rcv_calculate_len64(h32, attrs); 567 + len = xfrm_user_rcv_calculate_len64(h32, attrs, maxtype); 607 568 /* The message doesn't need translation */ 608 569 if (len == nlmsg_len(h32)) 609 570 return NULL; ··· 613 574 if (!h64) 614 575 return ERR_PTR(-ENOMEM); 615 576 616 - err = xfrm_xlate32(h64, h32, attrs, len, type, extack); 577 + err = xfrm_xlate32(h64, h32, attrs, len, type, maxtype, extack); 617 578 if (err < 0) { 618 579 kvfree(h64); 619 580 return ERR_PTR(err);
+1 -1
net/xfrm/xfrm_ipcomp.c
··· 241 241 break; 242 242 } 243 243 244 - WARN_ON(!pos); 244 + WARN_ON(list_entry_is_head(pos, &ipcomp_tfms_list, list)); 245 245 246 246 if (--pos->users) 247 247 return;
+12 -20
net/xfrm/xfrm_policy.c
··· 155 155 __read_mostly; 156 156 157 157 static struct kmem_cache *xfrm_dst_cache __ro_after_init; 158 - static __read_mostly seqcount_mutex_t xfrm_policy_hash_generation; 159 158 160 159 static struct rhashtable xfrm_policy_inexact_table; 161 160 static const struct rhashtable_params xfrm_pol_inexact_params; ··· 584 585 return; 585 586 586 587 spin_lock_bh(&net->xfrm.xfrm_policy_lock); 587 - write_seqcount_begin(&xfrm_policy_hash_generation); 588 + write_seqcount_begin(&net->xfrm.xfrm_policy_hash_generation); 588 589 589 590 odst = rcu_dereference_protected(net->xfrm.policy_bydst[dir].table, 590 591 lockdep_is_held(&net->xfrm.xfrm_policy_lock)); ··· 595 596 rcu_assign_pointer(net->xfrm.policy_bydst[dir].table, ndst); 596 597 net->xfrm.policy_bydst[dir].hmask = nhashmask; 597 598 598 - write_seqcount_end(&xfrm_policy_hash_generation); 599 + write_seqcount_end(&net->xfrm.xfrm_policy_hash_generation); 599 600 spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 600 601 601 602 synchronize_rcu(); ··· 1244 1245 } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq)); 1245 1246 1246 1247 spin_lock_bh(&net->xfrm.xfrm_policy_lock); 1247 - write_seqcount_begin(&xfrm_policy_hash_generation); 1248 + write_seqcount_begin(&net->xfrm.xfrm_policy_hash_generation); 1248 1249 1249 1250 /* make sure that we can insert the indirect policies again before 1250 1251 * we start with destructive action. ··· 1353 1354 1354 1355 out_unlock: 1355 1356 __xfrm_policy_inexact_flush(net); 1356 - write_seqcount_end(&xfrm_policy_hash_generation); 1357 + write_seqcount_end(&net->xfrm.xfrm_policy_hash_generation); 1357 1358 spin_unlock_bh(&net->xfrm.xfrm_policy_lock); 1358 1359 1359 1360 mutex_unlock(&hash_resize_mutex); ··· 2090 2091 if (unlikely(!daddr || !saddr)) 2091 2092 return NULL; 2092 2093 2093 - retry: 2094 - sequence = read_seqcount_begin(&xfrm_policy_hash_generation); 2095 2094 rcu_read_lock(); 2096 - 2097 - chain = policy_hash_direct(net, daddr, saddr, family, dir); 2098 - if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) { 2099 - rcu_read_unlock(); 2100 - goto retry; 2101 - } 2095 + retry: 2096 + do { 2097 + sequence = read_seqcount_begin(&net->xfrm.xfrm_policy_hash_generation); 2098 + chain = policy_hash_direct(net, daddr, saddr, family, dir); 2099 + } while (read_seqcount_retry(&net->xfrm.xfrm_policy_hash_generation, sequence)); 2102 2100 2103 2101 ret = NULL; 2104 2102 hlist_for_each_entry_rcu(pol, chain, bydst) { ··· 2126 2130 } 2127 2131 2128 2132 skip_inexact: 2129 - if (read_seqcount_retry(&xfrm_policy_hash_generation, sequence)) { 2130 - rcu_read_unlock(); 2133 + if (read_seqcount_retry(&net->xfrm.xfrm_policy_hash_generation, sequence)) 2131 2134 goto retry; 2132 - } 2133 2135 2134 - if (ret && !xfrm_pol_hold_rcu(ret)) { 2135 - rcu_read_unlock(); 2136 + if (ret && !xfrm_pol_hold_rcu(ret)) 2136 2137 goto retry; 2137 - } 2138 2138 fail: 2139 2139 rcu_read_unlock(); 2140 2140 ··· 4081 4089 /* Initialize the per-net locks here */ 4082 4090 spin_lock_init(&net->xfrm.xfrm_state_lock); 4083 4091 spin_lock_init(&net->xfrm.xfrm_policy_lock); 4092 + seqcount_spinlock_init(&net->xfrm.xfrm_policy_hash_generation, &net->xfrm.xfrm_policy_lock); 4084 4093 mutex_init(&net->xfrm.xfrm_cfg_mutex); 4085 4094 4086 4095 rv = xfrm_statistics_init(net); ··· 4126 4133 { 4127 4134 register_pernet_subsys(&xfrm_net_ops); 4128 4135 xfrm_dev_init(); 4129 - seqcount_mutex_init(&xfrm_policy_hash_generation, &hash_resize_mutex); 4130 4136 xfrm_input_init(); 4131 4137 4132 4138 #ifdef CONFIG_XFRM_ESPINTCP
+10
net/xfrm/xfrm_user.c
··· 2811 2811 2812 2812 err = link->doit(skb, nlh, attrs); 2813 2813 2814 + /* We need to free skb allocated in xfrm_alloc_compat() before 2815 + * returning from this function, because consume_skb() won't take 2816 + * care of frag_list since netlink destructor sets 2817 + * sbk->head to NULL. (see netlink_skb_destructor()) 2818 + */ 2819 + if (skb_has_frag_list(skb)) { 2820 + kfree_skb(skb_shinfo(skb)->frag_list); 2821 + skb_shinfo(skb)->frag_list = NULL; 2822 + } 2823 + 2814 2824 err: 2815 2825 kvfree(nlh64); 2816 2826 return err;
+163 -2
tools/testing/selftests/net/ipsec.c
··· 484 484 MONITOR_ACQUIRE, 485 485 EXPIRE_STATE, 486 486 EXPIRE_POLICY, 487 + SPDINFO_ATTRS, 487 488 }; 488 489 const char *desc_name[] = { 489 490 "create tunnel", 490 491 "alloc spi", 491 492 "monitor acquire", 492 493 "expire state", 493 - "expire policy" 494 + "expire policy", 495 + "spdinfo attributes", 496 + "" 494 497 }; 495 498 struct xfrm_desc { 496 499 enum desc_type type; ··· 1596 1593 return ret; 1597 1594 } 1598 1595 1596 + static int xfrm_spdinfo_set_thresh(int xfrm_sock, uint32_t *seq, 1597 + unsigned thresh4_l, unsigned thresh4_r, 1598 + unsigned thresh6_l, unsigned thresh6_r, 1599 + bool add_bad_attr) 1600 + 1601 + { 1602 + struct { 1603 + struct nlmsghdr nh; 1604 + union { 1605 + uint32_t unused; 1606 + int error; 1607 + }; 1608 + char attrbuf[MAX_PAYLOAD]; 1609 + } req; 1610 + struct xfrmu_spdhthresh thresh; 1611 + 1612 + memset(&req, 0, sizeof(req)); 1613 + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.unused)); 1614 + req.nh.nlmsg_type = XFRM_MSG_NEWSPDINFO; 1615 + req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 1616 + req.nh.nlmsg_seq = (*seq)++; 1617 + 1618 + thresh.lbits = thresh4_l; 1619 + thresh.rbits = thresh4_r; 1620 + if (rtattr_pack(&req.nh, sizeof(req), XFRMA_SPD_IPV4_HTHRESH, &thresh, sizeof(thresh))) 1621 + return -1; 1622 + 1623 + thresh.lbits = thresh6_l; 1624 + thresh.rbits = thresh6_r; 1625 + if (rtattr_pack(&req.nh, sizeof(req), XFRMA_SPD_IPV6_HTHRESH, &thresh, sizeof(thresh))) 1626 + return -1; 1627 + 1628 + if (add_bad_attr) { 1629 + BUILD_BUG_ON(XFRMA_IF_ID <= XFRMA_SPD_MAX + 1); 1630 + if (rtattr_pack(&req.nh, sizeof(req), XFRMA_IF_ID, NULL, 0)) { 1631 + pr_err("adding attribute failed: no space"); 1632 + return -1; 1633 + } 1634 + } 1635 + 1636 + if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) { 1637 + pr_err("send()"); 1638 + return -1; 1639 + } 1640 + 1641 + if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) { 1642 + pr_err("recv()"); 1643 + return -1; 1644 + } else if (req.nh.nlmsg_type != NLMSG_ERROR) { 1645 + printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type); 1646 + return -1; 1647 + } 1648 + 1649 + if (req.error) { 1650 + printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error)); 1651 + return -1; 1652 + } 1653 + 1654 + return 0; 1655 + } 1656 + 1657 + static int xfrm_spdinfo_attrs(int xfrm_sock, uint32_t *seq) 1658 + { 1659 + struct { 1660 + struct nlmsghdr nh; 1661 + union { 1662 + uint32_t unused; 1663 + int error; 1664 + }; 1665 + char attrbuf[MAX_PAYLOAD]; 1666 + } req; 1667 + 1668 + if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 31, 120, 16, false)) { 1669 + pr_err("Can't set SPD HTHRESH"); 1670 + return KSFT_FAIL; 1671 + } 1672 + 1673 + memset(&req, 0, sizeof(req)); 1674 + 1675 + req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.unused)); 1676 + req.nh.nlmsg_type = XFRM_MSG_GETSPDINFO; 1677 + req.nh.nlmsg_flags = NLM_F_REQUEST; 1678 + req.nh.nlmsg_seq = (*seq)++; 1679 + if (send(xfrm_sock, &req, req.nh.nlmsg_len, 0) < 0) { 1680 + pr_err("send()"); 1681 + return KSFT_FAIL; 1682 + } 1683 + 1684 + if (recv(xfrm_sock, &req, sizeof(req), 0) < 0) { 1685 + pr_err("recv()"); 1686 + return KSFT_FAIL; 1687 + } else if (req.nh.nlmsg_type == XFRM_MSG_NEWSPDINFO) { 1688 + size_t len = NLMSG_PAYLOAD(&req.nh, sizeof(req.unused)); 1689 + struct rtattr *attr = (void *)req.attrbuf; 1690 + int got_thresh = 0; 1691 + 1692 + for (; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { 1693 + if (attr->rta_type == XFRMA_SPD_IPV4_HTHRESH) { 1694 + struct xfrmu_spdhthresh *t = RTA_DATA(attr); 1695 + 1696 + got_thresh++; 1697 + if (t->lbits != 32 || t->rbits != 31) { 1698 + pr_err("thresh differ: %u, %u", 1699 + t->lbits, t->rbits); 1700 + return KSFT_FAIL; 1701 + } 1702 + } 1703 + if (attr->rta_type == XFRMA_SPD_IPV6_HTHRESH) { 1704 + struct xfrmu_spdhthresh *t = RTA_DATA(attr); 1705 + 1706 + got_thresh++; 1707 + if (t->lbits != 120 || t->rbits != 16) { 1708 + pr_err("thresh differ: %u, %u", 1709 + t->lbits, t->rbits); 1710 + return KSFT_FAIL; 1711 + } 1712 + } 1713 + } 1714 + if (got_thresh != 2) { 1715 + pr_err("only %d thresh returned by XFRM_MSG_GETSPDINFO", got_thresh); 1716 + return KSFT_FAIL; 1717 + } 1718 + } else if (req.nh.nlmsg_type != NLMSG_ERROR) { 1719 + printk("expected NLMSG_ERROR, got %d", (int)req.nh.nlmsg_type); 1720 + return KSFT_FAIL; 1721 + } else { 1722 + printk("NLMSG_ERROR: %d: %s", req.error, strerror(-req.error)); 1723 + return -1; 1724 + } 1725 + 1726 + /* Restore the default */ 1727 + if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 32, 128, 128, false)) { 1728 + pr_err("Can't restore SPD HTHRESH"); 1729 + return KSFT_FAIL; 1730 + } 1731 + 1732 + /* 1733 + * At this moment xfrm uses nlmsg_parse_deprecated(), which 1734 + * implies NL_VALIDATE_LIBERAL - ignoring attributes with 1735 + * (type > maxtype). nla_parse_depricated_strict() would enforce 1736 + * it. Or even stricter nla_parse(). 1737 + * Right now it's not expected to fail, but to be ignored. 1738 + */ 1739 + if (xfrm_spdinfo_set_thresh(xfrm_sock, seq, 32, 32, 128, 128, true)) 1740 + return KSFT_PASS; 1741 + 1742 + return KSFT_PASS; 1743 + } 1744 + 1599 1745 static int child_serv(int xfrm_sock, uint32_t *seq, 1600 1746 unsigned int nr, int cmd_fd, void *buf, struct xfrm_desc *desc) 1601 1747 { ··· 1868 1716 break; 1869 1717 case EXPIRE_POLICY: 1870 1718 ret = xfrm_expire_policy(xfrm_sock, &seq, nr, &desc); 1719 + break; 1720 + case SPDINFO_ATTRS: 1721 + ret = xfrm_spdinfo_attrs(xfrm_sock, &seq); 1871 1722 break; 1872 1723 default: 1873 1724 printk("Unknown desc type %d", desc.type); ··· 2149 1994 * sizeof(xfrm_user_polexpire) = 168 | sizeof(xfrm_user_polexpire) = 176 2150 1995 * 2151 1996 * Check the affected by the UABI difference structures. 1997 + * Also, check translation for xfrm_set_spdinfo: it has it's own attributes 1998 + * which needs to be correctly copied, but not translated. 2152 1999 */ 2153 - const unsigned int compat_plan = 4; 2000 + const unsigned int compat_plan = 5; 2154 2001 static int write_compat_struct_tests(int test_desc_fd) 2155 2002 { 2156 2003 struct xfrm_desc desc = {}; ··· 2173 2016 return -1; 2174 2017 2175 2018 desc.type = EXPIRE_POLICY; 2019 + if (__write_desc(test_desc_fd, &desc)) 2020 + return -1; 2021 + 2022 + desc.type = SPDINFO_ATTRS; 2176 2023 if (__write_desc(test_desc_fd, &desc)) 2177 2024 return -1; 2178 2025