Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1431600 > unrolled thread

[PATCH v4 00/29] virtually mapped stacks and thread_info cleanup

Started byAndy Lutomirski <luto@kernel.org>
First post2016-06-27 00:00 +0200
Last post2016-06-28 15:30 +0200
Articles 20 on this page of 70 — 11 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v4 00/29] virtually mapped stacks and thread_info cleanup Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 07/29] mm: Fix memcg stack accounting for sub-page stacks Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 24/29] x86/entry: Get rid of pt_regs_to_thread_info() Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
      Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a  non-default stack Borislav Petkov <bp@alien8.de> - 2016-07-02 19:30 +0200
        Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a  non-default stack Josh Poimboeuf <jpoimboe@redhat.com> - 2016-07-02 20:40 +0200
          Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a  non-default stack Borislav Petkov <bp@alien8.de> - 2016-07-03 11:50 +0200
          Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a  non-default stack Andy Lutomirski <luto@amacapital.net> - 2016-07-03 16:30 +0200
            Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a  non-default stack Borislav Petkov <bp@alien8.de> - 2016-07-03 20:50 +0200
    [PATCH v4 12/29] x86/dumpstack: When dumping stack bytes due to OOPS, start with regs->sp Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 06/29] mm: Track NR_KERNEL_STACK in KiB instead of number of stacks Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 14/29] x86/dumpstack/64: Handle faults when printing the "Stack:" part of an OOPS Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
    [PATCH v4 26/29] sched: Allow putting thread_info into task_struct Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
      Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting  thread_info into task_struct Mark Rutland <mark.rutland@arm.com> - 2016-07-11 12:10 +0200
        Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting  thread_info into task_struct Andy Lutomirski <luto@amacapital.net> - 2016-07-11 17:00 +0200
          Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting  thread_info into task_struct Mark Rutland <mark.rutland@arm.com> - 2016-07-11 17:10 +0200
          Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting  thread_info into task_struct Mark Rutland <mark.rutland@arm.com> - 2016-07-11 18:40 +0200
            Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting  thread_info into task_struct Linus Torvalds <torvalds@linux-foundation.org> - 2016-07-11 18:50 +0200
    [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about vmapped stacks Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:00 +0200
      Re: [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about  vmapped stacks Borislav Petkov <bp@alien8.de> - 2016-06-30 21:40 +0200
        Re: [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about  vmapped stacks Andy Lutomirski <luto@amacapital.net> - 2016-07-06 15:30 +0200
    [PATCH v4 25/29] um: Stop conflating task_struct::stack with thread_info Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 25/29] um: Stop conflating task_struct::stack with thread_info Andy Lutomirski <luto@amacapital.net> - 2016-06-27 01:50 +0200
      Re: [PATCH v4 25/29] um: Stop conflating task_struct::stack with thread_info Brian Gerst <brgerst@gmail.com> - 2016-06-27 01:50 +0200
    [PATCH v4 22/29] x86/asm: Move 'status' from struct thread_info to struct thread_struct Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 22/29] x86/asm: Move 'status' from struct thread_info  to struct thread_struct Brian Gerst <brgerst@gmail.com> - 2016-06-27 02:00 +0200
        Re: [PATCH v4 22/29] x86/asm: Move 'status' from struct thread_info  to struct thread_struct Andy Lutomirski <luto@amacapital.net> - 2016-06-27 02:30 +0200
          Re: [PATCH v4 22/29] x86/asm: Move 'status' from struct thread_info  to struct thread_struct Brian Gerst <brgerst@gmail.com> - 2016-06-27 02:40 +0200
            Re: [PATCH v4 22/29] x86/asm: Move 'status' from struct thread_info  to struct thread_struct Andy Lutomirski <luto@amacapital.net> - 2016-06-27 02:50 +0200
    [PATCH v4 19/29] signal: Consolidate {TS,TLF}_RESTORE_SIGMASK code Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Brian Gerst <brgerst@gmail.com> - 2016-06-27 17:10 +0200
        Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Brian Gerst <brgerst@gmail.com> - 2016-06-27 17:20 +0200
          Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Andy Lutomirski <luto@amacapital.net> - 2016-06-27 17:30 +0200
            Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Andy Lutomirski <luto@amacapital.net> - 2016-06-27 18:00 +0200
              Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Brian Gerst <brgerst@gmail.com> - 2016-06-27 18:20 +0200
                Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Andy Lutomirski <luto@amacapital.net> - 2016-06-27 18:40 +0200
                  Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Brian Gerst <brgerst@gmail.com> - 2016-06-27 19:10 +0200
                    Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Brian Gerst <brgerst@gmail.com> - 2016-06-27 19:30 +0200
              Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Linus Torvalds <torvalds@linux-foundation.org> - 2016-06-27 19:30 +0200
                Re: [PATCH v4 15/29] x86/mm/64: Enable vmapped stacks Andy Lutomirski <luto@amacapital.net> - 2016-06-27 19:40 +0200
    [PATCH v4 18/29] x86: Move addr_limit to thread_struct Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 17/29] x86: Move uaccess_err and sig_on_uaccess_err to thread_struct Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 03/29] x86/mm/hotplug: Don't remove PGD entries in remove_pagetable() Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 23/29] kdb: Use task_cpu() instead of task_thread_info()->cpu Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 16/29] x86/mm: Improve stack-overflow #PF handling Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 20/29] x86/smp: Remove stack_smp_processor_id() Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 09:40 +0200
        Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in  rxkad Herbert Xu <herbert@gondor.apana.org.au> - 2016-06-28 09:40 +0200
          Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 11:10 +0200
            Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in  rxkad Herbert Xu <herbert@gondor.apana.org.au> - 2016-06-28 11:50 +0200
      Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 09:50 +0200
      Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 10:00 +0200
    [PATCH v4 04/29] x86/cpa: In populate_pgd, don't set the pgd entry until it's populated Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 04/29] x86/cpa: In populate_pgd, don't set the pgd  entry until it's populated Borislav Petkov <bp@alien8.de> - 2016-06-28 21:10 +0200
        Re: [PATCH v4 04/29] x86/cpa: In populate_pgd, don't set the pgd  entry until it's populated Andy Lutomirski <luto@amacapital.net> - 2016-06-28 21:10 +0200
    [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
      Re: [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Marcel Holtmann <marcel@holtmann.org> - 2016-06-27 08:00 +0200
        Re: [PATCH v4 01/29] bluetooth: Switch SMP to  crypto_cipher_encrypt_one() Ingo Molnar <mingo@kernel.org> - 2016-06-27 11:00 +0200
          Re: [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Marcel Holtmann <marcel@holtmann.org> - 2016-06-28 00:40 +0200
            Re: [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Andy Lutomirski <luto@amacapital.net> - 2016-06-28 00:40 +0200
              Re: [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Marcel Holtmann <marcel@holtmann.org> - 2016-07-04 20:00 +0200
                Re: [PATCH v4 01/29] bluetooth: Switch SMP to crypto_cipher_encrypt_one() Andy Lutomirski <luto@amacapital.net> - 2016-07-06 15:20 +0200
    [PATCH v4 21/29] x86/smp: Remove unnecessary initialization of thread_info::cpu Andy Lutomirski <luto@kernel.org> - 2016-06-27 00:10 +0200
    Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in  rxkad Herbert Xu <herbert@gondor.apana.org.au> - 2016-06-28 10:00 +0200
      Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 11:00 +0200
        Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in  rxkad Herbert Xu <herbert@gondor.apana.org.au> - 2016-06-28 11:50 +0200
          Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 12:10 +0200
            Re: [PATCH v4 02/29] rxrpc: Avoid using stack memory in SG lists in rxkad David Howells <dhowells@redhat.com> - 2016-06-28 15:30 +0200

Page 1 of 4  [1] 2 3 4  Next page →


#1431600 — [PATCH v4 00/29] virtually mapped stacks and thread_info cleanup

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 00/29] virtually mapped stacks and thread_info cleanup
Message-ID<rOqfT-8f8-5@gated-at.bofh.it>
Hi all-

Since the dawn of time, a kernel stack overflow has been a real PITA
to debug, has caused nondeterministic crashes some time after the
actual overflow, and has generally been easy to exploit for root.

With this series, arches can enable HAVE_ARCH_VMAP_STACK.  Arches
that enable it (just x86 for now) get virtually mapped stacks with
guard pages.  This causes reliable faults when the stack overflows.

If the arch implements it well, we get a nice OOPS on stack overflow
(as opposed to panicing directly or otherwise exploding badly).  On
x86, the OOPS is nice, has a usable call trace, and the overflowing
task is killed cleanly.

This series (starting with this version, v4) also extensively cleans
up thread_info.  thread_info has been partially redundant with
thread_struct for a long time -- both are places for arch code to
add additional per-task variables.  thread_struct is much cleaner:
it's always in task_struct, and there's nothing particularly magical
about it.  So this series contains a bunch of cleanups on x86 to
move almost everything from thread_info to thread_struct (which,
even by itself, deletes more code than it adds) and to remove x86's
dependence on thread_info's position on the stack.  Then it opts x86
into a new config option THREAD_INFO_IN_TASK to get rid of
arch-specific thread_info entirely and simply embed a defanged
thread_info (containing only flags) and 'int cpu' into task_struct.

Once thread_info stops being magical, there's another benefit: we
can free the thread stack as soon as the task is dead (without
waiting for RCU) and then, if vmapped stacks are in use, cache the
entire stack for reuse on the same cpu.

This seems to be an overall speedup of about 0.5-1 µs per
pthread_create/join in a simple test -- a percpu cache of vmalloced
stacks appears to be a bit faster than a high-order stack
allocation, at least when the cache hits.  (I expect that workloads
with a low cache hit rate are likely to be dominated by other
effects anyway.)

This does not address interrupt stacks.

It's worth noting that s390 has an arch-specific gcc feature that
detects stack overflows by adjusting function prologues.  Arches
with features like that may wish to avoid using vmapped stacks to
minimize the performance hit.

Known issues:
 - tcp md5, virtio_net, and virtio_console will have issues.  Eric Dumazet
   has a patch for tcp md5, and Michael Tsirkin says he'll fix virtio_net
   and virtio_console.

Changes from v3:
 - Minor cleanups
 - Rebased onto Linus' tree
 - All the thread_info stuff is new

Changes from v2:
 - Delete kerne_unmap_pages_in_pgd rather than hardening it (Borislav)
 - Fix sub-page stack accounting better (Josh)

Changes from v1:
 - Fix rewind_stack_and_do_exit (Josh)
 - Fix deadlock under load
 - Clean up generic stack vmalloc code
 - Many other minor fixes

Andy Lutomirski (25):
  bluetooth: Switch SMP to crypto_cipher_encrypt_one()
  x86/cpa: In populate_pgd, don't set the pgd entry until it's populated
  x86/mm: Remove kernel_unmap_pages_in_pgd() and
    efi_cleanup_page_tables()
  mm: Track NR_KERNEL_STACK in KiB instead of number of stacks
  mm: Fix memcg stack accounting for sub-page stacks
  dma-api: Teach the "DMA-from-stack" check about vmapped stacks
  fork: Add generic vmalloced stack support
  x86/die: Don't try to recover from an OOPS on a non-default stack
  x86/dumpstack: When OOPSing, rewind the stack before do_exit
  x86/dumpstack: When dumping stack bytes due to OOPS, start with
    regs->sp
  x86/dumpstack: Try harder to get a call trace on stack overflow
  x86/dumpstack/64: Handle faults when printing the "Stack:" part of an
    OOPS
  x86/mm/64: Enable vmapped stacks
  x86/mm: Improve stack-overflow #PF handling
  x86: Move uaccess_err and sig_on_uaccess_err to thread_struct
  x86: Move addr_limit to thread_struct
  signal: Consolidate {TS,TLF}_RESTORE_SIGMASK code
  x86/smp: Remove stack_smp_processor_id()
  x86/smp: Remove unnecessary initialization of thread_info::cpu
  x86/asm: Move 'status' from struct thread_info to struct thread_struct
  kdb: Use task_cpu() instead of task_thread_info()->cpu
  sched: Allow putting thread_info into task_struct
  x86: Move thread_info into task_struct
  sched: Free the stack early if CONFIG_THREAD_INFO_IN_TASK
  fork: Cache two thread stacks per cpu if CONFIG_VMAP_STACK is set

Herbert Xu (1):
  rxrpc: Avoid using stack memory in SG lists in rxkad

Ingo Molnar (1):
  x86/mm/hotplug: Don't remove PGD entries in remove_pagetable()

Linus Torvalds (2):
  x86/entry: Get rid of pt_regs_to_thread_info()
  um: Stop conflating task_struct::stack with thread_info

 arch/Kconfig                              |  29 ++++++
 arch/alpha/include/asm/thread_info.h      |  27 -----
 arch/ia64/include/asm/thread_info.h       |  30 +-----
 arch/microblaze/include/asm/thread_info.h |  27 -----
 arch/powerpc/include/asm/thread_info.h    |  25 -----
 arch/sh/include/asm/thread_info.h         |  26 -----
 arch/sparc/include/asm/thread_info_64.h   |  24 -----
 arch/tile/include/asm/thread_info.h       |  27 -----
 arch/x86/Kconfig                          |   2 +
 arch/x86/entry/common.c                   |  25 ++---
 arch/x86/entry/entry_32.S                 |  11 +++
 arch/x86/entry/entry_64.S                 |  20 +++-
 arch/x86/entry/vsyscall/vsyscall_64.c     |   6 +-
 arch/x86/include/asm/checksum_32.h        |   3 +-
 arch/x86/include/asm/cpu.h                |   1 -
 arch/x86/include/asm/efi.h                |   1 -
 arch/x86/include/asm/pgtable_types.h      |   2 -
 arch/x86/include/asm/processor.h          |  32 ++++--
 arch/x86/include/asm/smp.h                |   6 --
 arch/x86/include/asm/switch_to.h          |  34 ++++++-
 arch/x86/include/asm/syscall.h            |  23 +----
 arch/x86/include/asm/thread_info.h        | 102 +------------------
 arch/x86/include/asm/traps.h              |   6 ++
 arch/x86/include/asm/uaccess.h            |  10 +-
 arch/x86/kernel/asm-offsets.c             |   5 +-
 arch/x86/kernel/cpu/common.c              |   2 +-
 arch/x86/kernel/dumpstack.c               |  20 +++-
 arch/x86/kernel/dumpstack_32.c            |   4 +-
 arch/x86/kernel/dumpstack_64.c            |  16 ++-
 arch/x86/kernel/fpu/init.c                |   1 -
 arch/x86/kernel/irq_64.c                  |   3 +-
 arch/x86/kernel/process.c                 |   6 +-
 arch/x86/kernel/process_64.c              |   4 +-
 arch/x86/kernel/ptrace.c                  |   2 +-
 arch/x86/kernel/smpboot.c                 |   1 -
 arch/x86/kernel/traps.c                   |  32 ++++++
 arch/x86/lib/copy_user_64.S               |   8 +-
 arch/x86/lib/csum-wrappers_64.c           |   1 +
 arch/x86/lib/getuser.S                    |  20 ++--
 arch/x86/lib/putuser.S                    |  10 +-
 arch/x86/lib/usercopy_64.c                |   2 +-
 arch/x86/mm/extable.c                     |   2 +-
 arch/x86/mm/fault.c                       |  41 +++++++-
 arch/x86/mm/init_64.c                     |  27 -----
 arch/x86/mm/pageattr.c                    |  32 +-----
 arch/x86/mm/tlb.c                         |  15 +++
 arch/x86/platform/efi/efi.c               |   2 -
 arch/x86/platform/efi/efi_32.c            |   3 -
 arch/x86/platform/efi/efi_64.c            |   5 -
 arch/x86/um/ptrace_32.c                   |   8 +-
 drivers/base/node.c                       |   3 +-
 drivers/pnp/isapnp/proc.c                 |   2 +-
 fs/proc/meminfo.c                         |   2 +-
 include/linux/init_task.h                 |   9 ++
 include/linux/kdb.h                       |   2 +-
 include/linux/memcontrol.h                |   2 +-
 include/linux/mmzone.h                    |   2 +-
 include/linux/sched.h                     | 115 +++++++++++++++++++++-
 include/linux/thread_info.h               |  56 +++--------
 init/Kconfig                              |   3 +
 init/init_task.c                          |   7 +-
 kernel/fork.c                             | 158 +++++++++++++++++++++++++-----
 kernel/sched/core.c                       |   9 ++
 kernel/sched/sched.h                      |   4 +
 lib/bitmap.c                              |   2 +-
 lib/dma-debug.c                           |  39 ++++++--
 mm/memcontrol.c                           |   2 +-
 mm/page_alloc.c                           |   3 +-
 net/bluetooth/smp.c                       |  67 ++++++-------
 net/rxrpc/ar-internal.h                   |   1 +
 net/rxrpc/rxkad.c                         | 103 ++++++++-----------
 71 files changed, 714 insertions(+), 648 deletions(-)

-- 
2.7.4

[toc] | [next] | [standalone]


#1431601 — [PATCH v4 07/29] mm: Fix memcg stack accounting for sub-page stacks

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 07/29] mm: Fix memcg stack accounting for sub-page stacks
Message-ID<rOqfU-8f8-17@gated-at.bofh.it>
In reply to#1431600
We should account for stacks regardless of stack size, and we need
to account in sub-page units if THREAD_SIZE < PAGE_SIZE.  Change the
units to kilobytes and Move it into account_kernel_stack().

Fixes: 12580e4b54ba8 ("mm: memcontrol: report kernel stack usage in cgroup2 memory.stat")
Cc: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: linux-mm@kvack.org
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 include/linux/memcontrol.h |  2 +-
 kernel/fork.c              | 19 ++++++++-----------
 mm/memcontrol.c            |  2 +-
 3 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index a805474df4ab..3b653b86bb8f 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -52,7 +52,7 @@ enum mem_cgroup_stat_index {
 	MEM_CGROUP_STAT_SWAP,		/* # of pages, swapped out */
 	MEM_CGROUP_STAT_NSTATS,
 	/* default hierarchy stats */
-	MEMCG_KERNEL_STACK = MEM_CGROUP_STAT_NSTATS,
+	MEMCG_KERNEL_STACK_KB = MEM_CGROUP_STAT_NSTATS,
 	MEMCG_SLAB_RECLAIMABLE,
 	MEMCG_SLAB_UNRECLAIMABLE,
 	MEMCG_SOCK,
diff --git a/kernel/fork.c b/kernel/fork.c
index 466ba8febe3b..146c9840c079 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -165,20 +165,12 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
 	struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP,
 						  THREAD_SIZE_ORDER);
 
-	if (page)
-		memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK,
-					    1 << THREAD_SIZE_ORDER);
-
 	return page ? page_address(page) : NULL;
 }
 
 static inline void free_thread_stack(unsigned long *stack)
 {
-	struct page *page = virt_to_page(stack);
-
-	memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK,
-				    -(1 << THREAD_SIZE_ORDER));
-	__free_kmem_pages(page, THREAD_SIZE_ORDER);
+	free_kmem_pages((unsigned long)stack, THREAD_SIZE_ORDER);
 }
 # else
 static struct kmem_cache *thread_stack_cache;
@@ -223,10 +215,15 @@ static struct kmem_cache *mm_cachep;
 
 static void account_kernel_stack(unsigned long *stack, int account)
 {
-	struct zone *zone = page_zone(virt_to_page(stack));
+	/* All stack pages are in the same zone and belong to the same memcg. */
+	struct page *first_page = virt_to_page(stack);
 
-	mod_zone_page_state(zone, NR_KERNEL_STACK_KB,
+	mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB,
 			    THREAD_SIZE / 1024 * account);
+
+	memcg_kmem_update_page_stat(
+		first_page, MEMCG_KERNEL_STACK_KB,
+		account * (THREAD_SIZE / 1024));
 }
 
 void free_task(struct task_struct *tsk)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index ac8664db3823..ee44afc1f2d0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5133,7 +5133,7 @@ static int memory_stat_show(struct seq_file *m, void *v)
 	seq_printf(m, "file %llu\n",
 		   (u64)stat[MEM_CGROUP_STAT_CACHE] * PAGE_SIZE);
 	seq_printf(m, "kernel_stack %llu\n",
-		   (u64)stat[MEMCG_KERNEL_STACK] * PAGE_SIZE);
+		   (u64)stat[MEMCG_KERNEL_STACK_KB] * 1024);
 	seq_printf(m, "slab %llu\n",
 		   (u64)(stat[MEMCG_SLAB_RECLAIMABLE] +
 			 stat[MEMCG_SLAB_UNRECLAIMABLE]) * PAGE_SIZE);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1431602 — [PATCH v4 24/29] x86/entry: Get rid of pt_regs_to_thread_info()

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 24/29] x86/entry: Get rid of pt_regs_to_thread_info()
Message-ID<rOqfU-8f8-25@gated-at.bofh.it>
In reply to#1431600
From: Linus Torvalds <torvalds@linux-foundation.org>

It was a nice optimization while it lasted, but thread_info is moving
and this optimization will no longer work.

Quoting Linus:

    Oh Gods, Andy. That pt_regs_to_thread_info() thing made me want
    to do unspeakable acts on a poor innocent wax figure that looked
    _exactly_ like you.

[changelog written by Andy]
Message-Id: <CA+55aFxvZhBu9U1cqpVm4frv0p5mqu=0TxsSqE-=95ft8HvCVA@mail.gmail.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/entry/common.c | 21 +++++++--------------
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index c4150bec7982..804487f126cb 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -31,13 +31,6 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
-static struct thread_info *pt_regs_to_thread_info(struct pt_regs *regs)
-{
-	unsigned long top_of_stack =
-		(unsigned long)(regs + 1) + TOP_OF_KERNEL_STACK_PADDING;
-	return (struct thread_info *)(top_of_stack - THREAD_SIZE);
-}
-
 #ifdef CONFIG_CONTEXT_TRACKING
 /* Called on entry from user mode with IRQs off. */
 __visible void enter_from_user_mode(void)
@@ -78,7 +71,7 @@ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
  */
 unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	unsigned long ret = 0;
 	u32 work;
 
@@ -156,7 +149,7 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
 long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
 				unsigned long phase1_result)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	long ret = 0;
 	u32 work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
 
@@ -239,7 +232,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
 		/* Disable IRQs and retry */
 		local_irq_disable();
 
-		cached_flags = READ_ONCE(pt_regs_to_thread_info(regs)->flags);
+		cached_flags = READ_ONCE(current_thread_info()->flags);
 
 		if (!(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
 			break;
@@ -250,7 +243,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
 /* Called with IRQs disabled. */
 __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	u32 cached_flags;
 
 	if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
@@ -309,7 +302,7 @@ static void syscall_slow_exit_work(struct pt_regs *regs, u32 cached_flags)
  */
 __visible inline void syscall_return_slowpath(struct pt_regs *regs)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	u32 cached_flags = READ_ONCE(ti->flags);
 
 	CT_WARN_ON(ct_state() != CONTEXT_KERNEL);
@@ -332,7 +325,7 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)
 #ifdef CONFIG_X86_64
 __visible void do_syscall_64(struct pt_regs *regs)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	unsigned long nr = regs->orig_ax;
 
 	enter_from_user_mode();
@@ -365,7 +358,7 @@ __visible void do_syscall_64(struct pt_regs *regs)
  */
 static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
 {
-	struct thread_info *ti = pt_regs_to_thread_info(regs);
+	struct thread_info *ti = current_thread_info();
 	unsigned int nr = (unsigned int)regs->orig_ax;
 
 #ifdef CONFIG_IA32_EMULATION
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1431603 — [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rOqfU-8f8-37@gated-at.bofh.it>
In reply to#1431600
It's not going to work, because the scheduler will explode if we try
to schedule when running on an IST stack or similar.

This will matter when we let kernel stack overflows (which are #DF)
call die().

Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/kernel/dumpstack.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index ef8017ca5ba9..352f022cfd5b 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -245,6 +245,9 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
 		return;
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
+	if (((current_stack_pointer() ^ (current_top_of_stack() - 1))
+	     & ~(THREAD_SIZE - 1)) != 0)
+		panic("Fatal exception on special stack");
 	if (panic_on_oops)
 		panic("Fatal exception");
 	do_exit(signr);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1435848 — Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromBorislav Petkov <bp@alien8.de>
Date2016-07-02 19:30 +0200
SubjectRe: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rQwTU-6l3-35@gated-at.bofh.it>
In reply to#1431603
On Sun, Jun 26, 2016 at 02:55:32PM -0700, Andy Lutomirski wrote:
> It's not going to work, because the scheduler will explode if we try
> to schedule when running on an IST stack or similar.
> 
> This will matter when we let kernel stack overflows (which are #DF)
> call die().
> 
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
> ---
>  arch/x86/kernel/dumpstack.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
> index ef8017ca5ba9..352f022cfd5b 100644
> --- a/arch/x86/kernel/dumpstack.c
> +++ b/arch/x86/kernel/dumpstack.c
> @@ -245,6 +245,9 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
>  		return;
>  	if (in_interrupt())
>  		panic("Fatal exception in interrupt");
> +	if (((current_stack_pointer() ^ (current_top_of_stack() - 1))
> +	     & ~(THREAD_SIZE - 1)) != 0)

Ugh, that's hard to parse. You could remove the "!= 0" at least to
shorten it a bit and have one less braces level.

Or maybe even do something like that to make it a bit more readable:

        if ((current_stack_pointer() ^ (current_top_of_stack() - 1))
                        &
             ~(THREAD_SIZE - 1))
                panic("Fatal exception on non-default stack");

Meh.

> +		panic("Fatal exception on special stack");

			"Fatal exception on non-default stack"

maybe?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

[toc] | [prev] | [next] | [standalone]


#1435853 — Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromJosh Poimboeuf <jpoimboe@redhat.com>
Date2016-07-02 20:40 +0200
SubjectRe: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rQxZD-6Wy-11@gated-at.bofh.it>
In reply to#1435848
On Sat, Jul 02, 2016 at 07:24:41PM +0200, Borislav Petkov wrote:
> On Sun, Jun 26, 2016 at 02:55:32PM -0700, Andy Lutomirski wrote:
> > It's not going to work, because the scheduler will explode if we try
> > to schedule when running on an IST stack or similar.
> > 
> > This will matter when we let kernel stack overflows (which are #DF)
> > call die().
> > 
> > Signed-off-by: Andy Lutomirski <luto@kernel.org>
> > ---
> >  arch/x86/kernel/dumpstack.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
> > index ef8017ca5ba9..352f022cfd5b 100644
> > --- a/arch/x86/kernel/dumpstack.c
> > +++ b/arch/x86/kernel/dumpstack.c
> > @@ -245,6 +245,9 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
> >  		return;
> >  	if (in_interrupt())
> >  		panic("Fatal exception in interrupt");
> > +	if (((current_stack_pointer() ^ (current_top_of_stack() - 1))
> > +	     & ~(THREAD_SIZE - 1)) != 0)
> 
> Ugh, that's hard to parse. You could remove the "!= 0" at least to
> shorten it a bit and have one less braces level.
> 
> Or maybe even do something like that to make it a bit more readable:
> 
>         if ((current_stack_pointer() ^ (current_top_of_stack() - 1))
>                         &
>              ~(THREAD_SIZE - 1))
>                 panic("Fatal exception on non-default stack");
> 
> Meh.

A helper function would be even better.

The existing 'object_is_on_stack()' can probably be used:

	if (!object_is_on_stack(current_top_of_stack()))
		panic("...");

Though that function isn't quite accurately named.  It should really
have 'task_stack' in its name, like 'object_is_on_task_stack()'.  Or
even better, something more concise like 'on_task_stack()'.

-- 
Josh

[toc] | [prev] | [next] | [standalone]


#1435931 — Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromBorislav Petkov <bp@alien8.de>
Date2016-07-03 11:50 +0200
SubjectRe: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rQMci-73U-11@gated-at.bofh.it>
In reply to#1435853
On Sat, Jul 02, 2016 at 01:34:51PM -0500, Josh Poimboeuf wrote:
> The existing 'object_is_on_stack()' can probably be used:
> 
> 	if (!object_is_on_stack(current_top_of_stack()))
> 		panic("...");
> 
> Though that function isn't quite accurately named.  It should really
> have 'task_stack' in its name, like 'object_is_on_task_stack()'.  Or
> even better, something more concise like 'on_task_stack()'.

So I'm obviously missing something here:

object_is_on_stack() uses task_stack_page(current) -> task_struct.stack
while current_stack_pointer() reads %rsp directly.

I'm guessing %rsp and task_struct.stack are in sync?

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

[toc] | [prev] | [next] | [standalone]


#1435968 — Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromAndy Lutomirski <luto@amacapital.net>
Date2016-07-03 16:30 +0200
SubjectRe: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rQQzf-1jL-1@gated-at.bofh.it>
In reply to#1435853
On Sat, Jul 2, 2016 at 11:34 AM, Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> On Sat, Jul 02, 2016 at 07:24:41PM +0200, Borislav Petkov wrote:
>> On Sun, Jun 26, 2016 at 02:55:32PM -0700, Andy Lutomirski wrote:
>> > It's not going to work, because the scheduler will explode if we try
>> > to schedule when running on an IST stack or similar.
>> >
>> > This will matter when we let kernel stack overflows (which are #DF)
>> > call die().
>> >
>> > Signed-off-by: Andy Lutomirski <luto@kernel.org>
>> > ---
>> >  arch/x86/kernel/dumpstack.c | 3 +++
>> >  1 file changed, 3 insertions(+)
>> >
>> > diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
>> > index ef8017ca5ba9..352f022cfd5b 100644
>> > --- a/arch/x86/kernel/dumpstack.c
>> > +++ b/arch/x86/kernel/dumpstack.c
>> > @@ -245,6 +245,9 @@ void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
>> >             return;
>> >     if (in_interrupt())
>> >             panic("Fatal exception in interrupt");
>> > +   if (((current_stack_pointer() ^ (current_top_of_stack() - 1))
>> > +        & ~(THREAD_SIZE - 1)) != 0)
>>
>> Ugh, that's hard to parse. You could remove the "!= 0" at least to
>> shorten it a bit and have one less braces level.
>>
>> Or maybe even do something like that to make it a bit more readable:
>>
>>         if ((current_stack_pointer() ^ (current_top_of_stack() - 1))
>>                         &
>>              ~(THREAD_SIZE - 1))
>>                 panic("Fatal exception on non-default stack");
>>
>> Meh.
>
> A helper function would be even better.
>
> The existing 'object_is_on_stack()' can probably be used:
>
>         if (!object_is_on_stack(current_top_of_stack()))
>                 panic("...");
>
> Though that function isn't quite accurately named.  It should really
> have 'task_stack' in its name, like 'object_is_on_task_stack()'.  Or
> even better, something more concise like 'on_task_stack()'.
>

Given that the very next patch deletes this code, I vote for leaving
it alone.  Or I could fold the patches together.

--Andy

[toc] | [prev] | [next] | [standalone]


#1436023 — Re: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack

FromBorislav Petkov <bp@alien8.de>
Date2016-07-03 20:50 +0200
SubjectRe: [PATCH v4 10/29] x86/die: Don't try to recover from an OOPS on a non-default stack
Message-ID<rQUCR-3Hu-3@gated-at.bofh.it>
In reply to#1435968
On Sun, Jul 03, 2016 at 07:25:05AM -0700, Andy Lutomirski wrote:
> Given that the very next patch deletes this code, I vote for leaving
> it alone.  Or I could fold the patches together.

Ah, true. Yes, please fold them together.

-- 
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.

[toc] | [prev] | [next] | [standalone]


#1431604 — [PATCH v4 12/29] x86/dumpstack: When dumping stack bytes due to OOPS, start with regs->sp

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 12/29] x86/dumpstack: When dumping stack bytes due to OOPS, start with regs->sp
Message-ID<rOqfU-8f8-27@gated-at.bofh.it>
In reply to#1431600
The comment suggests that show_stack(NULL, NULL) should backtrace
the current context, but the code doesn't match the comment.  If
regs are given, start the "Stack:" hexdump at regs->sp.

Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/kernel/dumpstack_32.c | 4 +++-
 arch/x86/kernel/dumpstack_64.c | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index fef917e79b9d..948d77da3881 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -96,7 +96,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 	int i;
 
 	if (sp == NULL) {
-		if (task)
+		if (regs)
+			sp = (unsigned long *)regs->sp;
+		else if (task)
 			sp = (unsigned long *)task->thread.sp;
 		else
 			sp = (unsigned long *)&sp;
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index d558a8a49016..a81e1ef73bf2 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -264,7 +264,9 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 	 * back trace for this cpu:
 	 */
 	if (sp == NULL) {
-		if (task)
+		if (regs)
+			sp = (unsigned long *)regs->sp;
+		else if (task)
 			sp = (unsigned long *)task->thread.sp;
 		else
 			sp = (unsigned long *)&sp;
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1431605 — [PATCH v4 06/29] mm: Track NR_KERNEL_STACK in KiB instead of number of stacks

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 06/29] mm: Track NR_KERNEL_STACK in KiB instead of number of stacks
Message-ID<rOqfU-8f8-29@gated-at.bofh.it>
In reply to#1431600
Currently, NR_KERNEL_STACK tracks the number of kernel stacks in a
zone.  This only makes sense if each kernel stack exists entirely in
one zone, and allowing vmapped stacks could break this assumption.

Since frv has THREAD_SIZE < PAGE_SIZE, we need to track kernel stack
allocations in a unit that divides both THREAD_SIZE and PAGE_SIZE on
all architectures.  Keep it simple and use KiB.

Cc: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: linux-mm@kvack.org
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 drivers/base/node.c    | 3 +--
 fs/proc/meminfo.c      | 2 +-
 include/linux/mmzone.h | 2 +-
 kernel/fork.c          | 3 ++-
 mm/page_alloc.c        | 3 +--
 5 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/base/node.c b/drivers/base/node.c
index 560751bad294..27dc68a0ed2d 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -121,8 +121,7 @@ static ssize_t node_read_meminfo(struct device *dev,
 		       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
 		       nid, K(node_page_state(nid, NR_ANON_PAGES)),
 		       nid, K(i.sharedram),
-		       nid, node_page_state(nid, NR_KERNEL_STACK) *
-				THREAD_SIZE / 1024,
+		       nid, node_page_state(nid, NR_KERNEL_STACK_KB),
 		       nid, K(node_page_state(nid, NR_PAGETABLE)),
 		       nid, K(node_page_state(nid, NR_UNSTABLE_NFS)),
 		       nid, K(node_page_state(nid, NR_BOUNCE)),
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 83720460c5bc..239b5a06cee0 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -145,7 +145,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 				global_page_state(NR_SLAB_UNRECLAIMABLE)),
 		K(global_page_state(NR_SLAB_RECLAIMABLE)),
 		K(global_page_state(NR_SLAB_UNRECLAIMABLE)),
-		global_page_state(NR_KERNEL_STACK) * THREAD_SIZE / 1024,
+		global_page_state(NR_KERNEL_STACK_KB),
 		K(global_page_state(NR_PAGETABLE)),
 #ifdef CONFIG_QUICKLIST
 		K(quicklist_total_size()),
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 02069c23486d..63f05a7efb54 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -127,7 +127,7 @@ enum zone_stat_item {
 	NR_SLAB_RECLAIMABLE,
 	NR_SLAB_UNRECLAIMABLE,
 	NR_PAGETABLE,		/* used for pagetables */
-	NR_KERNEL_STACK,
+	NR_KERNEL_STACK_KB,	/* measured in KiB */
 	/* Second 128 byte cacheline */
 	NR_UNSTABLE_NFS,	/* NFS unstable pages */
 	NR_BOUNCE,
diff --git a/kernel/fork.c b/kernel/fork.c
index 4a7ec0c6c88c..466ba8febe3b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -225,7 +225,8 @@ static void account_kernel_stack(unsigned long *stack, int account)
 {
 	struct zone *zone = page_zone(virt_to_page(stack));
 
-	mod_zone_page_state(zone, NR_KERNEL_STACK, account);
+	mod_zone_page_state(zone, NR_KERNEL_STACK_KB,
+			    THREAD_SIZE / 1024 * account);
 }
 
 void free_task(struct task_struct *tsk)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 6903b695ebae..a277dea926c9 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4457,8 +4457,7 @@ void show_free_areas(unsigned int filter)
 			K(zone_page_state(zone, NR_SHMEM)),
 			K(zone_page_state(zone, NR_SLAB_RECLAIMABLE)),
 			K(zone_page_state(zone, NR_SLAB_UNRECLAIMABLE)),
-			zone_page_state(zone, NR_KERNEL_STACK) *
-				THREAD_SIZE / 1024,
+			zone_page_state(zone, NR_KERNEL_STACK_KB),
 			K(zone_page_state(zone, NR_PAGETABLE)),
 			K(zone_page_state(zone, NR_UNSTABLE_NFS)),
 			K(zone_page_state(zone, NR_BOUNCE)),
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1431606 — [PATCH v4 14/29] x86/dumpstack/64: Handle faults when printing the "Stack:" part of an OOPS

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 14/29] x86/dumpstack/64: Handle faults when printing the "Stack:" part of an OOPS
Message-ID<rOqfU-8f8-39@gated-at.bofh.it>
In reply to#1431600
If we overflow the stack into a guard page, we'll recursively fault
when trying to dump the contents of the guard page.  Use
probe_kernel_address so we can recover if this happens.

Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/kernel/dumpstack_64.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index a81e1ef73bf2..6dede08dd98b 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -274,6 +274,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 
 	stack = sp;
 	for (i = 0; i < kstack_depth_to_print; i++) {
+		unsigned long word;
+
 		if (stack >= irq_stack && stack <= irq_stack_end) {
 			if (stack == irq_stack_end) {
 				stack = (unsigned long *) (irq_stack_end[-1]);
@@ -283,12 +285,18 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 		if (kstack_end(stack))
 			break;
 		}
+
+		if (probe_kernel_address(stack, word))
+			break;
+
 		if ((i % STACKSLOTS_PER_LINE) == 0) {
 			if (i != 0)
 				pr_cont("\n");
-			printk("%s %016lx", log_lvl, *stack++);
+			printk("%s %016lx", log_lvl, word);
 		} else
-			pr_cont(" %016lx", *stack++);
+			pr_cont(" %016lx", word);
+
+		stack++;
 		touch_nmi_watchdog();
 	}
 	preempt_enable();
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1431607 — [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rOqfU-8f8-33@gated-at.bofh.it>
In reply to#1431600
If an arch opts in by setting CONFIG_THREAD_INFO_IN_TASK_STRUCT,
then thread_info is defined as a single 'u32 flags' and is the first
entry of task_struct.  thread_info::task is removed (it serves no
purpose if thread_info is embedded in task_struct), and
thread_info::cpu gets its own slot in task_struct.

This is heavily based on a patch written by Linus.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 include/linux/init_task.h   |  9 +++++++++
 include/linux/sched.h       | 36 ++++++++++++++++++++++++++++++++++--
 include/linux/thread_info.h | 15 +++++++++++++++
 init/Kconfig                |  3 +++
 init/init_task.c            |  7 +++++--
 kernel/sched/sched.h        |  4 ++++
 6 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index f8834f820ec2..9c04d44eeb3c 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -15,6 +15,8 @@
 #include <net/net_namespace.h>
 #include <linux/sched/rt.h>
 
+#include <asm/thread_info.h>
+
 #ifdef CONFIG_SMP
 # define INIT_PUSHABLE_TASKS(tsk)					\
 	.pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO),
@@ -183,12 +185,19 @@ extern struct task_group root_task_group;
 # define INIT_KASAN(tsk)
 #endif
 
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+# define INIT_TASK_TI(tsk) .thread_info = INIT_THREAD_INFO(tsk),
+#else
+# define INIT_TASK_TI(tsk)
+#endif
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
 #define INIT_TASK(tsk)	\
 {									\
+	INIT_TASK_TI(tsk)						\
 	.state		= 0,						\
 	.stack		= init_stack,					\
 	.usage		= ATOMIC_INIT(2),				\
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 569df670407a..4108b4880b86 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1456,6 +1456,13 @@ struct tlbflush_unmap_batch {
 };
 
 struct task_struct {
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	/*
+	 * For reasons of header soup (see current_thread_info()), this
+	 * must be the first element of task_struct.
+	 */
+	struct thread_info thread_info;
+#endif
 	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
 	void *stack;
 	atomic_t usage;
@@ -1465,6 +1472,9 @@ struct task_struct {
 #ifdef CONFIG_SMP
 	struct llist_node wake_entry;
 	int on_cpu;
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	unsigned int cpu;	/* current CPU */
+#endif
 	unsigned int wakee_flips;
 	unsigned long wakee_flip_decay_ts;
 	struct task_struct *last_wakee;
@@ -2557,7 +2567,9 @@ extern void set_curr_task(int cpu, struct task_struct *p);
 void yield(void);
 
 union thread_union {
+#ifndef CONFIG_THREAD_INFO_IN_TASK
 	struct thread_info thread_info;
+#endif
 	unsigned long stack[THREAD_SIZE/sizeof(long)];
 };
 
@@ -3045,10 +3057,26 @@ static inline void threadgroup_change_end(struct task_struct *tsk)
 	cgroup_threadgroup_change_end(tsk);
 }
 
-#ifndef __HAVE_THREAD_FUNCTIONS
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+
+static inline struct thread_info *task_thread_info(struct task_struct *task)
+{
+	return &task->thread_info;
+}
+static inline void *task_stack_page(const struct task_struct *task)
+{
+	return task->stack;
+}
+#define setup_thread_stack(new,old)	do { } while(0)
+static inline unsigned long *end_of_stack(const struct task_struct *task)
+{
+	return task->stack;
+}
+
+#elif !defined(__HAVE_THREAD_FUNCTIONS)
 
 #define task_thread_info(task)	((struct thread_info *)(task)->stack)
-#define task_stack_page(task)	((task)->stack)
+#define task_stack_page(task)	((void *)(task)->stack)
 
 static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
 {
@@ -3348,7 +3376,11 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
 
 static inline unsigned int task_cpu(const struct task_struct *p)
 {
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	return p->cpu;
+#else
 	return task_thread_info(p)->cpu;
+#endif
 }
 
 static inline int task_node(const struct task_struct *p)
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 352b1542f5cc..b2b32d63bc8e 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -13,6 +13,21 @@
 struct timespec;
 struct compat_timespec;
 
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+struct thread_info {
+	u32			flags;		/* low level flags */
+};
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.flags		= 0,			\
+}
+#endif
+
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+#define current_thread_info() ((struct thread_info *)current)
+#endif
+
 /*
  * System call restart block.
  */
diff --git a/init/Kconfig b/init/Kconfig
index f755a602d4a1..0c83af6d3753 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -26,6 +26,9 @@ config IRQ_WORK
 config BUILDTIME_EXTABLE_SORT
 	bool
 
+config THREAD_INFO_IN_TASK
+	bool
+
 menu "General setup"
 
 config BROKEN
diff --git a/init/init_task.c b/init/init_task.c
index ba0a7f362d9e..11f83be1fa79 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -22,5 +22,8 @@ EXPORT_SYMBOL(init_task);
  * Initial thread structure. Alignment of this is handled by a special
  * linker map entry.
  */
-union thread_union init_thread_union __init_task_data =
-	{ INIT_THREAD_INFO(init_task) };
+union thread_union init_thread_union __init_task_data = {
+#ifndef CONFIG_THREAD_INFO_IN_TASK
+	INIT_THREAD_INFO(init_task)
+#endif
+};
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 7cbeb92a1cb9..a1cabcea4c54 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -999,7 +999,11 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
 	 * per-task data have been completed by this moment.
 	 */
 	smp_wmb();
+#ifdef CONFIG_THREAD_INFO_IN_TASK
+	p->cpu = cpu;
+#else
 	task_thread_info(p)->cpu = cpu;
+#endif
 	p->wake_cpu = cpu;
 #endif
 }
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1440419 — Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromMark Rutland <mark.rutland@arm.com>
Date2016-07-11 12:10 +0200
SubjectRe: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rTGk2-5Co-29@gated-at.bofh.it>
In reply to#1431607
Hi,

On Sun, Jun 26, 2016 at 02:55:48PM -0700, Andy Lutomirski wrote:
> If an arch opts in by setting CONFIG_THREAD_INFO_IN_TASK_STRUCT,
> then thread_info is defined as a single 'u32 flags' and is the first
> entry of task_struct.  thread_info::task is removed (it serves no
> purpose if thread_info is embedded in task_struct), and
> thread_info::cpu gets its own slot in task_struct.
> 
> This is heavily based on a patch written by Linus.

I've been considering how we'd implement this for arm64, and I suspect
that we'll also need to fold our preempt_count into task_struct
(following from the style of asm-generic/preempt.h).

As far as I can see, we can't make our preempt-count a percpu variable
as with x86, as our percpu ops themselves are based on disabling
preemption.

To that end, would it be possible to keep the thread_info definition per
arch, even with CONFIG_THREAD_INFO_IN_TASK?

Thanks,
Mark.

> 
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
> ---
>  include/linux/init_task.h   |  9 +++++++++
>  include/linux/sched.h       | 36 ++++++++++++++++++++++++++++++++++--
>  include/linux/thread_info.h | 15 +++++++++++++++
>  init/Kconfig                |  3 +++
>  init/init_task.c            |  7 +++++--
>  kernel/sched/sched.h        |  4 ++++
>  6 files changed, 70 insertions(+), 4 deletions(-)
> 
> diff --git a/include/linux/init_task.h b/include/linux/init_task.h
> index f8834f820ec2..9c04d44eeb3c 100644
> --- a/include/linux/init_task.h
> +++ b/include/linux/init_task.h
> @@ -15,6 +15,8 @@
>  #include <net/net_namespace.h>
>  #include <linux/sched/rt.h>
>  
> +#include <asm/thread_info.h>
> +
>  #ifdef CONFIG_SMP
>  # define INIT_PUSHABLE_TASKS(tsk)					\
>  	.pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO),
> @@ -183,12 +185,19 @@ extern struct task_group root_task_group;
>  # define INIT_KASAN(tsk)
>  #endif
>  
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +# define INIT_TASK_TI(tsk) .thread_info = INIT_THREAD_INFO(tsk),
> +#else
> +# define INIT_TASK_TI(tsk)
> +#endif
> +
>  /*
>   *  INIT_TASK is used to set up the first task table, touch at
>   * your own risk!. Base=0, limit=0x1fffff (=2MB)
>   */
>  #define INIT_TASK(tsk)	\
>  {									\
> +	INIT_TASK_TI(tsk)						\
>  	.state		= 0,						\
>  	.stack		= init_stack,					\
>  	.usage		= ATOMIC_INIT(2),				\
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 569df670407a..4108b4880b86 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1456,6 +1456,13 @@ struct tlbflush_unmap_batch {
>  };
>  
>  struct task_struct {
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +	/*
> +	 * For reasons of header soup (see current_thread_info()), this
> +	 * must be the first element of task_struct.
> +	 */
> +	struct thread_info thread_info;
> +#endif
>  	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
>  	void *stack;
>  	atomic_t usage;
> @@ -1465,6 +1472,9 @@ struct task_struct {
>  #ifdef CONFIG_SMP
>  	struct llist_node wake_entry;
>  	int on_cpu;
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +	unsigned int cpu;	/* current CPU */
> +#endif
>  	unsigned int wakee_flips;
>  	unsigned long wakee_flip_decay_ts;
>  	struct task_struct *last_wakee;
> @@ -2557,7 +2567,9 @@ extern void set_curr_task(int cpu, struct task_struct *p);
>  void yield(void);
>  
>  union thread_union {
> +#ifndef CONFIG_THREAD_INFO_IN_TASK
>  	struct thread_info thread_info;
> +#endif
>  	unsigned long stack[THREAD_SIZE/sizeof(long)];
>  };
>  
> @@ -3045,10 +3057,26 @@ static inline void threadgroup_change_end(struct task_struct *tsk)
>  	cgroup_threadgroup_change_end(tsk);
>  }
>  
> -#ifndef __HAVE_THREAD_FUNCTIONS
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +
> +static inline struct thread_info *task_thread_info(struct task_struct *task)
> +{
> +	return &task->thread_info;
> +}
> +static inline void *task_stack_page(const struct task_struct *task)
> +{
> +	return task->stack;
> +}
> +#define setup_thread_stack(new,old)	do { } while(0)
> +static inline unsigned long *end_of_stack(const struct task_struct *task)
> +{
> +	return task->stack;
> +}
> +
> +#elif !defined(__HAVE_THREAD_FUNCTIONS)
>  
>  #define task_thread_info(task)	((struct thread_info *)(task)->stack)
> -#define task_stack_page(task)	((task)->stack)
> +#define task_stack_page(task)	((void *)(task)->stack)
>  
>  static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
>  {
> @@ -3348,7 +3376,11 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
>  
>  static inline unsigned int task_cpu(const struct task_struct *p)
>  {
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +	return p->cpu;
> +#else
>  	return task_thread_info(p)->cpu;
> +#endif
>  }
>  
>  static inline int task_node(const struct task_struct *p)
> diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
> index 352b1542f5cc..b2b32d63bc8e 100644
> --- a/include/linux/thread_info.h
> +++ b/include/linux/thread_info.h
> @@ -13,6 +13,21 @@
>  struct timespec;
>  struct compat_timespec;
>  
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +struct thread_info {
> +	u32			flags;		/* low level flags */
> +};
> +
> +#define INIT_THREAD_INFO(tsk)			\
> +{						\
> +	.flags		= 0,			\
> +}
> +#endif
> +
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +#define current_thread_info() ((struct thread_info *)current)
> +#endif
> +
>  /*
>   * System call restart block.
>   */
> diff --git a/init/Kconfig b/init/Kconfig
> index f755a602d4a1..0c83af6d3753 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -26,6 +26,9 @@ config IRQ_WORK
>  config BUILDTIME_EXTABLE_SORT
>  	bool
>  
> +config THREAD_INFO_IN_TASK
> +	bool
> +
>  menu "General setup"
>  
>  config BROKEN
> diff --git a/init/init_task.c b/init/init_task.c
> index ba0a7f362d9e..11f83be1fa79 100644
> --- a/init/init_task.c
> +++ b/init/init_task.c
> @@ -22,5 +22,8 @@ EXPORT_SYMBOL(init_task);
>   * Initial thread structure. Alignment of this is handled by a special
>   * linker map entry.
>   */
> -union thread_union init_thread_union __init_task_data =
> -	{ INIT_THREAD_INFO(init_task) };
> +union thread_union init_thread_union __init_task_data = {
> +#ifndef CONFIG_THREAD_INFO_IN_TASK
> +	INIT_THREAD_INFO(init_task)
> +#endif
> +};
> diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
> index 7cbeb92a1cb9..a1cabcea4c54 100644
> --- a/kernel/sched/sched.h
> +++ b/kernel/sched/sched.h
> @@ -999,7 +999,11 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
>  	 * per-task data have been completed by this moment.
>  	 */
>  	smp_wmb();
> +#ifdef CONFIG_THREAD_INFO_IN_TASK
> +	p->cpu = cpu;
> +#else
>  	task_thread_info(p)->cpu = cpu;
> +#endif
>  	p->wake_cpu = cpu;
>  #endif
>  }
> -- 
> 2.7.4
> 

[toc] | [prev] | [next] | [standalone]


#1440689 — Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromAndy Lutomirski <luto@amacapital.net>
Date2016-07-11 17:00 +0200
SubjectRe: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rTKQG-8n2-1@gated-at.bofh.it>
In reply to#1440419
On Jul 11, 2016 3:08 AM, "Mark Rutland" <mark.rutland@arm.com> wrote:
>
> Hi,
>
> On Sun, Jun 26, 2016 at 02:55:48PM -0700, Andy Lutomirski wrote:
> > If an arch opts in by setting CONFIG_THREAD_INFO_IN_TASK_STRUCT,
> > then thread_info is defined as a single 'u32 flags' and is the first
> > entry of task_struct.  thread_info::task is removed (it serves no
> > purpose if thread_info is embedded in task_struct), and
> > thread_info::cpu gets its own slot in task_struct.
> >
> > This is heavily based on a patch written by Linus.
>
> I've been considering how we'd implement this for arm64, and I suspect
> that we'll also need to fold our preempt_count into task_struct
> (following from the style of asm-generic/preempt.h).
>
> As far as I can see, we can't make our preempt-count a percpu variable
> as with x86, as our percpu ops themselves are based on disabling
> preemption.

How do you intend to find 'current' to get to the preempt count
without first disabling preemption?

>
> To that end, would it be possible to keep the thread_info definition per
> arch, even with CONFIG_THREAD_INFO_IN_TASK?

In principal, yes, but could you alternatively put it in
thread_struct?  My goal here is to encourage people to clean up their
use of thread_info vs thread_struct at the same time.  For x86, that
cleanup was trivial -- most of the work was addressing relative to
current instead of the stack pointer, and that had to happen
regardless.

--Andy

[toc] | [prev] | [next] | [standalone]


#1440698 — Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromMark Rutland <mark.rutland@arm.com>
Date2016-07-11 17:10 +0200
SubjectRe: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rTL0l-ej-3@gated-at.bofh.it>
In reply to#1440689
On Mon, Jul 11, 2016 at 07:55:17AM -0700, Andy Lutomirski wrote:
> On Jul 11, 2016 3:08 AM, "Mark Rutland" <mark.rutland@arm.com> wrote:
> >
> > Hi,
> >
> > On Sun, Jun 26, 2016 at 02:55:48PM -0700, Andy Lutomirski wrote:
> > > If an arch opts in by setting CONFIG_THREAD_INFO_IN_TASK_STRUCT,
> > > then thread_info is defined as a single 'u32 flags' and is the first
> > > entry of task_struct.  thread_info::task is removed (it serves no
> > > purpose if thread_info is embedded in task_struct), and
> > > thread_info::cpu gets its own slot in task_struct.
> > >
> > > This is heavily based on a patch written by Linus.
> >
> > I've been considering how we'd implement this for arm64, and I suspect
> > that we'll also need to fold our preempt_count into task_struct
> > (following from the style of asm-generic/preempt.h).
> >
> > As far as I can see, we can't make our preempt-count a percpu variable
> > as with x86, as our percpu ops themselves are based on disabling
> > preemption.
> 
> How do you intend to find 'current' to get to the preempt count
> without first disabling preemption?

Good point.

For some reason I had convinced myself that it only mattered for RMW
sequences, so evidently I hadn't considered things thoroughly enough. :(

> > To that end, would it be possible to keep the thread_info definition per
> > arch, even with CONFIG_THREAD_INFO_IN_TASK?
> 
> In principal, yes, but could you alternatively put it in
> thread_struct?  My goal here is to encourage people to clean up their
> use of thread_info vs thread_struct at the same time.  For x86, that
> cleanup was trivial -- most of the work was addressing relative to
> current instead of the stack pointer, and that had to happen
> regardless.

I'm more than happy to do that, modulo the above permitting.

Sorry for the noise!

Thanks,
Mark.

[toc] | [prev] | [next] | [standalone]


#1440748 — Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromMark Rutland <mark.rutland@arm.com>
Date2016-07-11 18:40 +0200
SubjectRe: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rTMpr-19f-13@gated-at.bofh.it>
In reply to#1440689
On Mon, Jul 11, 2016 at 09:06:58AM -0700, Linus Torvalds wrote:
> On Jul 11, 2016 7:55 AM, "Andy Lutomirski" <[1]luto@amacapital.net> wrote:
> >
> > How do you intend to find 'current' to get to the preempt count
> > without first disabling preemption?
>
> Actually, that is the classic case of "not a problem".
>
> The thing is, it doesn't matter if you schedule away while looking up
> current or the preempt count - because both values are idempotent wet
> scheduling.
>
> So until you do the wire that actually disables preemption you can
> schedule away as much as you want, and after that write you no longer
> will.

I was assuming a percpu pointer to current (or preempt count).

The percpu offset might be stale at the point you try to dereference
that, even though current itself hasn't changed, and you may access the
wrong CPU's value.

> This is different wrt a per-cpu area - which is clearly not idempotent wrt
> scheduling.
>
> The reason per-cpu works on x86 is that we have an atomic rmw operation
> that is *also* atomic wrt the CPU lookup (thanks to the segment base)

Sure, understood.

Mark.

[toc] | [prev] | [next] | [standalone]


#1440762 — Re: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2016-07-11 18:50 +0200
SubjectRe: [kernel-hardening] [PATCH v4 26/29] sched: Allow putting thread_info into task_struct
Message-ID<rTMz8-1cS-29@gated-at.bofh.it>
In reply to#1440748
On Mon, Jul 11, 2016 at 9:31 AM, Mark Rutland <mark.rutland@arm.com> wrote:
>>
>> So until you do the wire that actually disables preemption you can
>> schedule away as much as you want, and after that write you no longer
>> will.
>
> I was assuming a percpu pointer to current (or preempt count).

So for the same reason that is ok *iff* you have

 - some kind of dedicated percpu register (or other base pointer - x86
has the segment thing) that gets updated when you schedule.

 - an instruction that can load 'current' directly off that register atomically.

But yes, percpu data in general is obviously not safe to access
without preemption.

         Linus

[toc] | [prev] | [next] | [standalone]


#1431608 — [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about vmapped stacks

FromAndy Lutomirski <luto@kernel.org>
Date2016-06-27 00:00 +0200
Subject[PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about vmapped stacks
Message-ID<rOqfU-8f8-35@gated-at.bofh.it>
In reply to#1431600
If we're using CONFIG_VMAP_STACK and we manage to point an sg entry
at the stack, then either the sg page will be in highmem or sg_virt
will return the direct-map alias.  In neither case will the existing
check_for_stack() implementation realize that it's a stack page.

Fix it by explicitly checking for stack pages.

This has no effect by itself.  It's broken out for ease of review.

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 lib/dma-debug.c | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 51a76af25c66..5b2e63cba90e 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -22,6 +22,7 @@
 #include <linux/stacktrace.h>
 #include <linux/dma-debug.h>
 #include <linux/spinlock.h>
+#include <linux/vmalloc.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/export.h>
@@ -1162,11 +1163,35 @@ static void check_unmap(struct dma_debug_entry *ref)
 	put_hash_bucket(bucket, &flags);
 }
 
-static void check_for_stack(struct device *dev, void *addr)
+static void check_for_stack(struct device *dev,
+			    struct page *page, size_t offset)
 {
-	if (object_is_on_stack(addr))
-		err_printk(dev, NULL, "DMA-API: device driver maps memory from "
-				"stack [addr=%p]\n", addr);
+	void *addr;
+	struct vm_struct *stack_vm_area = task_stack_vm_area(current);
+
+	if (!stack_vm_area) {
+		/* Stack is direct-mapped. */
+		if (PageHighMem(page))
+			return;
+		addr = page_address(page) + offset;
+		if (object_is_on_stack(addr))
+			err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [addr=%p]\n",
+				   addr);
+	} else {
+		/* Stack is vmalloced. */
+		int i;
+
+		for (i = 0; i < stack_vm_area->nr_pages; i++) {
+			if (page != stack_vm_area->pages[i])
+				continue;
+
+			addr = (u8 *)current->stack + i * PAGE_SIZE +
+				offset;
+			err_printk(dev, NULL, "DMA-API: device driver maps memory from stack [probable addr=%p]\n",
+				   addr);
+			break;
+		}
+	}
 }
 
 static inline bool overlap(void *addr, unsigned long len, void *start, void *end)
@@ -1289,10 +1314,11 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 	if (map_single)
 		entry->type = dma_debug_single;
 
+	check_for_stack(dev, page, offset);
+
 	if (!PageHighMem(page)) {
 		void *addr = page_address(page) + offset;
 
-		check_for_stack(dev, addr);
 		check_for_illegal_area(dev, addr, size);
 	}
 
@@ -1384,8 +1410,9 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
 		entry->sg_call_ents   = nents;
 		entry->sg_mapped_ents = mapped_ents;
 
+		check_for_stack(dev, sg_page(s), s->offset);
+
 		if (!PageHighMem(sg_page(s))) {
-			check_for_stack(dev, sg_virt(s));
 			check_for_illegal_area(dev, sg_virt(s), sg_dma_len(s));
 		}
 
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1434811 — Re: [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about vmapped stacks

FromBorislav Petkov <bp@alien8.de>
Date2016-06-30 21:40 +0200
SubjectRe: [PATCH v4 08/29] dma-api: Teach the "DMA-from-stack" check about vmapped stacks
Message-ID<rPPYB-58Z-25@gated-at.bofh.it>
In reply to#1431608
On Sun, Jun 26, 2016 at 02:55:30PM -0700, Andy Lutomirski wrote:
> If we're using CONFIG_VMAP_STACK and we manage to point an sg entry
> at the stack, then either the sg page will be in highmem or sg_virt
> will return the direct-map alias.  In neither case will the existing
> check_for_stack() implementation realize that it's a stack page.
> 
> Fix it by explicitly checking for stack pages.
> 
> This has no effect by itself.  It's broken out for ease of review.
> 
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Andy Lutomirski <luto@kernel.org>
> ---
>  lib/dma-debug.c | 39 +++++++++++++++++++++++++++++++++------
>  1 file changed, 33 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/dma-debug.c b/lib/dma-debug.c
> index 51a76af25c66..5b2e63cba90e 100644
> --- a/lib/dma-debug.c
> +++ b/lib/dma-debug.c
> @@ -22,6 +22,7 @@
>  #include <linux/stacktrace.h>
>  #include <linux/dma-debug.h>
>  #include <linux/spinlock.h>
> +#include <linux/vmalloc.h>
>  #include <linux/debugfs.h>
>  #include <linux/uaccess.h>
>  #include <linux/export.h>
> @@ -1162,11 +1163,35 @@ static void check_unmap(struct dma_debug_entry *ref)
>  	put_hash_bucket(bucket, &flags);
>  }
>  
> -static void check_for_stack(struct device *dev, void *addr)
> +static void check_for_stack(struct device *dev,
> +			    struct page *page, size_t offset)
>  {
> -	if (object_is_on_stack(addr))
> -		err_printk(dev, NULL, "DMA-API: device driver maps memory from "
> -				"stack [addr=%p]\n", addr);
> +	void *addr;
> +	struct vm_struct *stack_vm_area = task_stack_vm_area(current);

lib/dma-debug.c: In function ‘check_for_stack’:
lib/dma-debug.c:1170:36: error: implicit declaration of function ‘task_stack_vm_area’ [-Werror=implicit-function-declaration]
  struct vm_struct *stack_vm_area = task_stack_vm_area(current);
                                    ^
lib/dma-debug.c:1170:36: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
cc1: some warnings being treated as errors
make[1]: *** [lib/dma-debug.o] Error 1
make: *** [lib] Error 2
make: *** Waiting for unfinished jobs....

Probably reorder pieces from patch 9 to earlier ones...

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | linux.kernel


csiph-web