diff options
author | Jason Gunthorpe <jgg@mellanox.com> | 2019-05-23 10:40:24 -0400 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2019-06-24 16:38:18 -0400 |
commit | 2dcc3eb8ab50c9ca816cc60abfd94bea559d3e86 (patch) | |
tree | f993a20fd2e73d85bbb61d1ba118eac9ae5410f5 | |
parent | 187229c2ddd12a5bb5cd6bb3fbef9ecbc6eead92 (diff) |
mm/hmm: Poison hmm_range during unregister
Trying to misuse a range outside its lifetime is a kernel bug. Use poison
bytes to help detect this condition. Double unregister will reliably crash.
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Reviewed-by: Jérôme Glisse <jglisse@redhat.com>
Reviewed-by: John Hubbard <jhubbard@nvidia.com>
Acked-by: Souptick Joarder <jrdr.linux@gmail.com>
Reviewed-by: Ralph Campbell <rcampbell@nvidia.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Tested-by: Philip Yang <Philip.Yang@amd.com>
-rw-r--r-- | mm/hmm.c | 14 |
1 files changed, 8 insertions, 6 deletions
@@ -925,19 +925,21 @@ void hmm_range_unregister(struct hmm_range *range) | |||
925 | { | 925 | { |
926 | struct hmm *hmm = range->hmm; | 926 | struct hmm *hmm = range->hmm; |
927 | 927 | ||
928 | /* Sanity check this really should not happen. */ | ||
929 | if (hmm == NULL || range->end <= range->start) | ||
930 | return; | ||
931 | |||
932 | mutex_lock(&hmm->lock); | 928 | mutex_lock(&hmm->lock); |
933 | list_del_init(&range->list); | 929 | list_del_init(&range->list); |
934 | mutex_unlock(&hmm->lock); | 930 | mutex_unlock(&hmm->lock); |
935 | 931 | ||
936 | /* Drop reference taken by hmm_range_register() */ | 932 | /* Drop reference taken by hmm_range_register() */ |
937 | range->valid = false; | ||
938 | mmput(hmm->mm); | 933 | mmput(hmm->mm); |
939 | hmm_put(hmm); | 934 | hmm_put(hmm); |
940 | range->hmm = NULL; | 935 | |
936 | /* | ||
937 | * The range is now invalid and the ref on the hmm is dropped, so | ||
938 | * poison the pointer. Leave other fields in place, for the caller's | ||
939 | * use. | ||
940 | */ | ||
941 | range->valid = false; | ||
942 | memset(&range->hmm, POISON_INUSE, sizeof(range->hmm)); | ||
941 | } | 943 | } |
942 | EXPORT_SYMBOL(hmm_range_unregister); | 944 | EXPORT_SYMBOL(hmm_range_unregister); |
943 | 945 | ||