Add a new bpf_lsm_genl_family_rcv_msg() BPF hook called from within the genl_family_rcv_msg() function. The hook sees the genl family, net, cmd, and nlmsg_flags. As the hook receives all the information pre-parsed, it is not put into the sleepable list. There is already an existing LSM hook sitting right at netlink_send, however, it looks to be too coarse-grained to be used directly. The netlink_send hook sees the struct sock and struct skb, and thus must duplicate all the parsing inside BPF. The messages can actually contain multiple netlink datagrams, dynamic info (see e.g., selinux_nlmsg_lookup() in context of generic netlink), etc. The purpose of this hook is to mitigate, in a coarse-grained way, CVEs reachable via the corresponding control path: genl recvmsg. While looking at the recent CVEs, robots found ~300 CVEs reachable via the genl_rcv. We can roughly split them as follows: * Around 100 are ethtool-related. For more detailed information, see the following commit which adds even more finer-grained ethtool hooks. * Around 100 of the remaining are fully dominated by the new hook. * Around 100 remaining aren't fully mitigatable, as other control paths, besides the genl, lead to the buggy code. To be more precise, the following CVEs are properly mitigated by the new hook: * CVE-2021-47518 CVE-2021-47594 CVE-2021-47612 CVE-2022-48687 CVE-2022-49060 CVE-2022-49085 CVE-2022-49300 CVE-2022-49862 CVE-2022-49959 CVE-2022-50656 CVE-2022-50834 CVE-2022-50854 CVE-2023-52698 CVE-2023-52702 CVE-2023-52977 CVE-2023-53113 CVE-2023-53298 CVE-2023-53686 CVE-2023-53843 CVE-2024-26608 CVE-2024-26663 CVE-2024-26754 CVE-2024-26811 CVE-2024-26950 CVE-2024-27025 CVE-2024-27410 CVE-2024-36941 CVE-2024-38562 CVE-2024-43912 CVE-2024-45010 CVE-2024-46711 CVE-2024-49937 CVE-2024-50085 CVE-2025-21706 CVE-2025-21787 CVE-2025-21862 CVE-2025-21875 CVE-2025-21947 CVE-2025-22024 CVE-2025-38184 CVE-2025-38443 CVE-2025-40084 CVE-2025-68263 CVE-2025-68366 CVE-2026-23297 CVE-2026-23436 CVE-2026-43252 CVE-2026-43394 CVE-2026-53128 CVE-2026-53227 CVE-2026-53233 CVE-2026-53238 CVE-2026-53257 The following are mitigated as well, but, theoretically, could benefit from a finer-grained hook, running after a deeper parsing/taking locks (this is however out of scope for now to add finer-grained hooks for each involved subsystems, as, unlike ethtool, they are more-or-less evenly distributed): * CVE-2021-47250 CVE-2021-47257 CVE-2021-47554 CVE-2022-48915 CVE-2022-49374 CVE-2022-49505 CVE-2022-50042 CVE-2022-50678 CVE-2023-52845 CVE-2023-53141 CVE-2023-53543 CVE-2023-53652 CVE-2023-54031 CVE-2024-26725 CVE-2024-26951 CVE-2024-42073 CVE-2024-42154 CVE-2024-46676 CVE-2024-47687 CVE-2024-50028 CVE-2025-21973 CVE-2025-38020 CVE-2025-38628 CVE-2025-40254 CVE-2025-40321 CVE-2025-68785 CVE-2025-71091 CVE-2025-71297 CVE-2026-23321 CVE-2026-31707 CVE-2026-31744 CVE-2026-43012 CVE-2026-43467 CVE-2026-43481 CVE-2026-45840 CVE-2026-52978 CVE-2026-52979 CVE-2023-53570 CVE-2024-42114 CVE-2024-53189 CVE-2024-56663 CVE-2025-21909 CVE-2026-53182 Policies for selected CVEs are added in the corresponding selftests patch. Signed-off-by: Anton Protopopov --- include/linux/bpf_lsm.h | 2 ++ include/linux/bpf_lsm_hook_defs.h | 7 +++++++ net/netlink/genetlink.c | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 1e54c7cca27a..452b9d1d7c49 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -12,6 +12,8 @@ #include #include +struct genl_family; /* for the bpf_lsm_genl_family_rcv_msg hook */ + #ifdef CONFIG_BPF_LSM extern bool bpf_lsm_initialized __ro_after_init; diff --git a/include/linux/bpf_lsm_hook_defs.h b/include/linux/bpf_lsm_hook_defs.h index 29bc0b514d16..3f57022744a3 100644 --- a/include/linux/bpf_lsm_hook_defs.h +++ b/include/linux/bpf_lsm_hook_defs.h @@ -4,3 +4,10 @@ * This is a set of BPF LSM hooks, which are _not_ fully implemented * as LSM hooks. Thus, they only can be used by BPF LSM programs. */ + +#ifdef CONFIG_NET + +LSM_HOOK(int, 0, genl_family_rcv_msg, const struct genl_family *family, + const struct net *net, u32 cmd, u16 nlmsg_flags) + +#endif /* CONFIG_NET */ diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0da39eaed255..12b4f49c7253 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1161,6 +1162,7 @@ static int genl_family_rcv_msg(const struct genl_family *family, struct genlmsghdr *hdr = nlmsg_data(nlh); struct genl_split_ops op; int hdrlen; + int err; u8 flags; /* this family doesn't exist in this netns */ @@ -1187,6 +1189,10 @@ static int genl_family_rcv_msg(const struct genl_family *family, !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) return -EPERM; + err = bpf_lsm_hook(genl_family_rcv_msg, family, net, hdr->cmd, nlh->nlmsg_flags); + if (err) + return err; + if (flags & GENL_CMD_CAP_DUMP) return genl_family_rcv_msg_dumpit(family, skb, nlh, extack, &op, hdrlen, net); -- 2.43.0