diff options
author | Roland Dreier <roland@purestorage.com> | 2011-05-27 11:20:46 -0700 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-05-27 11:20:46 -0700 |
commit | 5b0baf05195696eeebc3ef70f7c9218166d33f3b (patch) | |
tree | da6d711d8e5ac52bccca2315513c2f1fcafd04b3 | |
parent | 03bc2a2304d6f018f3cd1a9fad5e6d0b2c80dd21 (diff) | |
download | libibverbs-5b0baf05195696eeebc3ef70f7c9218166d33f3b.tar.gz |
Fix crash if no devices and ibv_get_device_list() is called multiple times
If no devices are found, ibverbs_init() sets num_devices to 0. This
means the next call to __ibv_get_device_list() would call
ibverbs_init() again, which crashes because ibverbs_init() leaves
various internal pointers pointing to freed memory.
Fix this by using pthread_once() to call ibverbs_init() exactly once,
and then doing the right thing even if num_devices stays 0.
Tested-by: Yann Droneaud <ydroneaud@opteya.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r-- | src/device.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/src/device.c b/src/device.c index 185f4a6..5798895 100644 --- a/src/device.c +++ b/src/device.c @@ -49,32 +49,34 @@ #include "ibverbs.h" -static pthread_mutex_t device_list_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_once_t device_list_once = PTHREAD_ONCE_INIT; static int num_devices; static struct ibv_device **device_list; +static void count_devices(void) +{ + num_devices = ibverbs_init(&device_list); +} + struct ibv_device **__ibv_get_device_list(int *num) { - struct ibv_device **l = 0; + struct ibv_device **l; int i; if (num) *num = 0; - pthread_mutex_lock(&device_list_lock); - - if (!num_devices) - num_devices = ibverbs_init(&device_list); + pthread_once(&device_list_once, count_devices); if (num_devices < 0) { errno = -num_devices; - goto out; + return NULL; } l = calloc(num_devices + 1, sizeof (struct ibv_device *)); if (!l) { errno = ENOMEM; - goto out; + return NULL; } for (i = 0; i < num_devices; ++i) @@ -82,8 +84,6 @@ struct ibv_device **__ibv_get_device_list(int *num) if (num) *num = num_devices; -out: - pthread_mutex_unlock(&device_list_lock); return l; } default_symver(__ibv_get_device_list, ibv_get_device_list); |