summaryrefslogtreecommitdiffstats
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-10-21 21:35:32 +0200
committerJakub Kicinski <kuba@kernel.org>2022-10-25 04:08:46 +0200
commit4fa86555d1cd338afc6e6308cc1ff890a014ec8c (patch)
treee707212a1ba96a3966ad51ba3f9e8b5ee01e63a5 /net/netlink/genetlink.c
parentethtool: eeprom: fix null-deref on genl_info in dump (diff)
downloadlinux-4fa86555d1cd338afc6e6308cc1ff890a014ec8c.tar.xz
linux-4fa86555d1cd338afc6e6308cc1ff890a014ec8c.zip
genetlink: piggy back on resv_op to default to a reject policy
To keep backward compatibility we used to leave attribute parsing to the family if no policy is specified. This becomes tedious as we move to more strict validation. Families must define reject all policies if they don't want any attributes accepted. Piggy back on the resv_start_op field as the switchover point. AFAICT only ethtool has added new commands since the resv_start_op was defined, and it has per-op policies so this should be a no-op. Nonetheless the patch should still go into v6.1 for consistency. Link: https://lore.kernel.org/all/20221019125745.3f2e7659@kernel.org/ Link: https://lore.kernel.org/r/20221021193532.1511293-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to '')
-rw-r--r--net/netlink/genetlink.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 39b7c00e4cef..b1fd059c9992 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -78,10 +78,29 @@ static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
+/* We need the last attribute with non-zero ID therefore a 2-entry array */
+static struct nla_policy genl_policy_reject_all[] = {
+ { .type = NLA_REJECT },
+ { .type = NLA_REJECT },
+};
+
static int genl_ctrl_event(int event, const struct genl_family *family,
const struct genl_multicast_group *grp,
int grp_id);
+static void
+genl_op_fill_in_reject_policy(const struct genl_family *family,
+ struct genl_ops *op)
+{
+ BUILD_BUG_ON(ARRAY_SIZE(genl_policy_reject_all) - 1 != 1);
+
+ if (op->policy || op->cmd < family->resv_start_op)
+ return;
+
+ op->policy = genl_policy_reject_all;
+ op->maxattr = 1;
+}
+
static const struct genl_family *genl_family_find_byid(unsigned int id)
{
return idr_find(&genl_fam_idr, id);
@@ -113,6 +132,8 @@ static void genl_op_from_full(const struct genl_family *family,
op->maxattr = family->maxattr;
if (!op->policy)
op->policy = family->policy;
+
+ genl_op_fill_in_reject_policy(family, op);
}
static int genl_get_cmd_full(u32 cmd, const struct genl_family *family,
@@ -142,6 +163,8 @@ static void genl_op_from_small(const struct genl_family *family,
op->maxattr = family->maxattr;
op->policy = family->policy;
+
+ genl_op_fill_in_reject_policy(family, op);
}
static int genl_get_cmd_small(u32 cmd, const struct genl_family *family,