Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1611176 > unrolled thread
| Started by | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| First post | 2017-03-28 18:20 +0200 |
| Last post | 2017-03-28 18:30 +0200 |
| Articles | 9 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH 0/8] x86, kasan: add KASAN checks to atomic operations Dmitry Vyukov <dvyukov@google.com> - 2017-03-28 18:20 +0200
[PATCH 8/8] asm-generic, x86: add comments for atomic instrumentation Dmitry Vyukov <dvyukov@google.com> - 2017-03-28 18:20 +0200
[PATCH 3/8] x86: use long long for 64-bit atomic ops Dmitry Vyukov <dvyukov@google.com> - 2017-03-28 18:20 +0200
Re: [PATCH 3/8] x86: use long long for 64-bit atomic ops Matthew Wilcox <willy@infradead.org> - 2017-03-28 23:40 +0200
[PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations Dmitry Vyukov <dvyukov@google.com> - 2017-03-28 18:20 +0200
Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations Mark Rutland <mark.rutland@arm.com> - 2017-03-29 16:10 +0200
Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations Mark Rutland <mark.rutland@arm.com> - 2017-03-29 18:00 +0200
Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations Dmitry Vyukov <dvyukov@google.com> - 2017-03-29 18:00 +0200
Re: [PATCH 0/8] x86, kasan: add KASAN checks to atomic operations Dmitry Vyukov <dvyukov@google.com> - 2017-03-28 18:30 +0200
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-28 18:20 +0200 |
| Subject | [PATCH 0/8] x86, kasan: add KASAN checks to atomic operations |
| Message-ID | <tq20H-1Mi-39@gated-at.bofh.it> |
KASAN uses compiler instrumentation to intercept all memory accesses. But it does not see memory accesses done in assembly code. One notable user of assembly code is atomic operations. Frequently, for example, an atomic reference decrement is the last access to an object and a good candidate for a racy use-after-free. Atomic operations are defined in arch files, but KASAN instrumentation is required for several archs that support KASAN. Later we will need similar hooks for KMSAN (uninit use detector) and KTSAN (data race detector). This change introduces wrappers around atomic operations that can be used to add KASAN/KMSAN/KTSAN instrumentation across several archs, and adds KASAN checks to them. This patch uses the wrappers only for x86 arch. Arm64 will be switched later. And we also plan to instrument bitops in a similar way. Within a day it has found its first bug: BUG: KASAN: use-after-free in atomic_dec_and_test arch/x86/include/asm/atomic.h:123 [inline] at addr ffff880079c30158 Write of size 4 by task syz-executor6/25698 CPU: 2 PID: 25698 Comm: syz-executor6 Not tainted 4.10.0+ #302 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: kasan_check_write+0x14/0x20 mm/kasan/kasan.c:344 atomic_dec_and_test arch/x86/include/asm/atomic.h:123 [inline] put_task_struct include/linux/sched/task.h:93 [inline] put_ctx+0xcf/0x110 kernel/events/core.c:1131 perf_event_release_kernel+0x3ad/0xc90 kernel/events/core.c:4322 perf_release+0x37/0x50 kernel/events/core.c:4338 __fput+0x332/0x800 fs/file_table.c:209 ____fput+0x15/0x20 fs/file_table.c:245 task_work_run+0x197/0x260 kernel/task_work.c:116 exit_task_work include/linux/task_work.h:21 [inline] do_exit+0xb38/0x29c0 kernel/exit.c:880 do_group_exit+0x149/0x420 kernel/exit.c:984 get_signal+0x7e0/0x1820 kernel/signal.c:2318 do_signal+0xd2/0x2190 arch/x86/kernel/signal.c:808 exit_to_usermode_loop+0x200/0x2a0 arch/x86/entry/common.c:157 syscall_return_slowpath arch/x86/entry/common.c:191 [inline] do_syscall_64+0x6fc/0x930 arch/x86/entry/common.c:286 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x4458d9 RSP: 002b:00007f3f07187cf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca RAX: fffffffffffffe00 RBX: 00000000007080c8 RCX: 00000000004458d9 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000007080c8 RBP: 00000000007080a8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007f3f071889c0 R15: 00007f3f07188700 Object at ffff880079c30140, in cache task_struct size: 5376 Allocated: PID = 25681 kmem_cache_alloc_node+0x122/0x6f0 mm/slab.c:3662 alloc_task_struct_node kernel/fork.c:153 [inline] dup_task_struct kernel/fork.c:495 [inline] copy_process.part.38+0x19c8/0x4aa0 kernel/fork.c:1560 copy_process kernel/fork.c:1531 [inline] _do_fork+0x200/0x1010 kernel/fork.c:1994 SYSC_clone kernel/fork.c:2104 [inline] SyS_clone+0x37/0x50 kernel/fork.c:2098 do_syscall_64+0x2e8/0x930 arch/x86/entry/common.c:281 return_from_SYSCALL_64+0x0/0x7a Freed: PID = 25681 __cache_free mm/slab.c:3514 [inline] kmem_cache_free+0x71/0x240 mm/slab.c:3774 free_task_struct kernel/fork.c:158 [inline] free_task+0x151/0x1d0 kernel/fork.c:370 copy_process.part.38+0x18e5/0x4aa0 kernel/fork.c:1931 copy_process kernel/fork.c:1531 [inline] _do_fork+0x200/0x1010 kernel/fork.c:1994 SYSC_clone kernel/fork.c:2104 [inline] SyS_clone+0x37/0x50 kernel/fork.c:2098 do_syscall_64+0x2e8/0x930 arch/x86/entry/common.c:281 return_from_SYSCALL_64+0x0/0x7a Dmitry Vyukov (8): x86: remove unused atomic_inc_short() x86: un-macro-ify atomic ops implementation x86: use long long for 64-bit atomic ops asm-generic: add atomic-instrumented.h x86: switch atomic.h to use atomic-instrumented.h kasan: allow kasan_check_read/write() to accept pointers to volatiles asm-generic: add KASAN instrumentation to atomic operations asm-generic, x86: add comments for atomic instrumentation arch/tile/lib/atomic_asm_32.S | 3 +- arch/x86/include/asm/atomic.h | 174 +++++++------ arch/x86/include/asm/atomic64_32.h | 153 ++++++----- arch/x86/include/asm/atomic64_64.h | 155 ++++++----- arch/x86/include/asm/cmpxchg.h | 14 +- arch/x86/include/asm/cmpxchg_32.h | 8 +- arch/x86/include/asm/cmpxchg_64.h | 4 +- include/asm-generic/atomic-instrumented.h | 417 ++++++++++++++++++++++++++++++ include/linux/kasan-checks.h | 10 +- include/linux/types.h | 2 +- mm/kasan/kasan.c | 4 +- 11 files changed, 719 insertions(+), 225 deletions(-) create mode 100644 include/asm-generic/atomic-instrumented.h -- 2.12.2.564.g063fe858b8-goog
[toc] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-28 18:20 +0200 |
| Subject | [PATCH 8/8] asm-generic, x86: add comments for atomic instrumentation |
| Message-ID | <tq20H-1Mi-53@gated-at.bofh.it> |
| In reply to | #1611176 |
The comments are factored out from the code changes to make them
easier to read. Add them separately to explain some non-obvious
aspects.
Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: kasan-dev@googlegroups.com
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
---
arch/x86/include/asm/atomic.h | 7 +++++++
include/asm-generic/atomic-instrumented.h | 30 ++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 92dd59f24eba..b2a2220c7ac2 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -23,6 +23,13 @@
*/
static __always_inline int arch_atomic_read(const atomic_t *v)
{
+ /*
+ * Note: READ_ONCE() here leads to double instrumentation as
+ * both READ_ONCE() and atomic_read() contain instrumentation.
+ * This is a deliberate choice. READ_ONCE_NOCHECK() is compiled to a
+ * non-inlined function call that considerably increases binary size
+ * and stack usage under KASAN.
+ */
return READ_ONCE((v)->counter);
}
diff --git a/include/asm-generic/atomic-instrumented.h b/include/asm-generic/atomic-instrumented.h
index 7f8eb761f896..1134af090976 100644
--- a/include/asm-generic/atomic-instrumented.h
+++ b/include/asm-generic/atomic-instrumented.h
@@ -1,3 +1,15 @@
+/*
+ * This file provides wrappers with KASAN instrumentation for atomic operations.
+ * To use this functionality an arch's atomic.h file needs to define all
+ * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include
+ * this file at the end. This file provides atomic_read() that forwards to
+ * arch_atomic_read() for actual atomic operation.
+ * Note: if an arch atomic operation is implemented by means of other atomic
+ * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use
+ * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid
+ * double instrumentation.
+ */
+
#ifndef _LINUX_ATOMIC_INSTRUMENTED_H
#define _LINUX_ATOMIC_INSTRUMENTED_H
@@ -339,6 +351,15 @@ static __always_inline bool atomic64_add_negative(long long i, atomic64_t *v)
return arch_atomic64_add_negative(i, v);
}
+/*
+ * In the following macros we need to be careful to not clash with arch_ macros.
+ * arch_xchg() can be defined as an extended statement expression as well,
+ * if we define a __ptr variable, and arch_xchg() also defines __ptr variable,
+ * and we pass __ptr as an argument to arch_xchg(), it will use own __ptr
+ * instead of ours. This leads to unpleasant crashes. To avoid the problem
+ * the following macros declare variables with lots of underscores.
+ */
+
#define cmpxchg(ptr, old, new) \
({ \
__typeof__(ptr) ___ptr = (ptr); \
@@ -374,6 +395,15 @@ static __always_inline bool atomic64_add_negative(long long i, atomic64_t *v)
arch_cmpxchg64_local(____ptr, (old), (new)); \
})
+/*
+ * Originally we had the following code here:
+ * __typeof__(p1) ____p1 = (p1);
+ * kasan_check_write(____p1, 2 * sizeof(*____p1));
+ * arch_cmpxchg_double(____p1, (p2), (o1), (o2), (n1), (n2));
+ * But it leads to compilation failures (see gcc issue 72873).
+ * So for now it's left non-instrumented.
+ * There are few callers of cmpxchg_double(), so it's not critical.
+ */
#define cmpxchg_double(p1, p2, o1, o2, n1, n2) \
({ \
arch_cmpxchg_double((p1), (p2), (o1), (o2), (n1), (n2)); \
--
2.12.2.564.g063fe858b8-goog
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-28 18:20 +0200 |
| Subject | [PATCH 3/8] x86: use long long for 64-bit atomic ops |
| Message-ID | <tq20I-1Mi-63@gated-at.bofh.it> |
| In reply to | #1611176 |
Some 64-bit atomic operations use 'long long' as operand/return type
(e.g. asm-generic/atomic64.h, arch/x86/include/asm/atomic64_32.h);
while others use 'long' (e.g. arch/x86/include/asm/atomic64_64.h).
This makes it impossible to write portable code.
For example, there is no format specifier that prints result of
atomic64_read() without warnings. atomic64_try_cmpxchg() is almost
impossible to use in portable fashion because it requires either
'long *' or 'long long *' as argument depending on arch.
Switch arch/x86/include/asm/atomic64_64.h to 'long long'.
Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: kasan-dev@googlegroups.com
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
---
arch/x86/include/asm/atomic64_64.h | 54 +++++++++++++++++++-------------------
include/linux/types.h | 2 +-
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h
index 8db8879a6d8c..a62982a2b534 100644
--- a/arch/x86/include/asm/atomic64_64.h
+++ b/arch/x86/include/asm/atomic64_64.h
@@ -16,7 +16,7 @@
* Atomically reads the value of @v.
* Doesn't imply a read memory barrier.
*/
-static inline long atomic64_read(const atomic64_t *v)
+static inline long long atomic64_read(const atomic64_t *v)
{
return READ_ONCE((v)->counter);
}
@@ -28,7 +28,7 @@ static inline long atomic64_read(const atomic64_t *v)
*
* Atomically sets the value of @v to @i.
*/
-static inline void atomic64_set(atomic64_t *v, long i)
+static inline void atomic64_set(atomic64_t *v, long long i)
{
WRITE_ONCE(v->counter, i);
}
@@ -40,7 +40,7 @@ static inline void atomic64_set(atomic64_t *v, long i)
*
* Atomically adds @i to @v.
*/
-static __always_inline void atomic64_add(long i, atomic64_t *v)
+static __always_inline void atomic64_add(long long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "addq %1,%0"
: "=m" (v->counter)
@@ -54,7 +54,7 @@ static __always_inline void atomic64_add(long i, atomic64_t *v)
*
* Atomically subtracts @i from @v.
*/
-static inline void atomic64_sub(long i, atomic64_t *v)
+static inline void atomic64_sub(long long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "subq %1,%0"
: "=m" (v->counter)
@@ -70,7 +70,7 @@ static inline void atomic64_sub(long i, atomic64_t *v)
* true if the result is zero, or false for all
* other cases.
*/
-static inline bool atomic64_sub_and_test(long i, atomic64_t *v)
+static inline bool atomic64_sub_and_test(long long i, atomic64_t *v)
{
GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, "er", i, "%0", e);
}
@@ -136,7 +136,7 @@ static inline bool atomic64_inc_and_test(atomic64_t *v)
* if the result is negative, or false when
* result is greater than or equal to zero.
*/
-static inline bool atomic64_add_negative(long i, atomic64_t *v)
+static inline bool atomic64_add_negative(long long i, atomic64_t *v)
{
GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, "er", i, "%0", s);
}
@@ -148,22 +148,22 @@ static inline bool atomic64_add_negative(long i, atomic64_t *v)
*
* Atomically adds @i to @v and returns @i + @v
*/
-static __always_inline long atomic64_add_return(long i, atomic64_t *v)
+static __always_inline long long atomic64_add_return(long long i, atomic64_t *v)
{
return i + xadd(&v->counter, i);
}
-static inline long atomic64_sub_return(long i, atomic64_t *v)
+static inline long long atomic64_sub_return(long long i, atomic64_t *v)
{
return atomic64_add_return(-i, v);
}
-static inline long atomic64_fetch_add(long i, atomic64_t *v)
+static inline long long atomic64_fetch_add(long long i, atomic64_t *v)
{
return xadd(&v->counter, i);
}
-static inline long atomic64_fetch_sub(long i, atomic64_t *v)
+static inline long long atomic64_fetch_sub(long long i, atomic64_t *v)
{
return xadd(&v->counter, -i);
}
@@ -171,18 +171,18 @@ static inline long atomic64_fetch_sub(long i, atomic64_t *v)
#define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
#define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
-static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
+static inline long long atomic64_cmpxchg(atomic64_t *v, long long old, long long new)
{
return cmpxchg(&v->counter, old, new);
}
#define atomic64_try_cmpxchg atomic64_try_cmpxchg
-static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long *old, long new)
+static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long long *old, long long new)
{
return try_cmpxchg(&v->counter, old, new);
}
-static inline long atomic64_xchg(atomic64_t *v, long new)
+static inline long long atomic64_xchg(atomic64_t *v, long long new)
{
return xchg(&v->counter, new);
}
@@ -193,12 +193,12 @@ static inline long atomic64_xchg(atomic64_t *v, long new)
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
- * Atomically adds @a to @v, so long as it was not @u.
+ * Atomically adds @a to @v, so long long as it was not @u.
* Returns the old value of @v.
*/
-static inline bool atomic64_add_unless(atomic64_t *v, long a, long u)
+static inline bool atomic64_add_unless(atomic64_t *v, long long a, long long u)
{
- long c = atomic64_read(v);
+ long long c = atomic64_read(v);
do {
if (unlikely(c == u))
return false;
@@ -215,9 +215,9 @@ static inline bool atomic64_add_unless(atomic64_t *v, long a, long u)
* The function returns the old value of *v minus 1, even if
* the atomic variable, v, was not decremented.
*/
-static inline long atomic64_dec_if_positive(atomic64_t *v)
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
{
- long dec, c = atomic64_read(v);
+ long long dec, c = atomic64_read(v);
do {
dec = c - 1;
if (unlikely(dec < 0))
@@ -226,7 +226,7 @@ static inline long atomic64_dec_if_positive(atomic64_t *v)
return dec;
}
-static inline void atomic64_and(long i, atomic64_t *v)
+static inline void atomic64_and(long long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "andq %1,%0"
: "+m" (v->counter)
@@ -234,16 +234,16 @@ static inline void atomic64_and(long i, atomic64_t *v)
: "memory");
}
-static inline long atomic64_fetch_and(long i, atomic64_t *v)
+static inline long long atomic64_fetch_and(long long i, atomic64_t *v)
{
- long val = atomic64_read(v);
+ long long val = atomic64_read(v);
do {
} while (!atomic64_try_cmpxchg(v, &val, val & i));
return val;
}
-static inline void atomic64_or(long i, atomic64_t *v)
+static inline void atomic64_or(long long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "orq %1,%0"
: "+m" (v->counter)
@@ -251,16 +251,16 @@ static inline void atomic64_or(long i, atomic64_t *v)
: "memory");
}
-static inline long atomic64_fetch_or(long i, atomic64_t *v)
+static inline long long atomic64_fetch_or(long long i, atomic64_t *v)
{
- long val = atomic64_read(v);
+ long long val = atomic64_read(v);
do {
} while (!atomic64_try_cmpxchg(v, &val, val | i));
return val;
}
-static inline void atomic64_xor(long i, atomic64_t *v)
+static inline void atomic64_xor(long long i, atomic64_t *v)
{
asm volatile(LOCK_PREFIX "xorq %1,%0"
: "+m" (v->counter)
@@ -268,9 +268,9 @@ static inline void atomic64_xor(long i, atomic64_t *v)
: "memory");
}
-static inline long atomic64_fetch_xor(long i, atomic64_t *v)
+static inline long long atomic64_fetch_xor(long long i, atomic64_t *v)
{
- long val = atomic64_read(v);
+ long long val = atomic64_read(v);
do {
} while (!atomic64_try_cmpxchg(v, &val, val ^ i));
diff --git a/include/linux/types.h b/include/linux/types.h
index 1e7bd24848fc..569fc6db1bd5 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -177,7 +177,7 @@ typedef struct {
#ifdef CONFIG_64BIT
typedef struct {
- long counter;
+ long long counter;
} atomic64_t;
#endif
--
2.12.2.564.g063fe858b8-goog
[toc] | [prev] | [next] | [standalone]
| From | Matthew Wilcox <willy@infradead.org> |
|---|---|
| Date | 2017-03-28 23:40 +0200 |
| Subject | Re: [PATCH 3/8] x86: use long long for 64-bit atomic ops |
| Message-ID | <tq70n-5jM-25@gated-at.bofh.it> |
| In reply to | #1611180 |
On Tue, Mar 28, 2017 at 06:15:40PM +0200, Dmitry Vyukov wrote: > @@ -193,12 +193,12 @@ static inline long atomic64_xchg(atomic64_t *v, long new) > * @a: the amount to add to v... > * @u: ...unless v is equal to u. > * > - * Atomically adds @a to @v, so long as it was not @u. > + * Atomically adds @a to @v, so long long as it was not @u. > * Returns the old value of @v. > */ That's a clbuttic mistake! https://www.google.com/search?q=clbuttic
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-28 18:20 +0200 |
| Subject | [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations |
| Message-ID | <tq20I-1Mi-65@gated-at.bofh.it> |
| In reply to | #1611176 |
KASAN uses compiler instrumentation to intercept all memory accesses.
But it does not see memory accesses done in assembly code.
One notable user of assembly code is atomic operations. Frequently,
for example, an atomic reference decrement is the last access to an
object and a good candidate for a racy use-after-free.
Add manual KASAN checks to atomic operations.
Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will.deacon@arm.com>,
Cc: Andrew Morton <akpm@linux-foundation.org>,
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>,
Cc: Ingo Molnar <mingo@redhat.com>,
Cc: kasan-dev@googlegroups.com
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Cc: x86@kernel.org
---
include/asm-generic/atomic-instrumented.h | 76 +++++++++++++++++++++++++++++--
1 file changed, 72 insertions(+), 4 deletions(-)
diff --git a/include/asm-generic/atomic-instrumented.h b/include/asm-generic/atomic-instrumented.h
index fd483115d4c6..7f8eb761f896 100644
--- a/include/asm-generic/atomic-instrumented.h
+++ b/include/asm-generic/atomic-instrumented.h
@@ -1,44 +1,54 @@
#ifndef _LINUX_ATOMIC_INSTRUMENTED_H
#define _LINUX_ATOMIC_INSTRUMENTED_H
+#include <linux/kasan-checks.h>
+
static __always_inline int atomic_read(const atomic_t *v)
{
+ kasan_check_read(v, sizeof(*v));
return arch_atomic_read(v);
}
static __always_inline long long atomic64_read(const atomic64_t *v)
{
+ kasan_check_read(v, sizeof(*v));
return arch_atomic64_read(v);
}
static __always_inline void atomic_set(atomic_t *v, int i)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_set(v, i);
}
static __always_inline void atomic64_set(atomic64_t *v, long long i)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_set(v, i);
}
static __always_inline int atomic_xchg(atomic_t *v, int i)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_xchg(v, i);
}
static __always_inline long long atomic64_xchg(atomic64_t *v, long long i)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_xchg(v, i);
}
static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_cmpxchg(v, old, new);
}
static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
long long new)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_cmpxchg(v, old, new);
}
@@ -46,6 +56,8 @@ static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
#define atomic_try_cmpxchg atomic_try_cmpxchg
static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
{
+ kasan_check_write(v, sizeof(*v));
+ kasan_check_read(old, sizeof(*old));
return arch_atomic_try_cmpxchg(v, old, new);
}
#endif
@@ -55,12 +67,15 @@ static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long long *old,
long long new)
{
+ kasan_check_write(v, sizeof(*v));
+ kasan_check_read(old, sizeof(*old));
return arch_atomic64_try_cmpxchg(v, old, new);
}
#endif
static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
{
+ kasan_check_write(v, sizeof(*v));
return __arch_atomic_add_unless(v, a, u);
}
@@ -68,242 +83,295 @@ static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
static __always_inline bool atomic64_add_unless(atomic64_t *v, long long a,
long long u)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_add_unless(v, a, u);
}
static __always_inline void atomic_inc(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_inc(v);
}
static __always_inline void atomic64_inc(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_inc(v);
}
static __always_inline void atomic_dec(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_dec(v);
}
static __always_inline void atomic64_dec(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_dec(v);
}
static __always_inline void atomic_add(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_add(i, v);
}
static __always_inline void atomic64_add(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_add(i, v);
}
static __always_inline void atomic_sub(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_sub(i, v);
}
static __always_inline void atomic64_sub(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_sub(i, v);
}
static __always_inline void atomic_and(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_and(i, v);
}
static __always_inline void atomic64_and(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_and(i, v);
}
static __always_inline void atomic_or(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_or(i, v);
}
static __always_inline void atomic64_or(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_or(i, v);
}
static __always_inline void atomic_xor(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic_xor(i, v);
}
static __always_inline void atomic64_xor(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
arch_atomic64_xor(i, v);
}
static __always_inline int atomic_inc_return(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_inc_return(v);
}
static __always_inline long long atomic64_inc_return(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_inc_return(v);
}
static __always_inline int atomic_dec_return(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_dec_return(v);
}
static __always_inline long long atomic64_dec_return(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_dec_return(v);
}
static __always_inline long long atomic64_inc_not_zero(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_inc_not_zero(v);
}
static __always_inline long long atomic64_dec_if_positive(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_dec_if_positive(v);
}
static __always_inline bool atomic_dec_and_test(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_dec_and_test(v);
}
static __always_inline bool atomic64_dec_and_test(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_dec_and_test(v);
}
static __always_inline bool atomic_inc_and_test(atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_inc_and_test(v);
}
static __always_inline bool atomic64_inc_and_test(atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_inc_and_test(v);
}
static __always_inline int atomic_add_return(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_add_return(i, v);
}
static __always_inline long long atomic64_add_return(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_add_return(i, v);
}
static __always_inline int atomic_sub_return(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_sub_return(i, v);
}
static __always_inline long long atomic64_sub_return(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_sub_return(i, v);
}
static __always_inline int atomic_fetch_add(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_fetch_add(i, v);
}
static __always_inline long long atomic64_fetch_add(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_fetch_add(i, v);
}
static __always_inline int atomic_fetch_sub(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_fetch_sub(i, v);
}
static __always_inline long long atomic64_fetch_sub(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_fetch_sub(i, v);
}
static __always_inline int atomic_fetch_and(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_fetch_and(i, v);
}
static __always_inline long long atomic64_fetch_and(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_fetch_and(i, v);
}
static __always_inline int atomic_fetch_or(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_fetch_or(i, v);
}
static __always_inline long long atomic64_fetch_or(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_fetch_or(i, v);
}
static __always_inline int atomic_fetch_xor(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_fetch_xor(i, v);
}
static __always_inline long long atomic64_fetch_xor(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_fetch_xor(i, v);
}
static __always_inline bool atomic_sub_and_test(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_sub_and_test(i, v);
}
static __always_inline bool atomic64_sub_and_test(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_sub_and_test(i, v);
}
static __always_inline bool atomic_add_negative(int i, atomic_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic_add_negative(i, v);
}
static __always_inline bool atomic64_add_negative(long long i, atomic64_t *v)
{
+ kasan_check_write(v, sizeof(*v));
return arch_atomic64_add_negative(i, v);
}
#define cmpxchg(ptr, old, new) \
({ \
+ __typeof__(ptr) ___ptr = (ptr); \
+ kasan_check_write(___ptr, sizeof(*___ptr)); \
arch_cmpxchg((ptr), (old), (new)); \
})
#define sync_cmpxchg(ptr, old, new) \
({ \
- arch_sync_cmpxchg((ptr), (old), (new)); \
+ __typeof__(ptr) ___ptr = (ptr); \
+ kasan_check_write(___ptr, sizeof(*___ptr)); \
+ arch_sync_cmpxchg(___ptr, (old), (new)); \
})
#define cmpxchg_local(ptr, old, new) \
({ \
- arch_cmpxchg_local((ptr), (old), (new)); \
+ __typeof__(ptr) ____ptr = (ptr); \
+ kasan_check_write(____ptr, sizeof(*____ptr)); \
+ arch_cmpxchg_local(____ptr, (old), (new)); \
})
#define cmpxchg64(ptr, old, new) \
({ \
- arch_cmpxchg64((ptr), (old), (new)); \
+ __typeof__(ptr) ____ptr = (ptr); \
+ kasan_check_write(____ptr, sizeof(*____ptr)); \
+ arch_cmpxchg64(____ptr, (old), (new)); \
})
#define cmpxchg64_local(ptr, old, new) \
({ \
- arch_cmpxchg64_local((ptr), (old), (new)); \
+ __typeof__(ptr) ____ptr = (ptr); \
+ kasan_check_write(____ptr, sizeof(*____ptr)); \
+ arch_cmpxchg64_local(____ptr, (old), (new)); \
})
#define cmpxchg_double(p1, p2, o1, o2, n1, n2) \
--
2.12.2.564.g063fe858b8-goog
[toc] | [prev] | [next] | [standalone]
| From | Mark Rutland <mark.rutland@arm.com> |
|---|---|
| Date | 2017-03-29 16:10 +0200 |
| Subject | Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations |
| Message-ID | <tqmsq-7ZU-21@gated-at.bofh.it> |
| In reply to | #1611181 |
On Tue, Mar 28, 2017 at 06:15:44PM +0200, Dmitry Vyukov wrote:
> KASAN uses compiler instrumentation to intercept all memory accesses.
> But it does not see memory accesses done in assembly code.
> One notable user of assembly code is atomic operations. Frequently,
> for example, an atomic reference decrement is the last access to an
> object and a good candidate for a racy use-after-free.
>
> Add manual KASAN checks to atomic operations.
>
> Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Will Deacon <will.deacon@arm.com>,
> Cc: Andrew Morton <akpm@linux-foundation.org>,
> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>,
> Cc: Ingo Molnar <mingo@redhat.com>,
> Cc: kasan-dev@googlegroups.com
> Cc: linux-mm@kvack.org
> Cc: linux-kernel@vger.kernel.org
> Cc: x86@kernel.org
FWIW, I think that structuring the file this way will make it easier to
add the {acquire,release,relaxed} variants (as arm64 will need),
so this looks good to me.
As a heads-up, I wanted to have a go at that, but I wasn't able to apply
patch two onwards on v4.11-rc{3,4} or next-20170329. I was not able to
cleanly revert the instrumentation patches currently in next-20170329,
since other patches built atop of them.
It would be nice to see that sorted out.
Thanks,
Mark.
> ---
> include/asm-generic/atomic-instrumented.h | 76 +++++++++++++++++++++++++++++--
> 1 file changed, 72 insertions(+), 4 deletions(-)
>
> diff --git a/include/asm-generic/atomic-instrumented.h b/include/asm-generic/atomic-instrumented.h
> index fd483115d4c6..7f8eb761f896 100644
> --- a/include/asm-generic/atomic-instrumented.h
> +++ b/include/asm-generic/atomic-instrumented.h
> @@ -1,44 +1,54 @@
> #ifndef _LINUX_ATOMIC_INSTRUMENTED_H
> #define _LINUX_ATOMIC_INSTRUMENTED_H
>
> +#include <linux/kasan-checks.h>
> +
> static __always_inline int atomic_read(const atomic_t *v)
> {
> + kasan_check_read(v, sizeof(*v));
> return arch_atomic_read(v);
> }
>
> static __always_inline long long atomic64_read(const atomic64_t *v)
> {
> + kasan_check_read(v, sizeof(*v));
> return arch_atomic64_read(v);
> }
>
> static __always_inline void atomic_set(atomic_t *v, int i)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_set(v, i);
> }
>
> static __always_inline void atomic64_set(atomic64_t *v, long long i)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_set(v, i);
> }
>
> static __always_inline int atomic_xchg(atomic_t *v, int i)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_xchg(v, i);
> }
>
> static __always_inline long long atomic64_xchg(atomic64_t *v, long long i)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_xchg(v, i);
> }
>
> static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_cmpxchg(v, old, new);
> }
>
> static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
> long long new)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_cmpxchg(v, old, new);
> }
>
> @@ -46,6 +56,8 @@ static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
> #define atomic_try_cmpxchg atomic_try_cmpxchg
> static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
> {
> + kasan_check_write(v, sizeof(*v));
> + kasan_check_read(old, sizeof(*old));
> return arch_atomic_try_cmpxchg(v, old, new);
> }
> #endif
> @@ -55,12 +67,15 @@ static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
> static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long long *old,
> long long new)
> {
> + kasan_check_write(v, sizeof(*v));
> + kasan_check_read(old, sizeof(*old));
> return arch_atomic64_try_cmpxchg(v, old, new);
> }
> #endif
>
> static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
> {
> + kasan_check_write(v, sizeof(*v));
> return __arch_atomic_add_unless(v, a, u);
> }
>
> @@ -68,242 +83,295 @@ static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
> static __always_inline bool atomic64_add_unless(atomic64_t *v, long long a,
> long long u)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_add_unless(v, a, u);
> }
>
> static __always_inline void atomic_inc(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_inc(v);
> }
>
> static __always_inline void atomic64_inc(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_inc(v);
> }
>
> static __always_inline void atomic_dec(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_dec(v);
> }
>
> static __always_inline void atomic64_dec(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_dec(v);
> }
>
> static __always_inline void atomic_add(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_add(i, v);
> }
>
> static __always_inline void atomic64_add(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_add(i, v);
> }
>
> static __always_inline void atomic_sub(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_sub(i, v);
> }
>
> static __always_inline void atomic64_sub(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_sub(i, v);
> }
>
> static __always_inline void atomic_and(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_and(i, v);
> }
>
> static __always_inline void atomic64_and(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_and(i, v);
> }
>
> static __always_inline void atomic_or(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_or(i, v);
> }
>
> static __always_inline void atomic64_or(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_or(i, v);
> }
>
> static __always_inline void atomic_xor(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic_xor(i, v);
> }
>
> static __always_inline void atomic64_xor(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> arch_atomic64_xor(i, v);
> }
>
> static __always_inline int atomic_inc_return(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_inc_return(v);
> }
>
> static __always_inline long long atomic64_inc_return(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_inc_return(v);
> }
>
> static __always_inline int atomic_dec_return(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_dec_return(v);
> }
>
> static __always_inline long long atomic64_dec_return(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_dec_return(v);
> }
>
> static __always_inline long long atomic64_inc_not_zero(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_inc_not_zero(v);
> }
>
> static __always_inline long long atomic64_dec_if_positive(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_dec_if_positive(v);
> }
>
> static __always_inline bool atomic_dec_and_test(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_dec_and_test(v);
> }
>
> static __always_inline bool atomic64_dec_and_test(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_dec_and_test(v);
> }
>
> static __always_inline bool atomic_inc_and_test(atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_inc_and_test(v);
> }
>
> static __always_inline bool atomic64_inc_and_test(atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_inc_and_test(v);
> }
>
> static __always_inline int atomic_add_return(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_add_return(i, v);
> }
>
> static __always_inline long long atomic64_add_return(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_add_return(i, v);
> }
>
> static __always_inline int atomic_sub_return(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_sub_return(i, v);
> }
>
> static __always_inline long long atomic64_sub_return(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_sub_return(i, v);
> }
>
> static __always_inline int atomic_fetch_add(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_fetch_add(i, v);
> }
>
> static __always_inline long long atomic64_fetch_add(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_fetch_add(i, v);
> }
>
> static __always_inline int atomic_fetch_sub(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_fetch_sub(i, v);
> }
>
> static __always_inline long long atomic64_fetch_sub(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_fetch_sub(i, v);
> }
>
> static __always_inline int atomic_fetch_and(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_fetch_and(i, v);
> }
>
> static __always_inline long long atomic64_fetch_and(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_fetch_and(i, v);
> }
>
> static __always_inline int atomic_fetch_or(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_fetch_or(i, v);
> }
>
> static __always_inline long long atomic64_fetch_or(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_fetch_or(i, v);
> }
>
> static __always_inline int atomic_fetch_xor(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_fetch_xor(i, v);
> }
>
> static __always_inline long long atomic64_fetch_xor(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_fetch_xor(i, v);
> }
>
> static __always_inline bool atomic_sub_and_test(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_sub_and_test(i, v);
> }
>
> static __always_inline bool atomic64_sub_and_test(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_sub_and_test(i, v);
> }
>
> static __always_inline bool atomic_add_negative(int i, atomic_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic_add_negative(i, v);
> }
>
> static __always_inline bool atomic64_add_negative(long long i, atomic64_t *v)
> {
> + kasan_check_write(v, sizeof(*v));
> return arch_atomic64_add_negative(i, v);
> }
>
> #define cmpxchg(ptr, old, new) \
> ({ \
> + __typeof__(ptr) ___ptr = (ptr); \
> + kasan_check_write(___ptr, sizeof(*___ptr)); \
> arch_cmpxchg((ptr), (old), (new)); \
> })
>
> #define sync_cmpxchg(ptr, old, new) \
> ({ \
> - arch_sync_cmpxchg((ptr), (old), (new)); \
> + __typeof__(ptr) ___ptr = (ptr); \
> + kasan_check_write(___ptr, sizeof(*___ptr)); \
> + arch_sync_cmpxchg(___ptr, (old), (new)); \
> })
>
> #define cmpxchg_local(ptr, old, new) \
> ({ \
> - arch_cmpxchg_local((ptr), (old), (new)); \
> + __typeof__(ptr) ____ptr = (ptr); \
> + kasan_check_write(____ptr, sizeof(*____ptr)); \
> + arch_cmpxchg_local(____ptr, (old), (new)); \
> })
>
> #define cmpxchg64(ptr, old, new) \
> ({ \
> - arch_cmpxchg64((ptr), (old), (new)); \
> + __typeof__(ptr) ____ptr = (ptr); \
> + kasan_check_write(____ptr, sizeof(*____ptr)); \
> + arch_cmpxchg64(____ptr, (old), (new)); \
> })
>
> #define cmpxchg64_local(ptr, old, new) \
> ({ \
> - arch_cmpxchg64_local((ptr), (old), (new)); \
> + __typeof__(ptr) ____ptr = (ptr); \
> + kasan_check_write(____ptr, sizeof(*____ptr)); \
> + arch_cmpxchg64_local(____ptr, (old), (new)); \
> })
>
> #define cmpxchg_double(p1, p2, o1, o2, n1, n2) \
> --
> 2.12.2.564.g063fe858b8-goog
>
[toc] | [prev] | [next] | [standalone]
| From | Mark Rutland <mark.rutland@arm.com> |
|---|---|
| Date | 2017-03-29 18:00 +0200 |
| Subject | Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations |
| Message-ID | <tqoaS-AU-19@gated-at.bofh.it> |
| In reply to | #1611973 |
On Wed, Mar 29, 2017 at 05:52:43PM +0200, Dmitry Vyukov wrote:
> On Wed, Mar 29, 2017 at 4:00 PM, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Tue, Mar 28, 2017 at 06:15:44PM +0200, Dmitry Vyukov wrote:
> >> KASAN uses compiler instrumentation to intercept all memory accesses.
> >> But it does not see memory accesses done in assembly code.
> >> One notable user of assembly code is atomic operations. Frequently,
> >> for example, an atomic reference decrement is the last access to an
> >> object and a good candidate for a racy use-after-free.
> >>
> >> Add manual KASAN checks to atomic operations.
> >>
> >> Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
> >> Cc: Mark Rutland <mark.rutland@arm.com>
> >> Cc: Peter Zijlstra <peterz@infradead.org>
> >> Cc: Will Deacon <will.deacon@arm.com>,
> >> Cc: Andrew Morton <akpm@linux-foundation.org>,
> >> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>,
> >> Cc: Ingo Molnar <mingo@redhat.com>,
> >> Cc: kasan-dev@googlegroups.com
> >> Cc: linux-mm@kvack.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Cc: x86@kernel.org
> >
> > FWIW, I think that structuring the file this way will make it easier to
> > add the {acquire,release,relaxed} variants (as arm64 will need),
> > so this looks good to me.
> >
> > As a heads-up, I wanted to have a go at that, but I wasn't able to apply
> > patch two onwards on v4.11-rc{3,4} or next-20170329. I was not able to
> > cleanly revert the instrumentation patches currently in next-20170329,
> > since other patches built atop of them.
>
> I based it on git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
> locking/core
Ah; I should have guessed. ;)
Thanks for the pointer! I'll give that a go shortly.
Thanks,
Mark.
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-29 18:00 +0200 |
| Subject | Re: [PATCH 7/8] asm-generic: add KASAN instrumentation to atomic operations |
| Message-ID | <tqoaS-AU-21@gated-at.bofh.it> |
| In reply to | #1611973 |
On Wed, Mar 29, 2017 at 4:00 PM, Mark Rutland <mark.rutland@arm.com> wrote:
> On Tue, Mar 28, 2017 at 06:15:44PM +0200, Dmitry Vyukov wrote:
>> KASAN uses compiler instrumentation to intercept all memory accesses.
>> But it does not see memory accesses done in assembly code.
>> One notable user of assembly code is atomic operations. Frequently,
>> for example, an atomic reference decrement is the last access to an
>> object and a good candidate for a racy use-after-free.
>>
>> Add manual KASAN checks to atomic operations.
>>
>> Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: Peter Zijlstra <peterz@infradead.org>
>> Cc: Will Deacon <will.deacon@arm.com>,
>> Cc: Andrew Morton <akpm@linux-foundation.org>,
>> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>,
>> Cc: Ingo Molnar <mingo@redhat.com>,
>> Cc: kasan-dev@googlegroups.com
>> Cc: linux-mm@kvack.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: x86@kernel.org
>
> FWIW, I think that structuring the file this way will make it easier to
> add the {acquire,release,relaxed} variants (as arm64 will need),
> so this looks good to me.
>
> As a heads-up, I wanted to have a go at that, but I wasn't able to apply
> patch two onwards on v4.11-rc{3,4} or next-20170329. I was not able to
> cleanly revert the instrumentation patches currently in next-20170329,
> since other patches built atop of them.
I based it on git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
locking/core
> It would be nice to see that sorted out.
>
> Thanks,
> Mark.
>
>> ---
>> include/asm-generic/atomic-instrumented.h | 76 +++++++++++++++++++++++++++++--
>> 1 file changed, 72 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/asm-generic/atomic-instrumented.h b/include/asm-generic/atomic-instrumented.h
>> index fd483115d4c6..7f8eb761f896 100644
>> --- a/include/asm-generic/atomic-instrumented.h
>> +++ b/include/asm-generic/atomic-instrumented.h
>> @@ -1,44 +1,54 @@
>> #ifndef _LINUX_ATOMIC_INSTRUMENTED_H
>> #define _LINUX_ATOMIC_INSTRUMENTED_H
>>
>> +#include <linux/kasan-checks.h>
>> +
>> static __always_inline int atomic_read(const atomic_t *v)
>> {
>> + kasan_check_read(v, sizeof(*v));
>> return arch_atomic_read(v);
>> }
>>
>> static __always_inline long long atomic64_read(const atomic64_t *v)
>> {
>> + kasan_check_read(v, sizeof(*v));
>> return arch_atomic64_read(v);
>> }
>>
>> static __always_inline void atomic_set(atomic_t *v, int i)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_set(v, i);
>> }
>>
>> static __always_inline void atomic64_set(atomic64_t *v, long long i)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_set(v, i);
>> }
>>
>> static __always_inline int atomic_xchg(atomic_t *v, int i)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_xchg(v, i);
>> }
>>
>> static __always_inline long long atomic64_xchg(atomic64_t *v, long long i)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_xchg(v, i);
>> }
>>
>> static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_cmpxchg(v, old, new);
>> }
>>
>> static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
>> long long new)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_cmpxchg(v, old, new);
>> }
>>
>> @@ -46,6 +56,8 @@ static __always_inline long long atomic64_cmpxchg(atomic64_t *v, long long old,
>> #define atomic_try_cmpxchg atomic_try_cmpxchg
>> static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> + kasan_check_read(old, sizeof(*old));
>> return arch_atomic_try_cmpxchg(v, old, new);
>> }
>> #endif
>> @@ -55,12 +67,15 @@ static __always_inline bool atomic_try_cmpxchg(atomic_t *v, int *old, int new)
>> static __always_inline bool atomic64_try_cmpxchg(atomic64_t *v, long long *old,
>> long long new)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> + kasan_check_read(old, sizeof(*old));
>> return arch_atomic64_try_cmpxchg(v, old, new);
>> }
>> #endif
>>
>> static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return __arch_atomic_add_unless(v, a, u);
>> }
>>
>> @@ -68,242 +83,295 @@ static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u)
>> static __always_inline bool atomic64_add_unless(atomic64_t *v, long long a,
>> long long u)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_add_unless(v, a, u);
>> }
>>
>> static __always_inline void atomic_inc(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_inc(v);
>> }
>>
>> static __always_inline void atomic64_inc(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_inc(v);
>> }
>>
>> static __always_inline void atomic_dec(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_dec(v);
>> }
>>
>> static __always_inline void atomic64_dec(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_dec(v);
>> }
>>
>> static __always_inline void atomic_add(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_add(i, v);
>> }
>>
>> static __always_inline void atomic64_add(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_add(i, v);
>> }
>>
>> static __always_inline void atomic_sub(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_sub(i, v);
>> }
>>
>> static __always_inline void atomic64_sub(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_sub(i, v);
>> }
>>
>> static __always_inline void atomic_and(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_and(i, v);
>> }
>>
>> static __always_inline void atomic64_and(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_and(i, v);
>> }
>>
>> static __always_inline void atomic_or(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_or(i, v);
>> }
>>
>> static __always_inline void atomic64_or(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_or(i, v);
>> }
>>
>> static __always_inline void atomic_xor(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic_xor(i, v);
>> }
>>
>> static __always_inline void atomic64_xor(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> arch_atomic64_xor(i, v);
>> }
>>
>> static __always_inline int atomic_inc_return(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_inc_return(v);
>> }
>>
>> static __always_inline long long atomic64_inc_return(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_inc_return(v);
>> }
>>
>> static __always_inline int atomic_dec_return(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_dec_return(v);
>> }
>>
>> static __always_inline long long atomic64_dec_return(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_dec_return(v);
>> }
>>
>> static __always_inline long long atomic64_inc_not_zero(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_inc_not_zero(v);
>> }
>>
>> static __always_inline long long atomic64_dec_if_positive(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_dec_if_positive(v);
>> }
>>
>> static __always_inline bool atomic_dec_and_test(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_dec_and_test(v);
>> }
>>
>> static __always_inline bool atomic64_dec_and_test(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_dec_and_test(v);
>> }
>>
>> static __always_inline bool atomic_inc_and_test(atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_inc_and_test(v);
>> }
>>
>> static __always_inline bool atomic64_inc_and_test(atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_inc_and_test(v);
>> }
>>
>> static __always_inline int atomic_add_return(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_add_return(i, v);
>> }
>>
>> static __always_inline long long atomic64_add_return(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_add_return(i, v);
>> }
>>
>> static __always_inline int atomic_sub_return(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_sub_return(i, v);
>> }
>>
>> static __always_inline long long atomic64_sub_return(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_sub_return(i, v);
>> }
>>
>> static __always_inline int atomic_fetch_add(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_fetch_add(i, v);
>> }
>>
>> static __always_inline long long atomic64_fetch_add(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_fetch_add(i, v);
>> }
>>
>> static __always_inline int atomic_fetch_sub(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_fetch_sub(i, v);
>> }
>>
>> static __always_inline long long atomic64_fetch_sub(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_fetch_sub(i, v);
>> }
>>
>> static __always_inline int atomic_fetch_and(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_fetch_and(i, v);
>> }
>>
>> static __always_inline long long atomic64_fetch_and(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_fetch_and(i, v);
>> }
>>
>> static __always_inline int atomic_fetch_or(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_fetch_or(i, v);
>> }
>>
>> static __always_inline long long atomic64_fetch_or(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_fetch_or(i, v);
>> }
>>
>> static __always_inline int atomic_fetch_xor(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_fetch_xor(i, v);
>> }
>>
>> static __always_inline long long atomic64_fetch_xor(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_fetch_xor(i, v);
>> }
>>
>> static __always_inline bool atomic_sub_and_test(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_sub_and_test(i, v);
>> }
>>
>> static __always_inline bool atomic64_sub_and_test(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_sub_and_test(i, v);
>> }
>>
>> static __always_inline bool atomic_add_negative(int i, atomic_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic_add_negative(i, v);
>> }
>>
>> static __always_inline bool atomic64_add_negative(long long i, atomic64_t *v)
>> {
>> + kasan_check_write(v, sizeof(*v));
>> return arch_atomic64_add_negative(i, v);
>> }
>>
>> #define cmpxchg(ptr, old, new) \
>> ({ \
>> + __typeof__(ptr) ___ptr = (ptr); \
>> + kasan_check_write(___ptr, sizeof(*___ptr)); \
>> arch_cmpxchg((ptr), (old), (new)); \
>> })
>>
>> #define sync_cmpxchg(ptr, old, new) \
>> ({ \
>> - arch_sync_cmpxchg((ptr), (old), (new)); \
>> + __typeof__(ptr) ___ptr = (ptr); \
>> + kasan_check_write(___ptr, sizeof(*___ptr)); \
>> + arch_sync_cmpxchg(___ptr, (old), (new)); \
>> })
>>
>> #define cmpxchg_local(ptr, old, new) \
>> ({ \
>> - arch_cmpxchg_local((ptr), (old), (new)); \
>> + __typeof__(ptr) ____ptr = (ptr); \
>> + kasan_check_write(____ptr, sizeof(*____ptr)); \
>> + arch_cmpxchg_local(____ptr, (old), (new)); \
>> })
>>
>> #define cmpxchg64(ptr, old, new) \
>> ({ \
>> - arch_cmpxchg64((ptr), (old), (new)); \
>> + __typeof__(ptr) ____ptr = (ptr); \
>> + kasan_check_write(____ptr, sizeof(*____ptr)); \
>> + arch_cmpxchg64(____ptr, (old), (new)); \
>> })
>>
>> #define cmpxchg64_local(ptr, old, new) \
>> ({ \
>> - arch_cmpxchg64_local((ptr), (old), (new)); \
>> + __typeof__(ptr) ____ptr = (ptr); \
>> + kasan_check_write(____ptr, sizeof(*____ptr)); \
>> + arch_cmpxchg64_local(____ptr, (old), (new)); \
>> })
>>
>> #define cmpxchg_double(p1, p2, o1, o2, n1, n2) \
>> --
>> 2.12.2.564.g063fe858b8-goog
>>
>
> --
> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to kasan-dev+unsubscribe@googlegroups.com.
> To post to this group, send email to kasan-dev@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/20170329140000.GK23442%40leverpostej.
> For more options, visit https://groups.google.com/d/optout.
[toc] | [prev] | [next] | [standalone]
| From | Dmitry Vyukov <dvyukov@google.com> |
|---|---|
| Date | 2017-03-28 18:30 +0200 |
| Message-ID | <tq2am-1Rr-9@gated-at.bofh.it> |
| In reply to | #1611176 |
Andrew, This will go to tip/locking/core since it contains a bunch of conflicting patches. So please drop the following patch from me from mm: x86: remove unused atomic_inc_short() x86, asm-generic: add KASAN instrumentation to bitops x86: s/READ_ONCE_NOCHECK/READ_ONCE/ in arch_atomic_read() kasan: allow kasan_check_read/write() to accept pointers to volatiles asm-generic, x86: wrap atomic operations asm-generic: add KASAN instrumentation to atomic operations asm-generic: fix compilation failure in cmpxchg_double() On Tue, Mar 28, 2017 at 6:15 PM, Dmitry Vyukov <dvyukov@google.com> wrote: > KASAN uses compiler instrumentation to intercept all memory accesses. > But it does not see memory accesses done in assembly code. > One notable user of assembly code is atomic operations. Frequently, > for example, an atomic reference decrement is the last access to an > object and a good candidate for a racy use-after-free. > > Atomic operations are defined in arch files, but KASAN instrumentation > is required for several archs that support KASAN. Later we will need > similar hooks for KMSAN (uninit use detector) and KTSAN (data race > detector). > > This change introduces wrappers around atomic operations that can be > used to add KASAN/KMSAN/KTSAN instrumentation across several archs, > and adds KASAN checks to them. > > This patch uses the wrappers only for x86 arch. Arm64 will be switched > later. And we also plan to instrument bitops in a similar way. > > Within a day it has found its first bug: > > BUG: KASAN: use-after-free in atomic_dec_and_test > arch/x86/include/asm/atomic.h:123 [inline] at addr ffff880079c30158 > Write of size 4 by task syz-executor6/25698 > CPU: 2 PID: 25698 Comm: syz-executor6 Not tainted 4.10.0+ #302 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 > Call Trace: > kasan_check_write+0x14/0x20 mm/kasan/kasan.c:344 > atomic_dec_and_test arch/x86/include/asm/atomic.h:123 [inline] > put_task_struct include/linux/sched/task.h:93 [inline] > put_ctx+0xcf/0x110 kernel/events/core.c:1131 > perf_event_release_kernel+0x3ad/0xc90 kernel/events/core.c:4322 > perf_release+0x37/0x50 kernel/events/core.c:4338 > __fput+0x332/0x800 fs/file_table.c:209 > ____fput+0x15/0x20 fs/file_table.c:245 > task_work_run+0x197/0x260 kernel/task_work.c:116 > exit_task_work include/linux/task_work.h:21 [inline] > do_exit+0xb38/0x29c0 kernel/exit.c:880 > do_group_exit+0x149/0x420 kernel/exit.c:984 > get_signal+0x7e0/0x1820 kernel/signal.c:2318 > do_signal+0xd2/0x2190 arch/x86/kernel/signal.c:808 > exit_to_usermode_loop+0x200/0x2a0 arch/x86/entry/common.c:157 > syscall_return_slowpath arch/x86/entry/common.c:191 [inline] > do_syscall_64+0x6fc/0x930 arch/x86/entry/common.c:286 > entry_SYSCALL64_slow_path+0x25/0x25 > RIP: 0033:0x4458d9 > RSP: 002b:00007f3f07187cf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca > RAX: fffffffffffffe00 RBX: 00000000007080c8 RCX: 00000000004458d9 > RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000007080c8 > RBP: 00000000007080a8 R08: 0000000000000000 R09: 0000000000000000 > R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 > R13: 0000000000000000 R14: 00007f3f071889c0 R15: 00007f3f07188700 > Object at ffff880079c30140, in cache task_struct size: 5376 > Allocated: > PID = 25681 > kmem_cache_alloc_node+0x122/0x6f0 mm/slab.c:3662 > alloc_task_struct_node kernel/fork.c:153 [inline] > dup_task_struct kernel/fork.c:495 [inline] > copy_process.part.38+0x19c8/0x4aa0 kernel/fork.c:1560 > copy_process kernel/fork.c:1531 [inline] > _do_fork+0x200/0x1010 kernel/fork.c:1994 > SYSC_clone kernel/fork.c:2104 [inline] > SyS_clone+0x37/0x50 kernel/fork.c:2098 > do_syscall_64+0x2e8/0x930 arch/x86/entry/common.c:281 > return_from_SYSCALL_64+0x0/0x7a > Freed: > PID = 25681 > __cache_free mm/slab.c:3514 [inline] > kmem_cache_free+0x71/0x240 mm/slab.c:3774 > free_task_struct kernel/fork.c:158 [inline] > free_task+0x151/0x1d0 kernel/fork.c:370 > copy_process.part.38+0x18e5/0x4aa0 kernel/fork.c:1931 > copy_process kernel/fork.c:1531 [inline] > _do_fork+0x200/0x1010 kernel/fork.c:1994 > SYSC_clone kernel/fork.c:2104 [inline] > SyS_clone+0x37/0x50 kernel/fork.c:2098 > do_syscall_64+0x2e8/0x930 arch/x86/entry/common.c:281 > return_from_SYSCALL_64+0x0/0x7a > > Dmitry Vyukov (8): > x86: remove unused atomic_inc_short() > x86: un-macro-ify atomic ops implementation > x86: use long long for 64-bit atomic ops > asm-generic: add atomic-instrumented.h > x86: switch atomic.h to use atomic-instrumented.h > kasan: allow kasan_check_read/write() to accept pointers to volatiles > asm-generic: add KASAN instrumentation to atomic operations > asm-generic, x86: add comments for atomic instrumentation > > arch/tile/lib/atomic_asm_32.S | 3 +- > arch/x86/include/asm/atomic.h | 174 +++++++------ > arch/x86/include/asm/atomic64_32.h | 153 ++++++----- > arch/x86/include/asm/atomic64_64.h | 155 ++++++----- > arch/x86/include/asm/cmpxchg.h | 14 +- > arch/x86/include/asm/cmpxchg_32.h | 8 +- > arch/x86/include/asm/cmpxchg_64.h | 4 +- > include/asm-generic/atomic-instrumented.h | 417 ++++++++++++++++++++++++++++++ > include/linux/kasan-checks.h | 10 +- > include/linux/types.h | 2 +- > mm/kasan/kasan.c | 4 +- > 11 files changed, 719 insertions(+), 225 deletions(-) > create mode 100644 include/asm-generic/atomic-instrumented.h > > -- > 2.12.2.564.g063fe858b8-goog >
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web