From: Jiri Pirko <j...@mellanox.com>

Since mlxsw_sp_fib_create() and mlxsw_sp_mr_table_create()
use ERR_PTR macro to propagate int err through return of a pointer,
the return value is not NULL in case of failure. So if one
of the calls fails, one of vr->fib4, vr->fib6 or vr->mr4_table
is not NULL and mlxsw_sp_vr_is_used wrongly assumes
that vr is in use which leads to crash like following one:

[ 1293.949291] BUG: unable to handle kernel NULL pointer dereference at 
00000000000006c9
[ 1293.952729] IP: mlxsw_sp_mr_table_flush+0x15/0x70 [mlxsw_spectrum]

Fix this by using local variables to hold the pointers and set vr->*
only in case everything went fine.

Fixes: 76610ebbde18 ("mlxsw: spectrum_router: Refactor virtual router handling")
Fixes: a3d9bc506d64 ("mlxsw: spectrum_router: Extend virtual routers with IPv6 
support")
Fixes: d42b0965b1d4 ("mlxsw: spectrum_router: Add multicast routes notification 
handling functionality")
Signed-off-by: Jiri Pirko <j...@mellanox.com>
Reviewed-by: Ido Schimmel <ido...@mellanox.com>
Signed-off-by: Jiri Pirko <j...@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  | 32 ++++++++++++----------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index f0b25baba09a..dcc6305f7c22 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -788,6 +788,9 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct 
mlxsw_sp *mlxsw_sp,
                                              u32 tb_id,
                                              struct netlink_ext_ack *extack)
 {
+       struct mlxsw_sp_mr_table *mr4_table;
+       struct mlxsw_sp_fib *fib4;
+       struct mlxsw_sp_fib *fib6;
        struct mlxsw_sp_vr *vr;
        int err;
 
@@ -796,29 +799,30 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct 
mlxsw_sp *mlxsw_sp,
                NL_SET_ERR_MSG(extack, "spectrum: Exceeded number of supported 
virtual routers");
                return ERR_PTR(-EBUSY);
        }
-       vr->fib4 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
-       if (IS_ERR(vr->fib4))
-               return ERR_CAST(vr->fib4);
-       vr->fib6 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
-       if (IS_ERR(vr->fib6)) {
-               err = PTR_ERR(vr->fib6);
+       fib4 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
+       if (IS_ERR(fib4))
+               return ERR_CAST(fib4);
+       fib6 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
+       if (IS_ERR(fib6)) {
+               err = PTR_ERR(fib6);
                goto err_fib6_create;
        }
-       vr->mr4_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
-                                                MLXSW_SP_L3_PROTO_IPV4);
-       if (IS_ERR(vr->mr4_table)) {
-               err = PTR_ERR(vr->mr4_table);
+       mr4_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
+                                            MLXSW_SP_L3_PROTO_IPV4);
+       if (IS_ERR(mr4_table)) {
+               err = PTR_ERR(mr4_table);
                goto err_mr_table_create;
        }
+       vr->fib4 = fib4;
+       vr->fib6 = fib6;
+       vr->mr4_table = mr4_table;
        vr->tb_id = tb_id;
        return vr;
 
 err_mr_table_create:
-       mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6);
-       vr->fib6 = NULL;
+       mlxsw_sp_fib_destroy(mlxsw_sp, fib6);
 err_fib6_create:
-       mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4);
-       vr->fib4 = NULL;
+       mlxsw_sp_fib_destroy(mlxsw_sp, fib4);
        return ERR_PTR(err);
 }
 
-- 
2.14.3

Reply via email to