kmemcheck: rip it out
authorLevin, Alexander (Sasha Levin) <alexander.levin@verizon.com>
Thu, 16 Nov 2017 01:36:02 +0000 (17:36 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 16 Nov 2017 02:21:05 +0000 (18:21 -0800)
Fix up makefiles, remove references, and git rm kmemcheck.

Link: http://lkml.kernel.org/r/20171007030159.22241-4-alexander.levin@verizon.com
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Vegard Nossum <vegardno@ifi.uio.no>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Tim Hansen <devtimhansen@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
35 files changed:
Documentation/admin-guide/kernel-parameters.txt
Documentation/dev-tools/index.rst
Documentation/dev-tools/kmemcheck.rst [deleted file]
MAINTAINERS
arch/x86/Kconfig
arch/x86/include/asm/kmemcheck.h
arch/x86/include/asm/string_32.h
arch/x86/include/asm/string_64.h
arch/x86/kernel/cpu/intel.c
arch/x86/mm/Makefile
arch/x86/mm/init.c
arch/x86/mm/kmemcheck/Makefile [deleted file]
arch/x86/mm/kmemcheck/error.c
arch/x86/mm/kmemcheck/error.h
arch/x86/mm/kmemcheck/kmemcheck.c [deleted file]
arch/x86/mm/kmemcheck/opcode.c
arch/x86/mm/kmemcheck/opcode.h
arch/x86/mm/kmemcheck/pte.c
arch/x86/mm/kmemcheck/pte.h
arch/x86/mm/kmemcheck/selftest.c
arch/x86/mm/kmemcheck/selftest.h
arch/x86/mm/kmemcheck/shadow.c [deleted file]
arch/x86/mm/kmemcheck/shadow.h
include/linux/interrupt.h
include/linux/kmemcheck.h
kernel/softirq.c
kernel/sysctl.c
lib/Kconfig.debug
lib/Kconfig.kmemcheck [deleted file]
mm/Kconfig.debug
mm/Makefile
mm/kmemcheck.c
mm/slub.c
scripts/kernel-doc
tools/include/linux/kmemcheck.h

index b74e13312fdc291d55ac29b137cc8df4ee608b5e..00bb04972612c858c32299b8a379663c6946132a 100644 (file)
                        Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
                        the default is off.
 
-       kmemcheck=      [X86] Boot-time kmemcheck enable/disable/one-shot mode
-                       Valid arguments: 0, 1, 2
-                       kmemcheck=0 (disabled)
-                       kmemcheck=1 (enabled)
-                       kmemcheck=2 (one-shot mode)
-                       Default: 2 (one-shot mode)
-
        kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
                        Default is 0 (don't ignore, but inject #GP)
 
index a81787cd47d793746f28e1035630b13298dc65f8..e313925fb0fa50d5826dd194461f6e5ec00f424a 100644 (file)
@@ -21,7 +21,6 @@ whole; patches welcome!
    kasan
    ubsan
    kmemleak
-   kmemcheck
    gdb-kernel-debugging
    kgdb
    kselftest
diff --git a/Documentation/dev-tools/kmemcheck.rst b/Documentation/dev-tools/kmemcheck.rst
deleted file mode 100644 (file)
index 7f3d198..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-Getting started with kmemcheck
-==============================
-
-Vegard Nossum <vegardno@ifi.uio.no>
-
-
-Introduction
-------------
-
-kmemcheck is a debugging feature for the Linux Kernel. More specifically, it
-is a dynamic checker that detects and warns about some uses of uninitialized
-memory.
-
-Userspace programmers might be familiar with Valgrind's memcheck. The main
-difference between memcheck and kmemcheck is that memcheck works for userspace
-programs only, and kmemcheck works for the kernel only. The implementations
-are of course vastly different. Because of this, kmemcheck is not as accurate
-as memcheck, but it turns out to be good enough in practice to discover real
-programmer errors that the compiler is not able to find through static
-analysis.
-
-Enabling kmemcheck on a kernel will probably slow it down to the extent that
-the machine will not be usable for normal workloads such as e.g. an
-interactive desktop. kmemcheck will also cause the kernel to use about twice
-as much memory as normal. For this reason, kmemcheck is strictly a debugging
-feature.
-
-
-Downloading
------------
-
-As of version 2.6.31-rc1, kmemcheck is included in the mainline kernel.
-
-
-Configuring and compiling
--------------------------
-
-kmemcheck only works for the x86 (both 32- and 64-bit) platform. A number of
-configuration variables must have specific settings in order for the kmemcheck
-menu to even appear in "menuconfig". These are:
-
-- ``CONFIG_CC_OPTIMIZE_FOR_SIZE=n``
-       This option is located under "General setup" / "Optimize for size".
-
-       Without this, gcc will use certain optimizations that usually lead to
-       false positive warnings from kmemcheck. An example of this is a 16-bit
-       field in a struct, where gcc may load 32 bits, then discard the upper
-       16 bits. kmemcheck sees only the 32-bit load, and may trigger a
-       warning for the upper 16 bits (if they're uninitialized).
-
-- ``CONFIG_SLAB=y`` or ``CONFIG_SLUB=y``
-       This option is located under "General setup" / "Choose SLAB
-       allocator".
-
-- ``CONFIG_FUNCTION_TRACER=n``
-       This option is located under "Kernel hacking" / "Tracers" / "Kernel
-       Function Tracer"
-
-       When function tracing is compiled in, gcc emits a call to another
-       function at the beginning of every function. This means that when the
-       page fault handler is called, the ftrace framework will be called
-       before kmemcheck has had a chance to handle the fault. If ftrace then
-       modifies memory that was tracked by kmemcheck, the result is an
-       endless recursive page fault.
-
-- ``CONFIG_DEBUG_PAGEALLOC=n``
-       This option is located under "Kernel hacking" / "Memory Debugging"
-       / "Debug page memory allocations".
-
-In addition, I highly recommend turning on ``CONFIG_DEBUG_INFO=y``. This is also
-located under "Kernel hacking". With this, you will be able to get line number
-information from the kmemcheck warnings, which is extremely valuable in
-debugging a problem. This option is not mandatory, however, because it slows
-down the compilation process and produces a much bigger kernel image.
-
-Now the kmemcheck menu should be visible (under "Kernel hacking" / "Memory
-Debugging" / "kmemcheck: trap use of uninitialized memory"). Here follows
-a description of the kmemcheck configuration variables:
-
-- ``CONFIG_KMEMCHECK``
-       This must be enabled in order to use kmemcheck at all...
-
-- ``CONFIG_KMEMCHECK_``[``DISABLED`` | ``ENABLED`` | ``ONESHOT``]``_BY_DEFAULT``
-       This option controls the status of kmemcheck at boot-time. "Enabled"
-       will enable kmemcheck right from the start, "disabled" will boot the
-       kernel as normal (but with the kmemcheck code compiled in, so it can
-       be enabled at run-time after the kernel has booted), and "one-shot" is
-       a special mode which will turn kmemcheck off automatically after
-       detecting the first use of uninitialized memory.
-
-       If you are using kmemcheck to actively debug a problem, then you
-       probably want to choose "enabled" here.
-
-       The one-shot mode is mostly useful in automated test setups because it
-       can prevent floods of warnings and increase the chances of the machine
-       surviving in case something is really wrong. In other cases, the one-
-       shot mode could actually be counter-productive because it would turn
-       itself off at the very first error -- in the case of a false positive
-       too -- and this would come in the way of debugging the specific
-       problem you were interested in.
-
-       If you would like to use your kernel as normal, but with a chance to
-       enable kmemcheck in case of some problem, it might be a good idea to
-       choose "disabled" here. When kmemcheck is disabled, most of the run-
-       time overhead is not incurred, and the kernel will be almost as fast
-       as normal.
-
-- ``CONFIG_KMEMCHECK_QUEUE_SIZE``
-       Select the maximum number of error reports to store in an internal
-       (fixed-size) buffer. Since errors can occur virtually anywhere and in
-       any context, we need a temporary storage area which is guaranteed not
-       to generate any other page faults when accessed. The queue will be
-       emptied as soon as a tasklet may be scheduled. If the queue is full,
-       new error reports will be lost.
-
-       The default value of 64 is probably fine. If some code produces more
-       than 64 errors within an irqs-off section, then the code is likely to
-       produce many, many more, too, and these additional reports seldom give
-       any more information (the first report is usually the most valuable
-       anyway).
-
-       This number might have to be adjusted if you are not using serial
-       console or similar to capture the kernel log. If you are using the
-       "dmesg" command to save the log, then getting a lot of kmemcheck
-       warnings might overflow the kernel log itself, and the earlier reports
-       will get lost in that way instead. Try setting this to 10 or so on
-       such a setup.
-
-- ``CONFIG_KMEMCHECK_SHADOW_COPY_SHIFT``
-       Select the number of shadow bytes to save along with each entry of the
-       error-report queue. These bytes indicate what parts of an allocation
-       are initialized, uninitialized, etc. and will be displayed when an
-       error is detected to help the debugging of a particular problem.
-
-       The number entered here is actually the logarithm of the number of
-       bytes that will be saved. So if you pick for example 5 here, kmemcheck
-       will save 2^5 = 32 bytes.
-
-       The default value should be fine for debugging most problems. It also
-       fits nicely within 80 columns.
-
-- ``CONFIG_KMEMCHECK_PARTIAL_OK``
-       This option (when enabled) works around certain GCC optimizations that
-       produce 32-bit reads from 16-bit variables where the upper 16 bits are
-       thrown away afterwards.
-
-       The default value (enabled) is recommended. This may of course hide
-       some real errors, but disabling it would probably produce a lot of
-       false positives.
-
-- ``CONFIG_KMEMCHECK_BITOPS_OK``
-       This option silences warnings that would be generated for bit-field
-       accesses where not all the bits are initialized at the same time. This
-       may also hide some real bugs.
-
-       This option is probably obsolete, or it should be replaced with
-       the kmemcheck-/bitfield-annotations for the code in question. The
-       default value is therefore fine.
-
-Now compile the kernel as usual.
-
-
-How to use
-----------
-
-Booting
-~~~~~~~
-
-First some information about the command-line options. There is only one
-option specific to kmemcheck, and this is called "kmemcheck". It can be used
-to override the default mode as chosen by the ``CONFIG_KMEMCHECK_*_BY_DEFAULT``
-option. Its possible settings are:
-
-- ``kmemcheck=0`` (disabled)
-- ``kmemcheck=1`` (enabled)
-- ``kmemcheck=2`` (one-shot mode)
-
-If SLUB debugging has been enabled in the kernel, it may take precedence over
-kmemcheck in such a way that the slab caches which are under SLUB debugging
-will not be tracked by kmemcheck. In order to ensure that this doesn't happen
-(even though it shouldn't by default), use SLUB's boot option ``slub_debug``,
-like this: ``slub_debug=-``
-
-In fact, this option may also be used for fine-grained control over SLUB vs.
-kmemcheck. For example, if the command line includes
-``kmemcheck=1 slub_debug=,dentry``, then SLUB debugging will be used only
-for the "dentry" slab cache, and with kmemcheck tracking all the other
-caches. This is advanced usage, however, and is not generally recommended.
-
-
-Run-time enable/disable
-~~~~~~~~~~~~~~~~~~~~~~~
-
-When the kernel has booted, it is possible to enable or disable kmemcheck at
-run-time. WARNING: This feature is still experimental and may cause false
-positive warnings to appear. Therefore, try not to use this. If you find that
-it doesn't work properly (e.g. you see an unreasonable amount of warnings), I
-will be happy to take bug reports.
-
-Use the file ``/proc/sys/kernel/kmemcheck`` for this purpose, e.g.::
-
-       $ echo 0 > /proc/sys/kernel/kmemcheck # disables kmemcheck
-
-The numbers are the same as for the ``kmemcheck=`` command-line option.
-
-
-Debugging
-~~~~~~~~~
-
-A typical report will look something like this::
-
-    WARNING: kmemcheck: Caught 32-bit read from uninitialized memory (ffff88003e4a2024)
-    80000000000000000000000000000000000000000088ffff0000000000000000
-     i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
-             ^
-
-    Pid: 1856, comm: ntpdate Not tainted 2.6.29-rc5 #264 945P-A
-    RIP: 0010:[<ffffffff8104ede8>]  [<ffffffff8104ede8>] __dequeue_signal+0xc8/0x190
-    RSP: 0018:ffff88003cdf7d98  EFLAGS: 00210002
-    RAX: 0000000000000030 RBX: ffff88003d4ea968 RCX: 0000000000000009
-    RDX: ffff88003e5d6018 RSI: ffff88003e5d6024 RDI: ffff88003cdf7e84
-    RBP: ffff88003cdf7db8 R08: ffff88003e5d6000 R09: 0000000000000000
-    R10: 0000000000000080 R11: 0000000000000000 R12: 000000000000000e
-    R13: ffff88003cdf7e78 R14: ffff88003d530710 R15: ffff88003d5a98c8
-    FS:  0000000000000000(0000) GS:ffff880001982000(0063) knlGS:00000
-    CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
-    CR2: ffff88003f806ea0 CR3: 000000003c036000 CR4: 00000000000006a0
-    DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
-    DR3: 0000000000000000 DR6: 00000000ffff4ff0 DR7: 0000000000000400
-     [<ffffffff8104f04e>] dequeue_signal+0x8e/0x170
-     [<ffffffff81050bd8>] get_signal_to_deliver+0x98/0x390
-     [<ffffffff8100b87d>] do_notify_resume+0xad/0x7d0
-     [<ffffffff8100c7b5>] int_signal+0x12/0x17
-     [<ffffffffffffffff>] 0xffffffffffffffff
-
-The single most valuable information in this report is the RIP (or EIP on 32-
-bit) value. This will help us pinpoint exactly which instruction that caused
-the warning.
-
-If your kernel was compiled with ``CONFIG_DEBUG_INFO=y``, then all we have to do
-is give this address to the addr2line program, like this::
-
-       $ addr2line -e vmlinux -i ffffffff8104ede8
-       arch/x86/include/asm/string_64.h:12
-       include/asm-generic/siginfo.h:287
-       kernel/signal.c:380
-       kernel/signal.c:410
-
-The "``-e vmlinux``" tells addr2line which file to look in. **IMPORTANT:**
-This must be the vmlinux of the kernel that produced the warning in the
-first place! If not, the line number information will almost certainly be
-wrong.
-
-The "``-i``" tells addr2line to also print the line numbers of inlined
-functions.  In this case, the flag was very important, because otherwise,
-it would only have printed the first line, which is just a call to
-``memcpy()``, which could be called from a thousand places in the kernel, and
-is therefore not very useful.  These inlined functions would not show up in
-the stack trace above, simply because the kernel doesn't load the extra
-debugging information. This technique can of course be used with ordinary
-kernel oopses as well.
-
-In this case, it's the caller of ``memcpy()`` that is interesting, and it can be
-found in ``include/asm-generic/siginfo.h``, line 287::
-
-    281 static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
-    282 {
-    283         if (from->si_code < 0)
-    284                 memcpy(to, from, sizeof(*to));
-    285         else
-    286                 /* _sigchld is currently the largest know union member */
-    287                 memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
-    288 }
-
-Since this was a read (kmemcheck usually warns about reads only, though it can
-warn about writes to unallocated or freed memory as well), it was probably the
-"from" argument which contained some uninitialized bytes. Following the chain
-of calls, we move upwards to see where "from" was allocated or initialized,
-``kernel/signal.c``, line 380::
-
-    359 static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
-    360 {
-    ...
-    367         list_for_each_entry(q, &list->list, list) {
-    368                 if (q->info.si_signo == sig) {
-    369                         if (first)
-    370                                 goto still_pending;
-    371                         first = q;
-    ...
-    377         if (first) {
-    378 still_pending:
-    379                 list_del_init(&first->list);
-    380                 copy_siginfo(info, &first->info);
-    381                 __sigqueue_free(first);
-    ...
-    392         }
-    393 }
-
-Here, it is ``&first->info`` that is being passed on to ``copy_siginfo()``. The
-variable ``first`` was found on a list -- passed in as the second argument to
-``collect_signal()``. We  continue our journey through the stack, to figure out
-where the item on "list" was allocated or initialized. We move to line 410::
-
-    395 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
-    396                         siginfo_t *info)
-    397 {
-    ...
-    410                 collect_signal(sig, pending, info);
-    ...
-    414 }
-
-Now we need to follow the ``pending`` pointer, since that is being passed on to
-``collect_signal()`` as ``list``. At this point, we've run out of lines from the
-"addr2line" output. Not to worry, we just paste the next addresses from the
-kmemcheck stack dump, i.e.::
-
-     [<ffffffff8104f04e>] dequeue_signal+0x8e/0x170
-     [<ffffffff81050bd8>] get_signal_to_deliver+0x98/0x390
-     [<ffffffff8100b87d>] do_notify_resume+0xad/0x7d0
-     [<ffffffff8100c7b5>] int_signal+0x12/0x17
-
-       $ addr2line -e vmlinux -i ffffffff8104f04e ffffffff81050bd8 \
-               ffffffff8100b87d ffffffff8100c7b5
-       kernel/signal.c:446
-       kernel/signal.c:1806
-       arch/x86/kernel/signal.c:805
-       arch/x86/kernel/signal.c:871
-       arch/x86/kernel/entry_64.S:694
-
-Remember that since these addresses were found on the stack and not as the
-RIP value, they actually point to the _next_ instruction (they are return
-addresses). This becomes obvious when we look at the code for line 446::
-
-    422 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
-    423 {
-    ...
-    431                 signr = __dequeue_signal(&tsk->signal->shared_pending,
-    432                                                 mask, info);
-    433                        /*
-    434                         * itimer signal ?
-    435                         *
-    436                         * itimers are process shared and we restart periodic
-    437                         * itimers in the signal delivery path to prevent DoS
-    438                         * attacks in the high resolution timer case. This is
-    439                         * compliant with the old way of self restarting
-    440                         * itimers, as the SIGALRM is a legacy signal and only
-    441                         * queued once. Changing the restart behaviour to
-    442                         * restart the timer in the signal dequeue path is
-    443                         * reducing the timer noise on heavy loaded !highres
-    444                         * systems too.
-    445                         */
-    446                        if (unlikely(signr == SIGALRM)) {
-    ...
-    489 }
-
-So instead of looking at 446, we should be looking at 431, which is the line
-that executes just before 446. Here we see that what we are looking for is
-``&tsk->signal->shared_pending``.
-
-Our next task is now to figure out which function that puts items on this
-``shared_pending`` list. A crude, but efficient tool, is ``git grep``::
-
-       $ git grep -n 'shared_pending' kernel/
-       ...
-       kernel/signal.c:828:    pending = group ? &t->signal->shared_pending : &t->pending;
-       kernel/signal.c:1339:   pending = group ? &t->signal->shared_pending : &t->pending;
-       ...
-
-There were more results, but none of them were related to list operations,
-and these were the only assignments. We inspect the line numbers more closely
-and find that this is indeed where items are being added to the list::
-
-    816 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
-    817                                int group)
-    818 {
-    ...
-    828                pending = group ? &t->signal->shared_pending : &t->pending;
-    ...
-    851                q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
-    852                                                     (is_si_special(info) ||
-    853                                                      info->si_code >= 0)));
-    854                if (q) {
-    855                        list_add_tail(&q->list, &pending->list);
-    ...
-    890 }
-
-and::
-
-    1309 int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
-    1310 {
-    ....
-    1339        pending = group ? &t->signal->shared_pending : &t->pending;
-    1340        list_add_tail(&q->list, &pending->list);
-    ....
-    1347 }
-
-In the first case, the list element we are looking for, ``q``, is being
-returned from the function ``__sigqueue_alloc()``, which looks like an
-allocation function.  Let's take a look at it::
-
-    187 static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,
-    188                                                 int override_rlimit)
-    189 {
-    190                struct sigqueue *q = NULL;
-    191                struct user_struct *user;
-    192
-    193                /*
-    194                 * We won't get problems with the target's UID changing under us
-    195                 * because changing it requires RCU be used, and if t != current, the
-    196                 * caller must be holding the RCU readlock (by way of a spinlock) and
-    197                 * we use RCU protection here
-    198                 */
-    199                user = get_uid(__task_cred(t)->user);
-    200                atomic_inc(&user->sigpending);
-    201                if (override_rlimit ||
-    202                    atomic_read(&user->sigpending) <=
-    203                                t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
-    204                        q = kmem_cache_alloc(sigqueue_cachep, flags);
-    205                if (unlikely(q == NULL)) {
-    206                        atomic_dec(&user->sigpending);
-    207                        free_uid(user);
-    208                } else {
-    209                        INIT_LIST_HEAD(&q->list);
-    210                        q->flags = 0;
-    211                        q->user = user;
-    212                }
-    213
-    214                return q;
-    215 }
-
-We see that this function initializes ``q->list``, ``q->flags``, and
-``q->user``. It seems that now is the time to look at the definition of
-``struct sigqueue``, e.g.::
-
-    14 struct sigqueue {
-    15        struct list_head list;
-    16        int flags;
-    17        siginfo_t info;
-    18        struct user_struct *user;
-    19 };
-
-And, you might remember, it was a ``memcpy()`` on ``&first->info`` that
-caused the warning, so this makes perfect sense. It also seems reasonable
-to assume that it is the caller of ``__sigqueue_alloc()`` that has the
-responsibility of filling out (initializing) this member.
-
-But just which fields of the struct were uninitialized? Let's look at
-kmemcheck's report again::
-
-    WARNING: kmemcheck: Caught 32-bit read from uninitialized memory (ffff88003e4a2024)
-    80000000000000000000000000000000000000000088ffff0000000000000000
-     i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
-            ^
-
-These first two lines are the memory dump of the memory object itself, and
-the shadow bytemap, respectively. The memory object itself is in this case
-``&first->info``. Just beware that the start of this dump is NOT the start
-of the object itself! The position of the caret (^) corresponds with the
-address of the read (ffff88003e4a2024).
-
-The shadow bytemap dump legend is as follows:
-
-- i: initialized
-- u: uninitialized
-- a: unallocated (memory has been allocated by the slab layer, but has not
-  yet been handed off to anybody)
-- f: freed (memory has been allocated by the slab layer, but has been freed
-  by the previous owner)
-
-In order to figure out where (relative to the start of the object) the
-uninitialized memory was located, we have to look at the disassembly. For
-that, we'll need the RIP address again::
-
-    RIP: 0010:[<ffffffff8104ede8>]  [<ffffffff8104ede8>] __dequeue_signal+0xc8/0x190
-
-       $ objdump -d --no-show-raw-insn vmlinux | grep -C 8 ffffffff8104ede8:
-       ffffffff8104edc8:       mov    %r8,0x8(%r8)
-       ffffffff8104edcc:       test   %r10d,%r10d
-       ffffffff8104edcf:       js     ffffffff8104ee88 <__dequeue_signal+0x168>
-       ffffffff8104edd5:       mov    %rax,%rdx
-       ffffffff8104edd8:       mov    $0xc,%ecx
-       ffffffff8104eddd:       mov    %r13,%rdi
-       ffffffff8104ede0:       mov    $0x30,%eax
-       ffffffff8104ede5:       mov    %rdx,%rsi
-       ffffffff8104ede8:       rep movsl %ds:(%rsi),%es:(%rdi)
-       ffffffff8104edea:       test   $0x2,%al
-       ffffffff8104edec:       je     ffffffff8104edf0 <__dequeue_signal+0xd0>
-       ffffffff8104edee:       movsw  %ds:(%rsi),%es:(%rdi)
-       ffffffff8104edf0:       test   $0x1,%al
-       ffffffff8104edf2:       je     ffffffff8104edf5 <__dequeue_signal+0xd5>
-       ffffffff8104edf4:       movsb  %ds:(%rsi),%es:(%rdi)
-       ffffffff8104edf5:       mov    %r8,%rdi
-       ffffffff8104edf8:       callq  ffffffff8104de60 <__sigqueue_free>
-
-As expected, it's the "``rep movsl``" instruction from the ``memcpy()``
-that causes the warning. We know about ``REP MOVSL`` that it uses the register
-``RCX`` to count the number of remaining iterations. By taking a look at the
-register dump again (from the kmemcheck report), we can figure out how many
-bytes were left to copy::
-
-    RAX: 0000000000000030 RBX: ffff88003d4ea968 RCX: 0000000000000009
-
-By looking at the disassembly, we also see that ``%ecx`` is being loaded
-with the value ``$0xc`` just before (ffffffff8104edd8), so we are very
-lucky. Keep in mind that this is the number of iterations, not bytes. And
-since this is a "long" operation, we need to multiply by 4 to get the
-number of bytes. So this means that the uninitialized value was encountered
-at 4 * (0xc - 0x9) = 12 bytes from the start of the object.
-
-We can now try to figure out which field of the "``struct siginfo``" that
-was not initialized. This is the beginning of the struct::
-
-    40 typedef struct siginfo {
-    41        int si_signo;
-    42        int si_errno;
-    43        int si_code;
-    44
-    45        union {
-    ..
-    92        } _sifields;
-    93 } siginfo_t;
-
-On 64-bit, the int is 4 bytes long, so it must the union member that has
-not been initialized. We can verify this using gdb::
-
-       $ gdb vmlinux
-       ...
-       (gdb) p &((struct siginfo *) 0)->_sifields
-       $1 = (union {...} *) 0x10
-
-Actually, it seems that the union member is located at offset 0x10 -- which
-means that gcc has inserted 4 bytes of padding between the members ``si_code``
-and ``_sifields``. We can now get a fuller picture of the memory dump::
-
-                _----------------------------=> si_code
-               /        _--------------------=> (padding)
-              |        /        _------------=> _sifields(._kill._pid)
-              |       |        /        _----=> _sifields(._kill._uid)
-              |       |       |        /
-       -------|-------|-------|-------|
-       80000000000000000000000000000000000000000088ffff0000000000000000
-        i i i i u u u u i i i i i i i i u u u u u u u u u u u u u u u u
-
-This allows us to realize another important fact: ``si_code`` contains the
-value 0x80. Remember that x86 is little endian, so the first 4 bytes
-"80000000" are really the number 0x00000080. With a bit of research, we
-find that this is actually the constant ``SI_KERNEL`` defined in
-``include/asm-generic/siginfo.h``::
-
-    144 #define SI_KERNEL      0x80            /* sent by the kernel from somewhere     */
-
-This macro is used in exactly one place in the x86 kernel: In ``send_signal()``
-in ``kernel/signal.c``::
-
-    816 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
-    817                                int group)
-    818 {
-    ...
-    828                pending = group ? &t->signal->shared_pending : &t->pending;
-    ...
-    851                q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
-    852                                                     (is_si_special(info) ||
-    853                                                      info->si_code >= 0)));
-    854                if (q) {
-    855                        list_add_tail(&q->list, &pending->list);
-    856                        switch ((unsigned long) info) {
-    ...
-    865                        case (unsigned long) SEND_SIG_PRIV:
-    866                                q->info.si_signo = sig;
-    867                                q->info.si_errno = 0;
-    868                                q->info.si_code = SI_KERNEL;
-    869                                q->info.si_pid = 0;
-    870                                q->info.si_uid = 0;
-    871                                break;
-    ...
-    890 }
-
-Not only does this match with the ``.si_code`` member, it also matches the place
-we found earlier when looking for where siginfo_t objects are enqueued on the
-``shared_pending`` list.
-
-So to sum up: It seems that it is the padding introduced by the compiler
-between two struct fields that is uninitialized, and this gets reported when
-we do a ``memcpy()`` on the struct. This means that we have identified a false
-positive warning.
-
-Normally, kmemcheck will not report uninitialized accesses in ``memcpy()`` calls
-when both the source and destination addresses are tracked. (Instead, we copy
-the shadow bytemap as well). In this case, the destination address clearly
-was not tracked. We can dig a little deeper into the stack trace from above::
-
-       arch/x86/kernel/signal.c:805
-       arch/x86/kernel/signal.c:871
-       arch/x86/kernel/entry_64.S:694
-
-And we clearly see that the destination siginfo object is located on the
-stack::
-
-    782 static void do_signal(struct pt_regs *regs)
-    783 {
-    784                struct k_sigaction ka;
-    785                siginfo_t info;
-    ...
-    804                signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-    ...
-    854 }
-
-And this ``&info`` is what eventually gets passed to ``copy_siginfo()`` as the
-destination argument.
-
-Now, even though we didn't find an actual error here, the example is still a
-good one, because it shows how one would go about to find out what the report
-was all about.
-
-
-Annotating false positives
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are a few different ways to make annotations in the source code that
-will keep kmemcheck from checking and reporting certain allocations. Here
-they are:
-
-- ``__GFP_NOTRACK_FALSE_POSITIVE``
-       This flag can be passed to ``kmalloc()`` or ``kmem_cache_alloc()``
-       (therefore also to other functions that end up calling one of
-       these) to indicate that the allocation should not be tracked
-       because it would lead to a false positive report. This is a "big
-       hammer" way of silencing kmemcheck; after all, even if the false
-       positive pertains to particular field in a struct, for example, we
-       will now lose the ability to find (real) errors in other parts of
-       the same struct.
-
-       Example::
-
-           /* No warnings will ever trigger on accessing any part of x */
-           x = kmalloc(sizeof *x, GFP_KERNEL | __GFP_NOTRACK_FALSE_POSITIVE);
-
-- ``kmemcheck_bitfield_begin(name)``/``kmemcheck_bitfield_end(name)`` and
-       ``kmemcheck_annotate_bitfield(ptr, name)``
-       The first two of these three macros can be used inside struct
-       definitions to signal, respectively, the beginning and end of a
-       bitfield. Additionally, this will assign the bitfield a name, which
-       is given as an argument to the macros.
-
-       Having used these markers, one can later use
-       kmemcheck_annotate_bitfield() at the point of allocation, to indicate
-       which parts of the allocation is part of a bitfield.
-
-       Example::
-
-           struct foo {
-               int x;
-
-               kmemcheck_bitfield_begin(flags);
-               int flag_a:1;
-               int flag_b:1;
-               kmemcheck_bitfield_end(flags);
-
-               int y;
-           };
-
-           struct foo *x = kmalloc(sizeof *x);
-
-           /* No warnings will trigger on accessing the bitfield of x */
-           kmemcheck_annotate_bitfield(x, flags);
-
-       Note that ``kmemcheck_annotate_bitfield()`` can be used even before the
-       return value of ``kmalloc()`` is checked -- in other words, passing NULL
-       as the first argument is legal (and will do nothing).
-
-
-Reporting errors
-----------------
-
-As we have seen, kmemcheck will produce false positive reports. Therefore, it
-is not very wise to blindly post kmemcheck warnings to mailing lists and
-maintainers. Instead, I encourage maintainers and developers to find errors
-in their own code. If you get a warning, you can try to work around it, try
-to figure out if it's a real error or not, or simply ignore it. Most
-developers know their own code and will quickly and efficiently determine the
-root cause of a kmemcheck report. This is therefore also the most efficient
-way to work with kmemcheck.
-
-That said, we (the kmemcheck maintainers) will always be on the lookout for
-false positives that we can annotate and silence. So whatever you find,
-please drop us a note privately! Kernel configs and steps to reproduce (if
-available) are of course a great help too.
-
-Happy hacking!
-
-
-Technical description
----------------------
-
-kmemcheck works by marking memory pages non-present. This means that whenever
-somebody attempts to access the page, a page fault is generated. The page
-fault handler notices that the page was in fact only hidden, and so it calls
-on the kmemcheck code to make further investigations.
-
-When the investigations are completed, kmemcheck "shows" the page by marking
-it present (as it would be under normal circumstances). This way, the
-interrupted code can continue as usual.
-
-But after the instruction has been executed, we should hide the page again, so
-that we can catch the next access too! Now kmemcheck makes use of a debugging
-feature of the processor, namely single-stepping. When the processor has
-finished the one instruction that generated the memory access, a debug
-exception is raised. From here, we simply hide the page again and continue
-execution, this time with the single-stepping feature turned off.
-
-kmemcheck requires some assistance from the memory allocator in order to work.
-The memory allocator needs to
-
-  1. Tell kmemcheck about newly allocated pages and pages that are about to
-     be freed. This allows kmemcheck to set up and tear down the shadow memory
-     for the pages in question. The shadow memory stores the status of each
-     byte in the allocation proper, e.g. whether it is initialized or
-     uninitialized.
-
-  2. Tell kmemcheck which parts of memory should be marked uninitialized.
-     There are actually a few more states, such as "not yet allocated" and
-     "recently freed".
-
-If a slab cache is set up using the SLAB_NOTRACK flag, it will never return
-memory that can take page faults because of kmemcheck.
-
-If a slab cache is NOT set up using the SLAB_NOTRACK flag, callers can still
-request memory with the __GFP_NOTRACK or __GFP_NOTRACK_FALSE_POSITIVE flags.
-This does not prevent the page faults from occurring, however, but marks the
-object in question as being initialized so that no warnings will ever be
-produced for this object.
-
-Currently, the SLAB and SLUB allocators are supported by kmemcheck.
index 7e9c887ad951215464705d112377e4e2266a9d76..ac814d3dd1c1d97a614e086f4ea2fcd58178a03a 100644 (file)
@@ -7688,16 +7688,6 @@ F:       include/linux/kdb.h
 F:     include/linux/kgdb.h
 F:     kernel/debug/
 
-KMEMCHECK
-M:     Vegard Nossum <vegardno@ifi.uio.no>
-M:     Pekka Enberg <penberg@kernel.org>
-S:     Maintained
-F:     Documentation/dev-tools/kmemcheck.rst
-F:     arch/x86/include/asm/kmemcheck.h
-F:     arch/x86/mm/kmemcheck/
-F:     include/linux/kmemcheck.h
-F:     mm/kmemcheck.c
-
 KMEMLEAK
 M:     Catalin Marinas <catalin.marinas@arm.com>
 S:     Maintained
index f08977d82ca0dd2cb49ee4798b45245fa1b5999c..cb678192da4a41ff8bf0c6bdddadf720d77f8735 100644 (file)
@@ -112,7 +112,6 @@ config X86
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_KASAN                  if X86_64 && SPARSEMEM_VMEMMAP
        select HAVE_ARCH_KGDB
-       select HAVE_ARCH_KMEMCHECK
        select HAVE_ARCH_MMAP_RND_BITS          if MMU
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS   if MMU && COMPAT
        select HAVE_ARCH_COMPAT_MMAP_BASES      if MMU && COMPAT
@@ -1430,7 +1429,7 @@ config ARCH_DMA_ADDR_T_64BIT
 
 config X86_DIRECT_GBPAGES
        def_bool y
-       depends on X86_64 && !DEBUG_PAGEALLOC && !KMEMCHECK
+       depends on X86_64 && !DEBUG_PAGEALLOC
        ---help---
          Certain kernel features effectively disable kernel
          linear 1 GB mappings (even if the CPU otherwise
index 945a0337fbcf54c8da8eb5ee49916886704e3947..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,43 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ASM_X86_KMEMCHECK_H
-#define ASM_X86_KMEMCHECK_H
-
-#include <linux/types.h>
-#include <asm/ptrace.h>
-
-#ifdef CONFIG_KMEMCHECK
-bool kmemcheck_active(struct pt_regs *regs);
-
-void kmemcheck_show(struct pt_regs *regs);
-void kmemcheck_hide(struct pt_regs *regs);
-
-bool kmemcheck_fault(struct pt_regs *regs,
-       unsigned long address, unsigned long error_code);
-bool kmemcheck_trap(struct pt_regs *regs);
-#else
-static inline bool kmemcheck_active(struct pt_regs *regs)
-{
-       return false;
-}
-
-static inline void kmemcheck_show(struct pt_regs *regs)
-{
-}
-
-static inline void kmemcheck_hide(struct pt_regs *regs)
-{
-}
-
-static inline bool kmemcheck_fault(struct pt_regs *regs,
-       unsigned long address, unsigned long error_code)
-{
-       return false;
-}
-
-static inline bool kmemcheck_trap(struct pt_regs *regs)
-{
-       return false;
-}
-#endif /* CONFIG_KMEMCHECK */
-
-#endif
index 076502241eae19f82b23e08731856cfd31a29620..55d392c6bd29b3aae8034061ddc7c094fe0cf6fe 100644 (file)
@@ -179,8 +179,6 @@ static inline void *__memcpy3d(void *to, const void *from, size_t len)
  *     No 3D Now!
  */
 
-#ifndef CONFIG_KMEMCHECK
-
 #if (__GNUC__ >= 4)
 #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
 #else
@@ -189,13 +187,6 @@ static inline void *__memcpy3d(void *to, const void *from, size_t len)
         ? __constant_memcpy((t), (f), (n))     \
         : __memcpy((t), (f), (n)))
 #endif
-#else
-/*
- * kmemcheck becomes very happy if we use the REP instructions unconditionally,
- * because it means that we know both memory operands in advance.
- */
-#define memcpy(t, f, n) __memcpy((t), (f), (n))
-#endif
 
 #endif
 #endif /* !CONFIG_FORTIFY_SOURCE */
index 0b1b4445f4c5af048eacb41363c06925e2652f5c..533f74c300c254c7008b508e8262c341a13c90e5 100644 (file)
@@ -33,7 +33,6 @@ extern void *memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 
 #ifndef CONFIG_FORTIFY_SOURCE
-#ifndef CONFIG_KMEMCHECK
 #if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
 #define memcpy(dst, src, len)                                  \
 ({                                                             \
@@ -46,13 +45,6 @@ extern void *__memcpy(void *to, const void *from, size_t len);
        __ret;                                                  \
 })
 #endif
-#else
-/*
- * kmemcheck becomes very happy if we use the REP instructions unconditionally,
- * because it means that we know both memory operands in advance.
- */
-#define memcpy(dst, src, len) __inline_memcpy((dst), (src), (len))
-#endif
 #endif /* !CONFIG_FORTIFY_SOURCE */
 
 #define __HAVE_ARCH_MEMSET
index b720dacac0519568405ab07fbce1217422328527..b1af22073e28cd59e773518a5f32f947287b5567 100644 (file)
@@ -187,21 +187,6 @@ static void early_init_intel(struct cpuinfo_x86 *c)
        if (c->x86 == 6 && c->x86_model < 15)
                clear_cpu_cap(c, X86_FEATURE_PAT);
 
-#ifdef CONFIG_KMEMCHECK
-       /*
-        * P4s have a "fast strings" feature which causes single-
-        * stepping REP instructions to only generate a #DB on
-        * cache-line boundaries.
-        *
-        * Ingo Molnar reported a Pentium D (model 6) and a Xeon
-        * (model 2) with the same problem.
-        */
-       if (c->x86 == 15)
-               if (msr_clear_bit(MSR_IA32_MISC_ENABLE,
-                                 MSR_IA32_MISC_ENABLE_FAST_STRING_BIT) > 0)
-                       pr_info("kmemcheck: Disabling fast string operations\n");
-#endif
-
        /*
         * If fast string is not enabled in IA32_MISC_ENABLE for any reason,
         * clear the fast string and enhanced fast string CPU capabilities.
index 7ba7f3d7f477582516a9375f9a7d189e7249493d..8e13b8cc6bedb0dc84eea64cd80ca6ae39037eaa 100644 (file)
@@ -29,8 +29,6 @@ obj-$(CONFIG_X86_PTDUMP)      += debug_pagetables.o
 
 obj-$(CONFIG_HIGHMEM)          += highmem_32.o
 
-obj-$(CONFIG_KMEMCHECK)                += kmemcheck/
-
 KASAN_SANITIZE_kasan_init_$(BITS).o := n
 obj-$(CONFIG_KASAN)            += kasan_init_$(BITS).o
 
index ef94620ceb8a32baeb6db02e28bd5247419e9158..6fdf91ef130a4737ab434ce98f77b2583fe1840d 100644 (file)
@@ -163,12 +163,11 @@ static int page_size_mask;
 static void __init probe_page_size_mask(void)
 {
        /*
-        * For CONFIG_KMEMCHECK or pagealloc debugging, identity mapping will
-        * use small pages.
+        * For pagealloc debugging, identity mapping will use small pages.
         * This will simplify cpa(), which otherwise needs to support splitting
         * large pages into small in interrupt context, etc.
         */
-       if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled() && !IS_ENABLED(CONFIG_KMEMCHECK))
+       if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled())
                page_size_mask |= 1 << PG_LEVEL_2M;
        else
                direct_gbpages = 0;
diff --git a/arch/x86/mm/kmemcheck/Makefile b/arch/x86/mm/kmemcheck/Makefile
deleted file mode 100644 (file)
index 520b3bc..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-y := error.o kmemcheck.o opcode.o pte.o selftest.o shadow.o
index 872ec4159a68fb8378066a67c1818300d029b2aa..cec5940325151e407aa90128a35cb683afd436d7 100644 (file)
@@ -1,228 +1 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/interrupt.h>
-#include <linux/kdebug.h>
-#include <linux/kmemcheck.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/stacktrace.h>
-#include <linux/string.h>
-
-#include "error.h"
-#include "shadow.h"
-
-enum kmemcheck_error_type {
-       KMEMCHECK_ERROR_INVALID_ACCESS,
-       KMEMCHECK_ERROR_BUG,
-};
-
-#define SHADOW_COPY_SIZE (1 << CONFIG_KMEMCHECK_SHADOW_COPY_SHIFT)
-
-struct kmemcheck_error {
-       enum kmemcheck_error_type type;
-
-       union {
-               /* KMEMCHECK_ERROR_INVALID_ACCESS */
-               struct {
-                       /* Kind of access that caused the error */
-                       enum kmemcheck_shadow state;
-                       /* Address and size of the erroneous read */
-                       unsigned long   address;
-                       unsigned int    size;
-               };
-       };
-
-       struct pt_regs          regs;
-       struct stack_trace      trace;
-       unsigned long           trace_entries[32];
-
-       /* We compress it to a char. */
-       unsigned char           shadow_copy[SHADOW_COPY_SIZE];
-       unsigned char           memory_copy[SHADOW_COPY_SIZE];
-};
-
-/*
- * Create a ring queue of errors to output. We can't call printk() directly
- * from the kmemcheck traps, since this may call the console drivers and
- * result in a recursive fault.
- */
-static struct kmemcheck_error error_fifo[CONFIG_KMEMCHECK_QUEUE_SIZE];
-static unsigned int error_count;
-static unsigned int error_rd;
-static unsigned int error_wr;
-static unsigned int error_missed_count;
-
-static struct kmemcheck_error *error_next_wr(void)
-{
-       struct kmemcheck_error *e;
-
-       if (error_count == ARRAY_SIZE(error_fifo)) {
-               ++error_missed_count;
-               return NULL;
-       }
-
-       e = &error_fifo[error_wr];
-       if (++error_wr == ARRAY_SIZE(error_fifo))
-               error_wr = 0;
-       ++error_count;
-       return e;
-}
-
-static struct kmemcheck_error *error_next_rd(void)
-{
-       struct kmemcheck_error *e;
-
-       if (error_count == 0)
-               return NULL;
-
-       e = &error_fifo[error_rd];
-       if (++error_rd == ARRAY_SIZE(error_fifo))
-               error_rd = 0;
-       --error_count;
-       return e;
-}
-
-void kmemcheck_error_recall(void)
-{
-       static const char *desc[] = {
-               [KMEMCHECK_SHADOW_UNALLOCATED]          = "unallocated",
-               [KMEMCHECK_SHADOW_UNINITIALIZED]        = "uninitialized",
-               [KMEMCHECK_SHADOW_INITIALIZED]          = "initialized",
-               [KMEMCHECK_SHADOW_FREED]                = "freed",
-       };
-
-       static const char short_desc[] = {
-               [KMEMCHECK_SHADOW_UNALLOCATED]          = 'a',
-               [KMEMCHECK_SHADOW_UNINITIALIZED]        = 'u',
-               [KMEMCHECK_SHADOW_INITIALIZED]          = 'i',
-               [KMEMCHECK_SHADOW_FREED]                = 'f',
-       };
-
-       struct kmemcheck_error *e;
-       unsigned int i;
-
-       e = error_next_rd();
-       if (!e)
-               return;
-
-       switch (e->type) {
-       case KMEMCHECK_ERROR_INVALID_ACCESS:
-               printk(KERN_WARNING "WARNING: kmemcheck: Caught %d-bit read from %s memory (%p)\n",
-                       8 * e->size, e->state < ARRAY_SIZE(desc) ?
-                               desc[e->state] : "(invalid shadow state)",
-                       (void *) e->address);
-
-               printk(KERN_WARNING);
-               for (i = 0; i < SHADOW_COPY_SIZE; ++i)
-                       printk(KERN_CONT "%02x", e->memory_copy[i]);
-               printk(KERN_CONT "\n");
-
-               printk(KERN_WARNING);
-               for (i = 0; i < SHADOW_COPY_SIZE; ++i) {
-                       if (e->shadow_copy[i] < ARRAY_SIZE(short_desc))
-                               printk(KERN_CONT " %c", short_desc[e->shadow_copy[i]]);
-                       else
-                               printk(KERN_CONT " ?");
-               }
-               printk(KERN_CONT "\n");
-               printk(KERN_WARNING "%*c\n", 2 + 2
-                       * (int) (e->address & (SHADOW_COPY_SIZE - 1)), '^');
-               break;
-       case KMEMCHECK_ERROR_BUG:
-               printk(KERN_EMERG "ERROR: kmemcheck: Fatal error\n");
-               break;
-       }
-
-       __show_regs(&e->regs, 1);
-       print_stack_trace(&e->trace, 0);
-}
-
-static void do_wakeup(unsigned long data)
-{
-       while (error_count > 0)
-               kmemcheck_error_recall();
-
-       if (error_missed_count > 0) {
-               printk(KERN_WARNING "kmemcheck: Lost %d error reports because "
-                       "the queue was too small\n", error_missed_count);
-               error_missed_count = 0;
-       }
-}
-
-static DECLARE_TASKLET(kmemcheck_tasklet, &do_wakeup, 0);
-
-/*
- * Save the context of an error report.
- */
-void kmemcheck_error_save(enum kmemcheck_shadow state,
-       unsigned long address, unsigned int size, struct pt_regs *regs)
-{
-       static unsigned long prev_ip;
-
-       struct kmemcheck_error *e;
-       void *shadow_copy;
-       void *memory_copy;
-
-       /* Don't report several adjacent errors from the same EIP. */
-       if (regs->ip == prev_ip)
-               return;
-       prev_ip = regs->ip;
-
-       e = error_next_wr();
-       if (!e)
-               return;
-
-       e->type = KMEMCHECK_ERROR_INVALID_ACCESS;
-
-       e->state = state;
-       e->address = address;
-       e->size = size;
-
-       /* Save regs */
-       memcpy(&e->regs, regs, sizeof(*regs));
-
-       /* Save stack trace */
-       e->trace.nr_entries = 0;
-       e->trace.entries = e->trace_entries;
-       e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
-       e->trace.skip = 0;
-       save_stack_trace_regs(regs, &e->trace);
-
-       /* Round address down to nearest 16 bytes */
-       shadow_copy = kmemcheck_shadow_lookup(address
-               & ~(SHADOW_COPY_SIZE - 1));
-       BUG_ON(!shadow_copy);
-
-       memcpy(e->shadow_copy, shadow_copy, SHADOW_COPY_SIZE);
-
-       kmemcheck_show_addr(address);
-       memory_copy = (void *) (address & ~(SHADOW_COPY_SIZE - 1));
-       memcpy(e->memory_copy, memory_copy, SHADOW_COPY_SIZE);
-       kmemcheck_hide_addr(address);
-
-       tasklet_hi_schedule_first(&kmemcheck_tasklet);
-}
-
-/*
- * Save the context of a kmemcheck bug.
- */
-void kmemcheck_error_save_bug(struct pt_regs *regs)
-{
-       struct kmemcheck_error *e;
-
-       e = error_next_wr();
-       if (!e)
-               return;
-
-       e->type = KMEMCHECK_ERROR_BUG;
-
-       memcpy(&e->regs, regs, sizeof(*regs));
-
-       e->trace.nr_entries = 0;
-       e->trace.entries = e->trace_entries;
-       e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
-       e->trace.skip = 1;
-       save_stack_trace(&e->trace);
-
-       tasklet_hi_schedule_first(&kmemcheck_tasklet);
-}
index 39f80d7a874de97ee0b54ef68f117699e47ee7dc..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,16 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH__X86__MM__KMEMCHECK__ERROR_H
-#define ARCH__X86__MM__KMEMCHECK__ERROR_H
-
-#include <linux/ptrace.h>
-
-#include "shadow.h"
-
-void kmemcheck_error_save(enum kmemcheck_shadow state,
-       unsigned long address, unsigned int size, struct pt_regs *regs);
-
-void kmemcheck_error_save_bug(struct pt_regs *regs);
-
-void kmemcheck_error_recall(void);
-
-#endif
diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c
deleted file mode 100644 (file)
index 4515bae..0000000
+++ /dev/null
@@ -1,658 +0,0 @@
-/**
- * kmemcheck - a heavyweight memory checker for the linux kernel
- * Copyright (C) 2007, 2008  Vegard Nossum <vegardno@ifi.uio.no>
- * (With a lot of help from Ingo Molnar and Pekka Enberg.)
- *
- * 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.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kallsyms.h>
-#include <linux/kernel.h>
-#include <linux/kmemcheck.h>
-#include <linux/mm.h>
-#include <linux/page-flags.h>
-#include <linux/percpu.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <asm/cacheflush.h>
-#include <asm/kmemcheck.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-
-#include "error.h"
-#include "opcode.h"
-#include "pte.h"
-#include "selftest.h"
-#include "shadow.h"
-
-
-#ifdef CONFIG_KMEMCHECK_DISABLED_BY_DEFAULT
-#  define KMEMCHECK_ENABLED 0
-#endif
-
-#ifdef CONFIG_KMEMCHECK_ENABLED_BY_DEFAULT
-#  define KMEMCHECK_ENABLED 1
-#endif
-
-#ifdef CONFIG_KMEMCHECK_ONESHOT_BY_DEFAULT
-#  define KMEMCHECK_ENABLED 2
-#endif
-
-int kmemcheck_enabled = KMEMCHECK_ENABLED;
-
-int __init kmemcheck_init(void)
-{
-#ifdef CONFIG_SMP
-       /*
-        * Limit SMP to use a single CPU. We rely on the fact that this code
-        * runs before SMP is set up.
-        */
-       if (setup_max_cpus > 1) {
-               printk(KERN_INFO
-                       "kmemcheck: Limiting number of CPUs to 1.\n");
-               setup_max_cpus = 1;
-       }
-#endif
-
-       if (!kmemcheck_selftest()) {
-               printk(KERN_INFO "kmemcheck: self-tests failed; disabling\n");
-               kmemcheck_enabled = 0;
-               return -EINVAL;
-       }
-
-       printk(KERN_INFO "kmemcheck: Initialized\n");
-       return 0;
-}
-
-early_initcall(kmemcheck_init);
-
-/*
- * We need to parse the kmemcheck= option before any memory is allocated.
- */
-static int __init param_kmemcheck(char *str)
-{
-       int val;
-       int ret;
-
-       if (!str)
-               return -EINVAL;
-
-       ret = kstrtoint(str, 0, &val);
-       if (ret)
-               return ret;
-       kmemcheck_enabled = val;
-       return 0;
-}
-
-early_param("kmemcheck", param_kmemcheck);
-
-int kmemcheck_show_addr(unsigned long address)
-{
-       pte_t *pte;
-
-       pte = kmemcheck_pte_lookup(address);
-       if (!pte)
-               return 0;
-
-       set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
-       __flush_tlb_one(address);
-       return 1;
-}
-
-int kmemcheck_hide_addr(unsigned long address)
-{
-       pte_t *pte;
-
-       pte = kmemcheck_pte_lookup(address);
-       if (!pte)
-               return 0;
-
-       set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
-       __flush_tlb_one(address);
-       return 1;
-}
-
-struct kmemcheck_context {
-       bool busy;
-       int balance;
-
-       /*
-        * There can be at most two memory operands to an instruction, but
-        * each address can cross a page boundary -- so we may need up to
-        * four addresses that must be hidden/revealed for each fault.
-        */
-       unsigned long addr[4];
-       unsigned long n_addrs;
-       unsigned long flags;
-
-       /* Data size of the instruction that caused a fault. */
-       unsigned int size;
-};
-
-static DEFINE_PER_CPU(struct kmemcheck_context, kmemcheck_context);
-
-bool kmemcheck_active(struct pt_regs *regs)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-
-       return data->balance > 0;
-}
-
-/* Save an address that needs to be shown/hidden */
-static void kmemcheck_save_addr(unsigned long addr)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-
-       BUG_ON(data->n_addrs >= ARRAY_SIZE(data->addr));
-       data->addr[data->n_addrs++] = addr;
-}
-
-static unsigned int kmemcheck_show_all(void)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-       unsigned int i;
-       unsigned int n;
-
-       n = 0;
-       for (i = 0; i < data->n_addrs; ++i)
-               n += kmemcheck_show_addr(data->addr[i]);
-
-       return n;
-}
-
-static unsigned int kmemcheck_hide_all(void)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-       unsigned int i;
-       unsigned int n;
-
-       n = 0;
-       for (i = 0; i < data->n_addrs; ++i)
-               n += kmemcheck_hide_addr(data->addr[i]);
-
-       return n;
-}
-
-/*
- * Called from the #PF handler.
- */
-void kmemcheck_show(struct pt_regs *regs)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-
-       BUG_ON(!irqs_disabled());
-
-       if (unlikely(data->balance != 0)) {
-               kmemcheck_show_all();
-               kmemcheck_error_save_bug(regs);
-               data->balance = 0;
-               return;
-       }
-
-       /*
-        * None of the addresses actually belonged to kmemcheck. Note that
-        * this is not an error.
-        */
-       if (kmemcheck_show_all() == 0)
-               return;
-
-       ++data->balance;
-
-       /*
-        * The IF needs to be cleared as well, so that the faulting
-        * instruction can run "uninterrupted". Otherwise, we might take
-        * an interrupt and start executing that before we've had a chance
-        * to hide the page again.
-        *
-        * NOTE: In the rare case of multiple faults, we must not override
-        * the original flags:
-        */
-       if (!(regs->flags & X86_EFLAGS_TF))
-               data->flags = regs->flags;
-
-       regs->flags |= X86_EFLAGS_TF;
-       regs->flags &= ~X86_EFLAGS_IF;
-}
-
-/*
- * Called from the #DB handler.
- */
-void kmemcheck_hide(struct pt_regs *regs)
-{
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-       int n;
-
-       BUG_ON(!irqs_disabled());
-
-       if (unlikely(data->balance != 1)) {
-               kmemcheck_show_all();
-               kmemcheck_error_save_bug(regs);
-               data->n_addrs = 0;
-               data->balance = 0;
-
-               if (!(data->flags & X86_EFLAGS_TF))
-                       regs->flags &= ~X86_EFLAGS_TF;
-               if (data->flags & X86_EFLAGS_IF)
-                       regs->flags |= X86_EFLAGS_IF;
-               return;
-       }
-
-       if (kmemcheck_enabled)
-               n = kmemcheck_hide_all();
-       else
-               n = kmemcheck_show_all();
-
-       if (n == 0)
-               return;
-
-       --data->balance;
-
-       data->n_addrs = 0;
-
-       if (!(data->flags & X86_EFLAGS_TF))
-               regs->flags &= ~X86_EFLAGS_TF;
-       if (data->flags & X86_EFLAGS_IF)
-               regs->flags |= X86_EFLAGS_IF;
-}
-
-void kmemcheck_show_pages(struct page *p, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 0; i < n; ++i) {
-               unsigned long address;
-               pte_t *pte;
-               unsigned int level;
-
-               address = (unsigned long) page_address(&p[i]);
-               pte = lookup_address(address, &level);
-               BUG_ON(!pte);
-               BUG_ON(level != PG_LEVEL_4K);
-
-               set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT));
-               set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_HIDDEN));
-               __flush_tlb_one(address);
-       }
-}
-
-bool kmemcheck_page_is_tracked(struct page *p)
-{
-       /* This will also check the "hidden" flag of the PTE. */
-       return kmemcheck_pte_lookup((unsigned long) page_address(p));
-}
-
-void kmemcheck_hide_pages(struct page *p, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 0; i < n; ++i) {
-               unsigned long address;
-               pte_t *pte;
-               unsigned int level;
-
-               address = (unsigned long) page_address(&p[i]);
-               pte = lookup_address(address, &level);
-               BUG_ON(!pte);
-               BUG_ON(level != PG_LEVEL_4K);
-
-               set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_PRESENT));
-               set_pte(pte, __pte(pte_val(*pte) | _PAGE_HIDDEN));
-               __flush_tlb_one(address);
-       }
-}
-
-/* Access may NOT cross page boundary */
-static void kmemcheck_read_strict(struct pt_regs *regs,
-       unsigned long addr, unsigned int size)
-{
-       void *shadow;
-       enum kmemcheck_shadow status;
-
-       shadow = kmemcheck_shadow_lookup(addr);
-       if (!shadow)
-               return;
-
-       kmemcheck_save_addr(addr);
-       status = kmemcheck_shadow_test(shadow, size);
-       if (status == KMEMCHECK_SHADOW_INITIALIZED)
-               return;
-
-       if (kmemcheck_enabled)
-               kmemcheck_error_save(status, addr, size, regs);
-
-       if (kmemcheck_enabled == 2)
-               kmemcheck_enabled = 0;
-
-       /* Don't warn about it again. */
-       kmemcheck_shadow_set(shadow, size);
-}
-
-bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
-{
-       enum kmemcheck_shadow status;
-       void *shadow;
-
-       shadow = kmemcheck_shadow_lookup(addr);
-       if (!shadow)
-               return true;
-
-       status = kmemcheck_shadow_test_all(shadow, size);
-
-       return status == KMEMCHECK_SHADOW_INITIALIZED;
-}
-
-/* Access may cross page boundary */
-static void kmemcheck_read(struct pt_regs *regs,
-       unsigned long addr, unsigned int size)
-{
-       unsigned long page = addr & PAGE_MASK;
-       unsigned long next_addr = addr + size - 1;
-       unsigned long next_page = next_addr & PAGE_MASK;
-
-       if (likely(page == next_page)) {
-               kmemcheck_read_strict(regs, addr, size);
-               return;
-       }
-
-       /*
-        * What we do is basically to split the access across the
-        * two pages and handle each part separately. Yes, this means
-        * that we may now see reads that are 3 + 5 bytes, for
-        * example (and if both are uninitialized, there will be two
-        * reports), but it makes the code a lot simpler.
-        */
-       kmemcheck_read_strict(regs, addr, next_page - addr);
-       kmemcheck_read_strict(regs, next_page, next_addr - next_page);
-}
-
-static void kmemcheck_write_strict(struct pt_regs *regs,
-       unsigned long addr, unsigned int size)
-{
-       void *shadow;
-
-       shadow = kmemcheck_shadow_lookup(addr);
-       if (!shadow)
-               return;
-
-       kmemcheck_save_addr(addr);
-       kmemcheck_shadow_set(shadow, size);
-}
-
-static void kmemcheck_write(struct pt_regs *regs,
-       unsigned long addr, unsigned int size)
-{
-       unsigned long page = addr & PAGE_MASK;
-       unsigned long next_addr = addr + size - 1;
-       unsigned long next_page = next_addr & PAGE_MASK;
-
-       if (likely(page == next_page)) {
-               kmemcheck_write_strict(regs, addr, size);
-               return;
-       }
-
-       /* See comment in kmemcheck_read(). */
-       kmemcheck_write_strict(regs, addr, next_page - addr);
-       kmemcheck_write_strict(regs, next_page, next_addr - next_page);
-}
-
-/*
- * Copying is hard. We have two addresses, each of which may be split across
- * a page (and each page will have different shadow addresses).
- */
-static void kmemcheck_copy(struct pt_regs *regs,
-       unsigned long src_addr, unsigned long dst_addr, unsigned int size)
-{
-       uint8_t shadow[8];
-       enum kmemcheck_shadow status;
-
-       unsigned long page;
-       unsigned long next_addr;
-       unsigned long next_page;
-
-       uint8_t *x;
-       unsigned int i;
-       unsigned int n;
-
-       BUG_ON(size > sizeof(shadow));
-
-       page = src_addr & PAGE_MASK;
-       next_addr = src_addr + size - 1;
-       next_page = next_addr & PAGE_MASK;
-
-       if (likely(page == next_page)) {
-               /* Same page */
-               x = kmemcheck_shadow_lookup(src_addr);
-               if (x) {
-                       kmemcheck_save_addr(src_addr);
-                       for (i = 0; i < size; ++i)
-                               shadow[i] = x[i];
-               } else {
-                       for (i = 0; i < size; ++i)
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-               }
-       } else {
-               n = next_page - src_addr;
-               BUG_ON(n > sizeof(shadow));
-
-               /* First page */
-               x = kmemcheck_shadow_lookup(src_addr);
-               if (x) {
-                       kmemcheck_save_addr(src_addr);
-                       for (i = 0; i < n; ++i)
-                               shadow[i] = x[i];
-               } else {
-                       /* Not tracked */
-                       for (i = 0; i < n; ++i)
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-               }
-
-               /* Second page */
-               x = kmemcheck_shadow_lookup(next_page);
-               if (x) {
-                       kmemcheck_save_addr(next_page);
-                       for (i = n; i < size; ++i)
-                               shadow[i] = x[i - n];
-               } else {
-                       /* Not tracked */
-                       for (i = n; i < size; ++i)
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-               }
-       }
-
-       page = dst_addr & PAGE_MASK;
-       next_addr = dst_addr + size - 1;
-       next_page = next_addr & PAGE_MASK;
-
-       if (likely(page == next_page)) {
-               /* Same page */
-               x = kmemcheck_shadow_lookup(dst_addr);
-               if (x) {
-                       kmemcheck_save_addr(dst_addr);
-                       for (i = 0; i < size; ++i) {
-                               x[i] = shadow[i];
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-                       }
-               }
-       } else {
-               n = next_page - dst_addr;
-               BUG_ON(n > sizeof(shadow));
-
-               /* First page */
-               x = kmemcheck_shadow_lookup(dst_addr);
-               if (x) {
-                       kmemcheck_save_addr(dst_addr);
-                       for (i = 0; i < n; ++i) {
-                               x[i] = shadow[i];
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-                       }
-               }
-
-               /* Second page */
-               x = kmemcheck_shadow_lookup(next_page);
-               if (x) {
-                       kmemcheck_save_addr(next_page);
-                       for (i = n; i < size; ++i) {
-                               x[i - n] = shadow[i];
-                               shadow[i] = KMEMCHECK_SHADOW_INITIALIZED;
-                       }
-               }
-       }
-
-       status = kmemcheck_shadow_test(shadow, size);
-       if (status == KMEMCHECK_SHADOW_INITIALIZED)
-               return;
-
-       if (kmemcheck_enabled)
-               kmemcheck_error_save(status, src_addr, size, regs);
-
-       if (kmemcheck_enabled == 2)
-               kmemcheck_enabled = 0;
-}
-
-enum kmemcheck_method {
-       KMEMCHECK_READ,
-       KMEMCHECK_WRITE,
-};
-
-static void kmemcheck_access(struct pt_regs *regs,
-       unsigned long fallback_address, enum kmemcheck_method fallback_method)
-{
-       const uint8_t *insn;
-       const uint8_t *insn_primary;
-       unsigned int size;
-
-       struct kmemcheck_context *data = this_cpu_ptr(&kmemcheck_context);
-
-       /* Recursive fault -- ouch. */
-       if (data->busy) {
-               kmemcheck_show_addr(fallback_address);
-               kmemcheck_error_save_bug(regs);
-               return;
-       }
-
-       data->busy = true;
-
-       insn = (const uint8_t *) regs->ip;
-       insn_primary = kmemcheck_opcode_get_primary(insn);
-
-       kmemcheck_opcode_decode(insn, &size);
-
-       switch (insn_primary[0]) {
-#ifdef CONFIG_KMEMCHECK_BITOPS_OK
-               /* AND, OR, XOR */
-               /*
-                * Unfortunately, these instructions have to be excluded from
-                * our regular checking since they access only some (and not
-                * all) bits. This clears out "bogus" bitfield-access warnings.
-                */
-       case 0x80:
-       case 0x81:
-       case 0x82:
-       case 0x83:
-               switch ((insn_primary[1] >> 3) & 7) {
-                       /* OR */
-               case 1:
-                       /* AND */
-               case 4:
-                       /* XOR */
-               case 6:
-                       kmemcheck_write(regs, fallback_address, size);
-                       goto out;
-
-                       /* ADD */
-               case 0:
-                       /* ADC */
-               case 2:
-                       /* SBB */
-               case 3:
-                       /* SUB */
-               case 5:
-                       /* CMP */
-               case 7:
-                       break;
-               }
-               break;
-#endif
-
-               /* MOVS, MOVSB, MOVSW, MOVSD */
-       case 0xa4:
-       case 0xa5:
-               /*
-                * These instructions are special because they take two
-                * addresses, but we only get one page fault.
-                */
-               kmemcheck_copy(regs, regs->si, regs->di, size);
-               goto out;
-
-               /* CMPS, CMPSB, CMPSW, CMPSD */
-       case 0xa6:
-       case 0xa7:
-               kmemcheck_read(regs, regs->si, size);
-               kmemcheck_read(regs, regs->di, size);
-               goto out;
-       }
-
-       /*
-        * If the opcode isn't special in any way, we use the data from the
-        * page fault handler to determine the address and type of memory
-        * access.
-        */
-       switch (fallback_method) {
-       case KMEMCHECK_READ:
-               kmemcheck_read(regs, fallback_address, size);
-               goto out;
-       case KMEMCHECK_WRITE:
-               kmemcheck_write(regs, fallback_address, size);
-               goto out;
-       }
-
-out:
-       data->busy = false;
-}
-
-bool kmemcheck_fault(struct pt_regs *regs, unsigned long address,
-       unsigned long error_code)
-{
-       pte_t *pte;
-
-       /*
-        * XXX: Is it safe to assume that memory accesses from virtual 86
-        * mode or non-kernel code segments will _never_ access kernel
-        * memory (e.g. tracked pages)? For now, we need this to avoid
-        * invoking kmemcheck for PnP BIOS calls.
-        */
-       if (regs->flags & X86_VM_MASK)
-               return false;
-       if (regs->cs != __KERNEL_CS)
-               return false;
-
-       pte = kmemcheck_pte_lookup(address);
-       if (!pte)
-               return false;
-
-       WARN_ON_ONCE(in_nmi());
-
-       if (error_code & 2)
-               kmemcheck_access(regs, address, KMEMCHECK_WRITE);
-       else
-               kmemcheck_access(regs, address, KMEMCHECK_READ);
-
-       kmemcheck_show(regs);
-       return true;
-}
-
-bool kmemcheck_trap(struct pt_regs *regs)
-{
-       if (!kmemcheck_active(regs))
-               return false;
-
-       /* We're done. */
-       kmemcheck_hide(regs);
-       return true;
-}
index df8109ddf7fe30d60dfb077ff039f08f195c7f54..cec5940325151e407aa90128a35cb683afd436d7 100644 (file)
@@ -1,107 +1 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/types.h>
-
-#include "opcode.h"
-
-static bool opcode_is_prefix(uint8_t b)
-{
-       return
-               /* Group 1 */
-               b == 0xf0 || b == 0xf2 || b == 0xf3
-               /* Group 2 */
-               || b == 0x2e || b == 0x36 || b == 0x3e || b == 0x26
-               || b == 0x64 || b == 0x65
-               /* Group 3 */
-               || b == 0x66
-               /* Group 4 */
-               || b == 0x67;
-}
-
-#ifdef CONFIG_X86_64
-static bool opcode_is_rex_prefix(uint8_t b)
-{
-       return (b & 0xf0) == 0x40;
-}
-#else
-static bool opcode_is_rex_prefix(uint8_t b)
-{
-       return false;
-}
-#endif
-
-#define REX_W (1 << 3)
-
-/*
- * This is a VERY crude opcode decoder. We only need to find the size of the
- * load/store that caused our #PF and this should work for all the opcodes
- * that we care about. Moreover, the ones who invented this instruction set
- * should be shot.
- */
-void kmemcheck_opcode_decode(const uint8_t *op, unsigned int *size)
-{
-       /* Default operand size */
-       int operand_size_override = 4;
-
-       /* prefixes */
-       for (; opcode_is_prefix(*op); ++op) {
-               if (*op == 0x66)
-                       operand_size_override = 2;
-       }
-
-       /* REX prefix */
-       if (opcode_is_rex_prefix(*op)) {
-               uint8_t rex = *op;
-
-               ++op;
-               if (rex & REX_W) {
-                       switch (*op) {
-                       case 0x63:
-                               *size = 4;
-                               return;
-                       case 0x0f:
-                               ++op;
-
-                               switch (*op) {
-                               case 0xb6:
-                               case 0xbe:
-                                       *size = 1;
-                                       return;
-                               case 0xb7:
-                               case 0xbf:
-                                       *size = 2;
-                                       return;
-                               }
-
-                               break;
-                       }
-
-                       *size = 8;
-                       return;
-               }
-       }
-
-       /* escape opcode */
-       if (*op == 0x0f) {
-               ++op;
-
-               /*
-                * This is move with zero-extend and sign-extend, respectively;
-                * we don't have to think about 0xb6/0xbe, because this is
-                * already handled in the conditional below.
-                */
-               if (*op == 0xb7 || *op == 0xbf)
-                       operand_size_override = 2;
-       }
-
-       *size = (*op & 1) ? operand_size_override : 1;
-}
-
-const uint8_t *kmemcheck_opcode_get_primary(const uint8_t *op)
-{
-       /* skip prefixes */
-       while (opcode_is_prefix(*op))
-               ++op;
-       if (opcode_is_rex_prefix(*op))
-               ++op;
-       return op;
-}
index 51a1ce94c24a46068f1a7e38e11064ce5244ef43..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,10 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH__X86__MM__KMEMCHECK__OPCODE_H
-#define ARCH__X86__MM__KMEMCHECK__OPCODE_H
-
-#include <linux/types.h>
-
-void kmemcheck_opcode_decode(const uint8_t *op, unsigned int *size);
-const uint8_t *kmemcheck_opcode_get_primary(const uint8_t *op);
-
-#endif
index 8a03be90272a938012419086572092f16561039c..cec5940325151e407aa90128a35cb683afd436d7 100644 (file)
@@ -1,23 +1 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/mm.h>
-
-#include <asm/pgtable.h>
-
-#include "pte.h"
-
-pte_t *kmemcheck_pte_lookup(unsigned long address)
-{
-       pte_t *pte;
-       unsigned int level;
-
-       pte = lookup_address(address, &level);
-       if (!pte)
-               return NULL;
-       if (level != PG_LEVEL_4K)
-               return NULL;
-       if (!pte_hidden(*pte))
-               return NULL;
-
-       return pte;
-}
-
index b595612382c27b92d15586f2a08639a7b7c59d76..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,11 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH__X86__MM__KMEMCHECK__PTE_H
-#define ARCH__X86__MM__KMEMCHECK__PTE_H
-
-#include <linux/mm.h>
-
-#include <asm/pgtable.h>
-
-pte_t *kmemcheck_pte_lookup(unsigned long address);
-
-#endif
index 7ce0be1f99eb663755f31dd7b38c9032a50c4e2f..cec5940325151e407aa90128a35cb683afd436d7 100644 (file)
@@ -1,71 +1 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/bug.h>
-#include <linux/kernel.h>
-
-#include "opcode.h"
-#include "selftest.h"
-
-struct selftest_opcode {
-       unsigned int expected_size;
-       const uint8_t *insn;
-       const char *desc;
-};
-
-static const struct selftest_opcode selftest_opcodes[] = {
-       /* REP MOVS */
-       {1, "\xf3\xa4",                 "rep movsb <mem8>, <mem8>"},
-       {4, "\xf3\xa5",                 "rep movsl <mem32>, <mem32>"},
-
-       /* MOVZX / MOVZXD */
-       {1, "\x66\x0f\xb6\x51\xf8",     "movzwq <mem8>, <reg16>"},
-       {1, "\x0f\xb6\x51\xf8",         "movzwq <mem8>, <reg32>"},
-
-       /* MOVSX / MOVSXD */
-       {1, "\x66\x0f\xbe\x51\xf8",     "movswq <mem8>, <reg16>"},
-       {1, "\x0f\xbe\x51\xf8",         "movswq <mem8>, <reg32>"},
-
-#ifdef CONFIG_X86_64
-       /* MOVZX / MOVZXD */
-       {1, "\x49\x0f\xb6\x51\xf8",     "movzbq <mem8>, <reg64>"},
-       {2, "\x49\x0f\xb7\x51\xf8",     "movzbq <mem16>, <reg64>"},
-
-       /* MOVSX / MOVSXD */
-       {1, "\x49\x0f\xbe\x51\xf8",     "movsbq <mem8>, <reg64>"},
-       {2, "\x49\x0f\xbf\x51\xf8",     "movsbq <mem16>, <reg64>"},
-       {4, "\x49\x63\x51\xf8",         "movslq <mem32>, <reg64>"},
-#endif
-};
-
-static bool selftest_opcode_one(const struct selftest_opcode *op)
-{
-       unsigned size;
-
-       kmemcheck_opcode_decode(op->insn, &size);
-
-       if (size == op->expected_size)
-               return true;
-
-       printk(KERN_WARNING "kmemcheck: opcode %s: expected size %d, got %d\n",
-               op->desc, op->expected_size, size);
-       return false;
-}
-
-static bool selftest_opcodes_all(void)
-{
-       bool pass = true;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(selftest_opcodes); ++i)
-               pass = pass && selftest_opcode_one(&selftest_opcodes[i]);
-
-       return pass;
-}
-
-bool kmemcheck_selftest(void)
-{
-       bool pass = true;
-
-       pass = pass && selftest_opcodes_all();
-
-       return pass;
-}
index 8d759aae453db618011e63176227e555cc06246b..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,7 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH_X86_MM_KMEMCHECK_SELFTEST_H
-#define ARCH_X86_MM_KMEMCHECK_SELFTEST_H
-
-bool kmemcheck_selftest(void);
-
-#endif
diff --git a/arch/x86/mm/kmemcheck/shadow.c b/arch/x86/mm/kmemcheck/shadow.c
deleted file mode 100644 (file)
index c2638a7..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <linux/kmemcheck.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-#include "pte.h"
-#include "shadow.h"
-
-/*
- * Return the shadow address for the given address. Returns NULL if the
- * address is not tracked.
- *
- * We need to be extremely careful not to follow any invalid pointers,
- * because this function can be called for *any* possible address.
- */
-void *kmemcheck_shadow_lookup(unsigned long address)
-{
-       pte_t *pte;
-       struct page *page;
-
-       if (!virt_addr_valid(address))
-               return NULL;
-
-       pte = kmemcheck_pte_lookup(address);
-       if (!pte)
-               return NULL;
-
-       page = virt_to_page(address);
-       if (!page->shadow)
-               return NULL;
-       return page->shadow + (address & (PAGE_SIZE - 1));
-}
-
-static void mark_shadow(void *address, unsigned int n,
-       enum kmemcheck_shadow status)
-{
-       unsigned long addr = (unsigned long) address;
-       unsigned long last_addr = addr + n - 1;
-       unsigned long page = addr & PAGE_MASK;
-       unsigned long last_page = last_addr & PAGE_MASK;
-       unsigned int first_n;
-       void *shadow;
-
-       /* If the memory range crosses a page boundary, stop there. */
-       if (page == last_page)
-               first_n = n;
-       else
-               first_n = page + PAGE_SIZE - addr;
-
-       shadow = kmemcheck_shadow_lookup(addr);
-       if (shadow)
-               memset(shadow, status, first_n);
-
-       addr += first_n;
-       n -= first_n;
-
-       /* Do full-page memset()s. */
-       while (n >= PAGE_SIZE) {
-               shadow = kmemcheck_shadow_lookup(addr);
-               if (shadow)
-                       memset(shadow, status, PAGE_SIZE);
-
-               addr += PAGE_SIZE;
-               n -= PAGE_SIZE;
-       }
-
-       /* Do the remaining page, if any. */
-       if (n > 0) {
-               shadow = kmemcheck_shadow_lookup(addr);
-               if (shadow)
-                       memset(shadow, status, n);
-       }
-}
-
-void kmemcheck_mark_unallocated(void *address, unsigned int n)
-{
-       mark_shadow(address, n, KMEMCHECK_SHADOW_UNALLOCATED);
-}
-
-void kmemcheck_mark_uninitialized(void *address, unsigned int n)
-{
-       mark_shadow(address, n, KMEMCHECK_SHADOW_UNINITIALIZED);
-}
-
-/*
- * Fill the shadow memory of the given address such that the memory at that
- * address is marked as being initialized.
- */
-void kmemcheck_mark_initialized(void *address, unsigned int n)
-{
-       mark_shadow(address, n, KMEMCHECK_SHADOW_INITIALIZED);
-}
-EXPORT_SYMBOL_GPL(kmemcheck_mark_initialized);
-
-void kmemcheck_mark_freed(void *address, unsigned int n)
-{
-       mark_shadow(address, n, KMEMCHECK_SHADOW_FREED);
-}
-
-void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 0; i < n; ++i)
-               kmemcheck_mark_unallocated(page_address(&p[i]), PAGE_SIZE);
-}
-
-void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 0; i < n; ++i)
-               kmemcheck_mark_uninitialized(page_address(&p[i]), PAGE_SIZE);
-}
-
-void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n)
-{
-       unsigned int i;
-
-       for (i = 0; i < n; ++i)
-               kmemcheck_mark_initialized(page_address(&p[i]), PAGE_SIZE);
-}
-
-enum kmemcheck_shadow kmemcheck_shadow_test(void *shadow, unsigned int size)
-{
-#ifdef CONFIG_KMEMCHECK_PARTIAL_OK
-       uint8_t *x;
-       unsigned int i;
-
-       x = shadow;
-
-       /*
-        * Make sure _some_ bytes are initialized. Gcc frequently generates
-        * code to access neighboring bytes.
-        */
-       for (i = 0; i < size; ++i) {
-               if (x[i] == KMEMCHECK_SHADOW_INITIALIZED)
-                       return x[i];
-       }
-
-       return x[0];
-#else
-       return kmemcheck_shadow_test_all(shadow, size);
-#endif
-}
-
-enum kmemcheck_shadow kmemcheck_shadow_test_all(void *shadow, unsigned int size)
-{
-       uint8_t *x;
-       unsigned int i;
-
-       x = shadow;
-
-       /* All bytes must be initialized. */
-       for (i = 0; i < size; ++i) {
-               if (x[i] != KMEMCHECK_SHADOW_INITIALIZED)
-                       return x[i];
-       }
-
-       return x[0];
-}
-
-void kmemcheck_shadow_set(void *shadow, unsigned int size)
-{
-       uint8_t *x;
-       unsigned int i;
-
-       x = shadow;
-       for (i = 0; i < size; ++i)
-               x[i] = KMEMCHECK_SHADOW_INITIALIZED;
-}
index 49768dc18664bea7fb3b954de1fb47da20139baf..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,19 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ARCH__X86__MM__KMEMCHECK__SHADOW_H
-#define ARCH__X86__MM__KMEMCHECK__SHADOW_H
-
-enum kmemcheck_shadow {
-       KMEMCHECK_SHADOW_UNALLOCATED,
-       KMEMCHECK_SHADOW_UNINITIALIZED,
-       KMEMCHECK_SHADOW_INITIALIZED,
-       KMEMCHECK_SHADOW_FREED,
-};
-
-void *kmemcheck_shadow_lookup(unsigned long address);
-
-enum kmemcheck_shadow kmemcheck_shadow_test(void *shadow, unsigned int size);
-enum kmemcheck_shadow kmemcheck_shadow_test_all(void *shadow,
-                                               unsigned int size);
-void kmemcheck_shadow_set(void *shadow, unsigned int size);
-
-#endif
index baeb872283d91b8018773f52e8eb32f9897de3e2..69c238210325e7a894e4577afdf6d2397da433ea 100644 (file)
@@ -594,21 +594,6 @@ static inline void tasklet_hi_schedule(struct tasklet_struct *t)
                __tasklet_hi_schedule(t);
 }
 
-extern void __tasklet_hi_schedule_first(struct tasklet_struct *t);
-
-/*
- * This version avoids touching any other tasklets. Needed for kmemcheck
- * in order not to take any page faults while enqueueing this tasklet;
- * consider VERY carefully whether you really need this or
- * tasklet_hi_schedule()...
- */
-static inline void tasklet_hi_schedule_first(struct tasklet_struct *t)
-{
-       if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
-               __tasklet_hi_schedule_first(t);
-}
-
-
 static inline void tasklet_disable_nosync(struct tasklet_struct *t)
 {
        atomic_inc(&t->count);
index 7b1d7bead7d93ceb32dfdd43a4bb3c771ac69551..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,172 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LINUX_KMEMCHECK_H
-#define LINUX_KMEMCHECK_H
-
-#include <linux/mm_types.h>
-#include <linux/types.h>
-
-#ifdef CONFIG_KMEMCHECK
-extern int kmemcheck_enabled;
-
-/* The slab-related functions. */
-void kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node);
-void kmemcheck_free_shadow(struct page *page, int order);
-void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
-                         size_t size);
-void kmemcheck_slab_free(struct kmem_cache *s, void *object, size_t size);
-
-void kmemcheck_pagealloc_alloc(struct page *p, unsigned int order,
-                              gfp_t gfpflags);
-
-void kmemcheck_show_pages(struct page *p, unsigned int n);
-void kmemcheck_hide_pages(struct page *p, unsigned int n);
-
-bool kmemcheck_page_is_tracked(struct page *p);
-
-void kmemcheck_mark_unallocated(void *address, unsigned int n);
-void kmemcheck_mark_uninitialized(void *address, unsigned int n);
-void kmemcheck_mark_initialized(void *address, unsigned int n);
-void kmemcheck_mark_freed(void *address, unsigned int n);
-
-void kmemcheck_mark_unallocated_pages(struct page *p, unsigned int n);
-void kmemcheck_mark_uninitialized_pages(struct page *p, unsigned int n);
-void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n);
-
-int kmemcheck_show_addr(unsigned long address);
-int kmemcheck_hide_addr(unsigned long address);
-
-bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
-
-/*
- * Bitfield annotations
- *
- * How to use: If you have a struct using bitfields, for example
- *
- *     struct a {
- *             int x:8, y:8;
- *     };
- *
- * then this should be rewritten as
- *
- *     struct a {
- *             kmemcheck_bitfield_begin(flags);
- *             int x:8, y:8;
- *             kmemcheck_bitfield_end(flags);
- *     };
- *
- * Now the "flags_begin" and "flags_end" members may be used to refer to the
- * beginning and end, respectively, of the bitfield (and things like
- * &x.flags_begin is allowed). As soon as the struct is allocated, the bit-
- * fields should be annotated:
- *
- *     struct a *a = kmalloc(sizeof(struct a), GFP_KERNEL);
- *     kmemcheck_annotate_bitfield(a, flags);
- */
-#define kmemcheck_bitfield_begin(name) \
-       int name##_begin[0];
-
-#define kmemcheck_bitfield_end(name)   \
-       int name##_end[0];
-
-#define kmemcheck_annotate_bitfield(ptr, name)                         \
-       do {                                                            \
-               int _n;                                                 \
-                                                                       \
-               if (!ptr)                                               \
-                       break;                                          \
-                                                                       \
-               _n = (long) &((ptr)->name##_end)                        \
-                       - (long) &((ptr)->name##_begin);                \
-               BUILD_BUG_ON(_n < 0);                                   \
-                                                                       \
-               kmemcheck_mark_initialized(&((ptr)->name##_begin), _n); \
-       } while (0)
-
-#define kmemcheck_annotate_variable(var)                               \
-       do {                                                            \
-               kmemcheck_mark_initialized(&(var), sizeof(var));        \
-       } while (0)                                                     \
-
-#else
-#define kmemcheck_enabled 0
-
-static inline void
-kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node)
-{
-}
-
-static inline void
-kmemcheck_free_shadow(struct page *page, int order)
-{
-}
-
-static inline void
-kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
-                    size_t size)
-{
-}
-
-static inline void kmemcheck_slab_free(struct kmem_cache *s, void *object,
-                                      size_t size)
-{
-}
-
-static inline void kmemcheck_pagealloc_alloc(struct page *p,
-       unsigned int order, gfp_t gfpflags)
-{
-}
-
-static inline bool kmemcheck_page_is_tracked(struct page *p)
-{
-       return false;
-}
-
-static inline void kmemcheck_mark_unallocated(void *address, unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_uninitialized(void *address, unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_freed(void *address, unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_unallocated_pages(struct page *p,
-                                                   unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_uninitialized_pages(struct page *p,
-                                                     unsigned int n)
-{
-}
-
-static inline void kmemcheck_mark_initialized_pages(struct page *p,
-                                                   unsigned int n)
-{
-}
-
-static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
-{
-       return true;
-}
-
-#define kmemcheck_bitfield_begin(name)
-#define kmemcheck_bitfield_end(name)
-#define kmemcheck_annotate_bitfield(ptr, name) \
-       do {                                    \
-       } while (0)
-
-#define kmemcheck_annotate_variable(var)       \
-       do {                                    \
-       } while (0)
-
-#endif /* CONFIG_KMEMCHECK */
-
-#endif /* LINUX_KMEMCHECK_H */
index 662f7b1b7a78f6115a9f753e9ebba5a03774f426..2f5e87f1bae22f3df44fa4493fcc8b255882267f 100644 (file)
@@ -486,16 +486,6 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
 }
 EXPORT_SYMBOL(__tasklet_hi_schedule);
 
-void __tasklet_hi_schedule_first(struct tasklet_struct *t)
-{
-       lockdep_assert_irqs_disabled();
-
-       t->next = __this_cpu_read(tasklet_hi_vec.head);
-       __this_cpu_write(tasklet_hi_vec.head, t);
-       __raise_softirq_irqoff(HI_SOFTIRQ);
-}
-EXPORT_SYMBOL(__tasklet_hi_schedule_first);
-
 static __latent_entropy void tasklet_action(struct softirq_action *a)
 {
        struct tasklet_struct *list;
index 9576bd582d4a870f657d974e1e3beaca6ea635fa..7638e2f7fff8f295827c0747000e3bf395a1c61c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/proc_fs.h>
 #include <linux/security.h>
 #include <linux/ctype.h>
-#include <linux/kmemcheck.h>
 #include <linux/kmemleak.h>
 #include <linux/fs.h>
 #include <linux/init.h>
@@ -1173,15 +1172,6 @@ static struct ctl_table kern_table[] = {
                .extra1         = &zero,
                .extra2         = &one_thousand,
        },
-#endif
-#ifdef CONFIG_KMEMCHECK
-       {
-               .procname       = "kmemcheck",
-               .data           = &kmemcheck_enabled,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
 #endif
        {
                .procname       = "panic_on_warn",
index 07ce7449765a499b99c4d1982c8b41f2e01e111e..5402e395465926939b2f16c9d1a327686a550f1d 100644 (file)
@@ -504,7 +504,7 @@ config DEBUG_OBJECTS_ENABLE_DEFAULT
 
 config DEBUG_SLAB
        bool "Debug slab memory allocations"
-       depends on DEBUG_KERNEL && SLAB && !KMEMCHECK
+       depends on DEBUG_KERNEL && SLAB
        help
          Say Y here to have the kernel do limited verification on memory
          allocation as well as poisoning memory on free to catch use of freed
@@ -516,7 +516,7 @@ config DEBUG_SLAB_LEAK
 
 config SLUB_DEBUG_ON
        bool "SLUB debugging on by default"
-       depends on SLUB && SLUB_DEBUG && !KMEMCHECK
+       depends on SLUB && SLUB_DEBUG
        default n
        help
          Boot with debugging on by default. SLUB boots by default with
@@ -730,8 +730,6 @@ config DEBUG_STACKOVERFLOW
 
          If in doubt, say "N".
 
-source "lib/Kconfig.kmemcheck"
-
 source "lib/Kconfig.kasan"
 
 endmenu # "Memory Debugging"
diff --git a/lib/Kconfig.kmemcheck b/lib/Kconfig.kmemcheck
deleted file mode 100644 (file)
index 846e039..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-config HAVE_ARCH_KMEMCHECK
-       bool
-
-if HAVE_ARCH_KMEMCHECK
-
-menuconfig KMEMCHECK
-       bool "kmemcheck: trap use of uninitialized memory"
-       depends on DEBUG_KERNEL
-       depends on !X86_USE_3DNOW
-       depends on SLUB || SLAB
-       depends on !CC_OPTIMIZE_FOR_SIZE
-       depends on !FUNCTION_TRACER
-       select FRAME_POINTER
-       select STACKTRACE
-       default n
-       help
-         This option enables tracing of dynamically allocated kernel memory
-         to see if memory is used before it has been given an initial value.
-         Be aware that this requires half of your memory for bookkeeping and
-         will insert extra code at *every* read and write to tracked memory
-         thus slow down the kernel code (but user code is unaffected).
-
-         The kernel may be started with kmemcheck=0 or kmemcheck=1 to disable
-         or enable kmemcheck at boot-time. If the kernel is started with
-         kmemcheck=0, the large memory and CPU overhead is not incurred.
-
-choice
-       prompt "kmemcheck: default mode at boot"
-       depends on KMEMCHECK
-       default KMEMCHECK_ONESHOT_BY_DEFAULT
-       help
-         This option controls the default behaviour of kmemcheck when the
-         kernel boots and no kmemcheck= parameter is given.
-
-config KMEMCHECK_DISABLED_BY_DEFAULT
-       bool "disabled"
-       depends on KMEMCHECK
-
-config KMEMCHECK_ENABLED_BY_DEFAULT
-       bool "enabled"
-       depends on KMEMCHECK
-
-config KMEMCHECK_ONESHOT_BY_DEFAULT
-       bool "one-shot"
-       depends on KMEMCHECK
-       help
-         In one-shot mode, only the first error detected is reported before
-         kmemcheck is disabled.
-
-endchoice
-
-config KMEMCHECK_QUEUE_SIZE
-       int "kmemcheck: error queue size"
-       depends on KMEMCHECK
-       default 64
-       help
-         Select the maximum number of errors to store in the queue. Since
-         errors can occur virtually anywhere and in any context, we need a
-         temporary storage area which is guarantueed not to generate any
-         other faults. The queue will be emptied as soon as a tasklet may
-         be scheduled. If the queue is full, new error reports will be
-         lost.
-
-config KMEMCHECK_SHADOW_COPY_SHIFT
-       int "kmemcheck: shadow copy size (5 => 32 bytes, 6 => 64 bytes)"
-       depends on KMEMCHECK
-       range 2 8
-       default 5
-       help
-         Select the number of shadow bytes to save along with each entry of
-         the queue. These bytes indicate what parts of an allocation are
-         initialized, uninitialized, etc. and will be displayed when an
-         error is detected to help the debugging of a particular problem.
-
-config KMEMCHECK_PARTIAL_OK
-       bool "kmemcheck: allow partially uninitialized memory"
-       depends on KMEMCHECK
-       default y
-       help
-         This option works around certain GCC optimizations that produce
-         32-bit reads from 16-bit variables where the upper 16 bits are
-         thrown away afterwards. This may of course also hide some real
-         bugs.
-
-config KMEMCHECK_BITOPS_OK
-       bool "kmemcheck: allow bit-field manipulation"
-       depends on KMEMCHECK
-       default n
-       help
-         This option silences warnings that would be generated for bit-field
-         accesses where not all the bits are initialized at the same time.
-         This may also hide some real bugs.
-
-endif
index 5b0adf1435de7dba61e7d0b34c6a7fd912041fd1..e5e606ee5f715e846a19ea9186391c47a2efddc0 100644 (file)
@@ -11,7 +11,6 @@ config DEBUG_PAGEALLOC
        bool "Debug page memory allocations"
        depends on DEBUG_KERNEL
        depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC
-       depends on !KMEMCHECK
        select PAGE_EXTENSION
        select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC
        ---help---
index 4659b93cba43bbc868bceb606a4e2813528dd332..e7ebd176fb935e382c9da55c39fde038f256c9e5 100644 (file)
@@ -17,7 +17,6 @@ KCOV_INSTRUMENT_slub.o := n
 KCOV_INSTRUMENT_page_alloc.o := n
 KCOV_INSTRUMENT_debug-pagealloc.o := n
 KCOV_INSTRUMENT_kmemleak.o := n
-KCOV_INSTRUMENT_kmemcheck.o := n
 KCOV_INSTRUMENT_memcontrol.o := n
 KCOV_INSTRUMENT_mmzone.o := n
 KCOV_INSTRUMENT_vmstat.o := n
@@ -70,7 +69,6 @@ obj-$(CONFIG_KSM) += ksm.o
 obj-$(CONFIG_PAGE_POISONING) += page_poison.o
 obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_SLUB) += slub.o
-obj-$(CONFIG_KMEMCHECK) += kmemcheck.o
 obj-$(CONFIG_KASAN)    += kasan/
 obj-$(CONFIG_FAILSLAB) += failslab.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
index b3a4d61d341c6a5b6d5187207774a11d2a040c63..cec5940325151e407aa90128a35cb683afd436d7 100644 (file)
@@ -1,126 +1 @@
 // SPDX-License-Identifier: GPL-2.0
-#include <linux/gfp.h>
-#include <linux/mm_types.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include "slab.h"
-#include <linux/kmemcheck.h>
-
-void kmemcheck_alloc_shadow(struct page *page, int order, gfp_t flags, int node)
-{
-       struct page *shadow;
-       int pages;
-       int i;
-
-       pages = 1 << order;
-
-       /*
-        * With kmemcheck enabled, we need to allocate a memory area for the
-        * shadow bits as well.
-        */
-       shadow = alloc_pages_node(node, flags, order);
-       if (!shadow) {
-               if (printk_ratelimit())
-                       pr_err("kmemcheck: failed to allocate shadow bitmap\n");
-               return;
-       }
-
-       for(i = 0; i < pages; ++i)
-               page[i].shadow = page_address(&shadow[i]);
-
-       /*
-        * Mark it as non-present for the MMU so that our accesses to
-        * this memory will trigger a page fault and let us analyze
-        * the memory accesses.
-        */
-       kmemcheck_hide_pages(page, pages);
-}
-
-void kmemcheck_free_shadow(struct page *page, int order)
-{
-       struct page *shadow;
-       int pages;
-       int i;
-
-       if (!kmemcheck_page_is_tracked(page))
-               return;
-
-       pages = 1 << order;
-
-       kmemcheck_show_pages(page, pages);
-
-       shadow = virt_to_page(page[0].shadow);
-
-       for(i = 0; i < pages; ++i)
-               page[i].shadow = NULL;
-
-       __free_pages(shadow, order);
-}
-
-void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
-                         size_t size)
-{
-       if (unlikely(!object)) /* Skip object if allocation failed */
-               return;
-
-       /*
-        * Has already been memset(), which initializes the shadow for us
-        * as well.
-        */
-       if (gfpflags & __GFP_ZERO)
-               return;
-
-       /* No need to initialize the shadow of a non-tracked slab. */
-       if (s->flags & SLAB_NOTRACK)
-               return;
-
-       if (!kmemcheck_enabled || gfpflags & __GFP_NOTRACK) {
-               /*
-                * Allow notracked objects to be allocated from
-                * tracked caches. Note however that these objects
-                * will still get page faults on access, they just
-                * won't ever be flagged as uninitialized. If page
-                * faults are not acceptable, the slab cache itself
-                * should be marked NOTRACK.
-                */
-               kmemcheck_mark_initialized(object, size);
-       } else if (!s->ctor) {
-               /*
-                * New objects should be marked uninitialized before
-                * they're returned to the called.
-                */
-               kmemcheck_mark_uninitialized(object, size);
-       }
-}
-
-void kmemcheck_slab_free(struct kmem_cache *s, void *object, size_t size)
-{
-       /* TODO: RCU freeing is unsupported for now; hide false positives. */
-       if (!s->ctor && !(s->flags & SLAB_TYPESAFE_BY_RCU))
-               kmemcheck_mark_freed(object, size);
-}
-
-void kmemcheck_pagealloc_alloc(struct page *page, unsigned int order,
-                              gfp_t gfpflags)
-{
-       int pages;
-
-       if (gfpflags & (__GFP_HIGHMEM | __GFP_NOTRACK))
-               return;
-
-       pages = 1 << order;
-
-       /*
-        * NOTE: We choose to track GFP_ZERO pages too; in fact, they
-        * can become uninitialized by copying uninitialized memory
-        * into them.
-        */
-
-       /* XXX: Can use zone->node for node? */
-       kmemcheck_alloc_shadow(page, order, gfpflags, -1);
-
-       if (gfpflags & __GFP_ZERO)
-               kmemcheck_mark_initialized_pages(page, pages);
-       else
-               kmemcheck_mark_uninitialized_pages(page, pages);
-}
index c2c41e178acf28663d537291072406e08598b84b..cfd56e5a35fb9790ac6426dd62abb9964f1ce72b 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1371,7 +1371,7 @@ static inline void *slab_free_hook(struct kmem_cache *s, void *x)
         * So in order to make the debug calls that expect irqs to be
         * disabled we need to disable interrupts temporarily.
         */
-#if defined(CONFIG_KMEMCHECK) || defined(CONFIG_LOCKDEP)
+#ifdef CONFIG_LOCKDEP
        {
                unsigned long flags;
 
@@ -1399,8 +1399,7 @@ static inline void slab_free_freelist_hook(struct kmem_cache *s,
  * Compiler cannot detect this function can be removed if slab_free_hook()
  * evaluates to nothing.  Thus, catch all relevant config debug options here.
  */
-#if defined(CONFIG_KMEMCHECK) ||               \
-       defined(CONFIG_LOCKDEP) ||              \
+#if defined(CONFIG_LOCKDEP)    ||              \
        defined(CONFIG_DEBUG_KMEMLEAK) ||       \
        defined(CONFIG_DEBUG_OBJECTS_FREE) ||   \
        defined(CONFIG_KASAN)
index 67d051edd6151b8f3264840349cd4f985d815c1d..7bd52b8f63d48667cdb1d8ebe63896f2d8e3d176 100755 (executable)
@@ -2182,8 +2182,6 @@ sub dump_struct($$) {
        # strip comments:
        $members =~ s/\/\*.*?\*\///gos;
        $nested =~ s/\/\*.*?\*\///gos;
-       # strip kmemcheck_bitfield_{begin,end}.*;
-       $members =~ s/kmemcheck_bitfield_.*?;//gos;
        # strip attributes
        $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
        $members =~ s/__aligned\s*\([^;]*\)//gos;
index 2bccd2c7b8974e8568b9533ab27db27bdc004229..ea32a7d3cf1bc87963b259a9902042a7c33e41e4 100644 (file)
@@ -1,9 +1 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _LIBLOCKDEP_LINUX_KMEMCHECK_H_
-#define _LIBLOCKDEP_LINUX_KMEMCHECK_H_
-
-static inline void kmemcheck_mark_initialized(void *address, unsigned int n)
-{
-}
-
-#endif