From: Dmitry Vyukov <dvyukov@google.com>
To: Joonsoo Kim <js1304@gmail.com>
Cc: Alexander Potapenko <glider@google.com>,
Joonsoo Kim <iamjoonsoo.kim@lge.com>,
Andrey Konovalov <adech.fo@gmail.com>,
Christoph Lameter <cl@linux.com>,
Andrew Morton <akpm@linux-foundation.org>,
Andrey Ryabinin <ryabinin.a.a@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
kasan-dev <kasan-dev@googlegroups.com>,
LKML <linux-kernel@vger.kernel.org>,
Linux Memory Management List <linux-mm@kvack.org>
Subject: Re: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
Date: Fri, 19 Feb 2016 10:19:48 +0100 [thread overview]
Message-ID: <CACT4Y+Z60YxN6JKitsKLFfGFDFpVY3_rCPyz9m_3WtFeG+EbSQ@mail.gmail.com> (raw)
In-Reply-To: <CAAmzW4McCyLahXw2TV=OHBNwLSg2gq1Bq2n3mmaa7gLFEVGZ+w@mail.gmail.com>
On Fri, Feb 19, 2016 at 3:11 AM, Joonsoo Kim <js1304@gmail.com> wrote:
> 2016-02-18 23:06 GMT+09:00 Alexander Potapenko <glider@google.com>:
>> On Mon, Feb 1, 2016 at 3:47 AM, Joonsoo Kim <iamjoonsoo.kim@lge.com> wrote:
>>> On Wed, Jan 27, 2016 at 07:25:13PM +0100, Alexander Potapenko wrote:
>>>> Quarantine isolates freed objects in a separate queue. The objects are
>>>> returned to the allocator later, which helps to detect use-after-free
>>>> errors.
>>>>
>>>> Freed objects are first added to per-cpu quarantine queues.
>>>> When a cache is destroyed or memory shrinking is requested, the objects
>>>> are moved into the global quarantine queue. Whenever a kmalloc call
>>>> allows memory reclaiming, the oldest objects are popped out of the
>>>> global queue until the total size of objects in quarantine is less than
>>>> 3/4 of the maximum quarantine size (which is a fraction of installed
>>>> physical memory).
>>>
>>> Just wondering why not using time based approach rather than size
>>> based one. In heavy load condition, how much time do the object stay in
>>> quarantine?
>>>
>>>>
>>>> Right now quarantine support is only enabled in SLAB allocator.
>>>> Unification of KASAN features in SLAB and SLUB will be done later.
>>>>
>>>> This patch is based on the "mm: kasan: quarantine" patch originally
>>>> prepared by Dmitry Chernenkov.
>>>>
>>>> Signed-off-by: Alexander Potapenko <glider@google.com>
>>>> ---
>>>> include/linux/kasan.h | 30 ++++--
>>>> lib/test_kasan.c | 29 ++++++
>>>> mm/kasan/Makefile | 2 +-
>>>> mm/kasan/kasan.c | 68 +++++++++++-
>>>> mm/kasan/kasan.h | 11 +-
>>>> mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>> mm/kasan/report.c | 3 +-
>>>> mm/mempool.c | 7 +-
>>>> mm/page_alloc.c | 2 +-
>>>> mm/slab.c | 12 ++-
>>>> mm/slab.h | 4 +
>>>> mm/slab_common.c | 2 +
>>>> mm/slub.c | 4 +-
>>>> 13 files changed, 435 insertions(+), 23 deletions(-)
>>>>
>>>
>>> ...
>>>
>>>> +bool kasan_slab_free(struct kmem_cache *cache, void *object)
>>>> +{
>>>> +#ifdef CONFIG_SLAB
>>>> + /* RCU slabs could be legally used after free within the RCU period */
>>>> + if (unlikely(cache->flags & SLAB_DESTROY_BY_RCU))
>>>> + return false;
>>>> +
>>>> + if (likely(cache->flags & SLAB_KASAN)) {
>>>> + struct kasan_alloc_meta *alloc_info =
>>>> + get_alloc_info(cache, object);
>>>> + struct kasan_free_meta *free_info =
>>>> + get_free_info(cache, object);
>>>> +
>>>> + switch (alloc_info->state) {
>>>> + case KASAN_STATE_ALLOC:
>>>> + alloc_info->state = KASAN_STATE_QUARANTINE;
>>>> + quarantine_put(free_info, cache);
>>>
>>> quarantine_put() can be called regardless of SLAB_DESTROY_BY_RCU,
>>> although it's not much meaningful without poisoning. But, I have an
>>> idea to poison object on SLAB_DESTROY_BY_RCU cache.
>>>
>>> quarantine_put() moves per cpu list to global queue when
>>> list size reaches QUARANTINE_PERCPU_SIZE. If we call synchronize_rcu()
>>> at that time, after then, we can poison objects. With appropriate size
>>> setup, it would not be intrusive.
>>>
>> Won't this slow the quarantine down unpredictably (e.g. in the case
>> there're no RCU slabs in quarantine we'll still be waiting for
>> synchronize_rcu())?
>
> It could be handled by introducing one cpu variable.
>
>> Yet this is something worth looking into. Do you want RCU to be
>> handled in this patch set?
>
> No. It would be future work.
>
>>>> + set_track(&free_info->track, GFP_NOWAIT);
>>>
>>> set_track() can be called regardless of SLAB_DESTROY_BY_RCU.
>> Agreed, I can fix that if we decide to handle RCU in this patch
>> (otherwise it will lead to confusion).
>>
>>>
>>>> + kasan_poison_slab_free(cache, object);
>>>> + return true;
>>>> + case KASAN_STATE_QUARANTINE:
>>>> + case KASAN_STATE_FREE:
>>>> + pr_err("Double free");
>>>> + dump_stack();
>>>> + break;
>>>> + default:
>>>> + break;
>>>> + }
>>>> + }
>>>> + return false;
>>>> +#else
>>>> + kasan_poison_slab_free(cache, object);
>>>> + return false;
>>>> +#endif
>>>> +}
>>>> +
>>>
>>> ...
>>>
>>>> +void quarantine_reduce(void)
>>>> +{
>>>> + size_t new_quarantine_size;
>>>> + unsigned long flags;
>>>> + struct qlist to_free = QLIST_INIT;
>>>> + size_t size_to_free = 0;
>>>> + void **last;
>>>> +
>>>> + if (likely(ACCESS_ONCE(global_quarantine.bytes) <=
>>>> + smp_load_acquire(&quarantine_size)))
>>>> + return;
>>>> +
>>>> + spin_lock_irqsave(&quarantine_lock, flags);
>>>> +
>>>> + /* Update quarantine size in case of hotplug. Allocate a fraction of
>>>> + * the installed memory to quarantine minus per-cpu queue limits.
>>>> + */
>>>> + new_quarantine_size = (ACCESS_ONCE(totalram_pages) << PAGE_SHIFT) /
>>>> + QUARANTINE_FRACTION;
>>>> + new_quarantine_size -= QUARANTINE_PERCPU_SIZE * num_online_cpus();
>>>> + smp_store_release(&quarantine_size, new_quarantine_size);
>>>> +
>>>> + last = global_quarantine.head;
>>>> + while (last) {
>>>> + struct kmem_cache *cache = qlink_to_cache(last);
>>>> +
>>>> + size_to_free += cache->size;
>>>> + if (!*last || size_to_free >
>>>> + global_quarantine.bytes - QUARANTINE_LOW_SIZE)
>>>> + break;
>>>> + last = (void **) *last;
>>>> + }
>>>> + qlist_move(&global_quarantine, last, &to_free, size_to_free);
>>>> +
>>>> + spin_unlock_irqrestore(&quarantine_lock, flags);
>>>> +
>>>> + qlist_free_all(&to_free, NULL);
>>>> +}
>>>
>>> Isn't it better to call quarantine_reduce() in shrink_slab()?
>>> It will help to maximize quarantine time.
>> This is true, however if we don't call quarantine_reduce() from
>> kmalloc()/kfree() the size of the quarantine will be unpredictable.
>> There's a tradeoff between efficiency and space here, and at least in
>> some cases we may want to trade efficiency for space.
>
> size of the quarantine doesn't matter unless there is memory pressure.
> If memory pressure, shrink_slab() would be called and we can reduce
> size of quarantine. However, I don't think this is show stopper. We can
> do it when needed.
No, this does not work. We've tried.
The problem is fragmentation. When all memory is occupied by slab,
it's already too late to reclaim memory. Free objects are randomly
scattered over memory, so if you have just 1% of live objects, the
chances are that you won't be able to reclaim any single page.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2016-02-19 9:20 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-27 18:25 [PATCH v1 0/8] SLAB support for KASAN Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 1/8] kasan: Change the behavior of kmalloc_large_oob_right test Alexander Potapenko
2016-02-02 5:34 ` Andrew Morton
2016-02-02 15:29 ` Andrey Ryabinin
2016-02-02 16:25 ` Alexander Potapenko
2016-02-15 14:05 ` Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 2/8] mm, kasan: SLAB support Alexander Potapenko
2016-01-28 7:44 ` Joonsoo Kim
2016-01-28 12:37 ` Alexander Potapenko
2016-01-28 13:29 ` Alexander Potapenko
2016-02-01 2:15 ` Joonsoo Kim
2016-02-18 12:58 ` Alexander Potapenko
2016-02-19 1:41 ` Joonsoo Kim
2016-02-19 12:57 ` Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 3/8] mm, kasan: Added GFP flags to KASAN API Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections Alexander Potapenko
2016-01-28 14:53 ` Steven Rostedt
2016-01-29 11:33 ` Alexander Potapenko
2016-01-29 11:59 ` Alexander Potapenko
2016-01-29 14:45 ` Steven Rostedt
2016-02-16 15:32 ` Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB Alexander Potapenko
2016-01-28 7:40 ` Joonsoo Kim
2016-01-28 12:51 ` Alexander Potapenko
2016-01-28 13:27 ` Alexander Potapenko
2016-02-01 2:55 ` Joonsoo Kim
2016-02-16 18:37 ` Alexander Potapenko
2016-02-17 18:29 ` Alexander Potapenko
2016-02-18 8:13 ` Joonsoo Kim
2016-02-18 15:01 ` Alexander Potapenko
2016-02-18 7:58 ` Joonsoo Kim
2016-01-27 18:25 ` [PATCH v1 6/8] kasan: Test fix: Warn if the UAF could not be detected in kmalloc_uaf2 Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 7/8] kasan: Changed kmalloc_large_oob_right, added kmalloc_pagealloc_oob_right Alexander Potapenko
2016-01-27 18:25 ` [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation Alexander Potapenko
2016-02-01 2:47 ` Joonsoo Kim
2016-02-18 14:06 ` Alexander Potapenko
2016-02-19 2:11 ` Joonsoo Kim
2016-02-19 9:19 ` Dmitry Vyukov [this message]
2016-02-19 15:43 ` Christoph Lameter
2016-02-23 7:23 ` Joonsoo Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CACT4Y+Z60YxN6JKitsKLFfGFDFpVY3_rCPyz9m_3WtFeG+EbSQ@mail.gmail.com \
--to=dvyukov@google.com \
--cc=adech.fo@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cl@linux.com \
--cc=glider@google.com \
--cc=iamjoonsoo.kim@lge.com \
--cc=js1304@gmail.com \
--cc=kasan-dev@googlegroups.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=rostedt@goodmis.org \
--cc=ryabinin.a.a@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).