netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback
@ 2019-10-05 18:04 Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 01/10] net: genetlink: push doit/dumpit code from genl_family_rcv_msg Jiri Pirko
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

In generic netlink, parsing attributes for doit() callback is already
implemented. They are available in info->attrs.

For dumpit() however, each user which is interested in attributes have to
parse it manually. Even though the attributes may be (depending on flag)
already validated (by parse function).

Make usage of attributes in dumpit() more convenient and prepare
info->attrs too.

Patchset also make the existing users of genl_family_attrbuf() converted
to use info->attrs and removes the helper.

Jiri Pirko (10):
  net: genetlink: push doit/dumpit code from genl_family_rcv_msg
  net: genetlink: introduce dump info struct to be available during
    dumpit op
  net: genetlink: push attrbuf allocation and parsing to a separate
    function
  net: genetlink: parse attrs and store in contect info struct during
    dumpit
  net: ieee802154: have genetlink code to parse the attrs during dumpit
  net: nfc: have genetlink code to parse the attrs during dumpit
  net: tipc: have genetlink code to parse the attrs during dumpit
  net: tipc: allocate attrs locally instead of using genl_family_attrbuf
    in compat_dumpit()
  net: genetlink: remove unused genl_family_attrbuf()
  devlink: have genetlink code to parse the attrs during dumpit

 include/net/genetlink.h   |  20 ++-
 net/core/devlink.c        |  38 +----
 net/ieee802154/nl802154.c |  39 ++---
 net/netlink/genetlink.c   | 295 +++++++++++++++++++++++---------------
 net/nfc/netlink.c         |  17 +--
 net/tipc/netlink.c        |  21 +--
 net/tipc/netlink.h        |   1 -
 net/tipc/netlink_compat.c |  19 ++-
 net/tipc/node.c           |   6 +-
 net/tipc/socket.c         |   6 +-
 net/tipc/udp_media.c      |   6 +-
 11 files changed, 243 insertions(+), 225 deletions(-)

-- 
2.21.0


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [patch net-next 01/10] net: genetlink: push doit/dumpit code from genl_family_rcv_msg
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 02/10] net: genetlink: introduce dump info struct to be available during dumpit op Jiri Pirko
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Currently the function genl_family_rcv_msg() is quite big. Since it is
quite convenient, push code that is related to doit and dumpit ops into
separate functions.

Do small changes on the way, like rc/err unification, NULL check etc.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/netlink/genetlink.c | 173 ++++++++++++++++++++++------------------
 1 file changed, 96 insertions(+), 77 deletions(-)

diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index efccd1ac9a66..b5fa98b1577d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -498,95 +498,76 @@ static int genl_lock_done(struct netlink_callback *cb)
 	return rc;
 }
 
-static int genl_family_rcv_msg(const struct genl_family *family,
-			       struct sk_buff *skb,
-			       struct nlmsghdr *nlh,
-			       struct netlink_ext_ack *extack)
+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,
+				      int hdrlen, struct net *net)
 {
-	const struct genl_ops *ops;
-	struct net *net = sock_net(skb->sk);
-	struct genl_info info;
-	struct genlmsghdr *hdr = nlmsg_data(nlh);
-	struct nlattr **attrbuf;
-	int hdrlen, err;
-
-	/* this family doesn't exist in this netns */
-	if (!family->netnsok && !net_eq(net, &init_net))
-		return -ENOENT;
-
-	hdrlen = GENL_HDRLEN + family->hdrsize;
-	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
-		return -EINVAL;
+	int err;
 
-	ops = genl_get_cmd(hdr->cmd, family);
-	if (ops == NULL)
+	if (!ops->dumpit)
 		return -EOPNOTSUPP;
 
-	if ((ops->flags & GENL_ADMIN_PERM) &&
-	    !netlink_capable(skb, CAP_NET_ADMIN))
-		return -EPERM;
-
-	if ((ops->flags & GENL_UNS_ADMIN_PERM) &&
-	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-		return -EPERM;
-
-	if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) {
-		int rc;
-
-		if (ops->dumpit == NULL)
-			return -EOPNOTSUPP;
-
-		if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
-			int hdrlen = GENL_HDRLEN + family->hdrsize;
-
-			if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
-				return -EINVAL;
+	if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
+		if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+			return -EINVAL;
 
-			if (family->maxattr) {
-				unsigned int validate = NL_VALIDATE_STRICT;
-
-				if (ops->validate &
-				    GENL_DONT_VALIDATE_DUMP_STRICT)
-					validate = NL_VALIDATE_LIBERAL;
-				rc = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
-						    nlmsg_attrlen(nlh, hdrlen),
-						    family->maxattr,
-						    family->policy,
-						    validate, extack);
-				if (rc)
-					return rc;
-			}
+		if (family->maxattr) {
+			unsigned int validate = NL_VALIDATE_STRICT;
+
+			if (ops->validate & GENL_DONT_VALIDATE_DUMP_STRICT)
+				validate = NL_VALIDATE_LIBERAL;
+			err = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
+					     nlmsg_attrlen(nlh, hdrlen),
+					     family->maxattr, family->policy,
+					     validate, extack);
+			if (err)
+				return err;
 		}
+	}
 
-		if (!family->parallel_ops) {
-			struct netlink_dump_control c = {
-				.module = family->module,
-				/* we have const, but the netlink API doesn't */
-				.data = (void *)ops,
-				.start = genl_lock_start,
-				.dump = genl_lock_dumpit,
-				.done = genl_lock_done,
-			};
+	if (!family->parallel_ops) {
+		struct netlink_dump_control c = {
+			.module = family->module,
+			/* we have const, but the netlink API doesn't */
+			.data = (void *)ops,
+			.start = genl_lock_start,
+			.dump = genl_lock_dumpit,
+			.done = genl_lock_done,
+		};
 
-			genl_unlock();
-			rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
-			genl_lock();
+		genl_unlock();
+		err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+		genl_lock();
 
-		} else {
-			struct netlink_dump_control c = {
-				.module = family->module,
-				.start = ops->start,
-				.dump = ops->dumpit,
-				.done = ops->done,
-			};
+	} else {
+		struct netlink_dump_control c = {
+			.module = family->module,
+			.start = ops->start,
+			.dump = ops->dumpit,
+			.done = ops->done,
+		};
+
+		err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
+	}
 
-			rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
-		}
+	return err;
+}
 
-		return rc;
-	}
+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,
+				    int hdrlen, struct net *net)
+{
+	struct nlattr **attrbuf;
+	struct genl_info info;
+	int err;
 
-	if (ops->doit == NULL)
+	if (!ops->doit)
 		return -EOPNOTSUPP;
 
 	if (family->maxattr && family->parallel_ops) {
@@ -638,6 +619,44 @@ static int genl_family_rcv_msg(const struct genl_family *family,
 	return err;
 }
 
+static int genl_family_rcv_msg(const struct genl_family *family,
+			       struct sk_buff *skb,
+			       struct nlmsghdr *nlh,
+			       struct netlink_ext_ack *extack)
+{
+	const struct genl_ops *ops;
+	struct net *net = sock_net(skb->sk);
+	struct genlmsghdr *hdr = nlmsg_data(nlh);
+	int hdrlen;
+
+	/* this family doesn't exist in this netns */
+	if (!family->netnsok && !net_eq(net, &init_net))
+		return -ENOENT;
+
+	hdrlen = GENL_HDRLEN + family->hdrsize;
+	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+		return -EINVAL;
+
+	ops = genl_get_cmd(hdr->cmd, family);
+	if (ops == NULL)
+		return -EOPNOTSUPP;
+
+	if ((ops->flags & GENL_ADMIN_PERM) &&
+	    !netlink_capable(skb, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if ((ops->flags & GENL_UNS_ADMIN_PERM) &&
+	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP)
+		return genl_family_rcv_msg_dumpit(family, skb, nlh, extack,
+						  ops, hdrlen, net);
+	else
+		return genl_family_rcv_msg_doit(family, skb, nlh, extack,
+						ops, hdrlen, net);
+}
+
 static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 			struct netlink_ext_ack *extack)
 {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 02/10] net: genetlink: introduce dump info struct to be available during dumpit op
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 01/10] net: genetlink: push doit/dumpit code from genl_family_rcv_msg Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 03/10] net: genetlink: push attrbuf allocation and parsing to a separate function Jiri Pirko
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Currently the cb->data is taken by ops during non-parallel dumping.
Introduce a new structure genl_dumpit_info and store the ops there.
Distribute the info to both non-parallel and parallel dumping. Also add
a helper genl_dumpit_info() to easily get the info structure in the
dumpit callback from cb.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/genetlink.h | 14 ++++++++++++
 net/netlink/genetlink.c | 47 +++++++++++++++++++++++++++++++++--------
 2 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 9292f1c588b7..fb838f4b0089 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -127,6 +127,20 @@ enum genl_validate_flags {
 	GENL_DONT_VALIDATE_DUMP_STRICT		= BIT(2),
 };
 
+/**
+ * struct genl_info - info that is available during dumpit op call
+ * @ops: generic netlink ops - for internal genl code usage
+ */
+struct genl_dumpit_info {
+	const struct genl_ops *ops;
+};
+
+static inline const struct genl_dumpit_info *
+genl_dumpit_info(struct netlink_callback *cb)
+{
+	return cb->data;
+}
+
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index b5fa98b1577d..c785080e9401 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -458,10 +458,19 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
 }
 EXPORT_SYMBOL(genlmsg_put);
 
+static struct genl_dumpit_info *genl_dumpit_info_alloc(void)
+{
+	return kmalloc(sizeof(struct genl_dumpit_info), GFP_KERNEL);
+}
+
+static void genl_dumpit_info_free(const struct genl_dumpit_info *info)
+{
+	kfree(info);
+}
+
 static int genl_lock_start(struct netlink_callback *cb)
 {
-	/* our ops are always const - netlink API doesn't propagate that */
-	const struct genl_ops *ops = cb->data;
+	const struct genl_ops *ops = genl_dumpit_info(cb)->ops;
 	int rc = 0;
 
 	if (ops->start) {
@@ -474,8 +483,7 @@ static int genl_lock_start(struct netlink_callback *cb)
 
 static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	/* our ops are always const - netlink API doesn't propagate that */
-	const struct genl_ops *ops = cb->data;
+	const struct genl_ops *ops = genl_dumpit_info(cb)->ops;
 	int rc;
 
 	genl_lock();
@@ -486,8 +494,8 @@ static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 
 static int genl_lock_done(struct netlink_callback *cb)
 {
-	/* our ops are always const - netlink API doesn't propagate that */
-	const struct genl_ops *ops = cb->data;
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	const struct genl_ops *ops = info->ops;
 	int rc = 0;
 
 	if (ops->done) {
@@ -495,6 +503,19 @@ static int genl_lock_done(struct netlink_callback *cb)
 		rc = ops->done(cb);
 		genl_unlock();
 	}
+	genl_dumpit_info_free(info);
+	return rc;
+}
+
+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->ops;
+	int rc = 0;
+
+	if (ops->done)
+		rc = ops->done(cb);
+	genl_dumpit_info_free(info);
 	return rc;
 }
 
@@ -505,6 +526,7 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
 				      const struct genl_ops *ops,
 				      int hdrlen, struct net *net)
 {
+	struct genl_dumpit_info *info;
 	int err;
 
 	if (!ops->dumpit)
@@ -528,11 +550,17 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
 		}
 	}
 
+	/* Allocate dumpit info. It is going to be freed by done() callback. */
+	info = genl_dumpit_info_alloc();
+	if (!info)
+		return -ENOMEM;
+
+	info->ops = ops;
+
 	if (!family->parallel_ops) {
 		struct netlink_dump_control c = {
 			.module = family->module,
-			/* we have const, but the netlink API doesn't */
-			.data = (void *)ops,
+			.data = info,
 			.start = genl_lock_start,
 			.dump = genl_lock_dumpit,
 			.done = genl_lock_done,
@@ -545,9 +573,10 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
 	} else {
 		struct netlink_dump_control c = {
 			.module = family->module,
+			.data = info,
 			.start = ops->start,
 			.dump = ops->dumpit,
-			.done = ops->done,
+			.done = genl_parallel_done,
 		};
 
 		err = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 03/10] net: genetlink: push attrbuf allocation and parsing to a separate function
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 01/10] net: genetlink: push doit/dumpit code from genl_family_rcv_msg Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 02/10] net: genetlink: introduce dump info struct to be available during dumpit op Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 04/10] net: genetlink: parse attrs and store in contect info struct during dumpit Jiri Pirko
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

To be re-usable by dumpit as well, push the code that is taking care of
attrbuf allocation and parting from doit into separate function.
Introduce a helper to free the buffer too.

Check family->maxattr too before calling kfree() to be symmetrical with
the allocation check.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/netlink/genetlink.c | 67 +++++++++++++++++++++++++++--------------
 1 file changed, 45 insertions(+), 22 deletions(-)

diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index c785080e9401..a98c94594508 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -468,6 +468,45 @@ static void genl_dumpit_info_free(const struct genl_dumpit_info *info)
 	kfree(info);
 }
 
+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,
+				int hdrlen,
+				enum genl_validate_flags no_strict_flag)
+{
+	enum netlink_validation validate = ops->validate & no_strict_flag ?
+					   NL_VALIDATE_LIBERAL :
+					   NL_VALIDATE_STRICT;
+	struct nlattr **attrbuf;
+	int err;
+
+	if (family->maxattr && family->parallel_ops) {
+		attrbuf = kmalloc_array(family->maxattr + 1,
+					sizeof(struct nlattr *), GFP_KERNEL);
+		if (!attrbuf)
+			return ERR_PTR(-ENOMEM);
+	} else {
+		attrbuf = family->attrbuf;
+	}
+
+	err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
+			    family->policy, validate, extack);
+	if (err && family->maxattr && family->parallel_ops) {
+		kfree(attrbuf);
+		return ERR_PTR(err);
+	}
+	return attrbuf;
+}
+
+static void genl_family_rcv_msg_attrs_free(const struct genl_family *family,
+					   struct nlattr **attrbuf)
+{
+	if (family->maxattr && family->parallel_ops)
+		kfree(attrbuf);
+}
+
 static int genl_lock_start(struct netlink_callback *cb)
 {
 	const struct genl_ops *ops = genl_dumpit_info(cb)->ops;
@@ -599,26 +638,11 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
 	if (!ops->doit)
 		return -EOPNOTSUPP;
 
-	if (family->maxattr && family->parallel_ops) {
-		attrbuf = kmalloc_array(family->maxattr + 1,
-					sizeof(struct nlattr *),
-					GFP_KERNEL);
-		if (attrbuf == NULL)
-			return -ENOMEM;
-	} else
-		attrbuf = family->attrbuf;
-
-	if (attrbuf) {
-		enum netlink_validation validate = NL_VALIDATE_STRICT;
-
-		if (ops->validate & GENL_DONT_VALIDATE_STRICT)
-			validate = NL_VALIDATE_LIBERAL;
-
-		err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
-				    family->policy, validate, extack);
-		if (err < 0)
-			goto out;
-	}
+	attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
+						  ops, hdrlen,
+						  GENL_DONT_VALIDATE_STRICT);
+	if (IS_ERR(attrbuf))
+		return PTR_ERR(attrbuf);
 
 	info.snd_seq = nlh->nlmsg_seq;
 	info.snd_portid = NETLINK_CB(skb).portid;
@@ -642,8 +666,7 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
 		family->post_doit(ops, skb, &info);
 
 out:
-	if (family->parallel_ops)
-		kfree(attrbuf);
+	genl_family_rcv_msg_attrs_free(family, attrbuf);
 
 	return err;
 }
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 04/10] net: genetlink: parse attrs and store in contect info struct during dumpit
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (2 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 03/10] net: genetlink: push attrbuf allocation and parsing to a separate function Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 05/10] net: ieee802154: have genetlink code to parse the attrs " Jiri Pirko
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Extend the dumpit info struct for attrs. Instead of existing attribute
validation do parse them and save in the info struct. Caller can benefit
from this and does not have to do parse itself. In order to properly
free attrs, genl_family pointer needs to be added to dumpit info struct
as well.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/genetlink.h |  4 ++++
 net/netlink/genetlink.c | 39 ++++++++++++++++++++++-----------------
 2 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index fb838f4b0089..922dcc9348b1 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -129,10 +129,14 @@ enum genl_validate_flags {
 
 /**
  * struct genl_info - info that is available during dumpit op call
+ * @family: generic netlink family - for internal genl code usage
  * @ops: generic netlink ops - for internal genl code usage
+ * @attrs: netlink attributes
  */
 struct genl_dumpit_info {
+	const struct genl_family *family;
 	const struct genl_ops *ops;
+	struct nlattr **attrs;
 };
 
 static inline const struct genl_dumpit_info *
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index a98c94594508..8059118ee5a1 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -542,6 +542,7 @@ static int genl_lock_done(struct netlink_callback *cb)
 		rc = ops->done(cb);
 		genl_unlock();
 	}
+	genl_family_rcv_msg_attrs_free(info->family, info->attrs);
 	genl_dumpit_info_free(info);
 	return rc;
 }
@@ -554,6 +555,7 @@ static int genl_parallel_done(struct netlink_callback *cb)
 
 	if (ops->done)
 		rc = ops->done(cb);
+	genl_family_rcv_msg_attrs_free(info->family, info->attrs);
 	genl_dumpit_info_free(info);
 	return rc;
 }
@@ -566,35 +568,38 @@ static int genl_family_rcv_msg_dumpit(const struct genl_family *family,
 				      int hdrlen, struct net *net)
 {
 	struct genl_dumpit_info *info;
+	struct nlattr **attrs = NULL;
 	int err;
 
 	if (!ops->dumpit)
 		return -EOPNOTSUPP;
 
-	if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
-		if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
-			return -EINVAL;
+	if (ops->validate & GENL_DONT_VALIDATE_DUMP)
+		goto no_attrs;
 
-		if (family->maxattr) {
-			unsigned int validate = NL_VALIDATE_STRICT;
-
-			if (ops->validate & GENL_DONT_VALIDATE_DUMP_STRICT)
-				validate = NL_VALIDATE_LIBERAL;
-			err = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
-					     nlmsg_attrlen(nlh, hdrlen),
-					     family->maxattr, family->policy,
-					     validate, extack);
-			if (err)
-				return err;
-		}
-	}
+	if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+		return -EINVAL;
+
+	if (!family->maxattr)
+		goto no_attrs;
 
+	attrs = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
+						ops, hdrlen,
+						GENL_DONT_VALIDATE_DUMP_STRICT);
+	if (IS_ERR(attrs))
+		return PTR_ERR(attrs);
+
+no_attrs:
 	/* Allocate dumpit info. It is going to be freed by done() callback. */
 	info = genl_dumpit_info_alloc();
-	if (!info)
+	if (!info) {
+		genl_family_rcv_msg_attrs_free(family, attrs);
 		return -ENOMEM;
+	}
 
+	info->family = family;
 	info->ops = ops;
+	info->attrs = attrs;
 
 	if (!family->parallel_ops) {
 		struct netlink_dump_control c = {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 05/10] net: ieee802154: have genetlink code to parse the attrs during dumpit
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (3 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 04/10] net: genetlink: parse attrs and store in contect info struct during dumpit Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 06/10] net: nfc: " Jiri Pirko
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Benefit from the fact that the generic netlink code can parse the attrs
for dumpit op and avoid need to parse it in the op callback.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/ieee802154/nl802154.c | 39 ++++++++++++++-------------------------
 1 file changed, 14 insertions(+), 25 deletions(-)

diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index ffcfcef76291..7c5a1aa5adb4 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -236,21 +236,14 @@ nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
 			       struct cfg802154_registered_device **rdev,
 			       struct wpan_dev **wpan_dev)
 {
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
 	int err;
 
 	rtnl_lock();
 
 	if (!cb->args[0]) {
-		err = nlmsg_parse_deprecated(cb->nlh,
-					     GENL_HDRLEN + nl802154_fam.hdrsize,
-					     genl_family_attrbuf(&nl802154_fam),
-					     nl802154_fam.maxattr,
-					     nl802154_policy, NULL);
-		if (err)
-			goto out_unlock;
-
 		*wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
-							    genl_family_attrbuf(&nl802154_fam));
+							    info->attrs);
 		if (IS_ERR(*wpan_dev)) {
 			err = PTR_ERR(*wpan_dev);
 			goto out_unlock;
@@ -557,17 +550,8 @@ static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
 					struct netlink_callback *cb,
 					struct nl802154_dump_wpan_phy_state *state)
 {
-	struct nlattr **tb = genl_family_attrbuf(&nl802154_fam);
-	int ret = nlmsg_parse_deprecated(cb->nlh,
-					 GENL_HDRLEN + nl802154_fam.hdrsize,
-					 tb, nl802154_fam.maxattr,
-					 nl802154_policy, NULL);
-
-	/* TODO check if we can handle error here,
-	 * we have no backward compatibility
-	 */
-	if (ret)
-		return 0;
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+	struct nlattr **tb = info->attrs;
 
 	if (tb[NL802154_ATTR_WPAN_PHY])
 		state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
@@ -2203,7 +2187,8 @@ static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
 static const struct genl_ops nl802154_ops[] = {
 	{
 		.cmd = NL802154_CMD_GET_WPAN_PHY,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.doit = nl802154_get_wpan_phy,
 		.dumpit = nl802154_dump_wpan_phy,
 		.done = nl802154_dump_wpan_phy_done,
@@ -2343,7 +2328,8 @@ static const struct genl_ops nl802154_ops[] = {
 	},
 	{
 		.cmd = NL802154_CMD_GET_SEC_KEY,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		/* TODO .doit by matching key id? */
 		.dumpit = nl802154_dump_llsec_key,
 		.flags = GENL_ADMIN_PERM,
@@ -2369,7 +2355,8 @@ static const struct genl_ops nl802154_ops[] = {
 	/* TODO unique identifier must short+pan OR extended_addr */
 	{
 		.cmd = NL802154_CMD_GET_SEC_DEV,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		/* TODO .doit by matching extended_addr? */
 		.dumpit = nl802154_dump_llsec_dev,
 		.flags = GENL_ADMIN_PERM,
@@ -2395,7 +2382,8 @@ static const struct genl_ops nl802154_ops[] = {
 	/* TODO remove complete devkey, put it as nested? */
 	{
 		.cmd = NL802154_CMD_GET_SEC_DEVKEY,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		/* TODO doit by matching ??? */
 		.dumpit = nl802154_dump_llsec_devkey,
 		.flags = GENL_ADMIN_PERM,
@@ -2420,7 +2408,8 @@ static const struct genl_ops nl802154_ops[] = {
 	},
 	{
 		.cmd = NL802154_CMD_GET_SEC_LEVEL,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		/* TODO .doit by matching frame_type? */
 		.dumpit = nl802154_dump_llsec_seclevel,
 		.flags = GENL_ADMIN_PERM,
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 06/10] net: nfc: have genetlink code to parse the attrs during dumpit
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (4 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 05/10] net: ieee802154: have genetlink code to parse the attrs " Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 07/10] net: tipc: " Jiri Pirko
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Benefit from the fact that the generic netlink code can parse the attrs
for dumpit op and avoid need to parse it in the op callback.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/nfc/netlink.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 17e6ca62f1be..fd9ad534dd9b 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -102,22 +102,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
 
 static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
 {
-	struct nlattr **attrbuf = genl_family_attrbuf(&nfc_genl_family);
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
 	struct nfc_dev *dev;
-	int rc;
 	u32 idx;
 
-	rc = nlmsg_parse_deprecated(cb->nlh,
-				    GENL_HDRLEN + nfc_genl_family.hdrsize,
-				    attrbuf, nfc_genl_family.maxattr,
-				    nfc_genl_policy, NULL);
-	if (rc < 0)
-		return ERR_PTR(rc);
-
-	if (!attrbuf[NFC_ATTR_DEVICE_INDEX])
+	if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
 		return ERR_PTR(-EINVAL);
 
-	idx = nla_get_u32(attrbuf[NFC_ATTR_DEVICE_INDEX]);
+	idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
 
 	dev = nfc_get_device(idx);
 	if (!dev)
@@ -1697,7 +1689,8 @@ static const struct genl_ops nfc_genl_ops[] = {
 	},
 	{
 		.cmd = NFC_CMD_GET_TARGET,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit = nfc_genl_dump_targets,
 		.done = nfc_genl_dump_targets_done,
 	},
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 07/10] net: tipc: have genetlink code to parse the attrs during dumpit
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (5 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 06/10] net: nfc: " Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2021-04-15 21:24   ` Xin Long
  2019-10-05 18:04 ` [patch net-next 08/10] net: tipc: allocate attrs locally instead of using genl_family_attrbuf in compat_dumpit() Jiri Pirko
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Benefit from the fact that the generic netlink code can parse the attrs
for dumpit op and avoid need to parse it in the op callback.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/tipc/netlink.c   | 9 ++++++---
 net/tipc/node.c      | 6 +-----
 net/tipc/socket.c    | 6 +-----
 net/tipc/udp_media.c | 6 +-----
 4 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index d6165ad384c0..5f5df232d72b 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -176,7 +176,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
 	},
 	{
 		.cmd	= TIPC_NL_PUBL_GET,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit	= tipc_nl_publ_dump,
 	},
 	{
@@ -239,7 +240,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
 	},
 	{
 		.cmd	= TIPC_NL_MON_PEER_GET,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit	= tipc_nl_node_dump_monitor_peer,
 	},
 	{
@@ -250,7 +252,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
 #ifdef CONFIG_TIPC_MEDIA_UDP
 	{
 		.cmd	= TIPC_NL_UDP_GET_REMOTEIP,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit	= tipc_udp_nl_dump_remoteip,
 	},
 #endif
diff --git a/net/tipc/node.c b/net/tipc/node.c
index c8f6177dd5a2..f2e3cf70c922 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -2484,13 +2484,9 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
 	int err;
 
 	if (!prev_node) {
-		struct nlattr **attrs;
+		struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
 		struct nlattr *mon[TIPC_NLA_MON_MAX + 1];
 
-		err = tipc_nlmsg_parse(cb->nlh, &attrs);
-		if (err)
-			return err;
-
 		if (!attrs[TIPC_NLA_MON])
 			return -EINVAL;
 
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 3b9f8cc328f5..d579b64705b1 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -3588,13 +3588,9 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
 	struct tipc_sock *tsk;
 
 	if (!tsk_portid) {
-		struct nlattr **attrs;
+		struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
 		struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];
 
-		err = tipc_nlmsg_parse(cb->nlh, &attrs);
-		if (err)
-			return err;
-
 		if (!attrs[TIPC_NLA_SOCK])
 			return -EINVAL;
 
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 287df68721df..43ca5fd6574d 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -448,15 +448,11 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
 	int i;
 
 	if (!bid && !skip_cnt) {
+		struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
 		struct net *net = sock_net(skb->sk);
 		struct nlattr *battrs[TIPC_NLA_BEARER_MAX + 1];
-		struct nlattr **attrs;
 		char *bname;
 
-		err = tipc_nlmsg_parse(cb->nlh, &attrs);
-		if (err)
-			return err;
-
 		if (!attrs[TIPC_NLA_BEARER])
 			return -EINVAL;
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 08/10] net: tipc: allocate attrs locally instead of using genl_family_attrbuf in compat_dumpit()
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (6 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 07/10] net: tipc: " Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 09/10] net: genetlink: remove unused genl_family_attrbuf() Jiri Pirko
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

As this is the last user of genl_family_attrbuf, convert to allocate
attrs locally and do it in a similar way this is done in compat_doit().

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/tipc/netlink.c        | 12 ------------
 net/tipc/netlink.h        |  1 -
 net/tipc/netlink_compat.c | 19 +++++++++++++++----
 3 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 5f5df232d72b..d32bbd0f5e46 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -271,18 +271,6 @@ struct genl_family tipc_genl_family __ro_after_init = {
 	.n_ops		= ARRAY_SIZE(tipc_genl_v2_ops),
 };
 
-int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***attr)
-{
-	u32 maxattr = tipc_genl_family.maxattr;
-
-	*attr = genl_family_attrbuf(&tipc_genl_family);
-	if (!*attr)
-		return -EOPNOTSUPP;
-
-	return nlmsg_parse_deprecated(nlh, GENL_HDRLEN, *attr, maxattr,
-				      tipc_nl_policy, NULL);
-}
-
 int __init tipc_netlink_start(void)
 {
 	int res;
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h
index 4ba0ad422110..7cf777723e3e 100644
--- a/net/tipc/netlink.h
+++ b/net/tipc/netlink.h
@@ -38,7 +38,6 @@
 #include <net/netlink.h>
 
 extern struct genl_family tipc_genl_family;
-int tipc_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr ***buf);
 
 struct tipc_nl_msg {
 	struct sk_buff *skb;
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index e135d4e11231..4950b754dacd 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -186,6 +186,7 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
 	struct sk_buff *buf;
 	struct nlmsghdr *nlmsg;
 	struct netlink_callback cb;
+	struct nlattr **attrbuf;
 
 	memset(&cb, 0, sizeof(cb));
 	cb.nlh = (struct nlmsghdr *)arg->data;
@@ -201,19 +202,28 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
 		return -ENOMEM;
 	}
 
+	attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1,
+				sizeof(struct nlattr *), GFP_KERNEL);
+	if (!attrbuf) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
 	do {
 		int rem;
 
 		len = (*cmd->dumpit)(buf, &cb);
 
 		nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) {
-			struct nlattr **attrs;
-
-			err = tipc_nlmsg_parse(nlmsg, &attrs);
+			err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN,
+						     attrbuf,
+						     tipc_genl_family.maxattr,
+						     tipc_genl_family.policy,
+						     NULL);
 			if (err)
 				goto err_out;
 
-			err = (*cmd->format)(msg, attrs);
+			err = (*cmd->format)(msg, attrbuf);
 			if (err)
 				goto err_out;
 
@@ -231,6 +241,7 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
 	err = 0;
 
 err_out:
+	kfree(attrbuf);
 	tipc_dump_done(&cb);
 	kfree_skb(buf);
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 09/10] net: genetlink: remove unused genl_family_attrbuf()
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (7 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 08/10] net: tipc: allocate attrs locally instead of using genl_family_attrbuf in compat_dumpit() Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-05 18:04 ` [patch net-next 10/10] devlink: have genetlink code to parse the attrs during dumpit Jiri Pirko
  2019-10-06 13:45 ` [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback David Miller
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

genl_family_attrbuf() function is no longer used by anyone, so remove it.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/genetlink.h |  2 --
 net/netlink/genetlink.c | 19 -------------------
 2 files changed, 21 deletions(-)

diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 922dcc9348b1..74950663bb00 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -75,8 +75,6 @@ struct genl_family {
 	struct module		*module;
 };
 
-struct nlattr **genl_family_attrbuf(const struct genl_family *family);
-
 /**
  * struct genl_info - receiving information
  * @snd_seq: sending sequence number
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 8059118ee5a1..1b5046436765 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -1164,25 +1164,6 @@ static int __init genl_init(void)
 
 subsys_initcall(genl_init);
 
-/**
- * genl_family_attrbuf - return family's attrbuf
- * @family: the family
- *
- * Return the family's attrbuf, while validating that it's
- * actually valid to access it.
- *
- * You cannot use this function with a family that has parallel_ops
- * and you can only use it within (pre/post) doit/dumpit callbacks.
- */
-struct nlattr **genl_family_attrbuf(const struct genl_family *family)
-{
-	if (!WARN_ON(family->parallel_ops))
-		lockdep_assert_held(&genl_mutex);
-
-	return family->attrbuf;
-}
-EXPORT_SYMBOL(genl_family_attrbuf);
-
 static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
 			 gfp_t flags)
 {
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [patch net-next 10/10] devlink: have genetlink code to parse the attrs during dumpit
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (8 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 09/10] net: genetlink: remove unused genl_family_attrbuf() Jiri Pirko
@ 2019-10-05 18:04 ` Jiri Pirko
  2019-10-06 13:45 ` [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback David Miller
  10 siblings, 0 replies; 13+ messages in thread
From: Jiri Pirko @ 2019-10-05 18:04 UTC (permalink / raw)
  To: netdev
  Cc: davem, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Benefit from the fact that the generic netlink code can parse the attrs
for dumpit op and avoid need to parse it in the op callback.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/core/devlink.c | 38 ++++++--------------------------------
 1 file changed, 6 insertions(+), 32 deletions(-)

diff --git a/net/core/devlink.c b/net/core/devlink.c
index 6d16908f34b0..ae07ddb65f34 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -3935,29 +3935,19 @@ static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
 					     struct netlink_callback *cb)
 {
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
 	u64 ret_offset, start_offset, end_offset = 0;
+	struct nlattr **attrs = info->attrs;
 	struct devlink_region *region;
 	struct nlattr *chunks_attr;
 	const char *region_name;
 	struct devlink *devlink;
-	struct nlattr **attrs;
 	bool dump = true;
 	void *hdr;
 	int err;
 
 	start_offset = *((u64 *)&cb->args[0]);
 
-	attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
-	if (!attrs)
-		return -ENOMEM;
-
-	err = nlmsg_parse_deprecated(cb->nlh,
-				     GENL_HDRLEN + devlink_nl_family.hdrsize,
-				     attrs, DEVLINK_ATTR_MAX,
-				     devlink_nl_family.policy, cb->extack);
-	if (err)
-		goto out_free;
-
 	mutex_lock(&devlink_mutex);
 	devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
 	if (IS_ERR(devlink)) {
@@ -4034,7 +4024,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
 	genlmsg_end(skb, hdr);
 	mutex_unlock(&devlink->lock);
 	mutex_unlock(&devlink_mutex);
-	kfree(attrs);
 
 	return skb->len;
 
@@ -4044,8 +4033,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
 	mutex_unlock(&devlink->lock);
 out_dev:
 	mutex_unlock(&devlink_mutex);
-out_free:
-	kfree(attrs);
 	return err;
 }
 
@@ -4987,21 +4974,10 @@ devlink_health_reporter_get_from_info(struct devlink *devlink,
 static struct devlink_health_reporter *
 devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
 {
+	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
 	struct devlink_health_reporter *reporter;
+	struct nlattr **attrs = info->attrs;
 	struct devlink *devlink;
-	struct nlattr **attrs;
-	int err;
-
-	attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
-	if (!attrs)
-		return NULL;
-
-	err = nlmsg_parse_deprecated(cb->nlh,
-				     GENL_HDRLEN + devlink_nl_family.hdrsize,
-				     attrs, DEVLINK_ATTR_MAX,
-				     devlink_nl_family.policy, cb->extack);
-	if (err)
-		goto free;
 
 	mutex_lock(&devlink_mutex);
 	devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
@@ -5010,12 +4986,9 @@ devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
 
 	reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
 	mutex_unlock(&devlink_mutex);
-	kfree(attrs);
 	return reporter;
 unlock:
 	mutex_unlock(&devlink_mutex);
-free:
-	kfree(attrs);
 	return NULL;
 }
 
@@ -6146,7 +6119,8 @@ static const struct genl_ops devlink_nl_ops[] = {
 	},
 	{
 		.cmd = DEVLINK_CMD_REGION_READ,
-		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.validate = GENL_DONT_VALIDATE_STRICT |
+			    GENL_DONT_VALIDATE_DUMP_STRICT,
 		.dumpit = devlink_nl_cmd_region_read_dumpit,
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback
  2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
                   ` (9 preceding siblings ...)
  2019-10-05 18:04 ` [patch net-next 10/10] devlink: have genetlink code to parse the attrs during dumpit Jiri Pirko
@ 2019-10-06 13:45 ` David Miller
  10 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2019-10-06 13:45 UTC (permalink / raw)
  To: jiri
  Cc: netdev, jakub.kicinski, alex.aring, stefan, jon.maloy, ying.xue,
	johannes.berg, mkubecek, yuehaibing, mlxsw

From: Jiri Pirko <jiri@resnulli.us>
Date: Sat,  5 Oct 2019 20:04:32 +0200

> From: Jiri Pirko <jiri@mellanox.com>
> 
> In generic netlink, parsing attributes for doit() callback is already
> implemented. They are available in info->attrs.
> 
> For dumpit() however, each user which is interested in attributes have to
> parse it manually. Even though the attributes may be (depending on flag)
> already validated (by parse function).
> 
> Make usage of attributes in dumpit() more convenient and prepare
> info->attrs too.
> 
> Patchset also make the existing users of genl_family_attrbuf() converted
> to use info->attrs and removes the helper.

I really like this transformation, series applied, thanks Jiri.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [patch net-next 07/10] net: tipc: have genetlink code to parse the attrs during dumpit
  2019-10-05 18:04 ` [patch net-next 07/10] net: tipc: " Jiri Pirko
@ 2021-04-15 21:24   ` Xin Long
  0 siblings, 0 replies; 13+ messages in thread
From: Xin Long @ 2021-04-15 21:24 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: network dev, davem, Jakub Kicinski, alex.aring, stefan,
	Jon Maloy, Ying Xue, johannes.berg, Michal Kubecek, Yuehaibing,
	mlxsw

On Sat, Oct 5, 2019 at 2:09 PM Jiri Pirko <jiri@resnulli.us> wrote:
>
> From: Jiri Pirko <jiri@mellanox.com>
>
> Benefit from the fact that the generic netlink code can parse the attrs
> for dumpit op and avoid need to parse it in the op callback.
>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  net/tipc/netlink.c   | 9 ++++++---
>  net/tipc/node.c      | 6 +-----
>  net/tipc/socket.c    | 6 +-----
>  net/tipc/udp_media.c | 6 +-----
>  4 files changed, 9 insertions(+), 18 deletions(-)
>
> diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
> index d6165ad384c0..5f5df232d72b 100644
> --- a/net/tipc/netlink.c
> +++ b/net/tipc/netlink.c
> @@ -176,7 +176,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
>         },
>         {
>                 .cmd    = TIPC_NL_PUBL_GET,
> -               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
> +               .validate = GENL_DONT_VALIDATE_STRICT |
> +                           GENL_DONT_VALIDATE_DUMP_STRICT,
>                 .dumpit = tipc_nl_publ_dump,
>         },
>         {
> @@ -239,7 +240,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
>         },
>         {
>                 .cmd    = TIPC_NL_MON_PEER_GET,
> -               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
> +               .validate = GENL_DONT_VALIDATE_STRICT |
> +                           GENL_DONT_VALIDATE_DUMP_STRICT,
>                 .dumpit = tipc_nl_node_dump_monitor_peer,
>         },
>         {
> @@ -250,7 +252,8 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
>  #ifdef CONFIG_TIPC_MEDIA_UDP
>         {
>                 .cmd    = TIPC_NL_UDP_GET_REMOTEIP,
> -               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
> +               .validate = GENL_DONT_VALIDATE_STRICT |
> +                           GENL_DONT_VALIDATE_DUMP_STRICT,
>                 .dumpit = tipc_udp_nl_dump_remoteip,
>         },
Hi Jiri,

can I ask you why GENL_DONT_VALIDATE_DUMP_STRICT flag is needed when
using genl_dumpit_info(cb)->attrs in dumpit?

Thanks.

>  #endif
> diff --git a/net/tipc/node.c b/net/tipc/node.c
> index c8f6177dd5a2..f2e3cf70c922 100644
> --- a/net/tipc/node.c
> +++ b/net/tipc/node.c
> @@ -2484,13 +2484,9 @@ int tipc_nl_node_dump_monitor_peer(struct sk_buff *skb,
>         int err;
>
>         if (!prev_node) {
> -               struct nlattr **attrs;
> +               struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
>                 struct nlattr *mon[TIPC_NLA_MON_MAX + 1];
>
> -               err = tipc_nlmsg_parse(cb->nlh, &attrs);
> -               if (err)
> -                       return err;
> -
>                 if (!attrs[TIPC_NLA_MON])
>                         return -EINVAL;
>
> diff --git a/net/tipc/socket.c b/net/tipc/socket.c
> index 3b9f8cc328f5..d579b64705b1 100644
> --- a/net/tipc/socket.c
> +++ b/net/tipc/socket.c
> @@ -3588,13 +3588,9 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
>         struct tipc_sock *tsk;
>
>         if (!tsk_portid) {
> -               struct nlattr **attrs;
> +               struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
>                 struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];
>
> -               err = tipc_nlmsg_parse(cb->nlh, &attrs);
> -               if (err)
> -                       return err;
> -
>                 if (!attrs[TIPC_NLA_SOCK])
>                         return -EINVAL;
>
> diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
> index 287df68721df..43ca5fd6574d 100644
> --- a/net/tipc/udp_media.c
> +++ b/net/tipc/udp_media.c
> @@ -448,15 +448,11 @@ int tipc_udp_nl_dump_remoteip(struct sk_buff *skb, struct netlink_callback *cb)
>         int i;
>
>         if (!bid && !skip_cnt) {
> +               struct nlattr **attrs = genl_dumpit_info(cb)->attrs;
>                 struct net *net = sock_net(skb->sk);
>                 struct nlattr *battrs[TIPC_NLA_BEARER_MAX + 1];
> -               struct nlattr **attrs;
>                 char *bname;
>
> -               err = tipc_nlmsg_parse(cb->nlh, &attrs);
> -               if (err)
> -                       return err;
> -
>                 if (!attrs[TIPC_NLA_BEARER])
>                         return -EINVAL;
>
> --
> 2.21.0
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2021-04-15 21:24 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-05 18:04 [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback Jiri Pirko
2019-10-05 18:04 ` [patch net-next 01/10] net: genetlink: push doit/dumpit code from genl_family_rcv_msg Jiri Pirko
2019-10-05 18:04 ` [patch net-next 02/10] net: genetlink: introduce dump info struct to be available during dumpit op Jiri Pirko
2019-10-05 18:04 ` [patch net-next 03/10] net: genetlink: push attrbuf allocation and parsing to a separate function Jiri Pirko
2019-10-05 18:04 ` [patch net-next 04/10] net: genetlink: parse attrs and store in contect info struct during dumpit Jiri Pirko
2019-10-05 18:04 ` [patch net-next 05/10] net: ieee802154: have genetlink code to parse the attrs " Jiri Pirko
2019-10-05 18:04 ` [patch net-next 06/10] net: nfc: " Jiri Pirko
2019-10-05 18:04 ` [patch net-next 07/10] net: tipc: " Jiri Pirko
2021-04-15 21:24   ` Xin Long
2019-10-05 18:04 ` [patch net-next 08/10] net: tipc: allocate attrs locally instead of using genl_family_attrbuf in compat_dumpit() Jiri Pirko
2019-10-05 18:04 ` [patch net-next 09/10] net: genetlink: remove unused genl_family_attrbuf() Jiri Pirko
2019-10-05 18:04 ` [patch net-next 10/10] devlink: have genetlink code to parse the attrs during dumpit Jiri Pirko
2019-10-06 13:45 ` [patch net-next 00/10] net: genetlink: parse attrs for dumpit() callback David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).