[PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

Subsystems: networking [general], the rest

STALE2532d

6 messages, 2 authors, 2019-10-10 · open the first message on its own page

[PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Michal Kubecek <hidden>
Date: 2019-10-09 16:44:36

Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().

Fixes: c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing to a separate function")
Signed-off-by: Michal Kubecek <redacted>
---
 net/netlink/genetlink.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index ecc2bd3e73e4..c4bf8830eedf 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -639,21 +639,23 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
 				    const struct genl_ops *ops,
 				    int hdrlen, struct net *net)
 {
-	struct nlattr **attrbuf;
+	struct nlattr **attrbuf = NULL;
 	struct genl_info info;
 	int err;
 
 	if (!ops->doit)
 		return -EOPNOTSUPP;
 
+	if (!family->maxattr)
+		goto no_attrs;
 	attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
 						  ops, hdrlen,
 						  GENL_DONT_VALIDATE_STRICT,
-						  family->maxattr &&
 						  family->parallel_ops);
 	if (IS_ERR(attrbuf))
 		return PTR_ERR(attrbuf);
 
+no_attrs:
 	info.snd_seq = nlh->nlmsg_seq;
 	info.snd_portid = NETLINK_CB(skb).portid;
 	info.nlhdr = nlh;
-- 
2.23.0

Re: [PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Jiri Pirko <jiri@resnulli.us>
Date: 2019-10-10 08:40:06

Wed, Oct 09, 2019 at 06:44:32PM CEST, mkubecek@suse.cz wrote:
Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().
This is the original code before the changes:

        if (ops->doit == NULL)
                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;
        }

Looks like the __nlmsg_parse() is called no matter if maxattr if 0 or
not. It is only considered for allocation of attrbuf. This is in-sync
with the current code.

For dumpit, the check was there:

                        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;
                        }


quoted hunk
Fixes: c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing to a separate function")
Signed-off-by: Michal Kubecek <redacted>
---
net/netlink/genetlink.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index ecc2bd3e73e4..c4bf8830eedf 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -639,21 +639,23 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
				    const struct genl_ops *ops,
				    int hdrlen, struct net *net)
{
-	struct nlattr **attrbuf;
+	struct nlattr **attrbuf = NULL;
	struct genl_info info;
	int err;

	if (!ops->doit)
		return -EOPNOTSUPP;

+	if (!family->maxattr)
+		goto no_attrs;
	attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
						  ops, hdrlen,
						  GENL_DONT_VALIDATE_STRICT,
-						  family->maxattr &&
						  family->parallel_ops);
	if (IS_ERR(attrbuf))
		return PTR_ERR(attrbuf);

+no_attrs:
	info.snd_seq = nlh->nlmsg_seq;
	info.snd_portid = NETLINK_CB(skb).portid;
	info.nlhdr = nlh;
-- 
2.23.0

Re: [PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Michal Kubecek <hidden>
Date: 2019-10-10 09:13:52

On Thu, Oct 10, 2019 at 10:39:58AM +0200, Jiri Pirko wrote:
Wed, Oct 09, 2019 at 06:44:32PM CEST, mkubecek@suse.cz wrote:
quoted
Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().
This is the original code before the changes:

        if (ops->doit == NULL)
                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;
        }

Looks like the __nlmsg_parse() is called no matter if maxattr if 0 or
not. It is only considered for allocation of attrbuf. This is in-sync
with the current code.
If family->maxattr is 0, genl_register_family() sets family->attrbuf to
NULL so that attrbuf is also NULL and the whole "if (attrbuf) { ... }"
block is not executed.

Michal

Re: [PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Jiri Pirko <jiri@resnulli.us>
Date: 2019-10-10 09:30:22

Thu, Oct 10, 2019 at 11:13:47AM CEST, mkubecek@suse.cz wrote:
On Thu, Oct 10, 2019 at 10:39:58AM +0200, Jiri Pirko wrote:
quoted
Wed, Oct 09, 2019 at 06:44:32PM CEST, mkubecek@suse.cz wrote:
quoted
Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().
This is the original code before the changes:

        if (ops->doit == NULL)
                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;
        }

Looks like the __nlmsg_parse() is called no matter if maxattr if 0 or
not. It is only considered for allocation of attrbuf. This is in-sync
with the current code.
If family->maxattr is 0, genl_register_family() sets family->attrbuf to
NULL so that attrbuf is also NULL and the whole "if (attrbuf) { ... }"
block is not executed.
Ah, I missed that. Thanks!
Michal

Re: [PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Jiri Pirko <jiri@resnulli.us>
Date: 2019-10-10 09:32:00

Wed, Oct 09, 2019 at 06:44:32PM CEST, mkubecek@suse.cz wrote:
quoted hunk
Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().

Fixes: c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing to a separate function")
Signed-off-by: Michal Kubecek <redacted>
---
net/netlink/genetlink.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index ecc2bd3e73e4..c4bf8830eedf 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -639,21 +639,23 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
				    const struct genl_ops *ops,
				    int hdrlen, struct net *net)
{
-	struct nlattr **attrbuf;
+	struct nlattr **attrbuf = NULL;
	struct genl_info info;
	int err;

	if (!ops->doit)
		return -EOPNOTSUPP;

+	if (!family->maxattr)
+		goto no_attrs;
	attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
						  ops, hdrlen,
						  GENL_DONT_VALIDATE_STRICT,
-						  family->maxattr &&
						  family->parallel_ops);
Please also adjust genl_family_rcv_msg_attrs_free() call arg
below in this function in the similar way.


	if (IS_ERR(attrbuf))
		return PTR_ERR(attrbuf);

+no_attrs:
	info.snd_seq = nlh->nlmsg_seq;
	info.snd_portid = NETLINK_CB(skb).portid;
	info.nlhdr = nlh;
-- 
2.23.0

Re: [PATCH net-next] genetlink: do not parse attributes for families with zero maxattr

From: Michal Kubecek <hidden>
Date: 2019-10-10 10:45:48

On Thu, Oct 10, 2019 at 11:31:53AM +0200, Jiri Pirko wrote:
Wed, Oct 09, 2019 at 06:44:32PM CEST, mkubecek@suse.cz wrote:
quoted
Commit c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing
to a separate function") moved attribute buffer allocation and attribute
parsing from genl_family_rcv_msg_doit() into a separate function
genl_family_rcv_msg_attrs_parse() which, unlike the previous code, calls
__nlmsg_parse() even if family->maxattr is 0 (i.e. the family does its own
parsing). The parser error is ignored and does not propagate out of
genl_family_rcv_msg_attrs_parse() but an error message ("Unknown attribute
type") is set in extack and if further processing generates no error or
warning, it stays there and is interpreted as a warning by userspace.

Dumpit requests are not affected as genl_family_rcv_msg_dumpit() bypasses
the call of genl_family_rcv_msg_doit() if family->maxattr is zero. Do the
same also in genl_family_rcv_msg_doit().

Fixes: c10e6cf85e7d ("net: genetlink: push attrbuf allocation and parsing to a separate function")
Signed-off-by: Michal Kubecek <redacted>
---
net/netlink/genetlink.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index ecc2bd3e73e4..c4bf8830eedf 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -639,21 +639,23 @@ static int genl_family_rcv_msg_doit(const struct genl_family *family,
				    const struct genl_ops *ops,
				    int hdrlen, struct net *net)
{
-	struct nlattr **attrbuf;
+	struct nlattr **attrbuf = NULL;
	struct genl_info info;
	int err;

	if (!ops->doit)
		return -EOPNOTSUPP;

+	if (!family->maxattr)
+		goto no_attrs;
	attrbuf = genl_family_rcv_msg_attrs_parse(family, nlh, extack,
						  ops, hdrlen,
						  GENL_DONT_VALIDATE_STRICT,
-						  family->maxattr &&
						  family->parallel_ops);
Please also adjust genl_family_rcv_msg_attrs_free() call arg
below in this function in the similar way.
Sent v2.

Michal
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help