diff mbox series

[net-next,v13,3/8] net/sched: flower: Move filter handle initialization earlier

Message ID 20230217223620.28508-4-paulb@nvidia.com (mailing list archive)
State Accepted
Commit 08a0063df3aed8d76a4034279117db12dbc1050f
Delegated to: Netdev Maintainers
Headers show
Series net/sched: cls_api: Support hardware miss to tc action | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 95 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Paul Blakey Feb. 17, 2023, 10:36 p.m. UTC
To support miss to action during hardware offload the filter's
handle is needed when setting up the actions (tcf_exts_init()),
and before offloading.

Move filter handle initialization earlier.

Signed-off-by: Paul Blakey <paulb@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
 net/sched/cls_flower.c | 62 ++++++++++++++++++++++++------------------
 1 file changed, 35 insertions(+), 27 deletions(-)

Comments

Eric Dumazet Feb. 23, 2023, 10:24 a.m. UTC | #1
On Fri, Feb 17, 2023 at 11:36 PM Paul Blakey <paulb@nvidia.com> wrote:
>
> To support miss to action during hardware offload the filter's
> handle is needed when setting up the actions (tcf_exts_init()),
> and before offloading.
>
> Move filter handle initialization earlier.
>
> Signed-off-by: Paul Blakey <paulb@nvidia.com>
> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
> Reviewed-by: Simon Horman <simon.horman@corigine.com>
> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> ---

Error path is now potentially crashing because net pointer has not
been initialized.

I plan fixing this issue with the following:

diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index e960a46b05205bb0bca7dc0d21531e4d6a3853e3..475fe222a85566639bac75fc4a95bf649a10357d
100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -2200,8 +2200,9 @@ static int fl_change(struct net *net, struct
sk_buff *in_skb,
                fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);

                if (!tc_flags_valid(fnew->flags)) {
+                       kfree(fnew);
                        err = -EINVAL;
-                       goto errout;
+                       goto errout_tb;
                }
        }

@@ -2226,8 +2227,10 @@ static int fl_change(struct net *net, struct
sk_buff *in_skb,
                }
                spin_unlock(&tp->lock);

-               if (err)
-                       goto errout;
+               if (err) {
+                       kfree(fnew);
+                       goto errout_tb;
+               }
        }
        fnew->handle = handle;

@@ -2337,7 +2340,6 @@ static int fl_change(struct net *net, struct
sk_buff *in_skb,
        fl_mask_put(head, fnew->mask);
 errout_idr:
        idr_remove(&head->handle_idr, fnew->handle);
-errout:
        __fl_put(fnew);
 errout_tb:
        kfree(tb);
Paul Blakey Feb. 25, 2023, 7:53 a.m. UTC | #2
On 23/02/2023 12:24, Eric Dumazet wrote:
> On Fri, Feb 17, 2023 at 11:36 PM Paul Blakey <paulb@nvidia.com> wrote:
>>
>> To support miss to action during hardware offload the filter's
>> handle is needed when setting up the actions (tcf_exts_init()),
>> and before offloading.
>>
>> Move filter handle initialization earlier.
>>
>> Signed-off-by: Paul Blakey <paulb@nvidia.com>
>> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
>> Reviewed-by: Simon Horman <simon.horman@corigine.com>
>> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>> ---
> 
> Error path is now potentially crashing because net pointer has not
> been initialized.
> 
> I plan fixing this issue with the following:
> 
> diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
> index e960a46b05205bb0bca7dc0d21531e4d6a3853e3..475fe222a85566639bac75fc4a95bf649a10357d
> 100644
> --- a/net/sched/cls_flower.c
> +++ b/net/sched/cls_flower.c
> @@ -2200,8 +2200,9 @@ static int fl_change(struct net *net, struct
> sk_buff *in_skb,
>                  fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
> 
>                  if (!tc_flags_valid(fnew->flags)) {
> +                       kfree(fnew);
>                          err = -EINVAL;
> -                       goto errout;
> +                       goto errout_tb;
>                  }
>          }
> 
> @@ -2226,8 +2227,10 @@ static int fl_change(struct net *net, struct
> sk_buff *in_skb,
>                  }
>                  spin_unlock(&tp->lock);
> 
> -               if (err)
> -                       goto errout;
> +               if (err) {
> +                       kfree(fnew);
> +                       goto errout_tb;
> +               }
>          }
>          fnew->handle = handle;
> 
> @@ -2337,7 +2340,6 @@ static int fl_change(struct net *net, struct
> sk_buff *in_skb,
>          fl_mask_put(head, fnew->mask);
>   errout_idr:
>          idr_remove(&head->handle_idr, fnew->handle);
> -errout:
>          __fl_put(fnew);
>   errout_tb:
>          kfree(tb);


Notice that the bug was before this patch as well.
We init exts->net only in  fl_set_parms()->tcf_exts_validate(exts), and 
before this patch we called __fl_put() on two errors before that (like 
if tcf_exts_init() failed).


Here, its the same, we can't call __fl_put(fnew) till we called 
fl_set_parms(). So you're missing this "goto errorout_idr":


	err = tcf_exts_init_ex(&fnew->exts, net, TCA_FLOWER_ACT, 0, tp, handle, 
!tc_skip_hw(fnew->flags));
	if (err < 0)
		goto errout_idr;

Thanks,
Paul.
Eric Dumazet Feb. 25, 2023, 8:14 a.m. UTC | #3
On Sat, Feb 25, 2023 at 8:54 AM Paul Blakey <paulb@nvidia.com> wrote:
>
>
>
> On 23/02/2023 12:24, Eric Dumazet wrote:
> > On Fri, Feb 17, 2023 at 11:36 PM Paul Blakey <paulb@nvidia.com> wrote:
> >>
> >> To support miss to action during hardware offload the filter's
> >> handle is needed when setting up the actions (tcf_exts_init()),
> >> and before offloading.
> >>
> >> Move filter handle initialization earlier.
> >>
> >> Signed-off-by: Paul Blakey <paulb@nvidia.com>
> >> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
> >> Reviewed-by: Simon Horman <simon.horman@corigine.com>
> >> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >> ---
> >
> > Error path is now potentially crashing because net pointer has not
> > been initialized.
> >
> > I plan fixing this issue with the following:
> >
> > diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
> > index e960a46b05205bb0bca7dc0d21531e4d6a3853e3..475fe222a85566639bac75fc4a95bf649a10357d
> > 100644
> > --- a/net/sched/cls_flower.c
> > +++ b/net/sched/cls_flower.c
> > @@ -2200,8 +2200,9 @@ static int fl_change(struct net *net, struct
> > sk_buff *in_skb,
> >                  fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
> >
> >                  if (!tc_flags_valid(fnew->flags)) {
> > +                       kfree(fnew);
> >                          err = -EINVAL;
> > -                       goto errout;
> > +                       goto errout_tb;
> >                  }
> >          }
> >
> > @@ -2226,8 +2227,10 @@ static int fl_change(struct net *net, struct
> > sk_buff *in_skb,
> >                  }
> >                  spin_unlock(&tp->lock);
> >
> > -               if (err)
> > -                       goto errout;
> > +               if (err) {
> > +                       kfree(fnew);
> > +                       goto errout_tb;
> > +               }
> >          }
> >          fnew->handle = handle;
> >
> > @@ -2337,7 +2340,6 @@ static int fl_change(struct net *net, struct
> > sk_buff *in_skb,
> >          fl_mask_put(head, fnew->mask);
> >   errout_idr:
> >          idr_remove(&head->handle_idr, fnew->handle);
> > -errout:
> >          __fl_put(fnew);
> >   errout_tb:
> >          kfree(tb);
>
>
> Notice that the bug was before this patch as well.
> We init exts->net only in  fl_set_parms()->tcf_exts_validate(exts), and
> before this patch we called __fl_put() on two errors before that (like
> if tcf_exts_init() failed).
>
>
> Here, its the same, we can't call __fl_put(fnew) till we called
> fl_set_parms(). So you're missing this "goto errorout_idr":
>
>
>         err = tcf_exts_init_ex(&fnew->exts, net, TCA_FLOWER_ACT, 0, tp, handle,
> !tc_skip_hw(fnew->flags));
>         if (err < 0)
>                 goto errout_idr;
>
> Thanks,
> Paul.
>

The bug I am talking about is triggering because ->net pointer is not
initialized.

->net pointer is initialized in  tcf_exts_init_ex(), before any error
can be returned.
Paul Blakey Feb. 25, 2023, 6:10 p.m. UTC | #4
On 25/02/2023 10:14, Eric Dumazet wrote:
> On Sat, Feb 25, 2023 at 8:54 AM Paul Blakey <paulb@nvidia.com> wrote:
>>
>>
>>
>> On 23/02/2023 12:24, Eric Dumazet wrote:
>>> On Fri, Feb 17, 2023 at 11:36 PM Paul Blakey <paulb@nvidia.com> wrote:
>>>>
>>>> To support miss to action during hardware offload the filter's
>>>> handle is needed when setting up the actions (tcf_exts_init()),
>>>> and before offloading.
>>>>
>>>> Move filter handle initialization earlier.
>>>>
>>>> Signed-off-by: Paul Blakey <paulb@nvidia.com>
>>>> Reviewed-by: Jiri Pirko <jiri@nvidia.com>
>>>> Reviewed-by: Simon Horman <simon.horman@corigine.com>
>>>> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
>>>> ---
>>>
>>> Error path is now potentially crashing because net pointer has not
>>> been initialized.
>>>
>>> I plan fixing this issue with the following:
>>>
>>> diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
>>> index e960a46b05205bb0bca7dc0d21531e4d6a3853e3..475fe222a85566639bac75fc4a95bf649a10357d
>>> 100644
>>> --- a/net/sched/cls_flower.c
>>> +++ b/net/sched/cls_flower.c
>>> @@ -2200,8 +2200,9 @@ static int fl_change(struct net *net, struct
>>> sk_buff *in_skb,
>>>                   fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
>>>
>>>                   if (!tc_flags_valid(fnew->flags)) {
>>> +                       kfree(fnew);
>>>                           err = -EINVAL;
>>> -                       goto errout;
>>> +                       goto errout_tb;
>>>                   }
>>>           }
>>>
>>> @@ -2226,8 +2227,10 @@ static int fl_change(struct net *net, struct
>>> sk_buff *in_skb,
>>>                   }
>>>                   spin_unlock(&tp->lock);
>>>
>>> -               if (err)
>>> -                       goto errout;
>>> +               if (err) {
>>> +                       kfree(fnew);
>>> +                       goto errout_tb;
>>> +               }
>>>           }
>>>           fnew->handle = handle;
>>>
>>> @@ -2337,7 +2340,6 @@ static int fl_change(struct net *net, struct
>>> sk_buff *in_skb,
>>>           fl_mask_put(head, fnew->mask);
>>>    errout_idr:
>>>           idr_remove(&head->handle_idr, fnew->handle);
>>> -errout:
>>>           __fl_put(fnew);
>>>    errout_tb:
>>>           kfree(tb);
>>
>>
>> Notice that the bug was before this patch as well.
>> We init exts->net only in  fl_set_parms()->tcf_exts_validate(exts), and
>> before this patch we called __fl_put() on two errors before that (like
>> if tcf_exts_init() failed).
>>
>>
>> Here, its the same, we can't call __fl_put(fnew) till we called
>> fl_set_parms(). So you're missing this "goto errorout_idr":
>>
>>
>>          err = tcf_exts_init_ex(&fnew->exts, net, TCA_FLOWER_ACT, 0, tp, handle,
>> !tc_skip_hw(fnew->flags));
>>          if (err < 0)
>>                  goto errout_idr;
>>
>> Thanks,
>> Paul.
>>
> 
> The bug I am talking about is triggering because ->net pointer is not
> initialized.
> 
> ->net pointer is initialized in  tcf_exts_init_ex(), before any error
> can be returned.

Right, so all good!
diff mbox series

Patch

diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 885c95191ccf..be01d39dd7b9 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -2187,10 +2187,6 @@  static int fl_change(struct net *net, struct sk_buff *in_skb,
 	INIT_LIST_HEAD(&fnew->hw_list);
 	refcount_set(&fnew->refcnt, 1);
 
-	err = tcf_exts_init(&fnew->exts, net, TCA_FLOWER_ACT, 0);
-	if (err < 0)
-		goto errout;
-
 	if (tb[TCA_FLOWER_FLAGS]) {
 		fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
 
@@ -2200,15 +2196,45 @@  static int fl_change(struct net *net, struct sk_buff *in_skb,
 		}
 	}
 
+	if (!fold) {
+		spin_lock(&tp->lock);
+		if (!handle) {
+			handle = 1;
+			err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
+					    INT_MAX, GFP_ATOMIC);
+		} else {
+			err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
+					    handle, GFP_ATOMIC);
+
+			/* Filter with specified handle was concurrently
+			 * inserted after initial check in cls_api. This is not
+			 * necessarily an error if NLM_F_EXCL is not set in
+			 * message flags. Returning EAGAIN will cause cls_api to
+			 * try to update concurrently inserted rule.
+			 */
+			if (err == -ENOSPC)
+				err = -EAGAIN;
+		}
+		spin_unlock(&tp->lock);
+
+		if (err)
+			goto errout;
+	}
+	fnew->handle = handle;
+
+	err = tcf_exts_init(&fnew->exts, net, TCA_FLOWER_ACT, 0);
+	if (err < 0)
+		goto errout_idr;
+
 	err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE],
 			   tp->chain->tmplt_priv, flags, fnew->flags,
 			   extack);
 	if (err)
-		goto errout;
+		goto errout_idr;
 
 	err = fl_check_assign_mask(head, fnew, fold, mask);
 	if (err)
-		goto errout;
+		goto errout_idr;
 
 	err = fl_ht_insert_unique(fnew, fold, &in_ht);
 	if (err)
@@ -2274,29 +2300,9 @@  static int fl_change(struct net *net, struct sk_buff *in_skb,
 		refcount_dec(&fold->refcnt);
 		__fl_put(fold);
 	} else {
-		if (handle) {
-			/* user specifies a handle and it doesn't exist */
-			err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
-					    handle, GFP_ATOMIC);
-
-			/* Filter with specified handle was concurrently
-			 * inserted after initial check in cls_api. This is not
-			 * necessarily an error if NLM_F_EXCL is not set in
-			 * message flags. Returning EAGAIN will cause cls_api to
-			 * try to update concurrently inserted rule.
-			 */
-			if (err == -ENOSPC)
-				err = -EAGAIN;
-		} else {
-			handle = 1;
-			err = idr_alloc_u32(&head->handle_idr, fnew, &handle,
-					    INT_MAX, GFP_ATOMIC);
-		}
-		if (err)
-			goto errout_hw;
+		idr_replace(&head->handle_idr, fnew, fnew->handle);
 
 		refcount_inc(&fnew->refcnt);
-		fnew->handle = handle;
 		list_add_tail_rcu(&fnew->list, &fnew->mask->filters);
 		spin_unlock(&tp->lock);
 	}
@@ -2319,6 +2325,8 @@  static int fl_change(struct net *net, struct sk_buff *in_skb,
 				       fnew->mask->filter_ht_params);
 errout_mask:
 	fl_mask_put(head, fnew->mask);
+errout_idr:
+	idr_remove(&head->handle_idr, fnew->handle);
 errout:
 	__fl_put(fnew);
 errout_tb: