Message ID | 20211119142219.1519617-1-elver@google.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [1/2] kasan: add ability to detect double-kmem_cache_destroy() | expand |
On 11/19/21 15:22, Marco Elver wrote: > Because mm/slab_common.c is not instrumented with software KASAN modes, > it is not possible to detect use-after-free of the kmem_cache passed > into kmem_cache_destroy(). In particular, because of the s->refcount-- > and subsequent early return if non-zero, KASAN would never be able to > see the double-free via kmem_cache_free(kmem_cache, s). To be able to > detect a double-kmem_cache_destroy(), check accessibility of the > kmem_cache, and in case of failure return early. > > While KASAN_HW_TAGS is able to detect such bugs, by checking > accessibility and returning early we fail more gracefully and also > avoid corrupting reused objects (where tags mismatch). > > A recent case of a double-kmem_cache_destroy() was detected by KFENCE: > https://lkml.kernel.org/r/0000000000003f654905c168b09d@google.com > , which was not detectable by software KASAN modes. > > Signed-off-by: Marco Elver <elver@google.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> > --- > mm/slab_common.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/mm/slab_common.c b/mm/slab_common.c > index e5d080a93009..4bef4b6a2c76 100644 > --- a/mm/slab_common.c > +++ b/mm/slab_common.c > @@ -491,7 +491,7 @@ void kmem_cache_destroy(struct kmem_cache *s) > { > int err; > > - if (unlikely(!s)) > + if (unlikely(!s || !kasan_check_byte(s))) > return; > > cpus_read_lock(); >
On Fri, Nov 19, 2021 at 3:22 PM Marco Elver <elver@google.com> wrote: > > Because mm/slab_common.c is not instrumented with software KASAN modes, > it is not possible to detect use-after-free of the kmem_cache passed > into kmem_cache_destroy(). In particular, because of the s->refcount-- > and subsequent early return if non-zero, KASAN would never be able to > see the double-free via kmem_cache_free(kmem_cache, s). To be able to > detect a double-kmem_cache_destroy(), check accessibility of the > kmem_cache, and in case of failure return early. > > While KASAN_HW_TAGS is able to detect such bugs, by checking > accessibility and returning early we fail more gracefully and also > avoid corrupting reused objects (where tags mismatch). > > A recent case of a double-kmem_cache_destroy() was detected by KFENCE: > https://lkml.kernel.org/r/0000000000003f654905c168b09d@google.com > , which was not detectable by software KASAN modes. > > Signed-off-by: Marco Elver <elver@google.com> > --- > mm/slab_common.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/mm/slab_common.c b/mm/slab_common.c > index e5d080a93009..4bef4b6a2c76 100644 > --- a/mm/slab_common.c > +++ b/mm/slab_common.c > @@ -491,7 +491,7 @@ void kmem_cache_destroy(struct kmem_cache *s) > { > int err; > > - if (unlikely(!s)) > + if (unlikely(!s || !kasan_check_byte(s))) > return; > > cpus_read_lock(); > -- > 2.34.0.rc2.393.gf8c9666880-goog > Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com> Thanks!
diff --git a/mm/slab_common.c b/mm/slab_common.c index e5d080a93009..4bef4b6a2c76 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -491,7 +491,7 @@ void kmem_cache_destroy(struct kmem_cache *s) { int err; - if (unlikely(!s)) + if (unlikely(!s || !kasan_check_byte(s))) return; cpus_read_lock();
Because mm/slab_common.c is not instrumented with software KASAN modes, it is not possible to detect use-after-free of the kmem_cache passed into kmem_cache_destroy(). In particular, because of the s->refcount-- and subsequent early return if non-zero, KASAN would never be able to see the double-free via kmem_cache_free(kmem_cache, s). To be able to detect a double-kmem_cache_destroy(), check accessibility of the kmem_cache, and in case of failure return early. While KASAN_HW_TAGS is able to detect such bugs, by checking accessibility and returning early we fail more gracefully and also avoid corrupting reused objects (where tags mismatch). A recent case of a double-kmem_cache_destroy() was detected by KFENCE: https://lkml.kernel.org/r/0000000000003f654905c168b09d@google.com , which was not detectable by software KASAN modes. Signed-off-by: Marco Elver <elver@google.com> --- mm/slab_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)