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

Merge branch 'macsec-replace-custom-netlink-attribute-checks-with-policy-level-checks'

Sabrina Dubroca says:

====================
macsec: replace custom netlink attribute checks with policy-level checks

We can simplify attribute validation a lot by describing the accepted
ranges more precisely in the policies, using NLA_POLICY_MAX etc.

Some of the checks still need to be done later on, because the
attribute length and acceptable range can vary based on values that
can't be known when the policy is validated (cipher suite determines
the key length and valid ICV length, presence of XPN changes the PN
length, detection of duplicate SCIs or ANs, etc).

As a bonus, we get a few extack messages from the policy
validation. I'll add extack to the rest of the checks (mostly in the
genl commands) in an future series.

v1: https://lore.kernel.org/netdev/cover.1664379352.git.sd@queasysnail.net
====================

Link: https://patch.msgid.link/cover.1756202772.git.sd@queasysnail.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+38 -135
+38 -135
drivers/net/macsec.c
··· 1583 1583 if (IS_ERR(dev)) 1584 1584 return ERR_CAST(dev); 1585 1585 1586 - if (*assoc_num >= MACSEC_NUM_AN) 1587 - return ERR_PTR(-EINVAL); 1588 - 1589 1586 secy = &macsec_priv(dev)->secy; 1590 1587 tx_sc = &secy->tx_sc; 1591 1588 ··· 1643 1646 return ERR_PTR(-EINVAL); 1644 1647 1645 1648 *assoc_num = nla_get_u8(tb_sa[MACSEC_SA_ATTR_AN]); 1646 - if (*assoc_num >= MACSEC_NUM_AN) 1647 - return ERR_PTR(-EINVAL); 1648 1649 1649 1650 rx_sc = get_rxsc_from_nl(net, attrs, tb_rxsc, devp, secyp); 1650 1651 if (IS_ERR(rx_sc)) ··· 1665 1670 1666 1671 static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = { 1667 1672 [MACSEC_RXSC_ATTR_SCI] = { .type = NLA_U64 }, 1668 - [MACSEC_RXSC_ATTR_ACTIVE] = { .type = NLA_U8 }, 1673 + [MACSEC_RXSC_ATTR_ACTIVE] = NLA_POLICY_MAX(NLA_U8, 1), 1669 1674 }; 1670 1675 1671 1676 static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = { 1672 - [MACSEC_SA_ATTR_AN] = { .type = NLA_U8 }, 1673 - [MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 }, 1674 - [MACSEC_SA_ATTR_PN] = NLA_POLICY_MIN_LEN(4), 1675 - [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY, 1676 - .len = MACSEC_KEYID_LEN, }, 1677 - [MACSEC_SA_ATTR_KEY] = { .type = NLA_BINARY, 1678 - .len = MACSEC_MAX_KEY_LEN, }, 1677 + [MACSEC_SA_ATTR_AN] = NLA_POLICY_MAX(NLA_U8, MACSEC_NUM_AN - 1), 1678 + [MACSEC_SA_ATTR_ACTIVE] = NLA_POLICY_MAX(NLA_U8, 1), 1679 + [MACSEC_SA_ATTR_PN] = NLA_POLICY_MIN(NLA_UINT, 1), 1680 + [MACSEC_SA_ATTR_KEYID] = NLA_POLICY_EXACT_LEN(MACSEC_KEYID_LEN), 1681 + [MACSEC_SA_ATTR_KEY] = NLA_POLICY_MAX_LEN(MACSEC_MAX_KEY_LEN), 1679 1682 [MACSEC_SA_ATTR_SSCI] = { .type = NLA_U32 }, 1680 - [MACSEC_SA_ATTR_SALT] = { .type = NLA_BINARY, 1681 - .len = MACSEC_SALT_LEN, }, 1683 + [MACSEC_SA_ATTR_SALT] = NLA_POLICY_EXACT_LEN(MACSEC_SALT_LEN), 1682 1684 }; 1683 1685 1684 1686 static const struct nla_policy macsec_genl_offload_policy[NUM_MACSEC_OFFLOAD_ATTR] = { 1685 - [MACSEC_OFFLOAD_ATTR_TYPE] = { .type = NLA_U8 }, 1687 + [MACSEC_OFFLOAD_ATTR_TYPE] = NLA_POLICY_MAX(NLA_U8, MACSEC_OFFLOAD_MAX), 1686 1688 }; 1687 1689 1688 1690 /* Offloads an operation to a device driver */ ··· 1729 1737 if (!attrs[MACSEC_SA_ATTR_AN] || 1730 1738 !attrs[MACSEC_SA_ATTR_KEY] || 1731 1739 !attrs[MACSEC_SA_ATTR_KEYID]) 1732 - return false; 1733 - 1734 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_AN]) >= MACSEC_NUM_AN) 1735 - return false; 1736 - 1737 - if (attrs[MACSEC_SA_ATTR_PN] && 1738 - nla_get_u64(attrs[MACSEC_SA_ATTR_PN]) == 0) 1739 - return false; 1740 - 1741 - if (attrs[MACSEC_SA_ATTR_ACTIVE]) { 1742 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_ACTIVE]) > 1) 1743 - return false; 1744 - } 1745 - 1746 - if (nla_len(attrs[MACSEC_SA_ATTR_KEYID]) != MACSEC_KEYID_LEN) 1747 1740 return false; 1748 1741 1749 1742 return true; ··· 1786 1809 1787 1810 if (secy->xpn) { 1788 1811 if (!tb_sa[MACSEC_SA_ATTR_SSCI] || !tb_sa[MACSEC_SA_ATTR_SALT]) { 1789 - rtnl_unlock(); 1790 - return -EINVAL; 1791 - } 1792 - 1793 - if (nla_len(tb_sa[MACSEC_SA_ATTR_SALT]) != MACSEC_SALT_LEN) { 1794 - pr_notice("macsec: nl: add_rxsa: bad salt length: %d != %d\n", 1795 - nla_len(tb_sa[MACSEC_SA_ATTR_SALT]), 1796 - MACSEC_SALT_LEN); 1797 1812 rtnl_unlock(); 1798 1813 return -EINVAL; 1799 1814 } ··· 1864 1895 return err; 1865 1896 } 1866 1897 1867 - static bool validate_add_rxsc(struct nlattr **attrs) 1868 - { 1869 - if (!attrs[MACSEC_RXSC_ATTR_SCI]) 1870 - return false; 1871 - 1872 - if (attrs[MACSEC_RXSC_ATTR_ACTIVE]) { 1873 - if (nla_get_u8(attrs[MACSEC_RXSC_ATTR_ACTIVE]) > 1) 1874 - return false; 1875 - } 1876 - 1877 - return true; 1878 - } 1879 - 1880 1898 static int macsec_add_rxsc(struct sk_buff *skb, struct genl_info *info) 1881 1899 { 1882 1900 struct net_device *dev; ··· 1881 1925 if (parse_rxsc_config(attrs, tb_rxsc)) 1882 1926 return -EINVAL; 1883 1927 1884 - if (!validate_add_rxsc(tb_rxsc)) 1928 + if (!tb_rxsc[MACSEC_RXSC_ATTR_SCI]) 1885 1929 return -EINVAL; 1886 1930 1887 1931 rtnl_lock(); ··· 1940 1984 !attrs[MACSEC_SA_ATTR_KEYID]) 1941 1985 return false; 1942 1986 1943 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_AN]) >= MACSEC_NUM_AN) 1944 - return false; 1945 - 1946 - if (nla_get_u64(attrs[MACSEC_SA_ATTR_PN]) == 0) 1947 - return false; 1948 - 1949 - if (attrs[MACSEC_SA_ATTR_ACTIVE]) { 1950 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_ACTIVE]) > 1) 1951 - return false; 1952 - } 1953 - 1954 - if (nla_len(attrs[MACSEC_SA_ATTR_KEYID]) != MACSEC_KEYID_LEN) 1955 - return false; 1956 - 1957 1987 return true; 1958 1988 } 1959 1989 ··· 1994 2052 1995 2053 if (secy->xpn) { 1996 2054 if (!tb_sa[MACSEC_SA_ATTR_SSCI] || !tb_sa[MACSEC_SA_ATTR_SALT]) { 1997 - rtnl_unlock(); 1998 - return -EINVAL; 1999 - } 2000 - 2001 - if (nla_len(tb_sa[MACSEC_SA_ATTR_SALT]) != MACSEC_SALT_LEN) { 2002 - pr_notice("macsec: nl: add_txsa: bad salt length: %d != %d\n", 2003 - nla_len(tb_sa[MACSEC_SA_ATTR_SALT]), 2004 - MACSEC_SALT_LEN); 2005 2055 rtnl_unlock(); 2006 2056 return -EINVAL; 2007 2057 } ··· 2273 2339 attrs[MACSEC_SA_ATTR_SALT]) 2274 2340 return false; 2275 2341 2276 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_AN]) >= MACSEC_NUM_AN) 2277 - return false; 2278 - 2279 - if (attrs[MACSEC_SA_ATTR_PN] && nla_get_u64(attrs[MACSEC_SA_ATTR_PN]) == 0) 2280 - return false; 2281 - 2282 - if (attrs[MACSEC_SA_ATTR_ACTIVE]) { 2283 - if (nla_get_u8(attrs[MACSEC_SA_ATTR_ACTIVE]) > 1) 2284 - return false; 2285 - } 2286 - 2287 2342 return true; 2288 2343 } 2289 2344 ··· 2479 2556 if (parse_rxsc_config(attrs, tb_rxsc)) 2480 2557 return -EINVAL; 2481 2558 2482 - if (!validate_add_rxsc(tb_rxsc)) 2559 + if (!tb_rxsc[MACSEC_RXSC_ATTR_SCI]) 2483 2560 return -EINVAL; 2484 2561 2485 2562 rtnl_lock(); ··· 3757 3834 .name = "macsec", 3758 3835 }; 3759 3836 3837 + static int validate_cipher_suite(const struct nlattr *attr, 3838 + struct netlink_ext_ack *extack); 3760 3839 static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = { 3761 3840 [IFLA_MACSEC_SCI] = { .type = NLA_U64 }, 3762 3841 [IFLA_MACSEC_PORT] = { .type = NLA_U16 }, 3763 - [IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 }, 3764 - [IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 }, 3842 + [IFLA_MACSEC_ICV_LEN] = NLA_POLICY_RANGE(NLA_U8, MACSEC_MIN_ICV_LEN, MACSEC_STD_ICV_LEN), 3843 + [IFLA_MACSEC_CIPHER_SUITE] = NLA_POLICY_VALIDATE_FN(NLA_U64, validate_cipher_suite), 3765 3844 [IFLA_MACSEC_WINDOW] = { .type = NLA_U32 }, 3766 - [IFLA_MACSEC_ENCODING_SA] = { .type = NLA_U8 }, 3767 - [IFLA_MACSEC_ENCRYPT] = { .type = NLA_U8 }, 3768 - [IFLA_MACSEC_PROTECT] = { .type = NLA_U8 }, 3769 - [IFLA_MACSEC_INC_SCI] = { .type = NLA_U8 }, 3770 - [IFLA_MACSEC_ES] = { .type = NLA_U8 }, 3771 - [IFLA_MACSEC_SCB] = { .type = NLA_U8 }, 3772 - [IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 }, 3773 - [IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 }, 3774 - [IFLA_MACSEC_OFFLOAD] = { .type = NLA_U8 }, 3845 + [IFLA_MACSEC_ENCODING_SA] = NLA_POLICY_MAX(NLA_U8, MACSEC_NUM_AN - 1), 3846 + [IFLA_MACSEC_ENCRYPT] = NLA_POLICY_MAX(NLA_U8, 1), 3847 + [IFLA_MACSEC_PROTECT] = NLA_POLICY_MAX(NLA_U8, 1), 3848 + [IFLA_MACSEC_INC_SCI] = NLA_POLICY_MAX(NLA_U8, 1), 3849 + [IFLA_MACSEC_ES] = NLA_POLICY_MAX(NLA_U8, 1), 3850 + [IFLA_MACSEC_SCB] = NLA_POLICY_MAX(NLA_U8, 1), 3851 + [IFLA_MACSEC_REPLAY_PROTECT] = NLA_POLICY_MAX(NLA_U8, 1), 3852 + [IFLA_MACSEC_VALIDATION] = NLA_POLICY_MAX(NLA_U8, MACSEC_VALIDATE_MAX), 3853 + [IFLA_MACSEC_OFFLOAD] = NLA_POLICY_MAX(NLA_U8, MACSEC_OFFLOAD_MAX), 3775 3854 }; 3776 3855 3777 3856 static void macsec_free_netdev(struct net_device *dev) ··· 4227 4302 return err; 4228 4303 } 4229 4304 4305 + static int validate_cipher_suite(const struct nlattr *attr, 4306 + struct netlink_ext_ack *extack) 4307 + { 4308 + switch (nla_get_u64(attr)) { 4309 + case MACSEC_CIPHER_ID_GCM_AES_128: 4310 + case MACSEC_CIPHER_ID_GCM_AES_256: 4311 + case MACSEC_CIPHER_ID_GCM_AES_XPN_128: 4312 + case MACSEC_CIPHER_ID_GCM_AES_XPN_256: 4313 + case MACSEC_DEFAULT_CIPHER_ID: 4314 + return 0; 4315 + default: 4316 + return -EINVAL; 4317 + } 4318 + } 4319 + 4230 4320 static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[], 4231 4321 struct netlink_ext_ack *extack) 4232 4322 { 4233 - u64 csid = MACSEC_DEFAULT_CIPHER_ID; 4234 4323 u8 icv_len = MACSEC_DEFAULT_ICV_LEN; 4235 - int flag; 4236 4324 bool es, scb, sci; 4237 4325 4238 4326 if (!data) 4239 4327 return 0; 4240 - 4241 - if (data[IFLA_MACSEC_CIPHER_SUITE]) 4242 - csid = nla_get_u64(data[IFLA_MACSEC_CIPHER_SUITE]); 4243 4328 4244 4329 if (data[IFLA_MACSEC_ICV_LEN]) { 4245 4330 icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]); ··· 4266 4331 } 4267 4332 } 4268 4333 4269 - switch (csid) { 4270 - case MACSEC_CIPHER_ID_GCM_AES_128: 4271 - case MACSEC_CIPHER_ID_GCM_AES_256: 4272 - case MACSEC_CIPHER_ID_GCM_AES_XPN_128: 4273 - case MACSEC_CIPHER_ID_GCM_AES_XPN_256: 4274 - case MACSEC_DEFAULT_CIPHER_ID: 4275 - if (icv_len < MACSEC_MIN_ICV_LEN || 4276 - icv_len > MACSEC_STD_ICV_LEN) 4277 - return -EINVAL; 4278 - break; 4279 - default: 4280 - return -EINVAL; 4281 - } 4282 - 4283 - if (data[IFLA_MACSEC_ENCODING_SA]) { 4284 - if (nla_get_u8(data[IFLA_MACSEC_ENCODING_SA]) >= MACSEC_NUM_AN) 4285 - return -EINVAL; 4286 - } 4287 - 4288 - for (flag = IFLA_MACSEC_ENCODING_SA + 1; 4289 - flag < IFLA_MACSEC_VALIDATION; 4290 - flag++) { 4291 - if (data[flag]) { 4292 - if (nla_get_u8(data[flag]) > 1) 4293 - return -EINVAL; 4294 - } 4295 - } 4296 - 4297 4334 es = nla_get_u8_default(data[IFLA_MACSEC_ES], false); 4298 4335 sci = nla_get_u8_default(data[IFLA_MACSEC_INC_SCI], false); 4299 4336 scb = nla_get_u8_default(data[IFLA_MACSEC_SCB], false); 4300 4337 4301 4338 if ((sci && (scb || es)) || (scb && es)) 4302 - return -EINVAL; 4303 - 4304 - if (data[IFLA_MACSEC_VALIDATION] && 4305 - nla_get_u8(data[IFLA_MACSEC_VALIDATION]) > MACSEC_VALIDATE_MAX) 4306 4339 return -EINVAL; 4307 4340 4308 4341 if ((data[IFLA_MACSEC_REPLAY_PROTECT] &&