From patchwork Fri Nov 4 19:13:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032495 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3F140C43217 for ; Fri, 4 Nov 2022 19:13:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229781AbiKDTNz (ORCPT ); Fri, 4 Nov 2022 15:13:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229628AbiKDTNv (ORCPT ); Fri, 4 Nov 2022 15:13:51 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0EA794AF1A for ; Fri, 4 Nov 2022 12:13:49 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id A2644B82CD4 for ; Fri, 4 Nov 2022 19:13:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CAC2DC433B5; Fri, 4 Nov 2022 19:13:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589227; bh=YcbSssnL6pz5AMDkjvR2SMIJDO+wh5xCjQFRj5Yevmw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YoBuqirki9+UuA0unWlC+928wD+90Uf8n+y1fYfc9cRlgmh9nWLJFoyHVFuQ2PNZK xagJxO+KxKNGhQYv8UFy2cJGEiYbgRgYnUmMZwficTvzElCuE/K9wEP3x76uUZQUIs k9ElTSGyYN2doBs+cDlxO5GngCRunvDRGPxYl4nvo9JB8RpeDHKFu0CLAqXfDXMEcg 8RtsaRSzcs4ssgL/+84yVrMPp62k6gjqaHLbmzgJq4ozzpNu4hHu1m1YQRDxCEse9A TQSJ002S6R7Tqi27fuShynldp2JmD2zeYPdCXgonNXbCkqFqR51g3n7dp58sLD7P8w H9b5y6R5Xla6w== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 01/13] genetlink: refactor the cmd <> policy mapping dump Date: Fri, 4 Nov 2022 12:13:31 -0700 Message-Id: <20221104191343.690543-2-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org The code at the top of ctrl_dumppolicy() dumps mappings between ops and policies. It supports dumping both the entire family and single op if dump is filtered. But both of those cases are handled inside a loop, which makes the logic harder to follow and change. Refactor to split the two cases more clearly. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- v2: bring the comment back --- net/netlink/genetlink.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 3e16527beb91..0a7a856e9ce0 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1319,21 +1319,24 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) void *hdr; if (!ctx->policies) { - while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) { - struct genl_ops op; + struct genl_ops op; - if (ctx->single_op) { - int err; + if (ctx->single_op) { + int err; - err = genl_get_cmd(ctx->op, ctx->rt, &op); - if (WARN_ON(err)) - return skb->len; + err = genl_get_cmd(ctx->op, ctx->rt, &op); + if (WARN_ON(err)) + return err; - /* break out of the loop after this one */ - ctx->opidx = genl_get_cmd_cnt(ctx->rt); - } else { - genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op); - } + if (ctrl_dumppolicy_put_op(skb, cb, &op)) + return skb->len; + + /* don't enter the loop below */ + ctx->opidx = genl_get_cmd_cnt(ctx->rt); + } + + while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) { + genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op); if (ctrl_dumppolicy_put_op(skb, cb, &op)) return skb->len; From patchwork Fri Nov 4 19:13:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032498 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AAF5BC4332F for ; Fri, 4 Nov 2022 19:14:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229798AbiKDTN7 (ORCPT ); Fri, 4 Nov 2022 15:13:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229748AbiKDTNx (ORCPT ); Fri, 4 Nov 2022 15:13:53 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 77D204732F for ; Fri, 4 Nov 2022 12:13:50 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 18135B82F46 for ; Fri, 4 Nov 2022 19:13:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56E70C43470; Fri, 4 Nov 2022 19:13:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589227; bh=7bmUIvTh7m11eJkhXFQR5xxfAyOxMEzxBo/osUEWGsE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OjvvT8oQ4r4o/y1qrvvT2rdq/YwNhf8MooVxrM06NnMiLb8oRRefvNamd4535GSH8 dHcgDqRE/F+3yjuHt6B6ecgJS/pPIW8Ub4TyrTyVG3KcE5MRwjI7iNrkj3qXe/rlr9 80BgurDDod6Xr9EL3Cq2QROMgUwCMe3p8tcwe1//xfc0NtKUh2eQB09+Hr9AMY6jnn NLuz+EPHK7pQGTwYsHfFB+iR0jUqRPX1BzJarBQ3BiIhGpHrAKfj84dGADFf0H6xHJ RdrWIbZDWiL1mzungz0cFAy4gpcx059nyOyYjfoR6b2F1+kBwMjirZKg9h+IfoFRWD 2ln6AkL+N5Zdg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski , Johannes Berg Subject: [PATCH net-next v3 02/13] genetlink: move the private fields in struct genl_family Date: Fri, 4 Nov 2022 12:13:32 -0700 Message-Id: <20221104191343.690543-3-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Move the private fields down to form a "private section". Use the kdoc "private:" label comment thing to hide them from the main kdoc comment. Signed-off-by: Jakub Kicinski Reviewed-by: Johannes Berg Reviewed-by: Jacob Keller --- I did this cleanup to add more private fields but ended up not needing them. Still I think the commit makes sense? --- include/net/genetlink.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 9f97f73615b6..81180fc6526a 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -23,7 +23,6 @@ struct genl_info; /** * struct genl_family - generic netlink family - * @id: protocol family identifier (private) * @hdrsize: length of user specific header in bytes * @name: name of family * @version: protocol version @@ -43,8 +42,6 @@ struct genl_info; * @resv_start_op: first operation for which reserved fields of the header * can be validated and policies are required (see below); * new families should leave this field at zero - * @mcgrp_offset: starting number of multicast group IDs in this family - * (private) * @ops: the operations supported by this family * @n_ops: number of operations supported by this family * @small_ops: the small-struct operations supported by this family @@ -58,12 +55,10 @@ struct genl_info; * if policy is not provided core will reject all TLV attributes. */ struct genl_family { - int id; /* private */ unsigned int hdrsize; char name[GENL_NAMSIZ]; unsigned int version; unsigned int maxattr; - unsigned int mcgrp_offset; /* private */ u8 netnsok:1; u8 parallel_ops:1; u8 n_ops; @@ -81,6 +76,12 @@ struct genl_family { const struct genl_small_ops *small_ops; const struct genl_multicast_group *mcgrps; struct module *module; + +/* private: internal use only */ + /* protocol family identifier */ + int id; + /* starting number of multicast group IDs in this family */ + unsigned int mcgrp_offset; }; /** From patchwork Fri Nov 4 19:13:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032493 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69AB2C4332F for ; Fri, 4 Nov 2022 19:13:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229699AbiKDTNw (ORCPT ); Fri, 4 Nov 2022 15:13:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50154 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229574AbiKDTNv (ORCPT ); Fri, 4 Nov 2022 15:13:51 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4E284AF18 for ; Fri, 4 Nov 2022 12:13:49 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 3A74D62314 for ; Fri, 4 Nov 2022 19:13:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0827C43143; Fri, 4 Nov 2022 19:13:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589228; bh=nkQMFOjl2Ra+6gMMDn5goFmnSZOpL5UXpGeZfZOeCqo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=myffeyEEvY8CmWSLAjCGaZOJbfCyFt6ByRx8bpj2SXoAxI6lNIc596ujBwYEQcNKg 0vMv6zf3YpXQgfHAywgE5eWc0vT9DqgqE6DVOTBXZ1Dn4447cl2c7Fk21TLYErPr4t m5N1rWk//R2sZLDxsD7R9uDxfXt7Vjhk37euIuUO0ElR+AsR5gcVQ8xV6Fg5GmbqL5 bpj5P+Wb2qYG2mNvZv32cuQTpRz5yzZx2PZLDC339Qv73DtLav3RC0JhtczrbTLikM 6+8RXNeD8SBrw86Ylc4oFmNn5EhWQ8tSTFm/JsP8icjTGQRV3KANkDt9/ltoBmZFDe /L7g4RwBbmsVA== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski , mareklindner@neomailbox.ch, sw@simonwunderlich.de, a@unstable.cc, sven@narfation.org, jiri@nvidia.com, nhorman@tuxdriver.com, alex.aring@gmail.com, stefan@datenfreihafen.org, johannes@sipsolutions.net Subject: [PATCH net-next v3 03/13] genetlink: introduce split op representation Date: Fri, 4 Nov 2022 12:13:33 -0700 Message-Id: <20221104191343.690543-4-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org We currently have two forms of operations - small ops and "full" ops (or just ops). The former does not have pointers for some of the less commonly used features (namely dump start/done and policy). The "full" ops, however, still don't contain all the necessary information. In particular the policy is per command ID, while do and dump often accept different attributes. It's also not possible to define different pre_doit and post_doit callbacks for different commands within the family. At the same time a lot of commands do not support dumping and therefore all the dump-related information is wasted space. Create a new command representation which can hold info about a do implementation or a dump implementation, but not both at the same time. Use this new representation on the command execution path (genl_family_rcv_msg) as we either run a do or a dump and don't have to create a "full" op there. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- v2: - actually use the pre/post from the op - remove stray space - move a comment from patch 9 here CC: mareklindner@neomailbox.ch CC: sw@simonwunderlich.de CC: a@unstable.cc CC: sven@narfation.org CC: jiri@nvidia.com CC: nhorman@tuxdriver.com CC: alex.aring@gmail.com CC: stefan@datenfreihafen.org CC: johannes@sipsolutions.net --- include/net/genetlink.h | 60 +++++++++++++++++++++++++++-- net/batman-adv/netlink.c | 6 ++- net/core/devlink.c | 4 +- net/core/drop_monitor.c | 4 +- net/ieee802154/nl802154.c | 6 ++- net/netlink/genetlink.c | 79 +++++++++++++++++++++++++++++++-------- net/wireless/nl80211.c | 6 ++- 7 files changed, 136 insertions(+), 29 deletions(-) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 81180fc6526a..4be7989c451b 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -18,7 +18,7 @@ struct genl_multicast_group { u8 flags; }; -struct genl_ops; +struct genl_split_ops; struct genl_info; /** @@ -66,10 +66,10 @@ struct genl_family { u8 n_mcgrps; u8 resv_start_op; const struct nla_policy *policy; - int (*pre_doit)(const struct genl_ops *ops, + int (*pre_doit)(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info); - void (*post_doit)(const struct genl_ops *ops, + void (*post_doit)(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info); const struct genl_ops * ops; @@ -182,6 +182,58 @@ struct genl_ops { u8 validate; }; +/** + * struct genl_split_ops - generic netlink operations (do/dump split version) + * @cmd: command identifier + * @internal_flags: flags used by the family + * @flags: GENL_* flags (%GENL_ADMIN_PERM or %GENL_UNS_ADMIN_PERM) + * @validate: validation flags from enum genl_validate_flags + * @policy: netlink policy (takes precedence over family policy) + * @maxattr: maximum number of attributes supported + * + * Do callbacks: + * @pre_doit: called before an operation's @doit callback, it may + * do additional, common, filtering and return an error + * @doit: standard command callback + * @post_doit: called after an operation's @doit callback, it may + * undo operations done by pre_doit, for example release locks + * + * Dump callbacks: + * @start: start callback for dumps + * @dumpit: callback for dumpers + * @done: completion callback for dumps + * + * Do callbacks can be used if %GENL_CMD_CAP_DO is set in @flags. + * Dump callbacks can be used if %GENL_CMD_CAP_DUMP is set in @flags. + * Exactly one of those flags must be set. + */ +struct genl_split_ops { + union { + struct { + int (*pre_doit)(const struct genl_split_ops *ops, + struct sk_buff *skb, + struct genl_info *info); + int (*doit)(struct sk_buff *skb, + struct genl_info *info); + void (*post_doit)(const struct genl_split_ops *ops, + struct sk_buff *skb, + struct genl_info *info); + }; + struct { + int (*start)(struct netlink_callback *cb); + int (*dumpit)(struct sk_buff *skb, + struct netlink_callback *cb); + int (*done)(struct netlink_callback *cb); + }; + }; + const struct nla_policy *policy; + unsigned int maxattr; + u8 cmd; + u8 internal_flags; + u8 flags; + u8 validate; +}; + /** * struct genl_dumpit_info - info that is available during dumpit op call * @family: generic netlink family - for internal genl code usage @@ -190,7 +242,7 @@ struct genl_ops { */ struct genl_dumpit_info { const struct genl_family *family; - struct genl_ops op; + struct genl_split_ops op; struct nlattr **attrs; }; diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index a5e4a4e976cf..ad5714f737be 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c @@ -1267,7 +1267,8 @@ batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net, * * Return: 0 on success or negative error number in case of failure */ -static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, +static int batadv_pre_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct net *net = genl_info_net(info); @@ -1332,7 +1333,8 @@ static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, * @skb: Netlink message with request data * @info: receiver information */ -static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, +static void batadv_post_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct batadv_hard_iface *hard_iface; diff --git a/net/core/devlink.c b/net/core/devlink.c index 2dcf2bcc3527..40fcdded57e6 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -770,7 +770,7 @@ devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) #define DEVLINK_NL_FLAG_NEED_RATE_NODE BIT(3) #define DEVLINK_NL_FLAG_NEED_LINECARD BIT(4) -static int devlink_nl_pre_doit(const struct genl_ops *ops, +static int devlink_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info) { struct devlink_linecard *linecard; @@ -828,7 +828,7 @@ static int devlink_nl_pre_doit(const struct genl_ops *ops, return err; } -static void devlink_nl_post_doit(const struct genl_ops *ops, +static void devlink_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info) { struct devlink_linecard *linecard; diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 11aa6e8a3098..5a782d1d8fd3 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -1620,7 +1620,7 @@ static const struct genl_small_ops dropmon_ops[] = { }, }; -static int net_dm_nl_pre_doit(const struct genl_ops *ops, +static int net_dm_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info) { mutex_lock(&net_dm_mutex); @@ -1628,7 +1628,7 @@ static int net_dm_nl_pre_doit(const struct genl_ops *ops, return 0; } -static void net_dm_nl_post_doit(const struct genl_ops *ops, +static void net_dm_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, struct genl_info *info) { mutex_unlock(&net_dm_mutex); diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 38c4f3cb010e..b33d1b5eda87 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2157,7 +2157,8 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb, #define NL802154_FLAG_CHECK_NETDEV_UP 0x08 #define NL802154_FLAG_NEED_WPAN_DEV 0x10 -static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, +static int nl802154_pre_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct cfg802154_registered_device *rdev; @@ -2219,7 +2220,8 @@ static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, return 0; } -static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, +static void nl802154_post_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { if (info->user_ptr[1]) { diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0a7a856e9ce0..c66299740c05 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -189,6 +189,51 @@ static int genl_get_cmd(u32 cmd, const struct genl_family *family, return genl_get_cmd_small(cmd, family, op); } +static void +genl_cmd_full_to_split(struct genl_split_ops *op, + const struct genl_family *family, + const struct genl_ops *full, u8 flags) +{ + if (flags & GENL_CMD_CAP_DUMP) { + op->start = full->start; + op->dumpit = full->dumpit; + op->done = full->done; + } else { + op->pre_doit = family->pre_doit; + op->doit = full->doit; + op->post_doit = family->post_doit; + } + + op->policy = full->policy; + op->maxattr = full->maxattr; + + op->cmd = full->cmd; + op->internal_flags = full->internal_flags; + op->flags = full->flags; + op->validate = full->validate; + + /* Make sure flags include the GENL_CMD_CAP_DO / GENL_CMD_CAP_DUMP */ + op->flags |= flags; +} + +static int +genl_get_cmd_split(u32 cmd, u8 flags, const struct genl_family *family, + struct genl_split_ops *op) +{ + struct genl_ops full; + int err; + + err = genl_get_cmd(cmd, family, &full); + if (err) { + memset(op, 0, sizeof(*op)); + return err; + } + + genl_cmd_full_to_split(op, family, &full, flags); + + return 0; +} + static void genl_get_cmd_by_index(unsigned int i, const struct genl_family *family, struct genl_ops *op) @@ -544,7 +589,7 @@ static struct nlattr ** genl_family_rcv_msg_attrs_parse(const struct genl_family *family, struct nlmsghdr *nlh, struct netlink_ext_ack *extack, - const struct genl_ops *ops, + const struct genl_split_ops *ops, int hdrlen, enum genl_validate_flags no_strict_flag) { @@ -580,18 +625,19 @@ struct genl_start_context { const struct genl_family *family; struct nlmsghdr *nlh; struct netlink_ext_ack *extack; - const struct genl_ops *ops; + const struct genl_split_ops *ops; int hdrlen; }; static int genl_start(struct netlink_callback *cb) { struct genl_start_context *ctx = cb->data; - const struct genl_ops *ops = ctx->ops; + const struct genl_split_ops *ops; struct genl_dumpit_info *info; struct nlattr **attrs = NULL; int rc = 0; + ops = ctx->ops; if (ops->validate & GENL_DONT_VALIDATE_DUMP) goto no_attrs; @@ -633,7 +679,7 @@ static int genl_start(struct netlink_callback *cb) static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { - const struct genl_ops *ops = &genl_dumpit_info(cb)->op; + const struct genl_split_ops *ops = &genl_dumpit_info(cb)->op; int rc; genl_lock(); @@ -645,7 +691,7 @@ static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb) static int genl_lock_done(struct netlink_callback *cb) { const struct genl_dumpit_info *info = genl_dumpit_info(cb); - const struct genl_ops *ops = &info->op; + const struct genl_split_ops *ops = &info->op; int rc = 0; if (ops->done) { @@ -661,7 +707,7 @@ static int genl_lock_done(struct netlink_callback *cb) static int genl_parallel_done(struct netlink_callback *cb) { const struct genl_dumpit_info *info = genl_dumpit_info(cb); - const struct genl_ops *ops = &info->op; + const struct genl_split_ops *ops = &info->op; int rc = 0; if (ops->done) @@ -675,7 +721,7 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family, struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack, - const struct genl_ops *ops, + const struct genl_split_ops *ops, int hdrlen, struct net *net) { struct genl_start_context ctx; @@ -721,7 +767,7 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family, struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack, - const struct genl_ops *ops, + const struct genl_split_ops *ops, int hdrlen, struct net *net) { struct nlattr **attrbuf; @@ -747,16 +793,16 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family, genl_info_net_set(&info, net); memset(&info.user_ptr, 0, sizeof(info.user_ptr)); - if (family->pre_doit) { - err = family->pre_doit(ops, skb, &info); + if (ops->pre_doit) { + err = ops->pre_doit(ops, skb, &info); if (err) goto out; } err = ops->doit(skb, &info); - if (family->post_doit) - family->post_doit(ops, skb, &info); + if (ops->post_doit) + ops->post_doit(ops, skb, &info); out: genl_family_rcv_msg_attrs_free(attrbuf); @@ -801,8 +847,9 @@ static int genl_family_rcv_msg(const struct genl_family *family, { struct net *net = sock_net(skb->sk); struct genlmsghdr *hdr = nlmsg_data(nlh); - struct genl_ops op; + struct genl_split_ops op; int hdrlen; + u8 flags; /* this family doesn't exist in this netns */ if (!family->netnsok && !net_eq(net, &init_net)) @@ -815,7 +862,9 @@ static int genl_family_rcv_msg(const struct genl_family *family, if (genl_header_check(family, nlh, hdr, extack)) return -EINVAL; - if (genl_get_cmd(hdr->cmd, family, &op)) + flags = (nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP ? + GENL_CMD_CAP_DUMP : GENL_CMD_CAP_DO; + if (genl_get_cmd_split(hdr->cmd, flags, family, &op)) return -EOPNOTSUPP; if ((op.flags & GENL_ADMIN_PERM) && @@ -826,7 +875,7 @@ static int genl_family_rcv_msg(const struct genl_family *family, !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) return -EPERM; - if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) + if (flags & GENL_CMD_CAP_DUMP) return genl_family_rcv_msg_dumpit(family, skb, nlh, extack, &op, hdrlen, net); else diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 148f66edb015..1ad0326ff4dc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -16140,7 +16140,8 @@ static u32 nl80211_internal_flags[] = { #undef SELECTOR }; -static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, +static int nl80211_pre_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = NULL; @@ -16241,7 +16242,8 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, return err; } -static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb, +static void nl80211_post_doit(const struct genl_split_ops *ops, + struct sk_buff *skb, struct genl_info *info) { u32 internal_flags = nl80211_internal_flags[ops->internal_flags]; From patchwork Fri Nov 4 19:13:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032496 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C00EAC4332F for ; Fri, 4 Nov 2022 19:13:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229790AbiKDTNz (ORCPT ); Fri, 4 Nov 2022 15:13:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229704AbiKDTNw (ORCPT ); Fri, 4 Nov 2022 15:13:52 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C883C4AF18 for ; Fri, 4 Nov 2022 12:13:51 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7C65AB82F64 for ; Fri, 4 Nov 2022 19:13:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD822C433C1; Fri, 4 Nov 2022 19:13:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589229; bh=ac8f5N/2o1twO4/7bO4DSlb3uliAW6VmZKZZUqwFWho=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ndiUuaBauJESnBfF4FZkWtuWpe4sP1SgSe3TjZnCdSObSs/R72Aw776CMG4oP3mOy kWY1pZejHDya9loOKuDA3ZFgZAhdPmj3IKq9PWx38LzhJKkgVADDymNPUDsWAfWtuC 8d4+dtu7gLmgf5Jx+pT3QOLw3YM/BrpvaSng+9NCO6zc1th+KGsbtmlPev2NvE3ef0 EKDq4UzuN2d27elrgxOxMmBobCMEODurG3bOGWQFFU2BcXKO+mNKV1hfNoo0WNGtqi FxsjMrOatN1AoEXIIQn0bxT7Rbw0g0HhDNf1SINgOKY/sPKbZ2R2WrO+73I6zCkdzn o9OHgDCA94pVQ== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 04/13] genetlink: load policy based on validation flags Date: Fri, 4 Nov 2022 12:13:34 -0700 Message-Id: <20221104191343.690543-5-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Set the policy and maxattr pointers based on validation flags. genl_family_rcv_msg_attrs_parse() will do nothing and return NULL if maxattrs is zero, so no behavior change is expected. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- v2: improve commit msg --- net/netlink/genetlink.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index c66299740c05..770726ac491e 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -204,8 +204,14 @@ genl_cmd_full_to_split(struct genl_split_ops *op, op->post_doit = family->post_doit; } - op->policy = full->policy; - op->maxattr = full->maxattr; + if (flags & GENL_CMD_CAP_DUMP && + full->validate & GENL_DONT_VALIDATE_DUMP) { + op->policy = NULL; + op->maxattr = 0; + } else { + op->policy = full->policy; + op->maxattr = full->maxattr; + } op->cmd = full->cmd; op->internal_flags = full->internal_flags; @@ -638,10 +644,8 @@ static int genl_start(struct netlink_callback *cb) int rc = 0; ops = ctx->ops; - if (ops->validate & GENL_DONT_VALIDATE_DUMP) - goto no_attrs; - - if (ctx->nlh->nlmsg_len < nlmsg_msg_size(ctx->hdrlen)) + if (!(ops->validate & GENL_DONT_VALIDATE_DUMP) && + ctx->nlh->nlmsg_len < nlmsg_msg_size(ctx->hdrlen)) return -EINVAL; attrs = genl_family_rcv_msg_attrs_parse(ctx->family, ctx->nlh, ctx->extack, @@ -650,7 +654,6 @@ static int genl_start(struct netlink_callback *cb) if (IS_ERR(attrs)) return PTR_ERR(attrs); -no_attrs: info = genl_dumpit_info_alloc(); if (!info) { genl_family_rcv_msg_attrs_free(attrs); From patchwork Fri Nov 4 19:13:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032494 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F2EFC43219 for ; Fri, 4 Nov 2022 19:13:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229771AbiKDTNy (ORCPT ); Fri, 4 Nov 2022 15:13:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50166 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229651AbiKDTNw (ORCPT ); Fri, 4 Nov 2022 15:13:52 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FF754AF23 for ; Fri, 4 Nov 2022 12:13:51 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id F0A6DB82F63 for ; Fri, 4 Nov 2022 19:13:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4577AC43141; Fri, 4 Nov 2022 19:13:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589229; bh=sdaYGWsbV49j7YSP0I7vPI2V8O79GZlnLbcjhZhHuRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BiCr8tC8lR/xA+7/tYR1cka6tZQu77qKycRBlwfsQHtCASQEX/GJCbKKVBm5vqrbQ QtJV648GrMP18w/Vq2afyz2/Uz1hb2s8c/yWmNR4sXHDh+4kdcN4ytLFyOIZiyxvDz N6dnnWqKMqVT5Rx1fKIWhjNYeMDseDSQiE3pdfRRsG8Nob+Am7/DdGD/gmEBtTtBJ0 WXQksn05fLQ1nAzyoGOki9k7EvjIk4E6xncQ/M/kZevaGEwjx2JPDOBxkhun53ZNS5 ezl8tGDIR1g1hUQdgivXFrdiAaFTYyzwoZqRY/GJeBMhYzk/D+BTUxeZGz4Amtw7lK 0QrpPRMkzbHuw== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 05/13] genetlink: check for callback type at op load time Date: Fri, 4 Nov 2022 12:13:35 -0700 Message-Id: <20221104191343.690543-6-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Now that genl_get_cmd_split() is informed what type of callback user is trying to access (do or dump) we can check that this callback is indeed available and return an error early. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- net/netlink/genetlink.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 770726ac491e..7c04df1bee2b 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -189,11 +189,17 @@ static int genl_get_cmd(u32 cmd, const struct genl_family *family, return genl_get_cmd_small(cmd, family, op); } -static void +static int genl_cmd_full_to_split(struct genl_split_ops *op, const struct genl_family *family, const struct genl_ops *full, u8 flags) { + if ((flags & GENL_CMD_CAP_DO && !full->doit) || + (flags & GENL_CMD_CAP_DUMP && !full->dumpit)) { + memset(op, 0, sizeof(*op)); + return -ENOENT; + } + if (flags & GENL_CMD_CAP_DUMP) { op->start = full->start; op->dumpit = full->dumpit; @@ -220,6 +226,8 @@ genl_cmd_full_to_split(struct genl_split_ops *op, /* Make sure flags include the GENL_CMD_CAP_DO / GENL_CMD_CAP_DUMP */ op->flags |= flags; + + return 0; } static int @@ -235,9 +243,7 @@ genl_get_cmd_split(u32 cmd, u8 flags, const struct genl_family *family, return err; } - genl_cmd_full_to_split(op, family, &full, flags); - - return 0; + return genl_cmd_full_to_split(op, family, &full, flags); } static void genl_get_cmd_by_index(unsigned int i, @@ -730,9 +736,6 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family, struct genl_start_context ctx; int err; - if (!ops->dumpit) - return -EOPNOTSUPP; - ctx.family = family; ctx.nlh = nlh; ctx.extack = extack; @@ -777,9 +780,6 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family, struct genl_info info; int err; - if (!ops->doit) - return -EOPNOTSUPP; - attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack, ops, hdrlen, GENL_DONT_VALIDATE_STRICT); From patchwork Fri Nov 4 19:13:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032500 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5AE98C4332F for ; Fri, 4 Nov 2022 19:14:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229804AbiKDTOD (ORCPT ); Fri, 4 Nov 2022 15:14:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229770AbiKDTNx (ORCPT ); Fri, 4 Nov 2022 15:13:53 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D971D4AF31 for ; Fri, 4 Nov 2022 12:13:51 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7F4ADB82F65 for ; Fri, 4 Nov 2022 19:13:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C6290C43470; Fri, 4 Nov 2022 19:13:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589230; bh=Ot+USnzCw/8n69AvPboQgNTW+kvdksyzFglmKHCqATg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XjvtH5wX+cjRumQ7x0k8vmzxo9NvRsbL2JPuuTOKPi2CFAKyzLYtUnIloIkJd7egc JQeC+GDBaVALC8D1ZhSXYfqeNMaFUJfzXhZ4NyfLSy02K5wLB08B+n5xZzQwAwyzuo cXzDIs9yjQhMkZfsg036TZ+r4fi2iLddisk4cROezadxkq1ifoWJ9cuxuT3rbgRwLn y3qPJ+078l4oAlat8E3hHB/BNyDs8f5C5mUDpfBn3/lZa+S455qQzudLB6gVLcng7j bFJZlU0Ldm7v2KsCfl7ELThTmrQJo0vBnj/7TdnORvm/tESiRu3VVqVfEcodscbRkl gR7k5UrZCu0FA== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 06/13] genetlink: add policies for both doit and dumpit in ctrl_dumppolicy_start() Date: Fri, 4 Nov 2022 12:13:36 -0700 Message-Id: <20221104191343.690543-7-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Separate adding doit and dumpit policies for CTRL_CMD_GETPOLICY. This has no effect until we actually allow do and dump to come from different sources as netlink_policy_dump_add_policy() does deduplication. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- net/netlink/genetlink.c | 48 ++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 7c04df1bee2b..d0c35738839b 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1260,29 +1260,57 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) ctx->rt = rt; if (tb[CTRL_ATTR_OP]) { + struct genl_split_ops doit, dump; + ctx->single_op = true; ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]); - err = genl_get_cmd(ctx->op, rt, &op); - if (err) { + if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO, rt, &doit) && + genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP, rt, &dump)) { NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]); - return err; + return -ENOENT; } - if (!op.policy) - return -ENODATA; + if (doit.policy) { + err = netlink_policy_dump_add_policy(&ctx->state, + doit.policy, + doit.maxattr); + if (err) + goto err_free_state; + } + if (dump.policy) { + err = netlink_policy_dump_add_policy(&ctx->state, + dump.policy, + dump.maxattr); + if (err) + goto err_free_state; + } - return netlink_policy_dump_add_policy(&ctx->state, op.policy, - op.maxattr); + if (!ctx->state) + return -ENODATA; + return 0; } for (i = 0; i < genl_get_cmd_cnt(rt); i++) { + struct genl_split_ops doit, dumpit; + genl_get_cmd_by_index(i, rt, &op); - if (op.policy) { + genl_cmd_full_to_split(&doit, ctx->rt, &op, GENL_CMD_CAP_DO); + genl_cmd_full_to_split(&dumpit, ctx->rt, + &op, GENL_CMD_CAP_DUMP); + + if (doit.policy) { + err = netlink_policy_dump_add_policy(&ctx->state, + doit.policy, + doit.maxattr); + if (err) + goto err_free_state; + } + if (dumpit.policy) { err = netlink_policy_dump_add_policy(&ctx->state, - op.policy, - op.maxattr); + dumpit.policy, + dumpit.maxattr); if (err) goto err_free_state; } From patchwork Fri Nov 4 19:13:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032499 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7ED6AC43217 for ; Fri, 4 Nov 2022 19:14:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229799AbiKDTOB (ORCPT ); Fri, 4 Nov 2022 15:14:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229772AbiKDTNy (ORCPT ); Fri, 4 Nov 2022 15:13:54 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A0654C262 for ; Fri, 4 Nov 2022 12:13:53 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0DE3AB82CD4 for ; Fri, 4 Nov 2022 19:13:52 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 53323C433D7; Fri, 4 Nov 2022 19:13:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589230; bh=ayB4ERSIPd2fDk5/rsqYqi9EITGM9gJAScDbjIYK3HQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bCwl6xx3Js4pmIMaIBMmhitj5RdA27ESP3ky3xOqUByX/cxbcsdPKe5M4jv9i9JBB 5Kjt/mNudQf2IsfDtrri9DYQ3KSUAovIKv2m5pQrdRJ7f8iFdGWEoNYZnH0HujXlAe Xdg7+hvIR+scKIWfqi6GlhfbGEGdPXNgKouV8D1O1iqkE+yrJ4mWYP3+zLfmxkTasI d9TFtM+kkR7z97uXu2Mbl0isT+nAeu7bf0FCErX0yunnC1gbKEcIyLDpX9lcWJytoJ uH3WwXQVTXjDB7geM1j5bRVksDwLqUFxg1dg2JSRlpppQ9q6yU7czNNjROjqRg3nRl Wvz/QI1PPj5ug== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 07/13] genetlink: support split policies in ctrl_dumppolicy_put_op() Date: Fri, 4 Nov 2022 12:13:37 -0700 Message-Id: <20221104191343.690543-8-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Pass do and dump versions of the op to ctrl_dumppolicy_put_op() so that it can provide a different policy index for the two. Since we now look at policies, and those are set appropriately there's no need to look at the GENL_DONT_VALIDATE_DUMP flag. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- v2: while at it fix the whitespace to appease checkpatch --- net/netlink/genetlink.c | 55 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index d0c35738839b..93e33e20a0e8 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1345,7 +1345,8 @@ static void *ctrl_dumppolicy_prep(struct sk_buff *skb, static int ctrl_dumppolicy_put_op(struct sk_buff *skb, struct netlink_callback *cb, - struct genl_ops *op) + struct genl_split_ops *doit, + struct genl_split_ops *dumpit) { struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; struct nlattr *nest_pol, *nest_op; @@ -1353,10 +1354,7 @@ static int ctrl_dumppolicy_put_op(struct sk_buff *skb, int idx; /* skip if we have nothing to show */ - if (!op->policy) - return 0; - if (!op->doit && - (!op->dumpit || op->validate & GENL_DONT_VALIDATE_DUMP)) + if (!doit->policy && !dumpit->policy) return 0; hdr = ctrl_dumppolicy_prep(skb, cb); @@ -1367,21 +1365,26 @@ static int ctrl_dumppolicy_put_op(struct sk_buff *skb, if (!nest_pol) goto err; - nest_op = nla_nest_start(skb, op->cmd); + nest_op = nla_nest_start(skb, doit->cmd); if (!nest_op) goto err; - /* for now both do/dump are always the same */ - idx = netlink_policy_dump_get_policy_idx(ctx->state, - op->policy, - op->maxattr); + if (doit->policy) { + idx = netlink_policy_dump_get_policy_idx(ctx->state, + doit->policy, + doit->maxattr); - if (op->doit && nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx)) - goto err; + if (nla_put_u32(skb, CTRL_ATTR_POLICY_DO, idx)) + goto err; + } + if (dumpit->policy) { + idx = netlink_policy_dump_get_policy_idx(ctx->state, + dumpit->policy, + dumpit->maxattr); - if (op->dumpit && !(op->validate & GENL_DONT_VALIDATE_DUMP) && - nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx)) - goto err; + if (nla_put_u32(skb, CTRL_ATTR_POLICY_DUMP, idx)) + goto err; + } nla_nest_end(skb, nest_op); nla_nest_end(skb, nest_pol); @@ -1399,16 +1402,19 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) void *hdr; if (!ctx->policies) { + struct genl_split_ops doit, dumpit; struct genl_ops op; if (ctx->single_op) { - int err; - - err = genl_get_cmd(ctx->op, ctx->rt, &op); - if (WARN_ON(err)) - return err; + if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO, + ctx->rt, &doit) && + genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP, + ctx->rt, &dumpit)) { + WARN_ON(1); + return -ENOENT; + } - if (ctrl_dumppolicy_put_op(skb, cb, &op)) + if (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit)) return skb->len; /* don't enter the loop below */ @@ -1418,7 +1424,12 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) { genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op); - if (ctrl_dumppolicy_put_op(skb, cb, &op)) + genl_cmd_full_to_split(&doit, ctx->rt, + &op, GENL_CMD_CAP_DO); + genl_cmd_full_to_split(&dumpit, ctx->rt, + &op, GENL_CMD_CAP_DUMP); + + if (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit)) return skb->len; ctx->opidx++; From patchwork Fri Nov 4 19:13:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032497 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0E7B9C4332F for ; Fri, 4 Nov 2022 19:14:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229795AbiKDTN5 (ORCPT ); Fri, 4 Nov 2022 15:13:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50180 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229574AbiKDTNw (ORCPT ); Fri, 4 Nov 2022 15:13:52 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 392AA4C24E for ; Fri, 4 Nov 2022 12:13:52 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C811D62314 for ; Fri, 4 Nov 2022 19:13:51 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4DAFC433D6; Fri, 4 Nov 2022 19:13:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589231; bh=zRnVgGNUkGhmWpE7mtiGfMH9+PP3ODq9FHhzSoxbl7E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kH0XwTlWwlS6B1D+XB3RZjj7+9zvEg14TqPpOZwaYNG0wdHfZRyJgBBzck+uxSagG 2/gCxGvV6hYBbor0nNrtV5v+Gpqv61diGXdfKevWLHt5Z08lLezV+bqXfZ9FA12lzM d3XV/VcXl0lM2YTTvYcJ2KUPL4H2daNyFuo6wyHB/7THDuNo88/f8U81P4n0sgHin/ OrHgh4fBkIjP7PJsqPSjup73Db8YIcWq0dVNRDSavCBu7mnqWkJVLrCZIiCW8CCGPl sussVErJ5EvXkaZaaZ2iCmxPT33Ohu0XoaLq8LvXBYYo/xtj9YlLX1ABjQNIPzbgRz CD7nDtYOcM17Q== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 08/13] genetlink: inline genl_get_cmd() Date: Fri, 4 Nov 2022 12:13:38 -0700 Message-Id: <20221104191343.690543-9-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org All callers go via genl_get_cmd_split() now, so rename it to genl_get_cmd() remove the original. Reviewed-by: Jacob Keller Signed-off-by: Jakub Kicinski --- net/netlink/genetlink.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 93e33e20a0e8..ec32b6063a3f 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -181,14 +181,6 @@ static int genl_get_cmd_small(u32 cmd, const struct genl_family *family, return -ENOENT; } -static int genl_get_cmd(u32 cmd, const struct genl_family *family, - struct genl_ops *op) -{ - if (!genl_get_cmd_full(cmd, family, op)) - return 0; - return genl_get_cmd_small(cmd, family, op); -} - static int genl_cmd_full_to_split(struct genl_split_ops *op, const struct genl_family *family, @@ -231,13 +223,15 @@ genl_cmd_full_to_split(struct genl_split_ops *op, } static int -genl_get_cmd_split(u32 cmd, u8 flags, const struct genl_family *family, - struct genl_split_ops *op) +genl_get_cmd(u32 cmd, u8 flags, const struct genl_family *family, + struct genl_split_ops *op) { struct genl_ops full; int err; - err = genl_get_cmd(cmd, family, &full); + err = genl_get_cmd_full(cmd, family, &full); + if (err == -ENOENT) + err = genl_get_cmd_small(cmd, family, &full); if (err) { memset(op, 0, sizeof(*op)); return err; @@ -867,7 +861,7 @@ static int genl_family_rcv_msg(const struct genl_family *family, flags = (nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP ? GENL_CMD_CAP_DUMP : GENL_CMD_CAP_DO; - if (genl_get_cmd_split(hdr->cmd, flags, family, &op)) + if (genl_get_cmd(hdr->cmd, flags, family, &op)) return -EOPNOTSUPP; if ((op.flags & GENL_ADMIN_PERM) && @@ -1265,8 +1259,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) ctx->single_op = true; ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]); - if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO, rt, &doit) && - genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP, rt, &dump)) { + if (genl_get_cmd(ctx->op, GENL_CMD_CAP_DO, rt, &doit) && + genl_get_cmd(ctx->op, GENL_CMD_CAP_DUMP, rt, &dump)) { NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]); return -ENOENT; } @@ -1406,10 +1400,10 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) struct genl_ops op; if (ctx->single_op) { - if (genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DO, - ctx->rt, &doit) && - genl_get_cmd_split(ctx->op, GENL_CMD_CAP_DUMP, - ctx->rt, &dumpit)) { + if (genl_get_cmd(ctx->op, GENL_CMD_CAP_DO, + ctx->rt, &doit) && + genl_get_cmd(ctx->op, GENL_CMD_CAP_DUMP, + ctx->rt, &dumpit)) { WARN_ON(1); return -ENOENT; } From patchwork Fri Nov 4 19:13:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032502 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D27B2C433FE for ; Fri, 4 Nov 2022 19:14:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229788AbiKDTOL (ORCPT ); Fri, 4 Nov 2022 15:14:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229782AbiKDTNz (ORCPT ); Fri, 4 Nov 2022 15:13:55 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50B044D5C5 for ; Fri, 4 Nov 2022 12:13:54 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 01974B82F5F for ; Fri, 4 Nov 2022 19:13:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5B7D8C43470; Fri, 4 Nov 2022 19:13:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589231; bh=X+2EGai9yOk+u2+kfu492XH6fhvEuewwmGAEGLJEOJ0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YrKV7KifM1ThPt/rpf0syvT6GGZXUxar/DnNKW/FgDDDEigxeqMrCnMaxt/zotMCb WZ3neaQTeEcMTAgueFTmfxO1NKIcfcO/QKG3ARU39XRD9b0fEk41yMnKBzsPwOlAwt y74Auk76Lx7cQHse9T5gA4xXsztGf9VR9KvWfGL+LtCTdAkOLbr2+pJWB4JeKCMXhq I9c4rvzRquoswft14BV3Dk7io98Czzov6VXgI1CARgdbhdwNhhNLVdfOyGj3itSyum 9gtW25k3TNDhMrH2vl1ftcmhJz9XV3f+qqPpJd1iaKS+HpnzeKMb9FOUBVFJIthHE4 otbPphsnHY/1g== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 09/13] genetlink: add iterator for walking family ops Date: Fri, 4 Nov 2022 12:13:39 -0700 Message-Id: <20221104191343.690543-10-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Subsequent changes will expose split op structures to users, so walking the family ops with just an index will get harder. Add a structured iterator, convert the simple cases. Policy dumping needs more careful conversion. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- net/netlink/genetlink.c | 117 ++++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index ec32b6063a3f..06bf091c1b8a 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -252,6 +252,57 @@ static void genl_get_cmd_by_index(unsigned int i, WARN_ON_ONCE(1); } +struct genl_op_iter { + const struct genl_family *family; + struct genl_split_ops doit; + struct genl_split_ops dumpit; + int i; + u32 cmd; + u8 flags; +}; + +static bool +genl_op_iter_init(const struct genl_family *family, struct genl_op_iter *iter) +{ + iter->family = family; + iter->i = 0; + + iter->flags = 0; + + return genl_get_cmd_cnt(iter->family); +} + +static bool genl_op_iter_next(struct genl_op_iter *iter) +{ + struct genl_ops op; + + if (iter->i >= genl_get_cmd_cnt(iter->family)) + return false; + + genl_get_cmd_by_index(iter->i, iter->family, &op); + iter->i++; + + genl_cmd_full_to_split(&iter->doit, iter->family, &op, GENL_CMD_CAP_DO); + genl_cmd_full_to_split(&iter->dumpit, iter->family, + &op, GENL_CMD_CAP_DUMP); + + iter->cmd = iter->doit.cmd | iter->dumpit.cmd; + iter->flags = iter->doit.flags | iter->dumpit.flags; + + return true; +} + +static void +genl_op_iter_copy(struct genl_op_iter *dst, struct genl_op_iter *src) +{ + *dst = *src; +} + +static unsigned int genl_op_iter_idx(struct genl_op_iter *iter) +{ + return iter->i; +} + static int genl_allocate_reserve_groups(int n_groups, int *first_id) { unsigned long *new_groups; @@ -419,25 +470,23 @@ static void genl_unregister_mc_groups(const struct genl_family *family) static int genl_validate_ops(const struct genl_family *family) { - int i, j; + struct genl_op_iter i, j; if (WARN_ON(family->n_ops && !family->ops) || WARN_ON(family->n_small_ops && !family->small_ops)) return -EINVAL; - for (i = 0; i < genl_get_cmd_cnt(family); i++) { - struct genl_ops op; - - genl_get_cmd_by_index(i, family, &op); - if (op.dumpit == NULL && op.doit == NULL) + for (genl_op_iter_init(family, &i); genl_op_iter_next(&i); ) { + if (!(i.flags & (GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP))) return -EINVAL; - if (WARN_ON(op.cmd >= family->resv_start_op && op.validate)) + + if (WARN_ON(i.cmd >= family->resv_start_op && + (i.doit.validate || i.dumpit.validate))) return -EINVAL; - for (j = i + 1; j < genl_get_cmd_cnt(family); j++) { - struct genl_ops op2; - genl_get_cmd_by_index(j, family, &op2); - if (op.cmd == op2.cmd) + genl_op_iter_copy(&j, &i); + while (genl_op_iter_next(&j)) { + if (i.cmd == j.cmd) return -EINVAL; } } @@ -917,6 +966,7 @@ static struct genl_family genl_ctrl; static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq, u32 flags, struct sk_buff *skb, u8 cmd) { + struct genl_op_iter i; void *hdr; hdr = genlmsg_put(skb, portid, seq, &genl_ctrl, flags, cmd); @@ -930,33 +980,26 @@ static int ctrl_fill_info(const struct genl_family *family, u32 portid, u32 seq, nla_put_u32(skb, CTRL_ATTR_MAXATTR, family->maxattr)) goto nla_put_failure; - if (genl_get_cmd_cnt(family)) { + if (genl_op_iter_init(family, &i)) { struct nlattr *nla_ops; - int i; nla_ops = nla_nest_start_noflag(skb, CTRL_ATTR_OPS); if (nla_ops == NULL) goto nla_put_failure; - for (i = 0; i < genl_get_cmd_cnt(family); i++) { + while (genl_op_iter_next(&i)) { struct nlattr *nest; - struct genl_ops op; u32 op_flags; - genl_get_cmd_by_index(i, family, &op); - op_flags = op.flags; - if (op.dumpit) - op_flags |= GENL_CMD_CAP_DUMP; - if (op.doit) - op_flags |= GENL_CMD_CAP_DO; - if (op.policy) + op_flags = i.flags; + if (i.doit.policy || i.dumpit.policy) op_flags |= GENL_CMD_CAP_HASPOL; - nest = nla_nest_start_noflag(skb, i + 1); + nest = nla_nest_start_noflag(skb, genl_op_iter_idx(&i)); if (nest == NULL) goto nla_put_failure; - if (nla_put_u32(skb, CTRL_ATTR_OP_ID, op.cmd) || + if (nla_put_u32(skb, CTRL_ATTR_OP_ID, i.cmd) || nla_put_u32(skb, CTRL_ATTR_OP_FLAGS, op_flags)) goto nla_put_failure; @@ -1229,8 +1272,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; struct nlattr **tb = info->attrs; const struct genl_family *rt; - struct genl_ops op; - int err, i; + struct genl_op_iter i; + int err; BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); @@ -1285,26 +1328,18 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) return 0; } - for (i = 0; i < genl_get_cmd_cnt(rt); i++) { - struct genl_split_ops doit, dumpit; - - genl_get_cmd_by_index(i, rt, &op); - - genl_cmd_full_to_split(&doit, ctx->rt, &op, GENL_CMD_CAP_DO); - genl_cmd_full_to_split(&dumpit, ctx->rt, - &op, GENL_CMD_CAP_DUMP); - - if (doit.policy) { + for (genl_op_iter_init(rt, &i); genl_op_iter_next(&i); ) { + if (i.doit.policy) { err = netlink_policy_dump_add_policy(&ctx->state, - doit.policy, - doit.maxattr); + i.doit.policy, + i.doit.maxattr); if (err) goto err_free_state; } - if (dumpit.policy) { + if (i.dumpit.policy) { err = netlink_policy_dump_add_policy(&ctx->state, - dumpit.policy, - dumpit.maxattr); + i.dumpit.policy, + i.dumpit.maxattr); if (err) goto err_free_state; } From patchwork Fri Nov 4 19:13:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032503 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD28BC433FE for ; Fri, 4 Nov 2022 19:14:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229831AbiKDTOa (ORCPT ); Fri, 4 Nov 2022 15:14:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229792AbiKDTN4 (ORCPT ); Fri, 4 Nov 2022 15:13:56 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBDF64732F for ; Fri, 4 Nov 2022 12:13:54 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 7E0EAB82F63 for ; Fri, 4 Nov 2022 19:13:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4541C43141; Fri, 4 Nov 2022 19:13:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589232; bh=bXm+gDAWWC90mSM2QWPalihwCEFv1kOvpEwU37tcvuo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZOXy3tbzOtBR38Q5pTeqb0aRgPJwPy/yZclE4prQ0Jyo8UYiOqhZnZFF2DcADtjpF ScCG9EKf1hMi5wEKWFglNftA89Slq9Y08h++6Z3hRoLFNB1bEobsnD91Tfyx/+L1Kp FpPiBTcezKAZiOd7/TTJE9BKrzdLi7m8KzUQMbwN0XfikYf9x47l7eJlXVEvyEnyay Ej6rZ07CIL3OJCmQ4di+UtAdlNwIq9FKhVHDUVKlx0ChrqUXpvrFeAiaVRkwSCAc5N kS9j8HtmC70kD0gcqCGSWmc7hAzUvEbQ2KmkAKpiGdiTPonxc5/6xSHx0+Rp17nV+x BHHMAtWIVjdeQ== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 10/13] genetlink: use iterator in the op to policy map dumping Date: Fri, 4 Nov 2022 12:13:40 -0700 Message-Id: <20221104191343.690543-11-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org We can't put the full iterator in the struct ctrl_dump_policy_ctx because dump context is statically sized by netlink core. Allocate it dynamically. Rename policy to dump_map to make the logic a little easier to follow. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- net/netlink/genetlink.c | 49 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 06bf091c1b8a..4b8c65d9e9d3 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1252,10 +1252,10 @@ static int genl_ctrl_event(int event, const struct genl_family *family, struct ctrl_dump_policy_ctx { struct netlink_policy_dump_state *state; const struct genl_family *rt; - unsigned int opidx; + struct genl_op_iter *op_iter; u32 op; u16 fam_id; - u8 policies:1, + u8 dump_map:1, single_op:1; }; @@ -1325,9 +1325,16 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) if (!ctx->state) return -ENODATA; + + ctx->dump_map = 1; return 0; } + ctx->op_iter = kmalloc(sizeof(*ctx->op_iter), GFP_KERNEL); + if (!ctx->op_iter) + return -ENOMEM; + ctx->dump_map = genl_op_iter_init(rt, ctx->op_iter); + for (genl_op_iter_init(rt, &i); genl_op_iter_next(&i); ) { if (i.doit.policy) { err = netlink_policy_dump_add_policy(&ctx->state, @@ -1345,12 +1352,16 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) } } - if (!ctx->state) - return -ENODATA; + if (!ctx->state) { + err = -ENODATA; + goto err_free_op_iter; + } return 0; err_free_state: netlink_policy_dump_free(ctx->state); +err_free_op_iter: + kfree(ctx->op_iter); return err; } @@ -1430,11 +1441,10 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; void *hdr; - if (!ctx->policies) { - struct genl_split_ops doit, dumpit; - struct genl_ops op; - + if (ctx->dump_map) { if (ctx->single_op) { + struct genl_split_ops doit, dumpit; + if (genl_get_cmd(ctx->op, GENL_CMD_CAP_DO, ctx->rt, &doit) && genl_get_cmd(ctx->op, GENL_CMD_CAP_DUMP, @@ -1446,26 +1456,18 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) if (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit)) return skb->len; - /* don't enter the loop below */ - ctx->opidx = genl_get_cmd_cnt(ctx->rt); + /* done with the per-op policy index list */ + ctx->dump_map = 0; } - while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) { - genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op); - - genl_cmd_full_to_split(&doit, ctx->rt, - &op, GENL_CMD_CAP_DO); - genl_cmd_full_to_split(&dumpit, ctx->rt, - &op, GENL_CMD_CAP_DUMP); - - if (ctrl_dumppolicy_put_op(skb, cb, &doit, &dumpit)) + while (ctx->dump_map) { + if (ctrl_dumppolicy_put_op(skb, cb, + &ctx->op_iter->doit, + &ctx->op_iter->dumpit)) return skb->len; - ctx->opidx++; + ctx->dump_map = genl_op_iter_next(ctx->op_iter); } - - /* completed with the per-op policy index list */ - ctx->policies = true; } while (netlink_policy_dump_loop(ctx->state)) { @@ -1498,6 +1500,7 @@ static int ctrl_dumppolicy_done(struct netlink_callback *cb) { struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; + kfree(ctx->op_iter); netlink_policy_dump_free(ctx->state); return 0; } From patchwork Fri Nov 4 19:13:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032505 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D20CC4332F for ; Fri, 4 Nov 2022 19:14:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229841AbiKDTOe (ORCPT ); Fri, 4 Nov 2022 15:14:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50718 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229493AbiKDTOI (ORCPT ); Fri, 4 Nov 2022 15:14:08 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 55AF34D5D5 for ; Fri, 4 Nov 2022 12:13:55 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0DA5EB82F46 for ; Fri, 4 Nov 2022 19:13:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C408C433D6; Fri, 4 Nov 2022 19:13:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589232; bh=/qQgjt49tT0y+STbQf8q9CMYiaobhEoz9Zk1corcXm4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B7A9iLzITyozDZzGw0iloDXcHIZwQo2jKZ1n61dEOXy2SwQdU78ULjrWlDLebrFjh HyBbO5SL/PLo5lHkYIZ8+1UUDCA+zfG61vKLBkuv2+VcBtYOD+fDTh/4pHjUiweq/D WWh5eQ7kvwYJhTFdcPCPuH+uoNwF2EZMPm2bioqYvyaM9CKZ8M4Tper24nDaud8Qp3 iykp9KR4x/cGbRNo3FsFhT1nX+pvehg1vO06tPnKKKXL0e5Qt3hEHopbuvTeqyg4ui jevvJfr4s249BoK58D4UXWWj9zRgdynHVZYZ/3vum1AvVHnNcsH1pm2Q9l1qbBgcJb Ywez6Dlt2Uxjg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 11/13] genetlink: inline old iteration helpers Date: Fri, 4 Nov 2022 12:13:41 -0700 Message-Id: <20221104191343.690543-12-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org All dumpers use the iterators now, inline the cmd by index stuff into iterator code. Reviewed-by: Jacob Keller Signed-off-by: Jakub Kicinski --- net/netlink/genetlink.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 4b8c65d9e9d3..0a4f1470f442 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -118,11 +118,6 @@ static const struct genl_family *genl_family_find_byname(char *name) return NULL; } -static int genl_get_cmd_cnt(const struct genl_family *family) -{ - return family->n_ops + family->n_small_ops; -} - static void genl_op_from_full(const struct genl_family *family, unsigned int i, struct genl_ops *op) { @@ -240,18 +235,6 @@ genl_get_cmd(u32 cmd, u8 flags, const struct genl_family *family, return genl_cmd_full_to_split(op, family, &full, flags); } -static void genl_get_cmd_by_index(unsigned int i, - const struct genl_family *family, - struct genl_ops *op) -{ - if (i < family->n_ops) - genl_op_from_full(family, i, op); - else if (i < family->n_ops + family->n_small_ops) - genl_op_from_small(family, i - family->n_ops, op); - else - WARN_ON_ONCE(1); -} - struct genl_op_iter { const struct genl_family *family; struct genl_split_ops doit; @@ -269,22 +252,25 @@ genl_op_iter_init(const struct genl_family *family, struct genl_op_iter *iter) iter->flags = 0; - return genl_get_cmd_cnt(iter->family); + return iter->family->n_ops + iter->family->n_small_ops; } static bool genl_op_iter_next(struct genl_op_iter *iter) { + const struct genl_family *family = iter->family; struct genl_ops op; - if (iter->i >= genl_get_cmd_cnt(iter->family)) + if (iter->i < family->n_ops) + genl_op_from_full(family, iter->i, &op); + else if (iter->i < family->n_ops + family->n_small_ops) + genl_op_from_small(family, iter->i - family->n_ops, &op); + else return false; - genl_get_cmd_by_index(iter->i, iter->family, &op); iter->i++; - genl_cmd_full_to_split(&iter->doit, iter->family, &op, GENL_CMD_CAP_DO); - genl_cmd_full_to_split(&iter->dumpit, iter->family, - &op, GENL_CMD_CAP_DUMP); + genl_cmd_full_to_split(&iter->doit, family, &op, GENL_CMD_CAP_DO); + genl_cmd_full_to_split(&iter->dumpit, family, &op, GENL_CMD_CAP_DUMP); iter->cmd = iter->doit.cmd | iter->dumpit.cmd; iter->flags = iter->doit.flags | iter->dumpit.flags; From patchwork Fri Nov 4 19:13:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032501 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D08A1C4332F for ; Fri, 4 Nov 2022 19:14:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229811AbiKDTOK (ORCPT ); Fri, 4 Nov 2022 15:14:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50228 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229628AbiKDTNz (ORCPT ); Fri, 4 Nov 2022 15:13:55 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F8224D5C4 for ; Fri, 4 Nov 2022 12:13:54 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C2AA062314 for ; Fri, 4 Nov 2022 19:13:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D8171C43146; Fri, 4 Nov 2022 19:13:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589233; bh=dT0npTAMTTP6ciA2Vm2lKPmZ281tWWl9ptWEwCKtUk4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cT0oDzXicyhcFrgr+Ro3LZ9eLnU8sbskvjENVWz5IxDAQH9jwZ4UD/2+dz3ZAVs9R PDr1aCeil4WfdzBV3vF6D2yio8dMRtvY+N7SO2h9vTgrWKyuJc5XgEX8oTYMh8di+J 0Pp3YsH6mILjzs7gd6jww4VpFh2QnKe6AqEsBbW40fxqdhsVPpwMt/hC+y6G0Lhsd1 YsgWldgrLx+R4lu4WKqubuN2+gkJnQzMsph8zSmNpoyEZPA7OdzlvMkfi1SLCRVQqL wy6Qzto1G2onVBy9HVW1y7JlAAPG/Bg69YPjltEoE2nlcPAZjQn+eeisl9I9KW9HfK udlAtaImMsLfg== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 12/13] genetlink: allow families to use split ops directly Date: Fri, 4 Nov 2022 12:13:42 -0700 Message-Id: <20221104191343.690543-13-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Let families to hook in the new split ops. They are more flexible and should not be much larger than full ops. Each split op is 40B while full op is 48B. Devlink for example has 54 dos and 19 dumps, 2 of the dumps do not have a do -> 56 full commands = 2688B. Split ops would have taken 2920B, so 9% more space while allowing individual per/post doit and per-type policies. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- v3: - fix out-of-bounds access when split ops end in DO - fill in the reject-all policy for split ops --- include/net/genetlink.h | 5 ++ net/netlink/genetlink.c | 170 ++++++++++++++++++++++++++++++++++------ 2 files changed, 149 insertions(+), 26 deletions(-) diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 4be7989c451b..d21210709f84 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -46,6 +46,9 @@ struct genl_info; * @n_ops: number of operations supported by this family * @small_ops: the small-struct operations supported by this family * @n_small_ops: number of small-struct operations supported by this family + * @split_ops: the split do/dump form of operation definition + * @n_split_ops: number of entries in @split_ops, not that with split do/dump + * ops the number of entries is not the same as number of commands * * Attribute policies (the combination of @policy and @maxattr fields) * can be attached at the family level or at the operation level. @@ -63,6 +66,7 @@ struct genl_family { u8 parallel_ops:1; u8 n_ops; u8 n_small_ops; + u8 n_split_ops; u8 n_mcgrps; u8 resv_start_op; const struct nla_policy *policy; @@ -74,6 +78,7 @@ struct genl_family { struct genl_info *info); const struct genl_ops * ops; const struct genl_small_ops *small_ops; + const struct genl_split_ops *split_ops; const struct genl_multicast_group *mcgrps; struct module *module; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0a4f1470f442..90b0feb5eb73 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -101,6 +101,17 @@ genl_op_fill_in_reject_policy(const struct genl_family *family, op->maxattr = 1; } +static void +genl_op_fill_in_reject_policy_split(const struct genl_family *family, + struct genl_split_ops *op) +{ + if (op->policy) + 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); @@ -118,6 +129,16 @@ static const struct genl_family *genl_family_find_byname(char *name) return NULL; } +struct genl_op_iter { + const struct genl_family *family; + struct genl_split_ops doit; + struct genl_split_ops dumpit; + int cmd_idx; + int entry_idx; + u32 cmd; + u8 flags; +}; + static void genl_op_from_full(const struct genl_family *family, unsigned int i, struct genl_ops *op) { @@ -176,6 +197,50 @@ static int genl_get_cmd_small(u32 cmd, const struct genl_family *family, return -ENOENT; } +static void genl_op_from_split(struct genl_op_iter *iter) +{ + const struct genl_family *family = iter->family; + int i, cnt = 0; + + i = iter->entry_idx - family->n_ops - family->n_small_ops; + + if (family->split_ops[i + cnt].flags & GENL_CMD_CAP_DO) { + iter->doit = family->split_ops[i + cnt]; + genl_op_fill_in_reject_policy_split(family, &iter->doit); + cnt++; + } else { + memset(&iter->doit, 0, sizeof(iter->doit)); + } + + if (i + cnt < family->n_split_ops && + family->split_ops[i + cnt].flags & GENL_CMD_CAP_DUMP) { + iter->dumpit = family->split_ops[i + cnt]; + genl_op_fill_in_reject_policy_split(family, &iter->dumpit); + cnt++; + } else { + memset(&iter->dumpit, 0, sizeof(iter->dumpit)); + } + + WARN_ON(!cnt); + iter->entry_idx += cnt; +} + +static int +genl_get_cmd_split(u32 cmd, u8 flag, const struct genl_family *family, + struct genl_split_ops *op) +{ + int i; + + for (i = 0; i < family->n_split_ops; i++) + if (family->split_ops[i].cmd == cmd && + family->split_ops[i].flags & flag) { + *op = family->split_ops[i]; + return 0; + } + + return -ENOENT; +} + static int genl_cmd_full_to_split(struct genl_split_ops *op, const struct genl_family *family, @@ -227,50 +292,60 @@ genl_get_cmd(u32 cmd, u8 flags, const struct genl_family *family, err = genl_get_cmd_full(cmd, family, &full); if (err == -ENOENT) err = genl_get_cmd_small(cmd, family, &full); - if (err) { - memset(op, 0, sizeof(*op)); - return err; - } + /* Found one of legacy forms */ + if (err == 0) + return genl_cmd_full_to_split(op, family, &full, flags); - return genl_cmd_full_to_split(op, family, &full, flags); + err = genl_get_cmd_split(cmd, flags, family, op); + if (err) + memset(op, 0, sizeof(*op)); + return err; } -struct genl_op_iter { - const struct genl_family *family; - struct genl_split_ops doit; - struct genl_split_ops dumpit; - int i; - u32 cmd; - u8 flags; -}; - static bool genl_op_iter_init(const struct genl_family *family, struct genl_op_iter *iter) { iter->family = family; - iter->i = 0; + iter->cmd_idx = 0; + iter->entry_idx = 0; iter->flags = 0; - return iter->family->n_ops + iter->family->n_small_ops; + return iter->family->n_ops + + iter->family->n_small_ops + + iter->family->n_split_ops; } static bool genl_op_iter_next(struct genl_op_iter *iter) { const struct genl_family *family = iter->family; + bool legacy_op = true; struct genl_ops op; - if (iter->i < family->n_ops) - genl_op_from_full(family, iter->i, &op); - else if (iter->i < family->n_ops + family->n_small_ops) - genl_op_from_small(family, iter->i - family->n_ops, &op); - else + if (iter->entry_idx < family->n_ops) { + genl_op_from_full(family, iter->entry_idx, &op); + } else if (iter->entry_idx < family->n_ops + family->n_small_ops) { + genl_op_from_small(family, iter->entry_idx - family->n_ops, + &op); + } else if (iter->entry_idx < + family->n_ops + family->n_small_ops + family->n_split_ops) { + legacy_op = false; + /* updates entry_idx */ + genl_op_from_split(iter); + } else { return false; + } - iter->i++; + iter->cmd_idx++; - genl_cmd_full_to_split(&iter->doit, family, &op, GENL_CMD_CAP_DO); - genl_cmd_full_to_split(&iter->dumpit, family, &op, GENL_CMD_CAP_DUMP); + if (legacy_op) { + iter->entry_idx++; + + genl_cmd_full_to_split(&iter->doit, family, + &op, GENL_CMD_CAP_DO); + genl_cmd_full_to_split(&iter->dumpit, family, + &op, GENL_CMD_CAP_DUMP); + } iter->cmd = iter->doit.cmd | iter->dumpit.cmd; iter->flags = iter->doit.flags | iter->dumpit.flags; @@ -286,7 +361,7 @@ genl_op_iter_copy(struct genl_op_iter *dst, struct genl_op_iter *src) static unsigned int genl_op_iter_idx(struct genl_op_iter *iter) { - return iter->i; + return iter->cmd_idx; } static int genl_allocate_reserve_groups(int n_groups, int *first_id) @@ -454,12 +529,22 @@ static void genl_unregister_mc_groups(const struct genl_family *family) } } +static bool genl_split_op_check(const struct genl_split_ops *op) +{ + if (WARN_ON(hweight8(op->flags & (GENL_CMD_CAP_DO | + GENL_CMD_CAP_DUMP)) != 1)) + return true; + return false; +} + static int genl_validate_ops(const struct genl_family *family) { struct genl_op_iter i, j; + unsigned int s; if (WARN_ON(family->n_ops && !family->ops) || - WARN_ON(family->n_small_ops && !family->small_ops)) + WARN_ON(family->n_small_ops && !family->small_ops) || + WARN_ON(family->n_split_ops && !family->split_ops)) return -EINVAL; for (genl_op_iter_init(family, &i); genl_op_iter_next(&i); ) { @@ -477,6 +562,39 @@ static int genl_validate_ops(const struct genl_family *family) } } + if (family->n_split_ops) { + if (genl_split_op_check(&family->split_ops[0])) + return -EINVAL; + } + + for (s = 1; s < family->n_split_ops; s++) { + const struct genl_split_ops *a, *b; + + a = &family->split_ops[s - 1]; + b = &family->split_ops[s]; + + if (genl_split_op_check(b)) + return -EINVAL; + + /* Check sort order */ + if (a->cmd < b->cmd) + continue; + + if (a->internal_flags != b->internal_flags || + ((a->flags ^ b->flags) & ~(GENL_CMD_CAP_DO | + GENL_CMD_CAP_DUMP))) { + WARN_ON(1); + return -EINVAL; + } + + if ((a->flags & GENL_CMD_CAP_DO) && + (b->flags & GENL_CMD_CAP_DUMP)) + continue; + + WARN_ON(1); + return -EINVAL; + } + return 0; } From patchwork Fri Nov 4 19:13:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 13032504 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C08EC433FE for ; Fri, 4 Nov 2022 19:14:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229770AbiKDTOc (ORCPT ); Fri, 4 Nov 2022 15:14:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50716 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229489AbiKDTOI (ORCPT ); Fri, 4 Nov 2022 15:14:08 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B2EE4D5D6 for ; Fri, 4 Nov 2022 12:13:55 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0F9D1B82F66 for ; Fri, 4 Nov 2022 19:13:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5FDBCC433D7; Fri, 4 Nov 2022 19:13:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1667589233; bh=lGUowKPCdleRRa1Z8ZxxHSDgl6l5BApGhJyHI8oZM3Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b9R1B/+1N1Us9/YbsPDVCqrCKQ77Py32XcqnKyn7u4+IXGW4VjXFRA4Q1/pOnpMcl yoyD1dkUZPnG4KFKBShu4r6oqNTx9cWZD8Ja0zD1R9dzvGTQllg9NvKGtHH4VDoMZV NEW882MxPEmdyiisVkr6+WI6OQd7TBZN2DC0WOoHBZ/o3bQfHE4O+9CQfGtOmwd8UD lREPoS7Lg3fMD/tHaKdbqmb1KUibuYL7ZtznJM0JsrnF+vGIxaSuxsMNN/vOI0rGPI DZv0e3K2pvaRDP+uFSDYNc+27zTEBqzfAnMUP37eyFEDvOIzglrMH85ekZD0WYwA56 tqGyu2aiyzgow== From: Jakub Kicinski To: davem@davemloft.net Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com, jiri@resnulli.us, razor@blackwall.org, nicolas.dichtel@6wind.com, gnault@redhat.com, jacob.e.keller@intel.com, fw@strlen.de, Jakub Kicinski Subject: [PATCH net-next v3 13/13] genetlink: convert control family to split ops Date: Fri, 4 Nov 2022 12:13:43 -0700 Message-Id: <20221104191343.690543-14-kuba@kernel.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221104191343.690543-1-kuba@kernel.org> References: <20221104191343.690543-1-kuba@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Prove that the split ops work. Sadly we need to keep bug-wards compatibility and specify the same policy for dump as do, even tho we don't parse inputs for the dump. Signed-off-by: Jakub Kicinski Reviewed-by: Jacob Keller --- net/netlink/genetlink.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 90b0feb5eb73..362a61179036 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1609,14 +1609,22 @@ static int ctrl_dumppolicy_done(struct netlink_callback *cb) return 0; } -static const struct genl_ops genl_ctrl_ops[] = { +static const struct genl_split_ops genl_ctrl_ops[] = { { .cmd = CTRL_CMD_GETFAMILY, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .validate = GENL_DONT_VALIDATE_STRICT, .policy = ctrl_policy_family, .maxattr = ARRAY_SIZE(ctrl_policy_family) - 1, .doit = ctrl_getfamily, + .flags = GENL_CMD_CAP_DO, + }, + { + .cmd = CTRL_CMD_GETFAMILY, + .validate = GENL_DONT_VALIDATE_DUMP, + .policy = ctrl_policy_family, + .maxattr = ARRAY_SIZE(ctrl_policy_family) - 1, .dumpit = ctrl_dumpfamily, + .flags = GENL_CMD_CAP_DUMP, }, { .cmd = CTRL_CMD_GETPOLICY, @@ -1625,6 +1633,7 @@ static const struct genl_ops genl_ctrl_ops[] = { .start = ctrl_dumppolicy_start, .dumpit = ctrl_dumppolicy, .done = ctrl_dumppolicy_done, + .flags = GENL_CMD_CAP_DUMP, }, }; @@ -1634,8 +1643,8 @@ static const struct genl_multicast_group genl_ctrl_groups[] = { static struct genl_family genl_ctrl __ro_after_init = { .module = THIS_MODULE, - .ops = genl_ctrl_ops, - .n_ops = ARRAY_SIZE(genl_ctrl_ops), + .split_ops = genl_ctrl_ops, + .n_split_ops = ARRAY_SIZE(genl_ctrl_ops), .resv_start_op = CTRL_CMD_GETPOLICY + 1, .mcgrps = genl_ctrl_groups, .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),