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

selftests/net/ipsec: Add test for xfrm_spdattr_type_t

Set hthresh, dump it again and verify thresh.lbits && thresh.rbits.
They are passed as attributes of xfrm_spdattr_type_t, different from
other message attributes that use xfrm_attr_type_t.
Also, test attribute that is bigger than XFRMA_SPD_MAX, currently it
should be silently ignored.

Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Dmitry Safonov and committed by
Steffen Klassert
70bfdf62 4e950506

+163 -2
+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