| From 7fe7302ca0ca45ef063f6e3cac0e67a88f0620f4 Mon Sep 17 00:00:00 2001 |
| From: Jack Morgenstein <jackm@dev.mellanox.co.il> |
| Date: Wed, 15 Jan 2020 10:50:50 +0200 |
| Subject: [PATCH] IB/mlx4: Fix memory leak in add_gid error flow |
| |
| commit eaad647e5cc27f7b46a27f3b85b14c4c8a64bffa upstream. |
| |
| In procedure mlx4_ib_add_gid(), if the driver is unable to update the FW |
| gid table, there is a memory leak in the driver's copy of the gid table: |
| the gid entry's context buffer is not freed. |
| |
| If such an error occurs, free the entry's context buffer, and mark the |
| entry as available (by setting its context pointer to NULL). |
| |
| Fixes: e26be1bfef81 ("IB/mlx4: Implement ib_device callbacks") |
| Link: https://lore.kernel.org/r/20200115085050.73746-1-leon@kernel.org |
| Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> |
| Reviewed-by: Parav Pandit <parav@mellanox.com> |
| Signed-off-by: Leon Romanovsky <leonro@mellanox.com> |
| Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c |
| index 3791d06f59ff..120d75ea15f1 100644 |
| --- a/drivers/infiniband/hw/mlx4/main.c |
| +++ b/drivers/infiniband/hw/mlx4/main.c |
| @@ -246,6 +246,13 @@ static int mlx4_ib_update_gids(struct gid_entry *gids, |
| return mlx4_ib_update_gids_v1(gids, ibdev, port_num); |
| } |
| |
| +static void free_gid_entry(struct gid_entry *entry) |
| +{ |
| + memset(&entry->gid, 0, sizeof(entry->gid)); |
| + kfree(entry->ctx); |
| + entry->ctx = NULL; |
| +} |
| + |
| static int mlx4_ib_add_gid(const struct ib_gid_attr *attr, void **context) |
| { |
| struct mlx4_ib_dev *ibdev = to_mdev(attr->device); |
| @@ -306,6 +313,8 @@ static int mlx4_ib_add_gid(const struct ib_gid_attr *attr, void **context) |
| GFP_ATOMIC); |
| if (!gids) { |
| ret = -ENOMEM; |
| + *context = NULL; |
| + free_gid_entry(&port_gid_table->gids[free]); |
| } else { |
| for (i = 0; i < MLX4_MAX_PORT_GIDS; i++) { |
| memcpy(&gids[i].gid, &port_gid_table->gids[i].gid, sizeof(union ib_gid)); |
| @@ -317,6 +326,12 @@ static int mlx4_ib_add_gid(const struct ib_gid_attr *attr, void **context) |
| |
| if (!ret && hw_update) { |
| ret = mlx4_ib_update_gids(gids, ibdev, attr->port_num); |
| + if (ret) { |
| + spin_lock_bh(&iboe->lock); |
| + *context = NULL; |
| + free_gid_entry(&port_gid_table->gids[free]); |
| + spin_unlock_bh(&iboe->lock); |
| + } |
| kfree(gids); |
| } |
| |
| @@ -346,10 +361,7 @@ static int mlx4_ib_del_gid(const struct ib_gid_attr *attr, void **context) |
| if (!ctx->refcount) { |
| unsigned int real_index = ctx->real_index; |
| |
| - memset(&port_gid_table->gids[real_index].gid, 0, |
| - sizeof(port_gid_table->gids[real_index].gid)); |
| - kfree(port_gid_table->gids[real_index].ctx); |
| - port_gid_table->gids[real_index].ctx = NULL; |
| + free_gid_entry(&port_gid_table->gids[real_index]); |
| hw_update = 1; |
| } |
| } |
| -- |
| 2.7.4 |
| |