All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Potapenko <glider@google.com>
To: Alexey Klimov <klimov.linux@gmail.com>
Cc: Andrey Konovalov <adech.fo@gmail.com>,
	Christoph Lameter <cl@linux.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Joonsoo Kim <js1304@gmail.com>,
	Kostya Serebryany <kcc@google.com>,
	Andrey Ryabinin <aryabinin@virtuozzo.com>,
	kasan-dev <kasan-dev@googlegroups.com>,
	Linux Memory Management List <linux-mm@kvack.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v9] mm: kasan: Initial memory quarantine implementation
Date: Tue, 17 May 2016 10:55:13 +0200	[thread overview]
Message-ID: <CAG_fn=Vufm8aEa3DCX0d_fcAuezLE+42i+BGjWocRH=EthU=pg@mail.gmail.com> (raw)
In-Reply-To: <CALW4P+JNmSVg351vwZ410JxDxuqZ7unou+wWJm2+_Ugp4tE2JQ@mail.gmail.com>

Hello Alexey,

On Tue, May 17, 2016 at 12:03 AM, Alexey Klimov <klimov.linux@gmail.com> wrote:
> Hi Alexander,
>
> On Wed, May 11, 2016 at 6:18 PM, Alexander Potapenko <glider@google.com> 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).
>>
>> As long as an object remains in the quarantine, KASAN is able to report
>> accesses to it, so the chance of reporting a use-after-free is increased.
>> Once the object leaves quarantine, the allocator may reuse it, in which
>> case the object is unpoisoned and KASAN can't detect incorrect accesses
>> to it.
>>
>> 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. A number of improvements have been
>> suggested by Andrey Ryabinin.
>>
>> Signed-off-by: Alexander Potapenko <glider@google.com>
>> ---
>> v2: - added copyright comments
>>     - per request from Joonsoo Kim made __cache_free() more straightforward
>>     - added comments for smp_load_acquire()/smp_store_release()
>>
>> v3: - incorporate changes introduced by the "mm, kasan: SLAB support" patch
>>
>> v4: - fix kbuild compile-time error (missing ___cache_free() declaration)
>>       and a warning (wrong format specifier)
>>
>> v6: - extended the patch description
>>     - dropped the unused qlist_remove() function
>>
>> v9: - incorporate the fixes by Andrey Ryabinin:
>>       * Fix comment styles,
>>       * Get rid of some ifdefs
>>       * Revert needless functions renames in quarantine patch
>>       * Remove needless local_irq_save()/restore() in
>>         per_cpu_remove_cache()
>>       * Add new 'struct qlist_node' instead of 'void **' types. This makes
>>         code a bit more redable.
>>     - remove the non-deterministic quarantine test
>>     - dropped smp_load_acquire()/smp_store_release()
>> ---
>>  include/linux/kasan.h |  13 ++-
>>  mm/kasan/Makefile     |   1 +
>>  mm/kasan/kasan.c      |  57 ++++++++--
>>  mm/kasan/kasan.h      |  21 +++-
>>  mm/kasan/quarantine.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>  mm/kasan/report.c     |   1 +
>>  mm/mempool.c          |   2 +-
>>  mm/slab.c             |  12 ++-
>>  mm/slab.h             |   2 +
>>  mm/slab_common.c      |   2 +
>>  10 files changed, 387 insertions(+), 15 deletions(-)
>>  create mode 100644 mm/kasan/quarantine.c
>>
>> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
>> index 737371b..611927f 100644
>> --- a/include/linux/kasan.h
>> +++ b/include/linux/kasan.h
>> @@ -50,6 +50,8 @@ void kasan_free_pages(struct page *page, unsigned int order);
>>
>
> [...]
>
>> diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
>> new file mode 100644
>> index 0000000..4973505
>> --- /dev/null
>> +++ b/mm/kasan/quarantine.c
>> @@ -0,0 +1,291 @@
>> +/*
>> + * KASAN quarantine.
>> + *
>> + * Author: Alexander Potapenko <glider@google.com>
>> + * Copyright (C) 2016 Google, Inc.
>> + *
>> + * Based on code by Dmitry Chernenkov.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/gfp.h>
>> +#include <linux/hash.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mm.h>
>> +#include <linux/percpu.h>
>> +#include <linux/printk.h>
>> +#include <linux/shrinker.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> +#include <linux/types.h>
>> +
>> +#include "../slab.h"
>> +#include "kasan.h"
>> +
>> +/* Data structure and operations for quarantine queues. */
>> +
>> +/*
>> + * Each queue is a signle-linked list, which also stores the total size of
>> + * objects inside of it.
>> + */
>> +struct qlist_head {
>> +       struct qlist_node *head;
>> +       struct qlist_node *tail;
>> +       size_t bytes;
>> +};
>> +
>> +#define QLIST_INIT { NULL, NULL, 0 }
>> +
>> +static bool qlist_empty(struct qlist_head *q)
>> +{
>> +       return !q->head;
>> +}
>> +
>> +static void qlist_init(struct qlist_head *q)
>> +{
>> +       q->head = q->tail = NULL;
>> +       q->bytes = 0;
>> +}
>> +
>> +static void qlist_put(struct qlist_head *q, struct qlist_node *qlink,
>> +               size_t size)
>> +{
>> +       if (unlikely(qlist_empty(q)))
>> +               q->head = qlink;
>> +       else
>> +               q->tail->next = qlink;
>> +       q->tail = qlink;
>> +       qlink->next = NULL;
>> +       q->bytes += size;
>> +}
>> +
>> +static void qlist_move_all(struct qlist_head *from, struct qlist_head *to)
>> +{
>> +       if (unlikely(qlist_empty(from)))
>> +               return;
>> +
>> +       if (qlist_empty(to)) {
>> +               *to = *from;
>> +               qlist_init(from);
>> +               return;
>> +       }
>> +
>> +       to->tail->next = from->head;
>> +       to->tail = from->tail;
>> +       to->bytes += from->bytes;
>> +
>> +       qlist_init(from);
>> +}
>> +
>> +static void qlist_move(struct qlist_head *from, struct qlist_node *last,
>> +               struct qlist_head *to, size_t size)
>> +{
>> +       if (unlikely(last == from->tail)) {
>> +               qlist_move_all(from, to);
>> +               return;
>> +       }
>> +       if (qlist_empty(to))
>> +               to->head = from->head;
>> +       else
>> +               to->tail->next = from->head;
>> +       to->tail = last;
>> +       from->head = last->next;
>> +       last->next = NULL;
>> +       from->bytes -= size;
>> +       to->bytes += size;
>> +}
>
> I see conversation with Andrew in previous emails about moving this
> code above into generic library facility but I don't anything is going
> on here. I also feel like this belongs to lib/*.
> Do I miss something or did you decide to do it later?
>
> [...]
I remember Andrew said that, but I think it will be cleaner to make
that change in a separate patch.
> --
> Best regards, Klimov Alexey



-- 
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

WARNING: multiple messages have this Message-ID (diff)
From: Alexander Potapenko <glider@google.com>
To: Alexey Klimov <klimov.linux@gmail.com>
Cc: Andrey Konovalov <adech.fo@gmail.com>,
	Christoph Lameter <cl@linux.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Joonsoo Kim <iamjoonsoo.kim@lge.com>,
	Joonsoo Kim <js1304@gmail.com>,
	Kostya Serebryany <kcc@google.com>,
	Andrey Ryabinin <aryabinin@virtuozzo.com>,
	kasan-dev <kasan-dev@googlegroups.com>,
	Linux Memory Management List <linux-mm@kvack.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v9] mm: kasan: Initial memory quarantine implementation
Date: Tue, 17 May 2016 10:55:13 +0200	[thread overview]
Message-ID: <CAG_fn=Vufm8aEa3DCX0d_fcAuezLE+42i+BGjWocRH=EthU=pg@mail.gmail.com> (raw)
In-Reply-To: <CALW4P+JNmSVg351vwZ410JxDxuqZ7unou+wWJm2+_Ugp4tE2JQ@mail.gmail.com>

Hello Alexey,

On Tue, May 17, 2016 at 12:03 AM, Alexey Klimov <klimov.linux@gmail.com> wrote:
> Hi Alexander,
>
> On Wed, May 11, 2016 at 6:18 PM, Alexander Potapenko <glider@google.com> 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).
>>
>> As long as an object remains in the quarantine, KASAN is able to report
>> accesses to it, so the chance of reporting a use-after-free is increased.
>> Once the object leaves quarantine, the allocator may reuse it, in which
>> case the object is unpoisoned and KASAN can't detect incorrect accesses
>> to it.
>>
>> 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. A number of improvements have been
>> suggested by Andrey Ryabinin.
>>
>> Signed-off-by: Alexander Potapenko <glider@google.com>
>> ---
>> v2: - added copyright comments
>>     - per request from Joonsoo Kim made __cache_free() more straightforward
>>     - added comments for smp_load_acquire()/smp_store_release()
>>
>> v3: - incorporate changes introduced by the "mm, kasan: SLAB support" patch
>>
>> v4: - fix kbuild compile-time error (missing ___cache_free() declaration)
>>       and a warning (wrong format specifier)
>>
>> v6: - extended the patch description
>>     - dropped the unused qlist_remove() function
>>
>> v9: - incorporate the fixes by Andrey Ryabinin:
>>       * Fix comment styles,
>>       * Get rid of some ifdefs
>>       * Revert needless functions renames in quarantine patch
>>       * Remove needless local_irq_save()/restore() in
>>         per_cpu_remove_cache()
>>       * Add new 'struct qlist_node' instead of 'void **' types. This makes
>>         code a bit more redable.
>>     - remove the non-deterministic quarantine test
>>     - dropped smp_load_acquire()/smp_store_release()
>> ---
>>  include/linux/kasan.h |  13 ++-
>>  mm/kasan/Makefile     |   1 +
>>  mm/kasan/kasan.c      |  57 ++++++++--
>>  mm/kasan/kasan.h      |  21 +++-
>>  mm/kasan/quarantine.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>  mm/kasan/report.c     |   1 +
>>  mm/mempool.c          |   2 +-
>>  mm/slab.c             |  12 ++-
>>  mm/slab.h             |   2 +
>>  mm/slab_common.c      |   2 +
>>  10 files changed, 387 insertions(+), 15 deletions(-)
>>  create mode 100644 mm/kasan/quarantine.c
>>
>> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
>> index 737371b..611927f 100644
>> --- a/include/linux/kasan.h
>> +++ b/include/linux/kasan.h
>> @@ -50,6 +50,8 @@ void kasan_free_pages(struct page *page, unsigned int order);
>>
>
> [...]
>
>> diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
>> new file mode 100644
>> index 0000000..4973505
>> --- /dev/null
>> +++ b/mm/kasan/quarantine.c
>> @@ -0,0 +1,291 @@
>> +/*
>> + * KASAN quarantine.
>> + *
>> + * Author: Alexander Potapenko <glider@google.com>
>> + * Copyright (C) 2016 Google, Inc.
>> + *
>> + * Based on code by Dmitry Chernenkov.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * version 2 as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/gfp.h>
>> +#include <linux/hash.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mm.h>
>> +#include <linux/percpu.h>
>> +#include <linux/printk.h>
>> +#include <linux/shrinker.h>
>> +#include <linux/slab.h>
>> +#include <linux/string.h>
>> +#include <linux/types.h>
>> +
>> +#include "../slab.h"
>> +#include "kasan.h"
>> +
>> +/* Data structure and operations for quarantine queues. */
>> +
>> +/*
>> + * Each queue is a signle-linked list, which also stores the total size of
>> + * objects inside of it.
>> + */
>> +struct qlist_head {
>> +       struct qlist_node *head;
>> +       struct qlist_node *tail;
>> +       size_t bytes;
>> +};
>> +
>> +#define QLIST_INIT { NULL, NULL, 0 }
>> +
>> +static bool qlist_empty(struct qlist_head *q)
>> +{
>> +       return !q->head;
>> +}
>> +
>> +static void qlist_init(struct qlist_head *q)
>> +{
>> +       q->head = q->tail = NULL;
>> +       q->bytes = 0;
>> +}
>> +
>> +static void qlist_put(struct qlist_head *q, struct qlist_node *qlink,
>> +               size_t size)
>> +{
>> +       if (unlikely(qlist_empty(q)))
>> +               q->head = qlink;
>> +       else
>> +               q->tail->next = qlink;
>> +       q->tail = qlink;
>> +       qlink->next = NULL;
>> +       q->bytes += size;
>> +}
>> +
>> +static void qlist_move_all(struct qlist_head *from, struct qlist_head *to)
>> +{
>> +       if (unlikely(qlist_empty(from)))
>> +               return;
>> +
>> +       if (qlist_empty(to)) {
>> +               *to = *from;
>> +               qlist_init(from);
>> +               return;
>> +       }
>> +
>> +       to->tail->next = from->head;
>> +       to->tail = from->tail;
>> +       to->bytes += from->bytes;
>> +
>> +       qlist_init(from);
>> +}
>> +
>> +static void qlist_move(struct qlist_head *from, struct qlist_node *last,
>> +               struct qlist_head *to, size_t size)
>> +{
>> +       if (unlikely(last == from->tail)) {
>> +               qlist_move_all(from, to);
>> +               return;
>> +       }
>> +       if (qlist_empty(to))
>> +               to->head = from->head;
>> +       else
>> +               to->tail->next = from->head;
>> +       to->tail = last;
>> +       from->head = last->next;
>> +       last->next = NULL;
>> +       from->bytes -= size;
>> +       to->bytes += size;
>> +}
>
> I see conversation with Andrew in previous emails about moving this
> code above into generic library facility but I don't anything is going
> on here. I also feel like this belongs to lib/*.
> Do I miss something or did you decide to do it later?
>
> [...]
I remember Andrew said that, but I think it will be cleaner to make
that change in a separate patch.
> --
> Best regards, Klimov Alexey



-- 
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

--
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>

  reply	other threads:[~2016-05-17  8:55 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-11 17:18 [PATCH v9] mm: kasan: Initial memory quarantine implementation Alexander Potapenko
2016-05-11 17:18 ` Alexander Potapenko
2016-05-16 22:03 ` Alexey Klimov
2016-05-16 22:03   ` Alexey Klimov
2016-05-17  8:55   ` Alexander Potapenko [this message]
2016-05-17  8:55     ` Alexander Potapenko

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='CAG_fn=Vufm8aEa3DCX0d_fcAuezLE+42i+BGjWocRH=EthU=pg@mail.gmail.com' \
    --to=glider@google.com \
    --cc=adech.fo@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=aryabinin@virtuozzo.com \
    --cc=cl@linux.com \
    --cc=dvyukov@google.com \
    --cc=iamjoonsoo.kim@lge.com \
    --cc=js1304@gmail.com \
    --cc=kasan-dev@googlegroups.com \
    --cc=kcc@google.com \
    --cc=klimov.linux@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=rostedt@goodmis.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.