Skip to content

Commit 5c5702e

Browse files
paravmellanoxjgunthorpe
authored andcommitted
RDMA/core: Set right entry state before releasing reference
Currently add_modify_gid() for IB link layer has followong issue in cache update path. When GID update event occurs, core releases reference to the GID table without updating its state and/or entry pointer. CPU-0 CPU-1 ------ ----- ib_cache_update() IPoIB ULP add_modify_gid() [..] put_gid_entry() refcnt = 0, but state = valid, entry is valid. (work item is not yet executed). ipoib_create_ah() rdma_create_ah() rdma_get_gid_attr() <-- Tries to acquire gid_attr which has refcnt = 0. This is incorrect. GID entry state and entry pointer is provides the accurate GID enty state. Such fields must be updated with rwlock to protect against readers and, such fields must be in sane state before refcount can drop to zero. Otherwise above race condition can happen leading to use-after-free situation. Following backtrace has been observed when cache update for an IB port is triggered while IPoIB ULP is creating an AH. Therefore, when updating GID entry, first mark a valid entry as invalid through state and set the barrier so that no callers can acquired the GID entry, followed by release reference to it. refcount_t: increment on 0; use-after-free. WARNING: CPU: 4 PID: 29106 at lib/refcount.c:153 refcount_inc_checked+0x30/0x50 Workqueue: ib-comp-unb-wq ib_cq_poll_work [ib_core] RIP: 0010:refcount_inc_checked+0x30/0x50 RSP: 0018:ffff8802ad36f600 EFLAGS: 00010082 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000002 RSI: 0000000000000008 RDI: ffffffff86710100 RBP: ffff8802d6e60a30 R08: ffffed005d67bf8b R09: ffffed005d67bf8b R10: 0000000000000001 R11: ffffed005d67bf8a R12: ffff88027620cee8 R13: ffff8802d6e60988 R14: ffff8802d6e60a78 R15: 0000000000000202 FS: 0000000000000000(0000) GS:ffff8802eb200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f3ab35e5c88 CR3: 00000002ce84a000 CR4: 00000000000006e0 IPv6: ADDRCONF(NETDEV_CHANGE): ib1: link becomes ready Call Trace: rdma_get_gid_attr+0x220/0x310 [ib_core] ? lock_acquire+0x145/0x3a0 rdma_fill_sgid_attr+0x32c/0x470 [ib_core] rdma_create_ah+0x89/0x160 [ib_core] ? rdma_fill_sgid_attr+0x470/0x470 [ib_core] ? ipoib_create_ah+0x52/0x260 [ib_ipoib] ipoib_create_ah+0xf5/0x260 [ib_ipoib] ipoib_mcast_join_complete+0xbbe/0x2540 [ib_ipoib] Fixes: b150c38 ("IB/core: Introduce GID entry reference counts") Signed-off-by: Parav Pandit <parav@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
1 parent e8ef090 commit 5c5702e

File tree

1 file changed

+34
-34
lines changed

1 file changed

+34
-34
lines changed

drivers/infiniband/core/cache.c

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,39 @@ static int add_roce_gid(struct ib_gid_table_entry *entry)
337337
return 0;
338338
}
339339

340+
/**
341+
* del_gid - Delete GID table entry
342+
*
343+
* @ib_dev: IB device whose GID entry to be deleted
344+
* @port: Port number of the IB device
345+
* @table: GID table of the IB device for a port
346+
* @ix: GID entry index to delete
347+
*
348+
*/
349+
static void del_gid(struct ib_device *ib_dev, u8 port,
350+
struct ib_gid_table *table, int ix)
351+
{
352+
struct ib_gid_table_entry *entry;
353+
354+
lockdep_assert_held(&table->lock);
355+
356+
pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
357+
ib_dev->name, port, ix,
358+
table->data_vec[ix]->attr.gid.raw);
359+
360+
write_lock_irq(&table->rwlock);
361+
entry = table->data_vec[ix];
362+
entry->state = GID_TABLE_ENTRY_PENDING_DEL;
363+
/*
364+
* For non RoCE protocol, GID entry slot is ready to use.
365+
*/
366+
if (!rdma_protocol_roce(ib_dev, port))
367+
table->data_vec[ix] = NULL;
368+
write_unlock_irq(&table->rwlock);
369+
370+
put_gid_entry_locked(entry);
371+
}
372+
340373
/**
341374
* add_modify_gid - Add or modify GID table entry
342375
*
@@ -358,7 +391,7 @@ static int add_modify_gid(struct ib_gid_table *table,
358391
* this index.
359392
*/
360393
if (is_gid_entry_valid(table->data_vec[attr->index]))
361-
put_gid_entry(table->data_vec[attr->index]);
394+
del_gid(attr->device, attr->port_num, table, attr->index);
362395

363396
/*
364397
* Some HCA's report multiple GID entries with only one valid GID, and
@@ -386,39 +419,6 @@ static int add_modify_gid(struct ib_gid_table *table,
386419
return ret;
387420
}
388421

389-
/**
390-
* del_gid - Delete GID table entry
391-
*
392-
* @ib_dev: IB device whose GID entry to be deleted
393-
* @port: Port number of the IB device
394-
* @table: GID table of the IB device for a port
395-
* @ix: GID entry index to delete
396-
*
397-
*/
398-
static void del_gid(struct ib_device *ib_dev, u8 port,
399-
struct ib_gid_table *table, int ix)
400-
{
401-
struct ib_gid_table_entry *entry;
402-
403-
lockdep_assert_held(&table->lock);
404-
405-
pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
406-
ib_dev->name, port, ix,
407-
table->data_vec[ix]->attr.gid.raw);
408-
409-
write_lock_irq(&table->rwlock);
410-
entry = table->data_vec[ix];
411-
entry->state = GID_TABLE_ENTRY_PENDING_DEL;
412-
/*
413-
* For non RoCE protocol, GID entry slot is ready to use.
414-
*/
415-
if (!rdma_protocol_roce(ib_dev, port))
416-
table->data_vec[ix] = NULL;
417-
write_unlock_irq(&table->rwlock);
418-
419-
put_gid_entry_locked(entry);
420-
}
421-
422422
/* rwlock should be read locked, or lock should be held */
423423
static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
424424
const struct ib_gid_attr *val, bool default_gid,

0 commit comments

Comments
 (0)