(root)/
glibc-2.38/
support/
xsigstack.c
       1  /* sigaltstack wrappers.
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <support/xsignal.h>
      20  #include <support/support.h>
      21  #include <support/xunistd.h>
      22  #include <support/check.h>
      23  
      24  #include <stdlib.h>
      25  #include <string.h>
      26  #include <sys/mman.h>
      27  #include <sys/param.h> /* roundup, MAX */
      28  
      29  #ifndef MAP_NORESERVE
      30  # define MAP_NORESERVE 0
      31  #endif
      32  #ifndef MAP_STACK
      33  # define MAP_STACK 0
      34  #endif
      35  
      36  /* The "cookie" returned by xalloc_sigstack points to one of these
      37     structures.  */
      38  struct sigstack_desc
      39  {
      40    struct support_stack stack;
      41    stack_t alt_stack; /* The address and size of the stack itself.  */
      42    stack_t old_stack; /* The previous signal stack.  */
      43  };
      44  
      45  void *
      46  xalloc_sigstack (size_t size)
      47  {
      48    struct sigstack_desc *desc = xmalloc (sizeof (struct sigstack_desc));
      49    desc->stack = support_stack_alloc (size);
      50    desc->alt_stack.ss_sp    = desc->stack.stack;
      51    desc->alt_stack.ss_flags = 0;
      52    desc->alt_stack.ss_size  = desc->stack.size;
      53  
      54    if (sigaltstack (&desc->alt_stack, &desc->old_stack))
      55      FAIL_EXIT1 ("sigaltstack (new stack: sp=%p, size=%zu, flags=%u): %m\n",
      56                  desc->alt_stack.ss_sp, desc->alt_stack.ss_size,
      57                  desc->alt_stack.ss_flags);
      58  
      59    return desc;
      60  }
      61  
      62  void
      63  xfree_sigstack (void *stack)
      64  {
      65    struct sigstack_desc *desc = stack;
      66  
      67    if (sigaltstack (&desc->old_stack, 0))
      68      FAIL_EXIT1 ("sigaltstack (restore old stack: sp=%p, size=%zu, flags=%u): "
      69                  "%m\n", desc->old_stack.ss_sp, desc->old_stack.ss_size,
      70                  desc->old_stack.ss_flags);
      71    support_stack_free (&desc->stack);
      72    free (desc);
      73  }
      74  
      75  void
      76  xget_sigstack_location (const void *stack, unsigned char **addrp, size_t *sizep)
      77  {
      78    const struct sigstack_desc *desc = stack;
      79    *addrp = desc->alt_stack.ss_sp;
      80    *sizep = desc->alt_stack.ss_size;
      81  }