diff mbox series

[net] bnxt: prevent skb UAF after handing over to PTP worker

Message ID 20220921201005.335390-1-kuba@kernel.org (mailing list archive)
State Accepted
Commit c31f26c8f69f776759cbbdfb38e40ea91aa0dd65
Delegated to: Netdev Maintainers
Headers show
Series [net] bnxt: prevent skb UAF after handing over to PTP worker | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net
netdev/fixes_present success Fixes tag present in non-next series
netdev/subject_prefix success Link
netdev/cover_letter success Single patches do not need cover letters
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: 1 this patch: 1
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 Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1 this patch: 1
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 35 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Jakub Kicinski Sept. 21, 2022, 8:10 p.m. UTC
When reading the timestamp is required bnxt_tx_int() hands
over the ownership of the completed skb to the PTP worker.
The skb should not be used afterwards, as the worker may
run before the rest of our code and free the skb, leading
to a use-after-free.

Since dev_kfree_skb_any() accepts NULL make the loss of
ownership more obvious and set skb to NULL.

Fixes: 83bb623c968e ("bnxt_en: Transmit and retrieve packet timestamps")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: michael.chan@broadcom.com
CC: pavan.chebbi@broadcom.com
CC: edwin.peer@broadcom.com
CC: andrew.gospodarek@broadcom.com
---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Comments

Andy Gospodarek Sept. 21, 2022, 8:25 p.m. UTC | #1
On Wed, Sep 21, 2022 at 01:10:05PM -0700, Jakub Kicinski wrote:
> When reading the timestamp is required bnxt_tx_int() hands
> over the ownership of the completed skb to the PTP worker.
> The skb should not be used afterwards, as the worker may
> run before the rest of our code and free the skb, leading
> to a use-after-free.
> 
> Since dev_kfree_skb_any() accepts NULL make the loss of
> ownership more obvious and set skb to NULL.
> 
> Fixes: 83bb623c968e ("bnxt_en: Transmit and retrieve packet timestamps")
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>

In general this looks good to me.  Let's make sure Pavan and Michael
also agree.  Thanks for the patch!

Reviewed-by: Andy Gospodarek <gospo@broadcom.com>

> ---
> CC: michael.chan@broadcom.com
> CC: pavan.chebbi@broadcom.com
> CC: edwin.peer@broadcom.com
> CC: andrew.gospodarek@broadcom.com
> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index f46eefb5a029..96da0ba3d507 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> @@ -659,7 +659,6 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
>  
>  	for (i = 0; i < nr_pkts; i++) {
>  		struct bnxt_sw_tx_bd *tx_buf;
> -		bool compl_deferred = false;
>  		struct sk_buff *skb;
>  		int j, last;
>  
> @@ -668,6 +667,8 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
>  		skb = tx_buf->skb;
>  		tx_buf->skb = NULL;
>  
> +		tx_bytes += skb->len;
> +
>  		if (tx_buf->is_push) {
>  			tx_buf->is_push = 0;
>  			goto next_tx_int;
> @@ -688,8 +689,9 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
>  		}
>  		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
>  			if (bp->flags & BNXT_FLAG_CHIP_P5) {
> +				/* PTP worker takes ownership of the skb */
>  				if (!bnxt_get_tx_ts_p5(bp, skb))
> -					compl_deferred = true;
> +					skb = NULL;
>  				else
>  					atomic_inc(&bp->ptp_cfg->tx_avail);
>  			}
> @@ -698,9 +700,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
>  next_tx_int:
>  		cons = NEXT_TX(cons);
>  
> -		tx_bytes += skb->len;
> -		if (!compl_deferred)
> -			dev_kfree_skb_any(skb);
> +		dev_kfree_skb_any(skb);
>  	}
>  
>  	netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);
> -- 
> 2.37.3
>
Michael Chan Sept. 21, 2022, 9:15 p.m. UTC | #2
On Wed, Sep 21, 2022 at 1:26 PM Andy Gospodarek
<andrew.gospodarek@broadcom.com> wrote:
>
> On Wed, Sep 21, 2022 at 01:10:05PM -0700, Jakub Kicinski wrote:
> > When reading the timestamp is required bnxt_tx_int() hands
> > over the ownership of the completed skb to the PTP worker.
> > The skb should not be used afterwards, as the worker may
> > run before the rest of our code and free the skb, leading
> > to a use-after-free.
> >
> > Since dev_kfree_skb_any() accepts NULL make the loss of
> > ownership more obvious and set skb to NULL.
> >
> > Fixes: 83bb623c968e ("bnxt_en: Transmit and retrieve packet timestamps")
> > Signed-off-by: Jakub Kicinski <kuba@kernel.org>
>
> In general this looks good to me.  Let's make sure Pavan and Michael
> also agree.  Thanks for the patch!
>
> Reviewed-by: Andy Gospodarek <gospo@broadcom.com>

Thanks for catching this.

Reviewed-by: Michael Chan <michael.chan@broadcom.com>
patchwork-bot+netdevbpf@kernel.org Sept. 22, 2022, 2:40 p.m. UTC | #3
Hello:

This patch was applied to netdev/net.git (master)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 21 Sep 2022 13:10:05 -0700 you wrote:
> When reading the timestamp is required bnxt_tx_int() hands
> over the ownership of the completed skb to the PTP worker.
> The skb should not be used afterwards, as the worker may
> run before the rest of our code and free the skb, leading
> to a use-after-free.
> 
> Since dev_kfree_skb_any() accepts NULL make the loss of
> ownership more obvious and set skb to NULL.
> 
> [...]

Here is the summary with links:
  - [net] bnxt: prevent skb UAF after handing over to PTP worker
    https://git.kernel.org/netdev/net/c/c31f26c8f69f

You are awesome, thank you!
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index f46eefb5a029..96da0ba3d507 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -659,7 +659,6 @@  static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 
 	for (i = 0; i < nr_pkts; i++) {
 		struct bnxt_sw_tx_bd *tx_buf;
-		bool compl_deferred = false;
 		struct sk_buff *skb;
 		int j, last;
 
@@ -668,6 +667,8 @@  static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 		skb = tx_buf->skb;
 		tx_buf->skb = NULL;
 
+		tx_bytes += skb->len;
+
 		if (tx_buf->is_push) {
 			tx_buf->is_push = 0;
 			goto next_tx_int;
@@ -688,8 +689,9 @@  static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 		}
 		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
 			if (bp->flags & BNXT_FLAG_CHIP_P5) {
+				/* PTP worker takes ownership of the skb */
 				if (!bnxt_get_tx_ts_p5(bp, skb))
-					compl_deferred = true;
+					skb = NULL;
 				else
 					atomic_inc(&bp->ptp_cfg->tx_avail);
 			}
@@ -698,9 +700,7 @@  static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
 next_tx_int:
 		cons = NEXT_TX(cons);
 
-		tx_bytes += skb->len;
-		if (!compl_deferred)
-			dev_kfree_skb_any(skb);
+		dev_kfree_skb_any(skb);
 	}
 
 	netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);