Linux userland API discussions
 help / color / mirror / Atom feed
* [PATCH RFT v9 0/8] fork: Support shadow stacks in clone3()
From: Mark Brown @ 2024-08-19 19:24 UTC (permalink / raw)
  To: Rick P. Edgecombe, Deepak Gupta, Szabolcs Nagy, H.J. Lu,
	Florian Weimer, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Christian Brauner, Shuah Khan
  Cc: linux-kernel, Catalin Marinas, Will Deacon, jannh, bsegall,
	Yury Khrustalev, Wilco Dijkstra, linux-kselftest, linux-api,
	Mark Brown, Kees Cook, Kees Cook, Shuah Khan, David Hildenbrand,
	Mike Rapoport (IBM)

The kernel has recently added support for shadow stacks, currently
x86 only using their CET feature but both arm64 and RISC-V have
equivalent features (GCS and Zicfiss respectively), I am actively
working on GCS[1].  With shadow stacks the hardware maintains an
additional stack containing only the return addresses for branch
instructions which is not generally writeable by userspace and ensures
that any returns are to the recorded addresses.  This provides some
protection against ROP attacks and making it easier to collect call
stacks.  These shadow stacks are allocated in the address space of the
userspace process.

Our API for shadow stacks does not currently offer userspace any
flexiblity for managing the allocation of shadow stacks for newly
created threads, instead the kernel allocates a new shadow stack with
the same size as the normal stack whenever a thread is created with the
feature enabled.  The stacks allocated in this way are freed by the
kernel when the thread exits or shadow stacks are disabled for the
thread.  This lack of flexibility and control isn't ideal, in the vast
majority of cases the shadow stack will be over allocated and the
implicit allocation and deallocation is not consistent with other
interfaces.  As far as I can tell the interface is done in this manner
mainly because the shadow stack patches were in development since before
clone3() was implemented.

Since clone3() is readily extensible let's add support for specifying a
shadow stack when creating a new thread or process in a similar manner
to how the normal stack is specified, keeping the current implicit
allocation behaviour if one is not specified either with clone3() or
through the use of clone().  The user must provide a shadow stack
address and size, this must point to memory mapped for use as a shadow
stackby map_shadow_stack() with a shadow stack token at the top of the
stack.

Please note that the x86 portions of this code are build tested only, I
don't appear to have a system that can run CET avaible to me, I have
done testing with an integration into my pending work for GCS.  There is
some possibility that the arm64 implementation may require the use of
clone3() and explicit userspace allocation of shadow stacks, this is
still under discussion.

Please further note that the token consumption done by clone3() is not
currently implemented in an atomic fashion, Rick indicated that he would
look into fixing this if people are OK with the implementation.

A new architecture feature Kconfig option for shadow stacks is added as
here, this was suggested as part of the review comments for the arm64
GCS series and since we need to detect if shadow stacks are supported it
seemed sensible to roll it in here.

[1] https://lore.kernel.org/r/20231009-arm64-gcs-v6-0-78e55deaa4dd@kernel.org/

Signed-off-by: Mark Brown <broonie@kernel.org>
---
Changes in v9:
- Pull token validation earlier and report problems with an error return
  to parent rather than signal delivery to the child.
- Verify that the top of the supplied shadow stack is VM_SHADOW_STACK.
- Rework token validation to only do the page mapping once.
- Drop no longer needed support for testing for signals in selftest.
- Fix typo in comments.
- Link to v8: https://lore.kernel.org/r/20240808-clone3-shadow-stack-v8-0-0acf37caf14c@kernel.org

Changes in v8:
- Fix token verification with user specified shadow stack.
- Don't track user managed shadow stacks for child processes.
- Link to v7: https://lore.kernel.org/r/20240731-clone3-shadow-stack-v7-0-a9532eebfb1d@kernel.org

Changes in v7:
- Rebase onto v6.11-rc1.
- Typo fixes.
- Link to v6: https://lore.kernel.org/r/20240623-clone3-shadow-stack-v6-0-9ee7783b1fb9@kernel.org

Changes in v6:
- Rebase onto v6.10-rc3.
- Ensure we don't try to free the parent shadow stack in error paths of
  x86 arch code.
- Spelling fixes in userspace API document.
- Additional cleanups and improvements to the clone3() tests to support
  the shadow stack tests.
- Link to v5: https://lore.kernel.org/r/20240203-clone3-shadow-stack-v5-0-322c69598e4b@kernel.org

Changes in v5:
- Rebase onto v6.8-rc2.
- Rework ABI to have the user allocate the shadow stack memory with
  map_shadow_stack() and a token.
- Force inlining of the x86 shadow stack enablement.
- Move shadow stack enablement out into a shared header for reuse by
  other tests.
- Link to v4: https://lore.kernel.org/r/20231128-clone3-shadow-stack-v4-0-8b28ffe4f676@kernel.org

Changes in v4:
- Formatting changes.
- Use a define for minimum shadow stack size and move some basic
  validation to fork.c.
- Link to v3: https://lore.kernel.org/r/20231120-clone3-shadow-stack-v3-0-a7b8ed3e2acc@kernel.org

Changes in v3:
- Rebase onto v6.7-rc2.
- Remove stale shadow_stack in internal kargs.
- If a shadow stack is specified unconditionally use it regardless of
  CLONE_ parameters.
- Force enable shadow stacks in the selftest.
- Update changelogs for RISC-V feature rename.
- Link to v2: https://lore.kernel.org/r/20231114-clone3-shadow-stack-v2-0-b613f8681155@kernel.org

Changes in v2:
- Rebase onto v6.7-rc1.
- Remove ability to provide preallocated shadow stack, just specify the
  desired size.
- Link to v1: https://lore.kernel.org/r/20231023-clone3-shadow-stack-v1-0-d867d0b5d4d0@kernel.org

---
Mark Brown (8):
      Documentation: userspace-api: Add shadow stack API documentation
      selftests: Provide helper header for shadow stack testing
      mm: Introduce ARCH_HAS_USER_SHADOW_STACK
      fork: Add shadow stack support to clone3()
      selftests/clone3: Remove redundant flushes of output streams
      selftests/clone3: Factor more of main loop into test_clone3()
      selftests/clone3: Allow tests to flag if -E2BIG is a valid error code
      selftests/clone3: Test shadow stack support

 Documentation/userspace-api/index.rst             |   1 +
 Documentation/userspace-api/shadow_stack.rst      |  41 ++++
 arch/x86/Kconfig                                  |   1 +
 arch/x86/include/asm/shstk.h                      |  11 +-
 arch/x86/kernel/process.c                         |   2 +-
 arch/x86/kernel/shstk.c                           | 103 +++++++---
 fs/proc/task_mmu.c                                |   2 +-
 include/linux/mm.h                                |   2 +-
 include/linux/sched/task.h                        |  18 ++
 include/uapi/linux/sched.h                        |  13 +-
 kernel/fork.c                                     | 114 +++++++++--
 mm/Kconfig                                        |   6 +
 tools/testing/selftests/clone3/clone3.c           | 230 ++++++++++++++++++----
 tools/testing/selftests/clone3/clone3_selftests.h |  40 +++-
 tools/testing/selftests/ksft_shstk.h              |  63 ++++++
 15 files changed, 560 insertions(+), 87 deletions(-)
---
base-commit: 8400291e289ee6b2bf9779ff1c83a291501f017b
change-id: 20231019-clone3-shadow-stack-15d40d2bf536

Best regards,
-- 
Mark Brown <broonie@kernel.org>


^ permalink raw reply

* Re: [PATCH v3 1/3] riscv: mm: Use hint address in mmap if available
From: Charlie Jenkins @ 2024-08-19 17:00 UTC (permalink / raw)
  To: Levi Zim
  Cc: Palmer Dabbelt, cyy, alexghiti, Paul Walmsley, aou, shuah, corbet,
	linux-mm, linux-riscv, linux-kernel, linux-kselftest, linux-doc,
	linux-api
In-Reply-To: <MEYP282MB2312106710775098261AB348C68C2@MEYP282MB2312.AUSP282.PROD.OUTLOOK.COM>

On Mon, Aug 19, 2024 at 01:55:57PM +0800, Levi Zim wrote:
> On 2024-03-22 22:06, Palmer Dabbelt wrote:
> > On Thu, 01 Feb 2024 18:28:06 PST (-0800), Charlie Jenkins wrote:
> > > On Wed, Jan 31, 2024 at 11:59:43PM +0800, Yangyu Chen wrote:
> > > > On Wed, 2024-01-31 at 22:41 +0800, Yangyu Chen wrote:
> > > > > On Tue, 2024-01-30 at 17:07 -0800, Charlie Jenkins wrote:
> > > > > > On riscv it is guaranteed that the address returned by mmap is less
> > > > > > than
> > > > > > the hint address. Allow mmap to return an address all the way up to
> > > > > > addr, if provided, rather than just up to the lower address space.
> > > > > > > > This provides a performance benefit as well, allowing
> > > > mmap to exit
> > > > > > after
> > > > > > checking that the address is in range rather than searching for a
> > > > > > valid
> > > > > > address.
> > > > > > > > It is possible to provide an address that uses at most the same
> > > > > > number
> > > > > > of bits, however it is significantly more computationally expensive
> > > > > > to
> > > > > > provide that number rather than setting the max to be the hint
> > > > > > address.
> > > > > > There is the instruction clz/clzw in Zbb that returns the highest
> > > > > > set
> > > > > > bit
> > > > > > which could be used to performantly implement this, but it would
> > > > > > still
> > > > > > be slower than the current implementation. At worst case, half of
> > > > > > the
> > > > > > address would not be able to be allocated when a hint address is
> > > > > > provided.
> > > > > > > > Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
> > > > > > ---
> > > > > >  arch/riscv/include/asm/processor.h | 27 +++++++++++---------------
> > > > > > -
> > > > > >  1 file changed, 11 insertions(+), 16 deletions(-)
> > > > > > > > diff --git a/arch/riscv/include/asm/processor.h
> > > > > > b/arch/riscv/include/asm/processor.h
> > > > > > index f19f861cda54..8ece7a8f0e18 100644
> > > > > > --- a/arch/riscv/include/asm/processor.h
> > > > > > +++ b/arch/riscv/include/asm/processor.h
> > > > > > @@ -14,22 +14,16 @@
> > > > > >
> > > > > >  #include <asm/ptrace.h>
> > > > > >
> > > > > > -#ifdef CONFIG_64BIT
> > > > > > -#define DEFAULT_MAP_WINDOW    (UL(1) << (MMAP_VA_BITS - 1))
> > > > > > -#define STACK_TOP_MAX        TASK_SIZE_64
> > > > > > -
> > > > > >  #define arch_get_mmap_end(addr, len, flags)            \
> > > > > >  ({                                \
> > > > > >      unsigned long
> > > > > > mmap_end;                    \
> > > > > >      typeof(addr) _addr = (addr);                \
> > > > > > -    if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) &&
> > > > > > is_compat_task())) \
> > > > > > +    if ((_addr) == 0 ||                    \
> > > > > > +        (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||    \
> > > > > > +        ((_addr + len) > BIT(VA_BITS -
> > > > > > 1)))            \
> > > > > >          mmap_end = STACK_TOP_MAX;            \
> > > > > > -    else if ((_addr) >= VA_USER_SV57) \
> > > > > > -        mmap_end = STACK_TOP_MAX;            \
> > > > > > -    else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >=
> > > > > > VA_BITS_SV48)) \
> > > > > > -        mmap_end = VA_USER_SV48;            \
> > > > > >      else                            \
> > > > > > -        mmap_end = VA_USER_SV39;            \
> > > > > > +        mmap_end = (_addr + len);            \
> > > > > >      mmap_end;                        \
> > > > > >  })
> > > > > >
> > > > > > @@ -39,17 +33,18 @@
> > > > > >      typeof(addr) _addr = (addr);                \
> > > > > >      typeof(base) _base = (base);                \
> > > > > >      unsigned long rnd_gap = DEFAULT_MAP_WINDOW - (_base);    \
> > > > > > -    if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) &&
> > > > > > is_compat_task())) \
> > > > > > +    if ((_addr) == 0 ||                    \
> > > > > > +        (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||    \
> > > > > > +        ((_addr + len) > BIT(VA_BITS -
> > > > > > 1)))            \
> > > > > >          mmap_base = (_base);                \
> > > > > > -    else if (((_addr) >= VA_USER_SV57) && (VA_BITS >=
> > > > > > VA_BITS_SV57)) \
> > > > > > -        mmap_base = VA_USER_SV57 - rnd_gap; \
> > > > > > -    else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >=
> > > > > > VA_BITS_SV48)) \
> > > > > > -        mmap_base = VA_USER_SV48 - rnd_gap; \
> > > > > >      else                            \
> > > > > > -        mmap_base = VA_USER_SV39 - rnd_gap; \
> > > > > > +        mmap_base = (_addr + len) - rnd_gap; \
> > > > > >      mmap_base;                        \
> > > > > >  })
> > > > > >
> > > > > > +#ifdef CONFIG_64BIT
> > > > > > +#define DEFAULT_MAP_WINDOW    (UL(1) << (MMAP_VA_BITS - 1))
> > > > > > +#define STACK_TOP_MAX        TASK_SIZE_64
> > > > > >  #else
> > > > > >  #define DEFAULT_MAP_WINDOW    TASK_SIZE
> > > > > >  #define STACK_TOP_MAX        TASK_SIZE
> > > > > > > > I have carefully tested your patch on qemu with sv57. A
> > > > bug that
> > > > > needs
> > > > > to be solved is that mmap with the same hint address without
> > > > > MAP_FIXED
> > > > > set will fail the second time.
> > > > > > Userspace code to reproduce the bug:
> > > > > > #include <sys/mman.h>
> > > > > #include <stdio.h>
> > > > > #include <stdint.h>
> > > > > > void test(char *addr) {
> > > > >     char *res = mmap(addr, 4096, PROT_READ | PROT_WRITE,
> > > > > MAP_ANONYMOUS
> > > > > > MAP_PRIVATE, -1, 0);
> > > > >     printf("hint %p got %p.\n", addr, res);
> > > > > }
> > > > > > int main (void) {
> > > > >     test(1<<30);
> > > > >     test(1<<30);
> > > > >     test(1<<30);
> > > > >     return 0;
> > > > > }
> > > > > > output:
> > > > > > hint 0x40000000 got 0x40000000.
> > > > > hint 0x40000000 got 0xffffffffffffffff.
> > > > > hint 0x40000000 got 0xffffffffffffffff.
> > > > > > output on x86:
> > > > > > hint 0x40000000 got 0x40000000.
> > > > > hint 0x40000000 got 0x7f9171363000.
> > > > > hint 0x40000000 got 0x7f9171362000.
> > > > > > It may need to implement a special arch_get_unmapped_area and
> > > > > arch_get_unmapped_area_topdown function.
> > > > >
> > > > This is because hint address < rnd_gap. I have tried to let mmap_base =
> > > > min((_addr + len), (base) + TASK_SIZE - DEFAULT_MAP_WINDOW). However it
> > > > does not work for bottom-up while ulimit -s is unlimited. You said this
> > > > behavior is expected from patch v2 review. However it brings a new
> > > > regression even on sv39 systems.
> > > > 
> > > > I still don't know the reason why use addr+len as the upper-bound. I
> > > > think solution like x86/arm64/powerpc provide two address space switch
> > > > based on whether hint address above the default map window is enough.
> > > > 
> > > 
> > > Yep this is expected. It is up to the maintainers to decide.
> > 
> > Sorry I forgot to reply to this, I had a buffer sitting around somewhere
> > but I must have lost it.
> > 
> > I think Charlie's approach is the right way to go.  Putting my userspace
> > hat on, I'd much rather have my allocations fail rather than silently
> > ignore the hint when there's memory pressure.
> > 
> > If there's some real use case that needs these low hints to be silently
> > ignored under VA pressure then we can try and figure something out that
> > makes those applications work.
> 
> I could confirm that this patch has broken chromium's partition allocator on
> riscv64. The minimal reproduction I use is chromium-mmap.c:
> 
> #include <stdio.h>
> #include <sys/mman.h>
> 
> int main() {
>     void* expected = (void*)0x400000000;
>     void* addr = mmap(expected, 17179869184, PROT_NONE,
> MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
>     if (addr != expected) {

It is not valid to assume that the address returned by mmap will be the
hint address. If the hint address is not available, mmap will return a
different address.

>         printf("Not expected address: %p != %p\n", addr, expected);
>     }
>     expected = (void*)0x3fffff000;
>     addr = mmap(expected, 17179873280, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS,
> -1, 0);
>     if (addr != expected) {
>         printf("Not expected address: %p != %p\n", addr, expected);
>     }
>     return 0;
> }
> 
> The second mmap fails with ENOMEM. Manually reverting this commit fixes the
> issue for me. So I think it's clearly a regression and breaks userspace.
> 

The issue here is that overlapping memory is being requested. This
second mmap will never be able to provide an address at 0x3fffff000 with
a size of 0x400001000 since mmap just provided an address at 0x400000000
with a size of 0x400000000.

Before this patch, this request causes mmap to return a completely
arbitrary value. There is no reason to use a hint address in this manner
because the hint can never be respected. Since an arbitrary address is
desired, a hint of zero should be used.

This patch causes the behavior to be more deterministic. Instead of
providing an arbitrary address, it causes the address to be less than or
equal to the hint address. This allows for applications to make
assumptions about the returned address.

This code is unfortunately relying on the previously mostly undefined
behavior of the hint address in mmap. The goal of this patch is to help
developers have more consistent mmap behavior, but maybe it is necessary
to hide this behavior behind an mmap flag.

- Charlie

> See also https://github.com/riscv-forks/electron/issues/4
> 
> > > 
> > > - Charlie
> 
> Sincerely,
> Levi
> 

^ permalink raw reply

* Re: [PATCH v3 1/3] riscv: mm: Use hint address in mmap if available
From: Levi Zim @ 2024-08-19  5:55 UTC (permalink / raw)
  To: Palmer Dabbelt, Charlie Jenkins
  Cc: cyy, alexghiti, Paul Walmsley, aou, shuah, corbet, linux-mm,
	linux-riscv, linux-kernel, linux-kselftest, linux-doc, linux-api
In-Reply-To: <mhng-5d9bb6c0-9f40-44b2-b9dc-3823cf6dbdef@palmer-ri-x1c9>

On 2024-03-22 22:06, Palmer Dabbelt wrote:
> On Thu, 01 Feb 2024 18:28:06 PST (-0800), Charlie Jenkins wrote:
>> On Wed, Jan 31, 2024 at 11:59:43PM +0800, Yangyu Chen wrote:
>>> On Wed, 2024-01-31 at 22:41 +0800, Yangyu Chen wrote:
>>> > On Tue, 2024-01-30 at 17:07 -0800, Charlie Jenkins wrote:
>>> > > On riscv it is guaranteed that the address returned by mmap is less
>>> > > than
>>> > > the hint address. Allow mmap to return an address all the way up to
>>> > > addr, if provided, rather than just up to the lower address space.
>>> > > > > This provides a performance benefit as well, allowing mmap 
>>> to exit
>>> > > after
>>> > > checking that the address is in range rather than searching for a
>>> > > valid
>>> > > address.
>>> > > > > It is possible to provide an address that uses at most the same
>>> > > number
>>> > > of bits, however it is significantly more computationally expensive
>>> > > to
>>> > > provide that number rather than setting the max to be the hint
>>> > > address.
>>> > > There is the instruction clz/clzw in Zbb that returns the highest
>>> > > set
>>> > > bit
>>> > > which could be used to performantly implement this, but it would
>>> > > still
>>> > > be slower than the current implementation. At worst case, half of
>>> > > the
>>> > > address would not be able to be allocated when a hint address is
>>> > > provided.
>>> > > > > Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
>>> > > ---
>>> > >  arch/riscv/include/asm/processor.h | 27 +++++++++++---------------
>>> > > -
>>> > >  1 file changed, 11 insertions(+), 16 deletions(-)
>>> > > > > diff --git a/arch/riscv/include/asm/processor.h
>>> > > b/arch/riscv/include/asm/processor.h
>>> > > index f19f861cda54..8ece7a8f0e18 100644
>>> > > --- a/arch/riscv/include/asm/processor.h
>>> > > +++ b/arch/riscv/include/asm/processor.h
>>> > > @@ -14,22 +14,16 @@
>>> > >
>>> > >  #include <asm/ptrace.h>
>>> > >
>>> > > -#ifdef CONFIG_64BIT
>>> > > -#define DEFAULT_MAP_WINDOW    (UL(1) << (MMAP_VA_BITS - 1))
>>> > > -#define STACK_TOP_MAX        TASK_SIZE_64
>>> > > -
>>> > >  #define arch_get_mmap_end(addr, len, flags)            \
>>> > >  ({                                \
>>> > >      unsigned long
>>> > > mmap_end;                    \
>>> > >      typeof(addr) _addr = (addr);                \
>>> > > -    if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) &&
>>> > > is_compat_task())) \
>>> > > +    if ((_addr) == 0 ||                    \
>>> > > +        (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||    \
>>> > > +        ((_addr + len) > BIT(VA_BITS -
>>> > > 1)))            \
>>> > >          mmap_end = STACK_TOP_MAX;            \
>>> > > -    else if ((_addr) >= VA_USER_SV57) \
>>> > > -        mmap_end = STACK_TOP_MAX;            \
>>> > > -    else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >=
>>> > > VA_BITS_SV48)) \
>>> > > -        mmap_end = VA_USER_SV48;            \
>>> > >      else                            \
>>> > > -        mmap_end = VA_USER_SV39;            \
>>> > > +        mmap_end = (_addr + len);            \
>>> > >      mmap_end;                        \
>>> > >  })
>>> > >
>>> > > @@ -39,17 +33,18 @@
>>> > >      typeof(addr) _addr = (addr);                \
>>> > >      typeof(base) _base = (base);                \
>>> > >      unsigned long rnd_gap = DEFAULT_MAP_WINDOW - (_base);    \
>>> > > -    if ((_addr) == 0 || (IS_ENABLED(CONFIG_COMPAT) &&
>>> > > is_compat_task())) \
>>> > > +    if ((_addr) == 0 ||                    \
>>> > > +        (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||    \
>>> > > +        ((_addr + len) > BIT(VA_BITS -
>>> > > 1)))            \
>>> > >          mmap_base = (_base);                \
>>> > > -    else if (((_addr) >= VA_USER_SV57) && (VA_BITS >=
>>> > > VA_BITS_SV57)) \
>>> > > -        mmap_base = VA_USER_SV57 - rnd_gap; \
>>> > > -    else if ((((_addr) >= VA_USER_SV48)) && (VA_BITS >=
>>> > > VA_BITS_SV48)) \
>>> > > -        mmap_base = VA_USER_SV48 - rnd_gap; \
>>> > >      else                            \
>>> > > -        mmap_base = VA_USER_SV39 - rnd_gap; \
>>> > > +        mmap_base = (_addr + len) - rnd_gap; \
>>> > >      mmap_base;                        \
>>> > >  })
>>> > >
>>> > > +#ifdef CONFIG_64BIT
>>> > > +#define DEFAULT_MAP_WINDOW    (UL(1) << (MMAP_VA_BITS - 1))
>>> > > +#define STACK_TOP_MAX        TASK_SIZE_64
>>> > >  #else
>>> > >  #define DEFAULT_MAP_WINDOW    TASK_SIZE
>>> > >  #define STACK_TOP_MAX        TASK_SIZE
>>> > > > > I have carefully tested your patch on qemu with sv57. A bug 
>>> that
>>> > needs
>>> > to be solved is that mmap with the same hint address without
>>> > MAP_FIXED
>>> > set will fail the second time.
>>> > > Userspace code to reproduce the bug:
>>> > > #include <sys/mman.h>
>>> > #include <stdio.h>
>>> > #include <stdint.h>
>>> > > void test(char *addr) {
>>> >     char *res = mmap(addr, 4096, PROT_READ | PROT_WRITE,
>>> > MAP_ANONYMOUS
>>> > > MAP_PRIVATE, -1, 0);
>>> >     printf("hint %p got %p.\n", addr, res);
>>> > }
>>> > > int main (void) {
>>> >     test(1<<30);
>>> >     test(1<<30);
>>> >     test(1<<30);
>>> >     return 0;
>>> > }
>>> > > output:
>>> > > hint 0x40000000 got 0x40000000.
>>> > hint 0x40000000 got 0xffffffffffffffff.
>>> > hint 0x40000000 got 0xffffffffffffffff.
>>> > > output on x86:
>>> > > hint 0x40000000 got 0x40000000.
>>> > hint 0x40000000 got 0x7f9171363000.
>>> > hint 0x40000000 got 0x7f9171362000.
>>> > > It may need to implement a special arch_get_unmapped_area and
>>> > arch_get_unmapped_area_topdown function.
>>> >
>>> This is because hint address < rnd_gap. I have tried to let mmap_base =
>>> min((_addr + len), (base) + TASK_SIZE - DEFAULT_MAP_WINDOW). However it
>>> does not work for bottom-up while ulimit -s is unlimited. You said this
>>> behavior is expected from patch v2 review. However it brings a new
>>> regression even on sv39 systems.
>>>
>>> I still don't know the reason why use addr+len as the upper-bound. I
>>> think solution like x86/arm64/powerpc provide two address space switch
>>> based on whether hint address above the default map window is enough.
>>>
>>
>> Yep this is expected. It is up to the maintainers to decide.
>
> Sorry I forgot to reply to this, I had a buffer sitting around 
> somewhere but I must have lost it.
>
> I think Charlie's approach is the right way to go.  Putting my 
> userspace hat on, I'd much rather have my allocations fail rather than 
> silently ignore the hint when there's memory pressure.
>
> If there's some real use case that needs these low hints to be 
> silently ignored under VA pressure then we can try and figure 
> something out that makes those applications work.

I could confirm that this patch has broken chromium's partition 
allocator on riscv64. The minimal reproduction I use is chromium-mmap.c:

#include <stdio.h>
#include <sys/mman.h>

int main() {
     void* expected = (void*)0x400000000;
     void* addr = mmap(expected, 17179869184, PROT_NONE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     if (addr != expected) {
         printf("Not expected address: %p != %p\n", addr, expected);
     }
     expected = (void*)0x3fffff000;
     addr = mmap(expected, 17179873280, PROT_NONE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
     if (addr != expected) {
         printf("Not expected address: %p != %p\n", addr, expected);
     }
     return 0;
}

The second mmap fails with ENOMEM. Manually reverting this commit fixes 
the issue for me. So I think it's clearly a regression and breaks 
userspace.

See also https://github.com/riscv-forks/electron/issues/4

>>
>> - Charlie

Sincerely,
Levi


^ permalink raw reply

* Re: [PATCHv8 9/9] man2: Add uretprobe syscall page
From: Jiri Olsa @ 2024-08-17  8:58 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Jiri Olsa, Steven Rostedt, Masami Hiramatsu, Oleg Nesterov,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-kernel, linux-trace-kernel, linux-api, linux-man, x86, bpf,
	Song Liu, Yonghong Song, John Fastabend, Peter Zijlstra,
	Thomas Gleixner, Borislav Petkov (AMD), Ingo Molnar,
	Andy Lutomirski, Edgecombe, Rick P, Deepak Gupta
In-Reply-To: <ht6hc5dbvgx3ny22pvhiazs7vxjhiockr6glpho5bpp6hrwn4f@oew3iu7a62j2>

On Fri, Aug 16, 2024 at 11:56:39PM +0200, Alejandro Colomar wrote:
> Hi Jiri, Steven,
> 
> On Fri, Aug 16, 2024 at 08:55:47PM GMT, Alejandro Colomar wrote:
> > > hi,
> > > there are no args for x86.. it's there just to note that it might
> > > be different on other archs, so not sure what man page should say
> > > in such case.. keeping (void) is fine with me
> > 
> > Hmmm, then I'll remove that paragraph.  If that function is implemented
> > in another arch and the args are different, we can change the manual
> > page then.
> > 
> > > 
> > > > 
> > > > Please add the changes proposed below to your patch, tweak anything if
> > > > you consider it appropriate) and send it as v10.
> > > 
> > > it looks good to me, thanks a lot
> > > 
> > > Acked-by: From: Jiri Olsa <jolsa@kernel.org>
> 
> I have applied your patch with the tweaks I mentioned, and added several
> tags to the commit message.
> 
> It's currently here:
> <https://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git/commit/?h=contrib&id=977e3eecbb81b7398defc4e4f41810ca31d63c1b>
> 
> and will $soon be pushed to master.
> 
> Have a lovely night!
> Alex

great, thanks

jirka

^ permalink raw reply

* Re: [PATCHv8 9/9] man2: Add uretprobe syscall page
From: Alejandro Colomar @ 2024-08-16 21:56 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Steven Rostedt, Masami Hiramatsu, Oleg Nesterov,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-kernel, linux-trace-kernel, linux-api, linux-man, x86, bpf,
	Song Liu, Yonghong Song, John Fastabend, Peter Zijlstra,
	Thomas Gleixner, Borislav Petkov (AMD), Ingo Molnar,
	Andy Lutomirski, Edgecombe, Rick P, Deepak Gupta
In-Reply-To: <c7v4einpsvpswvj3rqn5esap2e5lpeiwacylqlzwdcp7slsgvg@jfmchkiqru4u>

[-- Attachment #1: Type: text/plain, Size: 1086 bytes --]

Hi Jiri, Steven,

On Fri, Aug 16, 2024 at 08:55:47PM GMT, Alejandro Colomar wrote:
> > hi,
> > there are no args for x86.. it's there just to note that it might
> > be different on other archs, so not sure what man page should say
> > in such case.. keeping (void) is fine with me
> 
> Hmmm, then I'll remove that paragraph.  If that function is implemented
> in another arch and the args are different, we can change the manual
> page then.
> 
> > 
> > > 
> > > Please add the changes proposed below to your patch, tweak anything if
> > > you consider it appropriate) and send it as v10.
> > 
> > it looks good to me, thanks a lot
> > 
> > Acked-by: From: Jiri Olsa <jolsa@kernel.org>

I have applied your patch with the tweaks I mentioned, and added several
tags to the commit message.

It's currently here:
<https://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git/commit/?h=contrib&id=977e3eecbb81b7398defc4e4f41810ca31d63c1b>

and will $soon be pushed to master.

Have a lovely night!
Alex


-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCHv8 9/9] man2: Add uretprobe syscall page
From: Alejandro Colomar @ 2024-08-16 18:55 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Steven Rostedt, Masami Hiramatsu, Oleg Nesterov,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-kernel, linux-trace-kernel, linux-api, linux-man, x86, bpf,
	Song Liu, Yonghong Song, John Fastabend, Peter Zijlstra,
	Thomas Gleixner, Borislav Petkov (AMD), Ingo Molnar,
	Andy Lutomirski, Edgecombe, Rick P, Deepak Gupta
In-Reply-To: <Zr-Gf3EEganRSzGM@krava>

[-- Attachment #1: Type: text/plain, Size: 3701 bytes --]

On Fri, Aug 16, 2024 at 07:03:59PM GMT, Jiri Olsa wrote:
> On Fri, Aug 16, 2024 at 01:42:26PM +0200, Alejandro Colomar wrote:
> > Hi Steven, Jiri,
> > 
> > On Wed, Aug 07, 2024 at 04:27:34PM GMT, Steven Rostedt wrote:
> > > Just in case nobody pinged you, the rest of the series is now in Linus's
> > > tree.
> > 
> > Thanks for the ping!
> > 
> > I have prepared some tweaks to the patch (see below).
> > Also, I have some doubts.  The prototype shows that it has no arguments
> > (void), but the text said that arguments, if any, are arch-specific.
> > Does any arch have arguments?  Should we use a variadic prototype (...)?
> 
> hi,
> there are no args for x86.. it's there just to note that it might
> be different on other archs, so not sure what man page should say
> in such case.. keeping (void) is fine with me

Hmmm, then I'll remove that paragraph.  If that function is implemented
in another arch and the args are different, we can change the manual
page then.

> 
> > 
> > Please add the changes proposed below to your patch, tweak anything if
> > you consider it appropriate) and send it as v10.
> 
> it looks good to me, thanks a lot
> 
> Acked-by: From: Jiri Olsa <jolsa@kernel.org>

Thanks!

Have a lovely day!
Alex

> 
> jirka
> 
> > 
> > Have a lovely day!
> > Alex
> > 
> > 
> > diff --git i/man/man2/uretprobe.2 w/man/man2/uretprobe.2
> > index cf1c2b0d8..51b566998 100644
> > --- i/man/man2/uretprobe.2
> > +++ w/man/man2/uretprobe.2
> > @@ -7,50 +7,43 @@ .SH NAME
> >  uretprobe \- execute pending return uprobes
> >  .SH SYNOPSIS
> >  .nf
> > -.B int uretprobe(void)
> > +.B int uretprobe(void);
> >  .fi
> >  .SH DESCRIPTION
> > -The
> >  .BR uretprobe ()
> > -system call is an alternative to breakpoint instructions for triggering return
> > -uprobe consumers.
> > +is an alternative to breakpoint instructions
> > +for triggering return uprobe consumers.
> >  .P
> >  Calls to
> >  .BR uretprobe ()
> > -system call are only made from the user-space trampoline provided by the kernel.
> > +are only made from the user-space trampoline provided by the kernel.
> >  Calls from any other place result in a
> >  .BR SIGILL .
> > -.SH RETURN VALUE
> > -The
> > +.P
> > +Details of the arguments (if any) passed to
> >  .BR uretprobe ()
> > -system call return value is architecture-specific.
> > +are architecture-specific.
> > +.SH RETURN VALUE
> > +The return value is architecture-specific.
> >  .SH ERRORS
> >  .TP
> >  .B SIGILL
> > -The
> >  .BR uretprobe ()
> > -system call was called by a user-space program.
> > +was called by a user-space program.
> >  .SH VERSIONS
> > -Details of the
> > -.BR uretprobe ()
> > -system call behavior vary across systems.
> > +The behavior varies across systems.
> >  .SH STANDARDS
> >  None.
> >  .SH HISTORY
> > -TBD
> > -.SH NOTES
> > -The
> > +Linux 6.11.
> > +.P
> >  .BR uretprobe ()
> > -system call was initially introduced for the x86_64 architecture
> > +was initially introduced for the x86_64 architecture
> >  where it was shown to be faster than breakpoint traps.
> >  It might be extended to other architectures.
> > -.P
> > -The
> > +.SH CAVEATS
> >  .BR uretprobe ()
> > -system call exists only to allow the invocation of return uprobe consumers.
> > +exists only to allow the invocation of return uprobe consumers.
> >  It should
> >  .B never
> >  be called directly.
> > -Details of the arguments (if any) passed to
> > -.BR uretprobe ()
> > -and the return value are architecture-specific.
> > 
> > -- 
> > <https://www.alejandro-colomar.es/>
> 

-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-16 17:17 UTC (permalink / raw)
  To: Jann Horn
  Cc: Edgecombe, Rick P, dietmar.eggemann@arm.com,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, catalin.marinas@arm.com,
	linux-api@vger.kernel.org, will@kernel.org
In-Reply-To: <CAG48ez2z5bRdKNddG+kEGz9A_m=66r38OHjyg6CapFTcjT9aRg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 924 bytes --]

On Fri, Aug 16, 2024 at 07:08:09PM +0200, Jann Horn wrote:

> Yeah, having a FOLL_FORCE write in clone3 would be a weakness for
> userspace CFI and probably make it possible to violate mseal()
> restrictions that are supposed to enforce that address space regions
> are read-only.

Note that this will only happen for shadow stack pages (with the new
version) and only for a valid token at the specific address.  mseal()ing
a shadow stack to be read only is hopefully not going to go terribly
well for userspace.

> Though, did anyone in the thread yet suggest that you could do this
> before the child process has fully materialized but after the child MM
> has been set up? Somewhere in copy_process() between copy_mm() and the
> "/* No more failure paths after this point. */" comment?

Yes, I'e got a version that does that waiting to go pending some
discussion on if we even do the check for the token in the child mm.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Jann Horn @ 2024-08-16 17:08 UTC (permalink / raw)
  To: Edgecombe, Rick P
  Cc: dietmar.eggemann@arm.com, broonie@kernel.org,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, catalin.marinas@arm.com,
	linux-api@vger.kernel.org, will@kernel.org
In-Reply-To: <f3a2a564094d05beac2dc5ab657cbc009c465667.camel@intel.com>

On Thu, Aug 15, 2024 at 2:18 AM Edgecombe, Rick P
<rick.p.edgecombe@intel.com> wrote:
> On Thu, 2024-08-08 at 09:15 +0100, Mark Brown wrote:
> > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> > +               goto out;
>
> The GUPs still seem a bit unfortunate for a couple reasons:
>  - We could do a CMPXCHG version and are just not (I see ARM has identical code
> in gcs_consume_token()). It's not the only race like this though FWIW.
>  - I *think* this is the only unprivileged FOLL_FORCE that can write to the
> current process in the kernel. As is, it could be used on normal RO mappings, at
> least in a limited way. Maybe another point for the VMA check. We'd want to
> check that it is normal shadow stack?

Yeah, having a FOLL_FORCE write in clone3 would be a weakness for
userspace CFI and probably make it possible to violate mseal()
restrictions that are supposed to enforce that address space regions
are read-only.

>  - Lingering doubts about the wisdom of doing GUPs during task creation.
>
> I don't think they are show stoppers, but the VMA check would be nice to have in
> the first upstream support.
[...]
> > +static void shstk_post_fork(struct task_struct *p,
> > +                           struct kernel_clone_args *args)
> > +{
> > +       if (!IS_ENABLED(CONFIG_ARCH_HAS_USER_SHADOW_STACK))
> > +               return;
> > +
> > +       if (!args->shadow_stack)
> > +               return;
> > +
> > +       if (arch_shstk_post_fork(p, args) != 0)
> > +               force_sig_fault_to_task(SIGSEGV, SEGV_CPERR, NULL, p);
> > +}
> > +
>
> Hmm, is this forcing the signal on the new task, which is set up on a user
> provided shadow stack that failed the token check? It would handle the signal
> with an arbitrary SSP then I think. We should probably fail the clone call in
> the parent instead, which can be done by doing the work in copy_process(). Do
> you see a problem with doing it at the end of copy_process()? I don't know if
> there could be ordering constraints.

FWIW I think we have things like force_fatal_sig() and
force_exit_sig() to send signals that userspace can't catch with
signal handlers - if you have to do the copying after the new task has
been set up, something along those lines might be the right way to
kill the child.

Though, did anyone in the thread yet suggest that you could do this
before the child process has fully materialized but after the child MM
has been set up? Somewhere in copy_process() between copy_mm() and the
"/* No more failure paths after this point. */" comment?

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-16 17:06 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Edgecombe, Rick P, dietmar.eggemann@arm.com,
	juri.lelli@redhat.com, linux-api@vger.kernel.org,
	shuah@kernel.org, brauner@kernel.org, dave.hansen@linux.intel.com,
	debug@rivosinc.com, mgorman@suse.de, Szabolcs.Nagy@arm.com,
	fweimer@redhat.com, linux-kernel@vger.kernel.org,
	mingo@redhat.com, hjl.tools@gmail.com, rostedt@goodmis.org,
	vincent.guittot@linaro.org, tglx@linutronix.de,
	vschneid@redhat.com, kees@kernel.org, will@kernel.org,
	hpa@zytor.com, peterz@infradead.org, jannh@google.com,
	bp@alien8.de, bsegall@google.com, linux-kselftest@vger.kernel.org,
	x86@kernel.org
In-Reply-To: <Zr9yiH6DP0IPac-H@arm.com>

[-- Attachment #1: Type: text/plain, Size: 857 bytes --]

On Fri, Aug 16, 2024 at 04:38:48PM +0100, Catalin Marinas wrote:
> On Fri, Aug 16, 2024 at 02:52:28PM +0000, Edgecombe, Rick P wrote:

> > On the x86 side, we don't have a shadow stack access CMPXCHG. We will have to
> > GUP and do a normal CMPXCHG off of the direct map to handle it fully properly in
> > any case (CLONE_VM or not).

> I guess we could do the same here and for the arm64 gcs_consume_token().
> Basically get_user_page_vma_remote() gives us the page together with the
> vma that you mentioned needs checking. We can then do a cmpxchg directly
> on the page_address(). It's probably faster anyway than doing GUP twice.

There was some complication with get_user_page_vma_remote() while I was
working on an earlier version which meant I didn't use it, though with
adding checking of VMAs perhaps whatever it was isn't such an issue any
more.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCHv8 9/9] man2: Add uretprobe syscall page
From: Jiri Olsa @ 2024-08-16 17:03 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Steven Rostedt, Masami Hiramatsu, Oleg Nesterov,
	Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	linux-kernel, linux-trace-kernel, linux-api, linux-man, x86, bpf,
	Song Liu, Yonghong Song, John Fastabend, Peter Zijlstra,
	Thomas Gleixner, Borislav Petkov (AMD), Ingo Molnar,
	Andy Lutomirski, Edgecombe, Rick P, Deepak Gupta
In-Reply-To: <ygpwfyjvhuctug2bsibvc7exbirahojuivglcfjusw4rrqeqhc@44h23muvk3xb>

On Fri, Aug 16, 2024 at 01:42:26PM +0200, Alejandro Colomar wrote:
> Hi Steven, Jiri,
> 
> On Wed, Aug 07, 2024 at 04:27:34PM GMT, Steven Rostedt wrote:
> > Just in case nobody pinged you, the rest of the series is now in Linus's
> > tree.
> 
> Thanks for the ping!
> 
> I have prepared some tweaks to the patch (see below).
> Also, I have some doubts.  The prototype shows that it has no arguments
> (void), but the text said that arguments, if any, are arch-specific.
> Does any arch have arguments?  Should we use a variadic prototype (...)?

hi,
there are no args for x86.. it's there just to note that it might
be different on other archs, so not sure what man page should say
in such case.. keeping (void) is fine with me

> 
> Please add the changes proposed below to your patch, tweak anything if
> you consider it appropriate) and send it as v10.

it looks good to me, thanks a lot

Acked-by: From: Jiri Olsa <jolsa@kernel.org>

jirka

> 
> Have a lovely day!
> Alex
> 
> 
> diff --git i/man/man2/uretprobe.2 w/man/man2/uretprobe.2
> index cf1c2b0d8..51b566998 100644
> --- i/man/man2/uretprobe.2
> +++ w/man/man2/uretprobe.2
> @@ -7,50 +7,43 @@ .SH NAME
>  uretprobe \- execute pending return uprobes
>  .SH SYNOPSIS
>  .nf
> -.B int uretprobe(void)
> +.B int uretprobe(void);
>  .fi
>  .SH DESCRIPTION
> -The
>  .BR uretprobe ()
> -system call is an alternative to breakpoint instructions for triggering return
> -uprobe consumers.
> +is an alternative to breakpoint instructions
> +for triggering return uprobe consumers.
>  .P
>  Calls to
>  .BR uretprobe ()
> -system call are only made from the user-space trampoline provided by the kernel.
> +are only made from the user-space trampoline provided by the kernel.
>  Calls from any other place result in a
>  .BR SIGILL .
> -.SH RETURN VALUE
> -The
> +.P
> +Details of the arguments (if any) passed to
>  .BR uretprobe ()
> -system call return value is architecture-specific.
> +are architecture-specific.
> +.SH RETURN VALUE
> +The return value is architecture-specific.
>  .SH ERRORS
>  .TP
>  .B SIGILL
> -The
>  .BR uretprobe ()
> -system call was called by a user-space program.
> +was called by a user-space program.
>  .SH VERSIONS
> -Details of the
> -.BR uretprobe ()
> -system call behavior vary across systems.
> +The behavior varies across systems.
>  .SH STANDARDS
>  None.
>  .SH HISTORY
> -TBD
> -.SH NOTES
> -The
> +Linux 6.11.
> +.P
>  .BR uretprobe ()
> -system call was initially introduced for the x86_64 architecture
> +was initially introduced for the x86_64 architecture
>  where it was shown to be faster than breakpoint traps.
>  It might be extended to other architectures.
> -.P
> -The
> +.SH CAVEATS
>  .BR uretprobe ()
> -system call exists only to allow the invocation of return uprobe consumers.
> +exists only to allow the invocation of return uprobe consumers.
>  It should
>  .B never
>  be called directly.
> -Details of the arguments (if any) passed to
> -.BR uretprobe ()
> -and the return value are architecture-specific.
> 
> -- 
> <https://www.alejandro-colomar.es/>


^ permalink raw reply

* Re: [PATCH RFT v8 0/9] fork: Support shadow stacks in clone3()
From: Mark Brown @ 2024-08-16 16:19 UTC (permalink / raw)
  To: Jann Horn
  Cc: brauner, Kees Cook, Rick P. Edgecombe, Deepak Gupta,
	Szabolcs Nagy, H.J. Lu, Florian Weimer, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider,
	Shuah Khan, linux-kernel, Catalin Marinas, Will Deacon,
	linux-kselftest, linux-api, David Hildenbrand
In-Reply-To: <CAG48ez38VVj10fixN5FYo1qujHSH17bPGynzUQugqeBRYAOBRw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 941 bytes --]

On Fri, Aug 16, 2024 at 05:52:20PM +0200, Jann Horn wrote:

> As a heads-up so you don't get surprised by this in the future:

> Because clone3() does not pass the flags in a register like clone()
> does, it is not available in places like docker containers that use
> the default Docker seccomp policy
> (https://github.com/moby/moby/blob/master/profiles/seccomp/default.json).
> Docker uses seccomp to filter clone() arguments (to prevent stuff like
> namespace creation), and that's not possible with clone3(), so
> clone3() is blocked.

This is probably fine, the existing shadow stack ABI provides a sensible
default behaviour for things that just use regular clone().  This series
just adds more control for things using clone3(), the main issue would
be anything that *needs* to specify stack size/placement and can't use
clone3().  That would need a separate userspace API if required, and
we'd still want to extend clone3() anyway.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 0/9] fork: Support shadow stacks in clone3()
From: Jann Horn @ 2024-08-16 15:52 UTC (permalink / raw)
  To: Mark Brown, brauner, Kees Cook
  Cc: Rick P. Edgecombe, Deepak Gupta, Szabolcs Nagy, H.J. Lu,
	Florian Weimer, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Shuah Khan, linux-kernel,
	Catalin Marinas, Will Deacon, linux-kselftest, linux-api,
	David Hildenbrand
In-Reply-To: <20240808-clone3-shadow-stack-v8-0-0acf37caf14c@kernel.org>

On Thu, Aug 8, 2024 at 10:16 AM Mark Brown <broonie@kernel.org> wrote:
> Since clone3() is readily extensible let's add support for specifying a
> shadow stack when creating a new thread or process in a similar manner
> to how the normal stack is specified, keeping the current implicit
> allocation behaviour if one is not specified either with clone3() or
> through the use of clone().  The user must provide a shadow stack
> address and size, this must point to memory mapped for use as a shadow
> stackby map_shadow_stack() with a shadow stack token at the top of the
> stack.

As a heads-up so you don't get surprised by this in the future:

Because clone3() does not pass the flags in a register like clone()
does, it is not available in places like docker containers that use
the default Docker seccomp policy
(https://github.com/moby/moby/blob/master/profiles/seccomp/default.json).
Docker uses seccomp to filter clone() arguments (to prevent stuff like
namespace creation), and that's not possible with clone3(), so
clone3() is blocked.

The same thing applies to things like sandboxed renderer processes of
web browsers - they want to block anything other than creating normal
threads, so they use seccomp to block stuff like namespace creation
and creating new processes.

I briefly mentioned this here during clone3 development, though I
probably should have been more explicit about how it would be
beneficial for clone3 to pass flags in a register:
<https://lore.kernel.org/all/CAG48ez3q=BeNcuVTKBN79kJui4vC6nw0Bfq6xc-i0neheT17TA@mail.gmail.com/>

So if you want your feature to be available in such contexts, you'll
probably have to either add a new syscall clone4() that passes the
flags in a register; or do the plumbing work required to make it
possible to seccomp-filter things other than register contexts (by
invoking seccomp again from the clone3 handler with some kinda
pseudo-syscall?); or change the signature of the existing syscall (but
that would require something like using the high bit of the size to
signal that there's a flags argument in another register, which is
probably more ugly than just adding a new syscall).

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-16 15:46 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Edgecombe, Rick P, dietmar.eggemann@arm.com,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com, jannh@google.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	will@kernel.org
In-Reply-To: <Zr9wSa2Yyq-MCWVq@arm.com>

[-- Attachment #1: Type: text/plain, Size: 853 bytes --]

On Fri, Aug 16, 2024 at 04:29:13PM +0100, Catalin Marinas wrote:
> On Fri, Aug 16, 2024 at 11:51:57AM +0100, Mark Brown wrote:

> > I change back to parsing the token in the parent but I don't want to end
> > up in a cycle of bouncing between the two implementations depending on
> > who's reviewed the most recent version.

> You and others spent a lot more time looking at shadow stacks than me.
> I'm not necessarily asking to change stuff but rather understand the
> choices made.

I'm a little ambivalent on this - on the one hand accessing the child's
memory is not a thing of great beauty but on the other hand it does
make the !CLONE_VM case more solid.  My general instinct is that the
ugliness is less of an issue than the "oh, there's a gap there" stuff
with the !CLONE_VM case since it's more "why are we doing that?" than
"we missed this".

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Catalin Marinas @ 2024-08-16 15:38 UTC (permalink / raw)
  To: Edgecombe, Rick P
  Cc: dietmar.eggemann@arm.com, juri.lelli@redhat.com,
	linux-api@vger.kernel.org, shuah@kernel.org, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	Szabolcs.Nagy@arm.com, fweimer@redhat.com,
	linux-kernel@vger.kernel.org, mingo@redhat.com,
	hjl.tools@gmail.com, rostedt@goodmis.org,
	vincent.guittot@linaro.org, tglx@linutronix.de,
	vschneid@redhat.com, kees@kernel.org, will@kernel.org,
	hpa@zytor.com, peterz@infradead.org, jannh@google.com,
	bp@alien8.de, bsegall@google.com, linux-kselftest@vger.kernel.org,
	broonie@kernel.org, x86@kernel.org
In-Reply-To: <23a8838adda28b03b3db77e135934e2da0599d0f.camel@intel.com>

On Fri, Aug 16, 2024 at 02:52:28PM +0000, Edgecombe, Rick P wrote:
> On Fri, 2024-08-16 at 09:44 +0100, Catalin Marinas wrote:
> > > After a token is consumed normally, it doesn't set it to zero. Instead it
> > > sets it to a "previous-ssp token". I don't think we actually want to do that here
> > > though because it involves the old SSP, which doesn't really apply in this
> > > case. I don't see any problem with zero, but was there any special thinking behind
> > > it?
> > 
> > BTW, since it's the parent setting up the shadow stack in its own
> > address space before forking, I think at least the read can avoid
> > access_remote_vm() and we could do it earlier, even before the new
> > process is created.
> 
> Hmm. Makes sense. It's a bit racy since the parent could consume that token from
> another thread, but it would be a race in any case.

More on the race below. If we handle it properly, we don't need the
separate checks.

> > > > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > > > +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> > > > +               goto out;
> > > 
> > > The GUPs still seem a bit unfortunate for a couple reasons:
> > >   - We could do a CMPXCHG version and are just not (I see ARM has identical
> > > code in gcs_consume_token()). It's not the only race like this though FWIW.
> > >   - I *think* this is the only unprivileged FOLL_FORCE that can write to the
> > > current process in the kernel. As is, it could be used on normal RO
> > > mappings, at
> > > least in a limited way. Maybe another point for the VMA check. We'd want to
> > > check that it is normal shadow stack?
> > >   - Lingering doubts about the wisdom of doing GUPs during task creation.
> > 
> > I don't like the access_remote_vm() either. In the common (practically
> > only) case with CLONE_VM, the mm is actually current->mm, so no need for
> > a GUP.
> 
> On the x86 side, we don't have a shadow stack access CMPXCHG. We will have to
> GUP and do a normal CMPXCHG off of the direct map to handle it fully properly in
> any case (CLONE_VM or not).

I guess we could do the same here and for the arm64 gcs_consume_token().
Basically get_user_page_vma_remote() gives us the page together with the
vma that you mentioned needs checking. We can then do a cmpxchg directly
on the page_address(). It's probably faster anyway than doing GUP twice.

-- 
Catalin

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-16 15:30 UTC (permalink / raw)
  To: Edgecombe, Rick P
  Cc: catalin.marinas@arm.com, dietmar.eggemann@arm.com,
	juri.lelli@redhat.com, linux-api@vger.kernel.org,
	shuah@kernel.org, brauner@kernel.org, dave.hansen@linux.intel.com,
	debug@rivosinc.com, mgorman@suse.de, Szabolcs.Nagy@arm.com,
	fweimer@redhat.com, linux-kernel@vger.kernel.org,
	mingo@redhat.com, hjl.tools@gmail.com, rostedt@goodmis.org,
	vincent.guittot@linaro.org, tglx@linutronix.de,
	vschneid@redhat.com, kees@kernel.org, will@kernel.org,
	hpa@zytor.com, peterz@infradead.org, jannh@google.com,
	bp@alien8.de, bsegall@google.com, linux-kselftest@vger.kernel.org,
	x86@kernel.org
In-Reply-To: <23a8838adda28b03b3db77e135934e2da0599d0f.camel@intel.com>

[-- Attachment #1: Type: text/plain, Size: 790 bytes --]

On Fri, Aug 16, 2024 at 02:52:28PM +0000, Edgecombe, Rick P wrote:
> On Fri, 2024-08-16 at 09:44 +0100, Catalin Marinas wrote:

> > BTW, since it's the parent setting up the shadow stack in its own
> > address space before forking, I think at least the read can avoid
> > access_remote_vm() and we could do it earlier, even before the new
> > process is created.

> Hmm. Makes sense. It's a bit racy since the parent could consume that token from
> another thread, but it would be a race in any case.

So it sounds like we might be coming round to this?  I've got a new
version that verifies the VM_SHADOW_STACK good to go but if we're going
to switch back to consuming the token in the parent context I may as
well do that.  Like I said in the other mail I'd rather not flip flop
on this.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Catalin Marinas @ 2024-08-16 15:29 UTC (permalink / raw)
  To: Mark Brown
  Cc: Edgecombe, Rick P, dietmar.eggemann@arm.com,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com, jannh@google.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	will@kernel.org
In-Reply-To: <c644d64b-f7d0-47de-b5ba-ae2ac1b46e1b@sirena.org.uk>

On Fri, Aug 16, 2024 at 11:51:57AM +0100, Mark Brown wrote:
> On Fri, Aug 16, 2024 at 09:44:46AM +0100, Catalin Marinas wrote:
> > We could, in theory, consume this token in the parent before the child
> > mm is created. The downside is that if a parent forks multiple
> > processes using the same shadow stack, it will have to set the token
> > each time. I'd be fine with this, that's really only for the mostly
> > theoretical case where one doesn't use CLONE_VM and still want a
> > separate stack and shadow stack.
> 
> I originally implemented things that way but people did complain about
> the !CLONE_VM case, which does TBH seem reasonable.  Note that the
> parent won't as standard be able to set the token again - since the
> shadow stack is not writable to userspace by default it'd instead need
> to allocate a whole new shadow stack for each child.

Ah, good point.

> I change back to parsing the token in the parent but I don't want to end
> up in a cycle of bouncing between the two implementations depending on
> who's reviewed the most recent version.

You and others spent a lot more time looking at shadow stacks than me.
I'm not necessarily asking to change stuff but rather understand the
choices made.

-- 
Catalin

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Edgecombe, Rick P @ 2024-08-16 14:52 UTC (permalink / raw)
  To: catalin.marinas@arm.com
  Cc: dietmar.eggemann@arm.com, juri.lelli@redhat.com,
	linux-api@vger.kernel.org, shuah@kernel.org, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	Szabolcs.Nagy@arm.com, fweimer@redhat.com,
	linux-kernel@vger.kernel.org, mingo@redhat.com,
	hjl.tools@gmail.com, rostedt@goodmis.org,
	vincent.guittot@linaro.org, tglx@linutronix.de,
	vschneid@redhat.com, kees@kernel.org, will@kernel.org,
	hpa@zytor.com, peterz@infradead.org, jannh@google.com,
	bp@alien8.de, bsegall@google.com, linux-kselftest@vger.kernel.org,
	broonie@kernel.org, x86@kernel.org
In-Reply-To: <Zr8RfoHZYRWem1K9@arm.com>

On Fri, 2024-08-16 at 09:44 +0100, Catalin Marinas wrote:
> > After a token is consumed normally, it doesn't set it to zero. Instead it
> > sets
> > it to a "previous-ssp token". I don't think we actually want to do that here
> > though because it involves the old SSP, which doesn't really apply in this
> > case.
> > I don't see any problem with zero, but was there any special thinking behind
> > it?
> 
> BTW, since it's the parent setting up the shadow stack in its own
> address space before forking, I think at least the read can avoid
> access_remote_vm() and we could do it earlier, even before the new
> process is created.

Hmm. Makes sense. It's a bit racy since the parent could consume that token from
another thread, but it would be a race in any case.

> 
> > > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > > +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> > > +               goto out;
> > 
> > The GUPs still seem a bit unfortunate for a couple reasons:
> >   - We could do a CMPXCHG version and are just not (I see ARM has identical
> > code
> > in gcs_consume_token()). It's not the only race like this though FWIW.
> >   - I *think* this is the only unprivileged FOLL_FORCE that can write to the
> > current process in the kernel. As is, it could be used on normal RO
> > mappings, at
> > least in a limited way. Maybe another point for the VMA check. We'd want to
> > check that it is normal shadow stack?
> >   - Lingering doubts about the wisdom of doing GUPs during task creation.
> 
> I don't like the access_remote_vm() either. In the common (practically
> only) case with CLONE_VM, the mm is actually current->mm, so no need for
> a GUP.

On the x86 side, we don't have a shadow stack access CMPXCHG. We will have to
GUP and do a normal CMPXCHG off of the direct map to handle it fully properly in
any case (CLONE_VM or not).

> 
> We could, in theory, consume this token in the parent before the child
> mm is created. The downside is that if a parent forks multiple
> processes using the same shadow stack, it will have to set the token
> each time. I'd be fine with this, that's really only for the mostly
> theoretical case where one doesn't use CLONE_VM and still want a
> separate stack and shadow stack.
> 
> > I don't think they are show stoppers, but the VMA check would be nice to
> > have in
> > the first upstream support.
> 
> Good point.


^ permalink raw reply

* Re: [PATCHv8 9/9] man2: Add uretprobe syscall page
From: Alejandro Colomar @ 2024-08-16 11:42 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Jiri Olsa, Oleg Nesterov, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, linux-kernel,
	linux-trace-kernel, linux-api, linux-man, x86, bpf, Song Liu,
	Yonghong Song, John Fastabend, Peter Zijlstra, Thomas Gleixner,
	Borislav Petkov (AMD), Ingo Molnar, Andy Lutomirski,
	Edgecombe, Rick P, Deepak Gupta
In-Reply-To: <20240807162734.100d3b55@gandalf.local.home>

[-- Attachment #1: Type: text/plain, Size: 2637 bytes --]

Hi Steven, Jiri,

On Wed, Aug 07, 2024 at 04:27:34PM GMT, Steven Rostedt wrote:
> Just in case nobody pinged you, the rest of the series is now in Linus's
> tree.

Thanks for the ping!

I have prepared some tweaks to the patch (see below).
Also, I have some doubts.  The prototype shows that it has no arguments
(void), but the text said that arguments, if any, are arch-specific.
Does any arch have arguments?  Should we use a variadic prototype (...)?

Please add the changes proposed below to your patch, tweak anything if
you consider it appropriate) and send it as v10.

Have a lovely day!
Alex


diff --git i/man/man2/uretprobe.2 w/man/man2/uretprobe.2
index cf1c2b0d8..51b566998 100644
--- i/man/man2/uretprobe.2
+++ w/man/man2/uretprobe.2
@@ -7,50 +7,43 @@ .SH NAME
 uretprobe \- execute pending return uprobes
 .SH SYNOPSIS
 .nf
-.B int uretprobe(void)
+.B int uretprobe(void);
 .fi
 .SH DESCRIPTION
-The
 .BR uretprobe ()
-system call is an alternative to breakpoint instructions for triggering return
-uprobe consumers.
+is an alternative to breakpoint instructions
+for triggering return uprobe consumers.
 .P
 Calls to
 .BR uretprobe ()
-system call are only made from the user-space trampoline provided by the kernel.
+are only made from the user-space trampoline provided by the kernel.
 Calls from any other place result in a
 .BR SIGILL .
-.SH RETURN VALUE
-The
+.P
+Details of the arguments (if any) passed to
 .BR uretprobe ()
-system call return value is architecture-specific.
+are architecture-specific.
+.SH RETURN VALUE
+The return value is architecture-specific.
 .SH ERRORS
 .TP
 .B SIGILL
-The
 .BR uretprobe ()
-system call was called by a user-space program.
+was called by a user-space program.
 .SH VERSIONS
-Details of the
-.BR uretprobe ()
-system call behavior vary across systems.
+The behavior varies across systems.
 .SH STANDARDS
 None.
 .SH HISTORY
-TBD
-.SH NOTES
-The
+Linux 6.11.
+.P
 .BR uretprobe ()
-system call was initially introduced for the x86_64 architecture
+was initially introduced for the x86_64 architecture
 where it was shown to be faster than breakpoint traps.
 It might be extended to other architectures.
-.P
-The
+.SH CAVEATS
 .BR uretprobe ()
-system call exists only to allow the invocation of return uprobe consumers.
+exists only to allow the invocation of return uprobe consumers.
 It should
 .B never
 be called directly.
-Details of the arguments (if any) passed to
-.BR uretprobe ()
-and the return value are architecture-specific.

-- 
<https://www.alejandro-colomar.es/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-16 10:51 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Edgecombe, Rick P, dietmar.eggemann@arm.com,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com, jannh@google.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	will@kernel.org
In-Reply-To: <Zr8RfoHZYRWem1K9@arm.com>

[-- Attachment #1: Type: text/plain, Size: 963 bytes --]

On Fri, Aug 16, 2024 at 09:44:46AM +0100, Catalin Marinas wrote:

> We could, in theory, consume this token in the parent before the child
> mm is created. The downside is that if a parent forks multiple
> processes using the same shadow stack, it will have to set the token
> each time. I'd be fine with this, that's really only for the mostly
> theoretical case where one doesn't use CLONE_VM and still want a
> separate stack and shadow stack.

I originally implemented things that way but people did complain about
the !CLONE_VM case, which does TBH seem reasonable.  Note that the
parent won't as standard be able to set the token again - since the
shadow stack is not writable to userspace by default it'd instead need
to allocate a whole new shadow stack for each child.

I change back to parsing the token in the parent but I don't want to end
up in a cycle of bouncing between the two implementations depending on
who's reviewed the most recent version.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Catalin Marinas @ 2024-08-16  8:44 UTC (permalink / raw)
  To: Edgecombe, Rick P
  Cc: dietmar.eggemann@arm.com, broonie@kernel.org,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com, jannh@google.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	will@kernel.org
In-Reply-To: <f3a2a564094d05beac2dc5ab657cbc009c465667.camel@intel.com>

On Thu, Aug 15, 2024 at 12:18:23AM +0000, Edgecombe, Rick P wrote:
> On Thu, 2024-08-08 at 09:15 +0100, Mark Brown wrote:
> > +int arch_shstk_post_fork(struct task_struct *t, struct kernel_clone_args
> > *args)
[...]
> > +       /* This should really be an atomic cmpxchg.  It is not. */
> > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > +                            FOLL_FORCE) != sizeof(val))
> > +               goto out;
> > +
> > +       if (val != expected)
> > +               goto out;
> > +       val = 0;
> 
> After a token is consumed normally, it doesn't set it to zero. Instead it sets
> it to a "previous-ssp token". I don't think we actually want to do that here
> though because it involves the old SSP, which doesn't really apply in this case.
> I don't see any problem with zero, but was there any special thinking behind it?

BTW, since it's the parent setting up the shadow stack in its own
address space before forking, I think at least the read can avoid
access_remote_vm() and we could do it earlier, even before the new
process is created.

> > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> > +               goto out;
> 
> The GUPs still seem a bit unfortunate for a couple reasons:
>  - We could do a CMPXCHG version and are just not (I see ARM has identical code
> in gcs_consume_token()). It's not the only race like this though FWIW.
>  - I *think* this is the only unprivileged FOLL_FORCE that can write to the
> current process in the kernel. As is, it could be used on normal RO mappings, at
> least in a limited way. Maybe another point for the VMA check. We'd want to
> check that it is normal shadow stack?
>  - Lingering doubts about the wisdom of doing GUPs during task creation.

I don't like the access_remote_vm() either. In the common (practically
only) case with CLONE_VM, the mm is actually current->mm, so no need for
a GUP.

We could, in theory, consume this token in the parent before the child
mm is created. The downside is that if a parent forks multiple
processes using the same shadow stack, it will have to set the token
each time. I'd be fine with this, that's really only for the mostly
theoretical case where one doesn't use CLONE_VM and still want a
separate stack and shadow stack.

> I don't think they are show stoppers, but the VMA check would be nice to have in
> the first upstream support.

Good point.

-- 
Catalin

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-15 14:24 UTC (permalink / raw)
  To: Edgecombe, Rick P
  Cc: dietmar.eggemann@arm.com, Szabolcs.Nagy@arm.com,
	brauner@kernel.org, dave.hansen@linux.intel.com,
	debug@rivosinc.com, mgorman@suse.de, vincent.guittot@linaro.org,
	fweimer@redhat.com, mingo@redhat.com, rostedt@goodmis.org,
	hjl.tools@gmail.com, tglx@linutronix.de, vschneid@redhat.com,
	shuah@kernel.org, hpa@zytor.com, peterz@infradead.org,
	bp@alien8.de, bsegall@google.com, x86@kernel.org,
	juri.lelli@redhat.com, jannh@google.com,
	linux-kselftest@vger.kernel.org, kees@kernel.org,
	linux-kernel@vger.kernel.org, catalin.marinas@arm.com,
	linux-api@vger.kernel.org, will@kernel.org
In-Reply-To: <f3a2a564094d05beac2dc5ab657cbc009c465667.camel@intel.com>

[-- Attachment #1: Type: text/plain, Size: 4165 bytes --]

On Thu, Aug 15, 2024 at 12:18:23AM +0000, Edgecombe, Rick P wrote:
> On Thu, 2024-08-08 at 09:15 +0100, Mark Brown wrote:

> > +       ssp = args->shadow_stack + args->shadow_stack_size;
> > +       addr = ssp - SS_FRAME_SIZE;
> > +       expected = ssp | BIT(0);

> > +       mm = get_task_mm(t);
> > +       if (!mm)
> > +               return -EFAULT;

> We could check that the VMA is shadow stack here. I'm not sure what could go
> wrong though. If you point it to RW memory it could start the thread with that
> as a shadow stack and just blow up at the first call. It might be nicer to fail
> earlier though.

Sure, I wasn't doing anything since like you say the new thread will
fail anyway but we can do the check.  As you point out below it'll close
down the possibility of writing to memory.

> > +       /* This should really be an atomic cmpxchg.  It is not. */
> > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > +                            FOLL_FORCE) != sizeof(val))
> > +               goto out;
> > +
> > +       if (val != expected)
> > +               goto out;
> > +       val = 0;

> After a token is consumed normally, it doesn't set it to zero. Instead it sets
> it to a "previous-ssp token". I don't think we actually want to do that here
> though because it involves the old SSP, which doesn't really apply in this case.
> I don't see any problem with zero, but was there any special thinking behind it?

I wasn't aware of the x86 behaviour for pivots here, 0 was just a
default thing to choose for an invalid value.  arm64 will also leave
a value on the outgoing stack as a product of the two step pivots we
have but it's not really something you'd look for.

> > +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> > +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> > +               goto out;

> The GUPs still seem a bit unfortunate for a couple reasons:
>  - We could do a CMPXCHG version and are just not (I see ARM has identical code
> in gcs_consume_token()). It's not the only race like this though FWIW.
>  - I *think* this is the only unprivileged FOLL_FORCE that can write to the
> current process in the kernel. As is, it could be used on normal RO mappings, at
> least in a limited way. Maybe another point for the VMA check. We'd want to
> check that it is normal shadow stack?
>  - Lingering doubts about the wisdom of doing GUPs during task creation.

> I don't think they are show stoppers, but the VMA check would be nice to have in
> the first upstream support.

The check you suggest for shadow stack memory should avoid abuse of the
FOLL_FORCE at least.  It'd be a bit narrow, you'd only be able to
overwrite a value where we managed to read a valid token, but it's
there.

> > +static void shstk_post_fork(struct task_struct *p,
> > +                           struct kernel_clone_args *args)
> > +{
> > +       if (!IS_ENABLED(CONFIG_ARCH_HAS_USER_SHADOW_STACK))
> > +               return;
> > +
> > +       if (!args->shadow_stack)
> > +               return;
> > +
> > +       if (arch_shstk_post_fork(p, args) != 0)
> > +               force_sig_fault_to_task(SIGSEGV, SEGV_CPERR, NULL, p);
> > +}

> Hmm, is this forcing the signal on the new task, which is set up on a user
> provided shadow stack that failed the token check? It would handle the signal
> with an arbitrary SSP then I think. We should probably fail the clone call in
> the parent instead, which can be done by doing the work in copy_process(). Do

One thing I was thinking when writing this was that I wanted to make it
possible to implement the check in the vDSO if there's any architectures
that could do so, avoiding any need to GUP, but I can't see that that's
actually been possible.

> you see a problem with doing it at the end of copy_process()? I don't know if
> there could be ordering constraints.

I was concerned when I was writing the code about ordring constraints,
but I did revise what the code was doing several times and as I was
saying in reply to Catalin I'm no longer sure those apply.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 0/9] fork: Support shadow stacks in clone3()
From: Edgecombe, Rick P @ 2024-08-15  0:19 UTC (permalink / raw)
  To: kees@kernel.org, broonie@kernel.org
  Cc: dietmar.eggemann@arm.com, catalin.marinas@arm.com,
	david@redhat.com, Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com,
	linux-kernel@vger.kernel.org, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	linux-api@vger.kernel.org, vschneid@redhat.com, shuah@kernel.org,
	will@kernel.org, hpa@zytor.com, peterz@infradead.org,
	jannh@google.com, bp@alien8.de, bsegall@google.com,
	linux-kselftest@vger.kernel.org, x86@kernel.org,
	juri.lelli@redhat.com
In-Reply-To: <202408081053.0EABACA@keescook>

On Thu, 2024-08-08 at 10:54 -0700, Kees Cook wrote:
> Tested-by: Kees Cook <kees@kernel.org>

I regression tested it with the CET enabled glibc selftests. No issues.

^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Edgecombe, Rick P @ 2024-08-15  0:18 UTC (permalink / raw)
  To: dietmar.eggemann@arm.com, broonie@kernel.org,
	Szabolcs.Nagy@arm.com, brauner@kernel.org,
	dave.hansen@linux.intel.com, debug@rivosinc.com, mgorman@suse.de,
	vincent.guittot@linaro.org, fweimer@redhat.com, mingo@redhat.com,
	rostedt@goodmis.org, hjl.tools@gmail.com, tglx@linutronix.de,
	vschneid@redhat.com, shuah@kernel.org, hpa@zytor.com,
	peterz@infradead.org, bp@alien8.de, bsegall@google.com,
	x86@kernel.org, juri.lelli@redhat.com
  Cc: jannh@google.com, linux-kselftest@vger.kernel.org,
	kees@kernel.org, linux-kernel@vger.kernel.org,
	catalin.marinas@arm.com, linux-api@vger.kernel.org,
	will@kernel.org
In-Reply-To: <20240808-clone3-shadow-stack-v8-4-0acf37caf14c@kernel.org>

On Thu, 2024-08-08 at 09:15 +0100, Mark Brown wrote:
> +int arch_shstk_post_fork(struct task_struct *t, struct kernel_clone_args
> *args)
> +{
> +       /*
> +        * SSP is aligned, so reserved bits and mode bit are a zero, just mark
> +        * the token 64-bit.
> +        */
> +       struct mm_struct *mm;
> +       unsigned long addr, ssp;
> +       u64 expected;
> +       u64 val;
> +       int ret = -EINVAL;

We should probably?
if (!features_enabled(ARCH_SHSTK_SHSTK))
	return 0;

> +
> +       ssp = args->shadow_stack + args->shadow_stack_size;
> +       addr = ssp - SS_FRAME_SIZE;
> +       expected = ssp | BIT(0);
> +
> +       mm = get_task_mm(t);
> +       if (!mm)
> +               return -EFAULT;

We could check that the VMA is shadow stack here. I'm not sure what could go
wrong though. If you point it to RW memory it could start the thread with that
as a shadow stack and just blow up at the first call. It might be nicer to fail
earlier though.

> +
> +       /* This should really be an atomic cmpxchg.  It is not. */
> +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> +                            FOLL_FORCE) != sizeof(val))
> +               goto out;
> +
> +       if (val != expected)
> +               goto out;
> +       val = 0;

After a token is consumed normally, it doesn't set it to zero. Instead it sets
it to a "previous-ssp token". I don't think we actually want to do that here
though because it involves the old SSP, which doesn't really apply in this case.
I don't see any problem with zero, but was there any special thinking behind it?

> +       if (access_remote_vm(mm, addr, &val, sizeof(val),
> +                            FOLL_FORCE | FOLL_WRITE) != sizeof(val))
> +               goto out;

The GUPs still seem a bit unfortunate for a couple reasons:
 - We could do a CMPXCHG version and are just not (I see ARM has identical code
in gcs_consume_token()). It's not the only race like this though FWIW.
 - I *think* this is the only unprivileged FOLL_FORCE that can write to the
current process in the kernel. As is, it could be used on normal RO mappings, at
least in a limited way. Maybe another point for the VMA check. We'd want to
check that it is normal shadow stack?
 - Lingering doubts about the wisdom of doing GUPs during task creation.

I don't think they are show stoppers, but the VMA check would be nice to have in
the first upstream support.

> +
> +       ret = 0;
> +
> +out:
> +       mmput(mm);
> +       return ret;
> +}
> +
> 
[snip]
> 
>  
> +static void shstk_post_fork(struct task_struct *p,
> +                           struct kernel_clone_args *args)
> +{
> +       if (!IS_ENABLED(CONFIG_ARCH_HAS_USER_SHADOW_STACK))
> +               return;
> +
> +       if (!args->shadow_stack)
> +               return;
> +
> +       if (arch_shstk_post_fork(p, args) != 0)
> +               force_sig_fault_to_task(SIGSEGV, SEGV_CPERR, NULL, p);
> +}
> +

Hmm, is this forcing the signal on the new task, which is set up on a user
provided shadow stack that failed the token check? It would handle the signal
with an arbitrary SSP then I think. We should probably fail the clone call in
the parent instead, which can be done by doing the work in copy_process(). Do
you see a problem with doing it at the end of copy_process()? I don't know if
there could be ordering constraints.


^ permalink raw reply

* Re: [PATCH RFT v8 4/9] fork: Add shadow stack support to clone3()
From: Mark Brown @ 2024-08-14 13:20 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Rick P. Edgecombe, Deepak Gupta, Szabolcs Nagy, H.J. Lu,
	Florian Weimer, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Christian Brauner, Shuah Khan,
	linux-kernel, Will Deacon, jannh, linux-kselftest, linux-api,
	Kees Cook
In-Reply-To: <Zrx7Lj09b99ozgAE@arm.com>

[-- Attachment #1: Type: text/plain, Size: 1229 bytes --]

On Wed, Aug 14, 2024 at 10:38:54AM +0100, Catalin Marinas wrote:
> On Tue, Aug 13, 2024 at 07:58:26PM +0100, Mark Brown wrote:

> > ISTR the concerns were around someone being clever with vfork() but I
> > don't remember anything super concrete.  In terms of the inconsistency
> > here that was actually another thing that came up - if userspace
> > specifies a stack for clone3() it'll just get used even with CLONE_VFORK
> > so it seemed to make sense to do the same thing for the shadow stack.
> > This was part of the thinking when we were looking at it, if you can
> > specify a regular stack you should be able to specify a shadow stack.

> Yes, I agree. But by this logic, I was wondering why the current clone()
> behaviour does not allocate a shadow stack when a new stack is
> requested with CLONE_VFORK. That's rather theoretical though and we may
> not want to change the ABI.

The default for vfork() is to reuse both the normal and shadow stacks,
clone3() does make it all much more flexible.  All the shadow stack
ABI predates clone3(), even if it ended up getting merged after.

> Anyway, I understood this patch now and the ABI decisions. FWIW:

> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

Thanks!

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH RFT v8 3/9] mm: Introduce ARCH_HAS_USER_SHADOW_STACK
From: Catalin Marinas @ 2024-08-14 10:41 UTC (permalink / raw)
  To: Mark Brown
  Cc: Rick P. Edgecombe, Deepak Gupta, Szabolcs Nagy, H.J. Lu,
	Florian Weimer, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, Peter Zijlstra, Juri Lelli,
	Vincent Guittot, Dietmar Eggemann, Steven Rostedt, Ben Segall,
	Mel Gorman, Valentin Schneider, Christian Brauner, Shuah Khan,
	linux-kernel, Will Deacon, jannh, linux-kselftest, linux-api,
	Kees Cook, David Hildenbrand
In-Reply-To: <20240808-clone3-shadow-stack-v8-3-0acf37caf14c@kernel.org>

On Thu, Aug 08, 2024 at 09:15:24AM +0100, Mark Brown wrote:
> Since multiple architectures have support for shadow stacks and we need to
> select support for this feature in several places in the generic code
> provide a generic config option that the architectures can select.
> 
> Suggested-by: David Hildenbrand <david@redhat.com>
> Acked-by: David Hildenbrand <david@redhat.com>
> Reviewed-by: Deepak Gupta <debug@rivosinc.com>
> Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox