diff options
author | Roland Dreier <rolandd@cisco.com> | 2007-07-10 11:23:18 -0700 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-07-10 11:23:18 -0700 |
commit | c09f36897390766ba366d9d7b51ae7f96aa9c1e9 (patch) | |
tree | 2bd0e0724a58493190b9288dfcff206f6d35382a | |
parent | e72219d2826cc58e197c5742441440468d99897b (diff) | |
download | libibverbs-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.c | 21 |
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; } |