From patchwork Fri Oct 2 09:09:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 267723 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49B76C4727F for ; Fri, 2 Oct 2020 09:09:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1991021789 for ; Fri, 2 Oct 2020 09:09:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387695AbgJBJJ6 (ORCPT ); Fri, 2 Oct 2020 05:09:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387638AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 46566C0613E4 for ; Fri, 2 Oct 2020 02:09:56 -0700 (PDT) Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1kOH4b-00F9QD-46; Fri, 02 Oct 2020 11:09:53 +0200 From: Johannes Berg To: netdev@vger.kernel.org Cc: Jakub Kicinski , Johannes Berg Subject: [PATCH 1/5] netlink: simplify netlink_policy_dump_start() prototype Date: Fri, 2 Oct 2020 11:09:40 +0200 Message-Id: <20201002110205.35dfe0fb3299.If2afc69c480c29c3dfc7c373c9a8b45678939746@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201002090944.195891-1-johannes@sipsolutions.net> References: <20201002090944.195891-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg Since moving the call to this to a dump start() handler we no longer need this to deal with being called after having been called already. Since that is the preferred way of doing things anyway, remove the code necessary for that and simply return the pointer (or an ERR_PTR()). Signed-off-by: Johannes Berg Reviewed-by: Jakub Kicinski --- include/net/netlink.h | 6 +++--- net/netlink/genetlink.c | 5 ++++- net/netlink/policy.c | 19 +++++++------------ 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 00258590f2cb..4be0ad237e57 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -1937,9 +1937,9 @@ void nla_get_range_signed(const struct nla_policy *pt, struct netlink_policy_dump_state; -int netlink_policy_dump_start(const struct nla_policy *policy, - unsigned int maxtype, - struct netlink_policy_dump_state **state); +struct netlink_policy_dump_state * +netlink_policy_dump_start(const struct nla_policy *policy, + unsigned int maxtype); bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state); int netlink_policy_dump_write(struct sk_buff *skb, struct netlink_policy_dump_state *state); diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index fad691037402..537472342781 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1164,7 +1164,10 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) if (!op.policy) return -ENODATA; - return netlink_policy_dump_start(op.policy, op.maxattr, &ctx->state); + ctx->state = netlink_policy_dump_start(op.policy, op.maxattr); + if (IS_ERR(ctx->state)) + return PTR_ERR(ctx->state); + return 0; } static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) diff --git a/net/netlink/policy.c b/net/netlink/policy.c index 0dc804afdb25..2a0d85cbc0a2 100644 --- a/net/netlink/policy.c +++ b/net/netlink/policy.c @@ -76,17 +76,14 @@ static unsigned int get_policy_idx(struct netlink_policy_dump_state *state, return -1; } -int netlink_policy_dump_start(const struct nla_policy *policy, - unsigned int maxtype, - struct netlink_policy_dump_state **statep) +struct netlink_policy_dump_state * +netlink_policy_dump_start(const struct nla_policy *policy, + unsigned int maxtype) { struct netlink_policy_dump_state *state; unsigned int policy_idx; int err; - if (*statep) - return 0; - /* * walk the policies and nested ones first, and build * a linear list of them. @@ -95,12 +92,12 @@ int netlink_policy_dump_start(const struct nla_policy *policy, state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), GFP_KERNEL); if (!state) - return -ENOMEM; + return ERR_PTR(-ENOMEM); state->n_alloc = INITIAL_POLICIES_ALLOC; err = add_policy(&state, policy, maxtype); if (err) - return err; + return ERR_PTR(err); for (policy_idx = 0; policy_idx < state->n_alloc && state->policies[policy_idx].policy; @@ -120,7 +117,7 @@ int netlink_policy_dump_start(const struct nla_policy *policy, policy[type].nested_policy, policy[type].len); if (err) - return err; + return ERR_PTR(err); break; default: break; @@ -128,9 +125,7 @@ int netlink_policy_dump_start(const struct nla_policy *policy, } } - *statep = state; - - return 0; + return state; } static bool From patchwork Fri Oct 2 09:09:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 267120 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4DEDEC4363D for ; Fri, 2 Oct 2020 09:09:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 19D5D20874 for ; Fri, 2 Oct 2020 09:09:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387689AbgJBJJ5 (ORCPT ); Fri, 2 Oct 2020 05:09:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387623AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BD0AC0613E5 for ; Fri, 2 Oct 2020 02:09:56 -0700 (PDT) Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1kOH4b-00F9QD-Cv; Fri, 02 Oct 2020 11:09:53 +0200 From: Johannes Berg To: netdev@vger.kernel.org Cc: Jakub Kicinski , Johannes Berg Subject: [PATCH 2/5] netlink: compare policy more accurately Date: Fri, 2 Oct 2020 11:09:41 +0200 Message-Id: <20201002110205.73a89b98cf10.I78718edf29745b8e5f5ea2d289e59c8884fdd8c7@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201002090944.195891-1-johannes@sipsolutions.net> References: <20201002090944.195891-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg The maxtype is really an integral part of the policy, and while we haven't gotten into a situation yet where this happens, it seems that some developer might eventually have two places pointing to identical policies, with different maxattr to exclude some attrs in one of the places. Even if not, it's really the right thing to compare both since the two data items fundamentally belong together. Signed-off-by: Johannes Berg Reviewed-by: Jakub Kicinski --- net/netlink/policy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/netlink/policy.c b/net/netlink/policy.c index 2a0d85cbc0a2..7bc8f81ecc43 100644 --- a/net/netlink/policy.c +++ b/net/netlink/policy.c @@ -35,7 +35,8 @@ static int add_policy(struct netlink_policy_dump_state **statep, return 0; for (i = 0; i < state->n_alloc; i++) { - if (state->policies[i].policy == policy) + if (state->policies[i].policy == policy && + state->policies[i].maxtype == maxtype) return 0; if (!state->policies[i].policy) { From patchwork Fri Oct 2 09:09:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 267721 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71AADC4363D for ; Fri, 2 Oct 2020 09:10:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 35D1B20679 for ; Fri, 2 Oct 2020 09:10:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387672AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387545AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3AE8DC0613E2 for ; Fri, 2 Oct 2020 02:09:56 -0700 (PDT) Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1kOH4b-00F9QD-LE; Fri, 02 Oct 2020 11:09:53 +0200 From: Johannes Berg To: netdev@vger.kernel.org Cc: Jakub Kicinski , Johannes Berg Subject: [PATCH 3/5] netlink: rework policy dump to support multiple policies Date: Fri, 2 Oct 2020 11:09:42 +0200 Message-Id: <20201002110205.2d0d1bd5027d.I525cd130f9c78d7a6acd90d735a67974e51fb73c@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201002090944.195891-1-johannes@sipsolutions.net> References: <20201002090944.195891-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg Rework the policy dump code a bit to support adding multiple policies to a single dump, in order to e.g. support per-op policies in generic netlink. Signed-off-by: Johannes Berg Reviewed-by: Jakub Kicinski --- include/net/netlink.h | 62 +++++++++++++++++++++++++++++++++++++++-- net/netlink/genetlink.c | 6 ++-- net/netlink/policy.c | 57 +++++++++++++++++++++++++++++-------- 3 files changed, 106 insertions(+), 19 deletions(-) diff --git a/include/net/netlink.h b/include/net/netlink.h index 4be0ad237e57..a929759a03f5 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -1937,12 +1937,68 @@ void nla_get_range_signed(const struct nla_policy *pt, struct netlink_policy_dump_state; -struct netlink_policy_dump_state * -netlink_policy_dump_start(const struct nla_policy *policy, - unsigned int maxtype); +/** + * netlink_policy_dump_add_policy - add a policy to the dump + * @pstate: state to add to, may be reallocated, must be %NULL the first time + * @policy: the new policy to add to the dump + * @maxtype: the new policy's max attr type + * + * Returns: 0 on success, a negative error code otherwise. + * + * Call this to allocate a policy dump state, and to add policies to it. This + * should be called from the dump start() callback. + * + * Note: on failures, any previously allocated state is freed. + */ +int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, + const struct nla_policy *policy, + unsigned int maxtype); + +/** + * netlink_policy_dump_get_policy_idx - retrieve policy index + * @state: the policy dump state + * @policy: the policy to find + * @maxattr: the policy's maxattr + * + * Returns: the index of the given policy in the dump state + * + * Call this to find a policy index when you've added multiple and e.g. + * need to tell userspace which command has which policy (by index). + * + * Note: this will WARN and return 0 if the policy isn't found, which + * means it wasn't added in the first place, which would be an + * internal consistency bug. + */ +int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state, + const struct nla_policy *policy, + unsigned int maxtype); + +/** + * netlink_policy_dump_loop - dumping loop indicator + * @state: the policy dump state + * + * Returns: %true if the dump continues, %false otherwise + * + * Note: this frees the dump state when finishing + */ bool netlink_policy_dump_loop(struct netlink_policy_dump_state *state); + +/** + * netlink_policy_dump_write - write current policy dump attributes + * @skb: the message skb to write to + * @state: the policy dump state + * + * Returns: 0 on success, an error code otherwise + */ int netlink_policy_dump_write(struct sk_buff *skb, struct netlink_policy_dump_state *state); + +/** + * netlink_policy_dump_free - free policy dump state + * @state: the policy dump state to free + * + * Call this from the done() method to ensure dump state is freed. + */ void netlink_policy_dump_free(struct netlink_policy_dump_state *state); #endif diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 537472342781..42777749d4d8 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1164,10 +1164,8 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) if (!op.policy) return -ENODATA; - ctx->state = netlink_policy_dump_start(op.policy, op.maxattr); - if (IS_ERR(ctx->state)) - return PTR_ERR(ctx->state); - return 0; + return netlink_policy_dump_add_policy(&ctx->state, op.policy, + op.maxattr); } static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) diff --git a/net/netlink/policy.c b/net/netlink/policy.c index 7bc8f81ecc43..d930064cbaf3 100644 --- a/net/netlink/policy.c +++ b/net/netlink/policy.c @@ -77,28 +77,41 @@ static unsigned int get_policy_idx(struct netlink_policy_dump_state *state, return -1; } -struct netlink_policy_dump_state * -netlink_policy_dump_start(const struct nla_policy *policy, - unsigned int maxtype) +static struct netlink_policy_dump_state *alloc_state(void) { struct netlink_policy_dump_state *state; + + state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), + GFP_KERNEL); + if (!state) + return ERR_PTR(-ENOMEM); + state->n_alloc = INITIAL_POLICIES_ALLOC; + + return state; +} + +int netlink_policy_dump_add_policy(struct netlink_policy_dump_state **pstate, + const struct nla_policy *policy, + unsigned int maxtype) +{ + struct netlink_policy_dump_state *state = *pstate; unsigned int policy_idx; int err; + if (!state) { + state = alloc_state(); + if (IS_ERR(state)) + return PTR_ERR(state); + } + /* * walk the policies and nested ones first, and build * a linear list of them. */ - state = kzalloc(struct_size(state, policies, INITIAL_POLICIES_ALLOC), - GFP_KERNEL); - if (!state) - return ERR_PTR(-ENOMEM); - state->n_alloc = INITIAL_POLICIES_ALLOC; - err = add_policy(&state, policy, maxtype); if (err) - return ERR_PTR(err); + return err; for (policy_idx = 0; policy_idx < state->n_alloc && state->policies[policy_idx].policy; @@ -118,7 +131,7 @@ netlink_policy_dump_start(const struct nla_policy *policy, policy[type].nested_policy, policy[type].len); if (err) - return ERR_PTR(err); + return err; break; default: break; @@ -126,7 +139,27 @@ netlink_policy_dump_start(const struct nla_policy *policy, } } - return state; + *pstate = state; + return 0; +} + +int netlink_policy_dump_get_policy_idx(struct netlink_policy_dump_state *state, + const struct nla_policy *policy, + unsigned int maxtype) +{ + unsigned int i; + + if (WARN_ON(!policy || !maxtype)) + return 0; + + for (i = 0; i < state->n_alloc; i++) { + if (state->policies[i].policy == policy && + state->policies[i].maxtype == maxtype) + return i; + } + + WARN_ON(1); + return 0; } static bool From patchwork Fri Oct 2 09:09:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 267119 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 342F4C4363D for ; Fri, 2 Oct 2020 09:10:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F06E120679 for ; Fri, 2 Oct 2020 09:10:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387701AbgJBJJ7 (ORCPT ); Fri, 2 Oct 2020 05:09:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387644AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50A92C0613E6 for ; Fri, 2 Oct 2020 02:09:56 -0700 (PDT) Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1kOH4b-00F9QD-U6; Fri, 02 Oct 2020 11:09:54 +0200 From: Johannes Berg To: netdev@vger.kernel.org Cc: Jakub Kicinski , Johannes Berg Subject: [PATCH 4/5] genetlink: factor skb preparation out of ctrl_dumppolicy() Date: Fri, 2 Oct 2020 11:09:43 +0200 Message-Id: <20201002110205.ce65a163aebd.I0e59ae414404a92143c6ed8b0b0caf7e0e0d11a0@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201002090944.195891-1-johannes@sipsolutions.net> References: <20201002090944.195891-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg We'll need this later for the per-op policy index dump. Signed-off-by: Johannes Berg Reviewed-by: Jakub Kicinski --- net/netlink/genetlink.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 42777749d4d8..0ab9549e30ee 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1168,23 +1168,35 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) op.maxattr); } +static void *ctrl_dumppolicy_prep(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; + void *hdr; + + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, &genl_ctrl, + NLM_F_MULTI, CTRL_CMD_GETPOLICY); + if (!hdr) + return NULL; + + if (nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, ctx->fam_id)) + return NULL; + + return hdr; +} + static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) { struct ctrl_dump_policy_ctx *ctx = (void *)cb->ctx; while (netlink_policy_dump_loop(ctx->state)) { - void *hdr; + void *hdr = ctrl_dumppolicy_prep(skb, cb); struct nlattr *nest; - hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, &genl_ctrl, - NLM_F_MULTI, CTRL_CMD_GETPOLICY); if (!hdr) goto nla_put_failure; - if (nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, ctx->fam_id)) - goto nla_put_failure; - nest = nla_nest_start(skb, CTRL_ATTR_POLICY); if (!nest) goto nla_put_failure; From patchwork Fri Oct 2 09:09:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 267118 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A156C4727F for ; Fri, 2 Oct 2020 09:10:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6C6A120679 for ; Fri, 2 Oct 2020 09:10:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387684AbgJBJJ5 (ORCPT ); Fri, 2 Oct 2020 05:09:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33650 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387620AbgJBJJ4 (ORCPT ); Fri, 2 Oct 2020 05:09:56 -0400 Received: from sipsolutions.net (s3.sipsolutions.net [IPv6:2a01:4f8:191:4433::2]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4130EC0613E3 for ; Fri, 2 Oct 2020 02:09:56 -0700 (PDT) Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1kOH4c-00F9QD-Aw; Fri, 02 Oct 2020 11:09:54 +0200 From: Johannes Berg To: netdev@vger.kernel.org Cc: Jakub Kicinski , Johannes Berg Subject: [PATCH 5/5] genetlink: properly support per-op policy dumping Date: Fri, 2 Oct 2020 11:09:44 +0200 Message-Id: <20201002110205.17810866ae42.I19674e30193a115c120d976d1e3ebc9ec7c8235e@changeid> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201002090944.195891-1-johannes@sipsolutions.net> References: <20201002090944.195891-1-johannes@sipsolutions.net> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Johannes Berg Add support for per-op policy dumping. The data is pretty much as before, except that now the assumption that the policy with index 0 is "the" policy no longer holds - you now need to look at the new CTRL_ATTR_OP_POLICY attribute which is a nested attr containing the cmd -> policy index mapping. When a single op is requested, the CTRL_ATTR_OP_POLICY will be added but the policy for this op is still guaranteed to be at index 0, so that's just for convenience. Signed-off-by: Johannes Berg --- include/uapi/linux/genetlink.h | 1 + net/netlink/genetlink.c | 107 ++++++++++++++++++++++++++++----- 2 files changed, 93 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h index 7dbe2d5d7d46..583dcc737250 100644 --- a/include/uapi/linux/genetlink.h +++ b/include/uapi/linux/genetlink.h @@ -65,6 +65,7 @@ enum { CTRL_ATTR_MCAST_GROUPS, CTRL_ATTR_POLICY, CTRL_ATTR_OP, + CTRL_ATTR_OP_POLICY, __CTRL_ATTR_MAX, }; diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 0ab9549e30ee..b2a87fbd3875 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -1112,7 +1112,12 @@ 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; + u32 op; u16 fam_id; + u8 policies:1, + single_op:1; }; static const struct nla_policy ctrl_policy_policy[] = { @@ -1129,7 +1134,7 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) struct nlattr **tb = info->attrs; const struct genl_family *rt; struct genl_ops op; - int err; + int err, i; BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); @@ -1150,22 +1155,40 @@ static int ctrl_dumppolicy_start(struct netlink_callback *cb) if (!rt) return -ENOENT; + ctx->rt = rt; + if (tb[CTRL_ATTR_OP]) { - err = genl_get_cmd(nla_get_u32(tb[CTRL_ATTR_OP]), rt, &op); + ctx->single_op = true; + ctx->op = nla_get_u32(tb[CTRL_ATTR_OP]); + + err = genl_get_cmd(ctx->op, rt, &op); if (err) { NL_SET_BAD_ATTR(cb->extack, tb[CTRL_ATTR_OP]); return err; } - } else { - op.policy = rt->policy; - op.maxattr = rt->maxattr; + + if (!op.policy) + return -ENODATA; + + return netlink_policy_dump_add_policy(&ctx->state, op.policy, + op.maxattr); } - if (!op.policy) - return -ENODATA; + for (i = 0; i < genl_get_cmd_cnt(rt); i++) { + genl_get_cmd_by_index(i, rt, &op); + + if (op.policy) { + err = netlink_policy_dump_add_policy(&ctx->state, + op.policy, + op.maxattr); + if (err) + return err; + } + } - return netlink_policy_dump_add_policy(&ctx->state, op.policy, - op.maxattr); + if (!ctx->state) + return -ENODATA; + return 0; } static void *ctrl_dumppolicy_prep(struct sk_buff *skb, @@ -1189,11 +1212,65 @@ static void *ctrl_dumppolicy_prep(struct sk_buff *skb, 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) { + if (ctx->single_op) { + struct nlattr *nest; + + hdr = ctrl_dumppolicy_prep(skb, cb); + if (!hdr) + goto nla_put_failure; + + nest = nla_nest_start(skb, CTRL_ATTR_OP_POLICY); + if (!nest) + goto nla_put_failure; + + if (nla_put_u32(skb, ctx->op, 0)) + goto nla_put_failure; + + nla_nest_end(skb, nest); + genlmsg_end(skb, hdr); + + /* skip loop below */ + ctx->opidx = genl_get_cmd_cnt(ctx->rt); + } + + while (ctx->opidx < genl_get_cmd_cnt(ctx->rt)) { + struct genl_ops op; + struct nlattr *nest; + int idx; + + hdr = ctrl_dumppolicy_prep(skb, cb); + if (!hdr) + goto nla_put_failure; + + genl_get_cmd_by_index(ctx->opidx, ctx->rt, &op); + + nest = nla_nest_start(skb, CTRL_ATTR_OP_POLICY); + if (!nest) + goto nla_put_failure; + + idx = netlink_policy_dump_get_policy_idx(ctx->state, + op.policy, + op.maxattr); + if (nla_put_u32(skb, op.cmd, idx)) + goto nla_put_failure; + + ctx->opidx++; + + nla_nest_end(skb, nest); + genlmsg_end(skb, hdr); + } + + /* completed with the per-op policy index list */ + ctx->policies = true; + } while (netlink_policy_dump_loop(ctx->state)) { - void *hdr = ctrl_dumppolicy_prep(skb, cb); struct nlattr *nest; + hdr = ctrl_dumppolicy_prep(skb, cb); if (!hdr) goto nla_put_failure; @@ -1201,20 +1278,20 @@ static int ctrl_dumppolicy(struct sk_buff *skb, struct netlink_callback *cb) if (!nest) goto nla_put_failure; + if (netlink_policy_dump_write(skb, ctx->state)) goto nla_put_failure; nla_nest_end(skb, nest); genlmsg_end(skb, hdr); - continue; - -nla_put_failure: - genlmsg_cancel(skb, hdr); - break; } return skb->len; + +nla_put_failure: + genlmsg_cancel(skb, hdr); + return skb->len; } static int ctrl_dumppolicy_done(struct netlink_callback *cb)