netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ido Schimmel <idosch@nvidia.com>
To: David Ahern <dsahern@kernel.org>
Cc: netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org,
	pabeni@redhat.com, edumazet@google.com, petrm@nvidia.com
Subject: Re: [PATCH net-next 1/2] nexthop: Fix out-of-bounds access during attribute validation
Date: Sun, 10 Mar 2024 23:41:53 +0200	[thread overview]
Message-ID: <Ze4pIe_E4BgkCP6w@shredder> (raw)
In-Reply-To: <a92e609b-f5c4-4e9a-8eb8-7e2c54f75215@kernel.org>

On Sun, Mar 10, 2024 at 11:54:59AM -0600, David Ahern wrote:
> On 3/10/24 11:32 AM, Ido Schimmel wrote:
> > diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
> > index 5eb3ba568f4e..f3df80d2b980 100644
> > --- a/net/ipv4/nexthop.c
> > +++ b/net/ipv4/nexthop.c
> > @@ -3253,8 +3253,9 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
> >  	int err;
> >  	u32 id;
> >  
> > -	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
> > -			  rtm_nh_policy_del, extack);
> > +	err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
> > +			  ARRAY_SIZE(rtm_nh_policy_del) - 1, rtm_nh_policy_del,
> 
> 'tb' on the stack only needs to be ARRAY_SIZE as well; that's the
> benefit of the approach - only declare what you need.

The reasoning for that is explained in Petr's commit message:

"
    - To allow querying for presence of the attribute, have all the attribute
      arrays sized to NHA_MAX, regardless of what is permitted by policy, and
      pass the corresponding value to nlmsg_parse() as well.
"

IOW, with resizing 'tb' to ARRAY_SIZE:

rtm_del_nexthop
    nh_valid_get_del_req
        if (tb[NHA_OP_FLAGS]) -> BOOM

However, I can add [1] and [2] as patches #1 and #2 and then squash [3]
into the current patch.

[1]
commit bf5184cc9a3596d3185c91f2f7986e7c6f2dba9c
Author: Ido Schimmel <idosch@nvidia.com>
Date:   Sun Mar 10 21:56:21 2024 +0200

    nexthop: Only parse NHA_OP_FLAGS for get messages that require it
    
    The attribute is parsed into 'op_flags' in nh_valid_get_del_req() which
    is called from the handlers of three message types: RTM_DELNEXTHOP,
    RTM_GETNEXTHOPBUCKET and RTM_GETNEXTHOP. The attribute is only used by
    the latter and rejected by the policies of the other two.
    
    Pass 'op_flags' as NULL from the handlers of the other two and only
    parse the attribute when the argument is not NULL.
    
    This is a preparation for a subsequent patch.
    
    Signed-off-by: Ido Schimmel <idosch@nvidia.com>

diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 5eb3ba568f4e..03bacf9c0502 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -3229,10 +3229,12 @@ static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
                return -EINVAL;
        }
 
-       if (tb[NHA_OP_FLAGS])
-               *op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
-       else
-               *op_flags = 0;
+       if (op_flags) {
+               if (tb[NHA_OP_FLAGS])
+                       *op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
+               else
+                       *op_flags = 0;
+       }
 
        return 0;
 }
@@ -3249,7 +3251,6 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
                .portid = NETLINK_CB(skb).portid,
        };
        struct nexthop *nh;
-       u32 op_flags;
        int err;
        u32 id;
 
@@ -3258,7 +3259,7 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
-       err = nh_valid_get_del_req(nlh, tb, &id, &op_flags, extack);
+       err = nh_valid_get_del_req(nlh, tb, &id, NULL, extack);
        if (err)
                return err;
 
@@ -3715,7 +3716,6 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
                                   struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[NHA_MAX + 1];
-       u32 op_flags;
        int err;
 
        err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
@@ -3723,7 +3723,7 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
-       err = nh_valid_get_del_req(nlh, tb, id, &op_flags, extack);
+       err = nh_valid_get_del_req(nlh, tb, id, NULL, extack);
        if (err)
                return err;

[2]
commit 585183403a6b692d71746527938b037f50feed65
Author: Ido Schimmel <idosch@nvidia.com>
Date:   Sun Mar 10 22:54:53 2024 +0200

    nexthop: Only parse NHA_OP_FLAGS for dump messages that require it
    
    The attribute is parsed in __nh_valid_dump_req() which is called by the
    dump handlers of RTM_GETNEXTHOP and RTM_GETNEXTHOPBUCKET although it is
    only used by the former and rejected by the policy of the latter.
    
    Move the parsing to nh_valid_dump_req() which is only called by the dump
    handler of RTM_GETNEXTHOP.
    
    This is a preparation for a subsequent patch.
    
    Signed-off-by: Ido Schimmel <idosch@nvidia.com>

diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 03bacf9c0502..573da3660cb3 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -3397,11 +3397,6 @@ static int __nh_valid_dump_req(const struct nlmsghdr *nlh, struct nlattr **tb,
                return -EINVAL;
        }
 
-       if (tb[NHA_OP_FLAGS])
-               filter->op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
-       else
-               filter->op_flags = 0;
-
        return 0;
 }
 
@@ -3417,6 +3412,11 @@ static int nh_valid_dump_req(const struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
+       if (tb[NHA_OP_FLAGS])
+               filter->op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
+       else
+               filter->op_flags = 0;
+
        return __nh_valid_dump_req(nlh, tb, filter, cb->extack);
 }

[3]
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index f6c9d834b989..0011b0076c5b 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -3243,8 +3243,8 @@ static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
 static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
                           struct netlink_ext_ack *extack)
 {
+       struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_del)];
        struct net *net = sock_net(skb->sk);
-       struct nlattr *tb[NHA_MAX + 1];
        struct nl_info nlinfo = {
                .nlh = nlh,
                .nl_net = net,
@@ -3277,8 +3277,8 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
 static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
                           struct netlink_ext_ack *extack)
 {
+       struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get)];
        struct net *net = sock_net(in_skb->sk);
-       struct nlattr *tb[NHA_MAX + 1];
        struct sk_buff *skb = NULL;
        struct nexthop *nh;
        u32 op_flags;
@@ -3406,7 +3406,7 @@ static int nh_valid_dump_req(const struct nlmsghdr *nlh,
                             struct nh_dump_filter *filter,
                             struct netlink_callback *cb)
 {
-       struct nlattr *tb[NHA_MAX + 1];
+       struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump)];
        int err;
 
        err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
@@ -3550,7 +3550,7 @@ static int nh_valid_dump_bucket_req(const struct nlmsghdr *nlh,
                                    struct netlink_callback *cb)
 {
        struct nlattr *res_tb[ARRAY_SIZE(rtm_nh_res_bucket_policy_dump)];
-       struct nlattr *tb[NHA_MAX + 1];
+       struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump_bucket)];
        int err;
 
        err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
@@ -3719,7 +3719,7 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
                                   u32 *id, u16 *bucket_index,
                                   struct netlink_ext_ack *extack)
 {
-       struct nlattr *tb[NHA_MAX + 1];
+       struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get_bucket)];
        int err;
 
        err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,

  reply	other threads:[~2024-03-10 21:42 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-10 17:32 [PATCH net-next 0/2] nexthop: Fix two nexthop group statistics issues Ido Schimmel
2024-03-10 17:32 ` [PATCH net-next 1/2] nexthop: Fix out-of-bounds access during attribute validation Ido Schimmel
2024-03-10 17:54   ` David Ahern
2024-03-10 21:41     ` Ido Schimmel [this message]
2024-03-11  1:10       ` David Ahern
2024-03-11 10:27       ` Petr Machata
2024-03-11 14:47       ` Jakub Kicinski
2024-03-11 15:52         ` Petr Machata
2024-03-10 17:32 ` [PATCH net-next 2/2] nexthop: Fix splat with CONFIG_DEBUG_PREEMPT=y Ido Schimmel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Ze4pIe_E4BgkCP6w@shredder \
    --to=idosch@nvidia.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=petrm@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).