aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2007-07-10 11:23:18 -0700
committerRoland Dreier <rolandd@cisco.com>2007-07-10 11:23:18 -0700
commitc09f36897390766ba366d9d7b51ae7f96aa9c1e9 (patch)
tree2bd0e0724a58493190b9288dfcff206f6d35382a
parente72219d2826cc58e197c5742441440468d99897b (diff)
downloadlibibverbs-c09f36897390766ba366d9d7b51ae7f96aa9c1e9.tar.gz
Fix too-big madvise() call in ibv_madvise_range()
When the first memory range found in ibv_madvise_range() is merged with the previous range before entering the loop that calls madvise(), a too-big range could be passed to madvise(). This could lead to trying to madvise() memory that has already been freed and unmapped, which causes madvise() and therefore ibv_reg_mr() to fail. Fix this by making sure we don't madvise() any memory outside the range passed into ibv_madvise_range(). This fixes <https://bugs.openfabrics.org/show_bug.cgi?id=682>. Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--src/memory.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/memory.c b/src/memory.c
index 7f49683..53d86b7 100644
--- a/src/memory.c
+++ b/src/memory.c
@@ -510,9 +510,24 @@ static int ibv_madvise_range(void *base, size_t size, int advice)
if ((inc == -1 && node->refcnt == 0) ||
(inc == 1 && node->refcnt == 1)) {
- ret = madvise((void *) node->start,
- node->end - node->start + 1,
- advice);
+ /*
+ * If this is the first time through the loop,
+ * and we merged this node with the previous
+ * one, then we only want to do the madvise()
+ * on start ... node->end (rather than
+ * starting at node->start).
+ *
+ * Otherwise we end up doing madvise() on
+ * bigger region than we're being asked to,
+ * and that may lead to a spurious failure.
+ */
+ if (start > node->start)
+ ret = madvise((void *) start, node->end - start + 1,
+ advice);
+ else
+ ret = madvise((void *) node->start,
+ node->end - node->start + 1,
+ advice);
if (ret)
goto out;
}