(root)/
gcc-13.2.0/
libssp/
ssp.c
       1  /* Stack protector support.
       2     Copyright (C) 2005-2023 Free Software Foundation, Inc.
       3  
       4  This file is part of GCC.
       5  
       6  GCC is free software; you can redistribute it and/or modify it under
       7  the terms of the GNU General Public License as published by the Free
       8  Software Foundation; either version 3, or (at your option) any later
       9  version.
      10  
      11  In addition to the permissions in the GNU General Public License, the
      12  Free Software Foundation gives you unlimited permission to link the
      13  compiled version of this file into combinations with other programs,
      14  and to distribute those combinations without any restriction coming
      15  from the use of this file.  (The General Public License restrictions
      16  do apply in other respects; for example, they cover modification of
      17  the file, and distribution when not linked into a combine
      18  executable.)
      19  
      20  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      21  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      22  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      23  for more details.
      24  
      25  Under Section 7 of GPL version 3, you are granted additional
      26  permissions described in the GCC Runtime Library Exception, version
      27  3.1, as published by the Free Software Foundation.
      28  
      29  You should have received a copy of the GNU General Public License and
      30  a copy of the GCC Runtime Library Exception along with this program;
      31  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      32  <http://www.gnu.org/licenses/>.  */
      33  
      34  
      35  #include "config.h"
      36  #ifdef HAVE_ALLOCA_H
      37  # include <alloca.h>
      38  #endif
      39  #ifdef HAVE_MALLOC_H
      40  # include <malloc.h>
      41  #endif
      42  #ifdef HAVE_STRING_H
      43  # include <string.h>
      44  #endif
      45  #ifdef HAVE_UNISTD_H
      46  # include <unistd.h>
      47  #endif
      48  #ifdef HAVE_FCNTL_H
      49  # include <fcntl.h>
      50  #endif
      51  #ifdef HAVE_PATHS_H
      52  # include <paths.h>
      53  #endif
      54  #ifndef _PATH_TTY
      55  /* Native win32 apps don't know about /dev/tty but can print directly
      56     to the console using  "CONOUT$"   */
      57  #if defined (_WIN32) && !defined (__CYGWIN__)
      58  #define WIN32_LEAN_AND_MEAN
      59  #include <windows.h>
      60  #include <wincrypt.h>
      61  # define _PATH_TTY "CONOUT$"
      62  #else
      63  # define _PATH_TTY "/dev/tty"
      64  #endif
      65  #endif
      66  #ifdef HAVE_SYSLOG_H
      67  # include <syslog.h>
      68  #endif
      69  
      70  void *__stack_chk_guard = 0;
      71  
      72  static void __attribute__ ((constructor))
      73  __guard_setup (void)
      74  {
      75    unsigned char *p;
      76  
      77    if (__stack_chk_guard != 0)
      78      return;
      79  
      80  #if defined (_WIN32) && !defined (__CYGWIN__)
      81    HCRYPTPROV hprovider = 0;
      82    if (CryptAcquireContext(&hprovider, NULL, NULL, PROV_RSA_FULL,
      83                            CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
      84      {
      85        if (CryptGenRandom(hprovider, sizeof (__stack_chk_guard),
      86            (BYTE *)&__stack_chk_guard) &&  __stack_chk_guard != 0)
      87          {
      88             CryptReleaseContext(hprovider, 0);
      89             return;
      90          }
      91        CryptReleaseContext(hprovider, 0);
      92      }
      93  #else
      94    int fd = open ("/dev/urandom", O_RDONLY);
      95    if (fd != -1)
      96      {
      97        ssize_t size = read (fd, &__stack_chk_guard,
      98                             sizeof (__stack_chk_guard));
      99        close (fd);
     100        if (size == sizeof(__stack_chk_guard) && __stack_chk_guard != 0)
     101          return;
     102      }
     103  
     104  #endif
     105    /* If a random generator can't be used, the protector switches the guard
     106       to the "terminator canary".  */
     107    p = (unsigned char *) &__stack_chk_guard;
     108    p[sizeof(__stack_chk_guard)-1] = 255;
     109    p[sizeof(__stack_chk_guard)-2] = '\n';
     110    p[0] = 0;
     111  }
     112  
     113  static void
     114  fail (const char *msg1, size_t msg1len, const char *msg3)
     115  {
     116  #ifdef __GNU_LIBRARY__
     117    extern char * __progname;
     118  #else
     119    static const char __progname[] = "";
     120  #endif
     121    int fd;
     122  
     123    /* Print error message directly to the tty.  This avoids Bad Things
     124       happening if stderr is redirected.  */
     125    fd = open (_PATH_TTY, O_WRONLY);
     126    if (fd != -1)
     127      {
     128        static const char msg2[] = " terminated\n";
     129        size_t progname_len, len;
     130        char *buf, *p;
     131  
     132        progname_len = strlen (__progname);
     133        len = msg1len + progname_len + sizeof(msg2)-1 + 1;
     134        p = buf = alloca (len);
     135  
     136        memcpy (p, msg1, msg1len);
     137        p += msg1len;
     138        memcpy (p, __progname, progname_len);
     139        p += progname_len;
     140        memcpy (p, msg2, sizeof(msg2));
     141  
     142        while (len > 0)
     143          {
     144            ssize_t wrote = write (fd, buf, len);
     145            if (wrote < 0)
     146              break;
     147            buf += wrote;
     148            len -= wrote;
     149          }
     150        close (fd);
     151      }
     152  
     153  #ifdef HAVE_SYSLOG_H
     154    /* Only send the error to syslog if there was no tty available.  */
     155    else
     156      syslog (LOG_CRIT, "%s", msg3);
     157  #endif /* HAVE_SYSLOG_H */
     158  
     159    /* Try very hard to exit.  Note that signals may be blocked preventing
     160       the first two options from working.  The use of volatile is here to
     161       prevent optimizers from "knowing" that __builtin_trap is called first,
     162       and that it doesn't return, and so "obviously" the rest of the code
     163       is dead.  */
     164    {
     165      volatile int state;
     166      for (state = 0; ; state++)
     167        switch (state)
     168          {
     169          case 0:
     170            __builtin_trap ();
     171            break;
     172          case 1:
     173            *(volatile int *)-1L = 0;
     174            break;
     175          case 2:
     176            _exit (127);
     177            break;
     178          }
     179    }
     180  }
     181  
     182  void
     183  __stack_chk_fail (void)
     184  {
     185    const char *msg = "*** stack smashing detected ***: ";
     186    fail (msg, strlen (msg), "stack smashing detected: terminated");
     187  }
     188  
     189  void
     190  __chk_fail (void)
     191  {
     192    const char *msg = "*** buffer overflow detected ***: ";
     193    fail (msg, strlen (msg), "buffer overflow detected: terminated");
     194  }
     195  
     196  #ifdef HAVE_HIDDEN_VISIBILITY
     197  void
     198  __attribute__((visibility ("hidden")))
     199  __stack_chk_fail_local (void)
     200  {
     201    __stack_chk_fail ();
     202  }
     203  #endif