From patchwork Tue May 24 14:35:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Romanovsky X-Patchwork-Id: 9133779 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2A8F8607D3 for ; Tue, 24 May 2016 14:36:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1D78D28117 for ; Tue, 24 May 2016 14:36:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1256D2827A; Tue, 24 May 2016 14:36:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9784E28117 for ; Tue, 24 May 2016 14:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755691AbcEXOgN (ORCPT ); Tue, 24 May 2016 10:36:13 -0400 Received: from mail.kernel.org ([198.145.29.136]:43085 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752991AbcEXOgM (ORCPT ); Tue, 24 May 2016 10:36:12 -0400 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7CA1720251; Tue, 24 May 2016 14:36:10 +0000 (UTC) Received: from localhost (unknown [213.57.247.249]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 0C131203A1; Tue, 24 May 2016 14:36:08 +0000 (UTC) From: Leon Romanovsky To: dledford@redhat.com Cc: linux-rdma@vger.kernel.org, Matan Barak , Leon Romanovsky , Haggai Eran Subject: [RFC ABI 2/8] lib/nlattr: Add parsing netlink and validate using callback Date: Tue, 24 May 2016 17:35:20 +0300 Message-Id: <1464100526-31730-3-git-send-email-leonro@mellanox.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464100526-31730-1-git-send-email-leonro@mellanox.com> References: <1464100526-31730-1-git-send-email-leonro@mellanox.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Matan Barak When parsing netlink packets, users may want to do some extra validations on the netlink attributes. Adding nla_parse_cb, which gets an extra callback parameter. This function is invoked for every netlink attribute. If the callback fails, parsing will fail as well. Signed-off-by: Leon Romanovsky Signed-off-by: Matan Barak Signed-off-by: Haggai Eran --- include/linux/netlink.h | 1 - include/net/netlink.h | 5 +++++ lib/nlattr.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/linux/netlink.h b/include/linux/netlink.h index da14ab6..a08b63b 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -117,7 +117,6 @@ netlink_skb_clone(struct sk_buff *skb, gfp_t gfp_mask) #define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN) - struct netlink_callback { struct sk_buff *skb; const struct nlmsghdr *nlh; diff --git a/include/net/netlink.h b/include/net/netlink.h index 0e31727..70ba851 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -149,6 +149,8 @@ * nla_find() find attribute in stream of attributes * nla_find_nested() find attribute in nested attributes * nla_parse() parse and validate stream of attrs + * nla_parse_cb() parse stream of attrs and call to + * callback for every nlattr * nla_parse_nested() parse nested attribuets * nla_for_each_attr() loop over all attributes * nla_for_each_nested() loop over the nested attributes @@ -237,6 +239,9 @@ int nla_validate(const struct nlattr *head, int len, int maxtype, const struct nla_policy *policy); int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, int len, const struct nla_policy *policy); +int nla_parse_cb(struct nlattr **tb, int maxtype, const struct nlattr *head, + int len, const struct nla_policy *policy, + int (*cb)(const struct nlattr *, void *), void *cb_priv); int nla_policy_len(const struct nla_policy *, int); struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype); size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); diff --git a/lib/nlattr.c b/lib/nlattr.c index f5907d2..ec79387 100644 --- a/lib/nlattr.c +++ b/lib/nlattr.c @@ -165,22 +165,28 @@ nla_policy_len(const struct nla_policy *p, int n) EXPORT_SYMBOL(nla_policy_len); /** - * nla_parse - Parse a stream of attributes into a tb buffer + * nla_parse_cb - Parse a stream of attributes into a tb buffer with callback * @tb: destination array with maxtype+1 elements * @maxtype: maximum attribute type to be expected * @head: head of attribute stream * @len: length of attribute stream * @policy: validation policy + * @cb: callback function and data, must not be NULL + * @cb_priv: private data for the callback * * Parses a stream of attributes and stores a pointer to each attribute in * the tb array accessible via the attribute type. Attributes with a type * exceeding maxtype will be silently ignored for backwards compatibility * reasons. policy may be set to NULL if no validation is required. + * For every validated nla, the function calls the user-space callback. + * If the callback fails (returns with non-zero value), parsing is terminated + * and this value is returned as error. * * Returns 0 on success or a negative error code. */ -int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, - int len, const struct nla_policy *policy) +int nla_parse_cb(struct nlattr **tb, int maxtype, const struct nlattr *head, + int len, const struct nla_policy *policy, + int (*cb)(const struct nlattr *, void *), void *cb_priv) { const struct nlattr *nla; int rem, err; @@ -196,6 +202,9 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, if (err < 0) goto errout; } + err = cb(nla, cb_priv); + if (err) + goto errout; tb[type] = (struct nlattr *)nla; } @@ -209,6 +218,34 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, errout: return err; } +EXPORT_SYMBOL(nla_parse_cb); + +static int nla_pass_all_cb(const struct nlattr *nla, void *priv) +{ + return 0; +} + +/** + * nla_parse - Parse a stream of attributes into a tb buffer + * @tb: destination array with maxtype+1 elements + * @maxtype: maximum attribute type to be expected + * @head: head of attribute stream + * @len: length of attribute stream + * @policy: validation policy + * + * Parses a stream of attributes and stores a pointer to each attribute in + * the tb array accessible via the attribute type. Attributes with a type + * exceeding maxtype will be silently ignored for backwards compatibility + * reasons. policy may be set to NULL if no validation is required. + * + * Returns 0 on success or a negative error code. + */ +int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, + int len, const struct nla_policy *policy) +{ + return nla_parse_cb(tb, maxtype, head, len, policy, nla_pass_all_cb, + NULL); +} EXPORT_SYMBOL(nla_parse); /**