• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2012 The Android Open Source Project
3   * All rights reserved.
4   *
5   * Redistribution and use in source and binary forms, with or without
6   * modification, are permitted provided that the following conditions
7   * are met:
8   *  * Redistributions of source code must retain the above copyright
9   *    notice, this list of conditions and the following disclaimer.
10   *  * Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in
12   *    the documentation and/or other materials provided with the
13   *    distribution.
14   *
15   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26   * SUCH DAMAGE.
27   */
28  
29  /*
30   * Copyright (c) 1988 Regents of the University of California.
31   * All rights reserved.
32   *
33   * Redistribution and use in source and binary forms, with or without
34   * modification, are permitted provided that the following conditions
35   * are met:
36   * 1. Redistributions of source code must retain the above copyright
37   *    notice, this list of conditions and the following disclaimer.
38   * 2. Redistributions in binary form must reproduce the above copyright
39   *    notice, this list of conditions and the following disclaimer in the
40   *    documentation and/or other materials provided with the distribution.
41   * 3. Neither the name of the University nor the names of its contributors
42   *    may be used to endorse or promote products derived from this software
43   *    without specific prior written permission.
44   *
45   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55   * SUCH DAMAGE.
56   */
57  
58  #include <poll.h>
59  #include <stdarg.h>
60  #include <stddef.h>
61  #include <stdio.h>
62  #include <stdlib.h>
63  #include <string.h>
64  #include <sys/cdefs.h>
65  #include <sys/select.h>
66  #include <sys/socket.h>
67  #include <sys/stat.h>
68  #include <unistd.h>
69  
70  #include "private/bionic_fortify.h"
71  
72  //
73  // For more about FORTIFY see:
74  //
75  //   https://android-developers.googleblog.com/2017/04/fortify-in-android.html
76  //
77  //   http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
78  //   http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
79  //
80  
__FD_ISSET_chk(int fd,const fd_set * set,size_t set_size)81  int __FD_ISSET_chk(int fd, const fd_set* set, size_t set_size) {
82    __check_fd_set("FD_ISSET", fd, set_size);
83    return __FD_ISSET(fd, set);
84  }
85  
__FD_CLR_chk(int fd,fd_set * set,size_t set_size)86  void __FD_CLR_chk(int fd, fd_set* set, size_t set_size) {
87    __check_fd_set("FD_CLR", fd, set_size);
88    __FD_CLR(fd, set);
89  }
90  
__FD_SET_chk(int fd,fd_set * set,size_t set_size)91  void __FD_SET_chk(int fd, fd_set* set, size_t set_size) {
92    __check_fd_set("FD_SET", fd, set_size);
93    __FD_SET(fd, set);
94  }
95  
__fgets_chk(char * dst,int supplied_size,FILE * stream,size_t dst_len_from_compiler)96  char* __fgets_chk(char* dst, int supplied_size, FILE* stream, size_t dst_len_from_compiler) {
97    __check_buffer_access("fgets", "write into", supplied_size, dst_len_from_compiler);
98    return fgets(dst, supplied_size, stream);
99  }
100  
__fread_chk(void * buf,size_t size,size_t count,FILE * stream,size_t buf_size)101  size_t __fread_chk(void* buf, size_t size, size_t count, FILE* stream, size_t buf_size) {
102    unsigned long total;
103    if (__predict_false(__builtin_umull_overflow(size, count, &total))) {
104      // overflow: trigger the error path in fread
105      return fread(buf, size, count, stream);
106    }
107    __check_buffer_access("fread", "write into", total, buf_size);
108    return fread(buf, size, count, stream);
109  }
110  
__fwrite_chk(const void * buf,size_t size,size_t count,FILE * stream,size_t buf_size)111  size_t __fwrite_chk(const void* buf, size_t size, size_t count, FILE* stream, size_t buf_size) {
112    unsigned long total;
113    if (__predict_false(__builtin_umull_overflow(size, count, &total))) {
114      // overflow: trigger the error path in fwrite
115      return fwrite(buf, size, count, stream);
116    }
117    __check_buffer_access("fwrite", "read from", total, buf_size);
118    return fwrite(buf, size, count, stream);
119  }
120  
__getcwd_chk(char * buf,size_t len,size_t actual_size)121  extern char* __getcwd_chk(char* buf, size_t len, size_t actual_size) {
122    __check_buffer_access("getcwd", "write into", len, actual_size);
123    return getcwd(buf, len);
124  }
125  
__memchr_chk(const void * s,int c,size_t n,size_t actual_size)126  void* __memchr_chk(const void* s, int c, size_t n, size_t actual_size) {
127    __check_buffer_access("memchr", "read from", n, actual_size);
128    return const_cast<void*>(memchr(s, c, n));
129  }
130  
131  // Runtime implementation of __builtin____memmove_chk (used directly by compiler, not in headers).
__memmove_chk(void * dst,const void * src,size_t len,size_t dst_len)132  extern "C" void* __memmove_chk(void* dst, const void* src, size_t len, size_t dst_len) {
133    __check_buffer_access("memmove", "write into", len, dst_len);
134    return memmove(dst, src, len);
135  }
136  
137  // memcpy is performance-critical enough that we have assembler __memcpy_chk implementations.
138  // This function is used to give better diagnostics than we can easily do from assembler.
__memcpy_chk_fail(void *,const void *,size_t count,size_t dst_len)139  extern "C" void* __memcpy_chk_fail(void* /*dst*/, const void* /*src*/, size_t count, size_t dst_len) {
140    __check_count("memcpy", "count", count);
141    __check_buffer_access("memcpy", "write into", count, dst_len);
142    abort(); // One of the above is supposed to have failed, otherwise we shouldn't have been called.
143  }
144  
__memrchr_chk(const void * s,int c,size_t n,size_t actual_size)145  void* __memrchr_chk(const void* s, int c, size_t n, size_t actual_size) {
146    __check_buffer_access("memrchr", "read from", n, actual_size);
147    return memrchr(const_cast<void *>(s), c, n);
148  }
149  
150  // memset is performance-critical enough that we have assembler __memset_chk implementations.
151  // This function is used to give better diagnostics than we can easily do from assembler.
__memset_chk_fail(void *,int,size_t count,size_t dst_len)152  extern "C" void* __memset_chk_fail(void* /*dst*/, int /*byte*/, size_t count, size_t dst_len) {
153    __check_count("memset", "count", count);
154    __check_buffer_access("memset", "write into", count, dst_len);
155    abort(); // One of the above is supposed to have failed, otherwise we shouldn't have been called.
156  }
157  
__poll_chk(pollfd * fds,nfds_t fd_count,int timeout,size_t fds_size)158  int __poll_chk(pollfd* fds, nfds_t fd_count, int timeout, size_t fds_size) {
159    __check_pollfd_array("poll", fds_size, fd_count);
160    return poll(fds, fd_count, timeout);
161  }
162  
__ppoll_chk(pollfd * fds,nfds_t fd_count,const timespec * timeout,const sigset_t * mask,size_t fds_size)163  int __ppoll_chk(pollfd* fds, nfds_t fd_count, const timespec* timeout,
164                  const sigset_t* mask, size_t fds_size) {
165    __check_pollfd_array("ppoll", fds_size, fd_count);
166    return ppoll(fds, fd_count, timeout, mask);
167  }
168  
__ppoll64_chk(pollfd * fds,nfds_t fd_count,const timespec * timeout,const sigset64_t * mask,size_t fds_size)169  int __ppoll64_chk(pollfd* fds, nfds_t fd_count, const timespec* timeout,
170                    const sigset64_t* mask, size_t fds_size) {
171    __check_pollfd_array("ppoll64", fds_size, fd_count);
172    return ppoll64(fds, fd_count, timeout, mask);
173  }
174  
__pread64_chk(int fd,void * buf,size_t count,off64_t offset,size_t buf_size)175  ssize_t __pread64_chk(int fd, void* buf, size_t count, off64_t offset, size_t buf_size) {
176    __check_count("pread64", "count", count);
177    __check_buffer_access("pread64", "write into", count, buf_size);
178    return pread64(fd, buf, count, offset);
179  }
180  
__pread_chk(int fd,void * buf,size_t count,off_t offset,size_t buf_size)181  ssize_t __pread_chk(int fd, void* buf, size_t count, off_t offset, size_t buf_size) {
182    __check_count("pread", "count", count);
183    __check_buffer_access("pread", "write into", count, buf_size);
184    return pread(fd, buf, count, offset);
185  }
186  
__pwrite64_chk(int fd,const void * buf,size_t count,off64_t offset,size_t buf_size)187  ssize_t __pwrite64_chk(int fd, const void* buf, size_t count, off64_t offset,
188                                    size_t buf_size) {
189    __check_count("pwrite64", "count", count);
190    __check_buffer_access("pwrite64", "read from", count, buf_size);
191    return pwrite64(fd, buf, count, offset);
192  }
193  
__pwrite_chk(int fd,const void * buf,size_t count,off_t offset,size_t buf_size)194  ssize_t __pwrite_chk(int fd, const void* buf, size_t count, off_t offset,
195                                  size_t buf_size) {
196    __check_count("pwrite", "count", count);
197    __check_buffer_access("pwrite", "read from", count, buf_size);
198    return pwrite(fd, buf, count, offset);
199  }
200  
__read_chk(int fd,void * buf,size_t count,size_t buf_size)201  ssize_t __read_chk(int fd, void* buf, size_t count, size_t buf_size) {
202    __check_count("read", "count", count);
203    __check_buffer_access("read", "write into", count, buf_size);
204    return read(fd, buf, count);
205  }
206  
__readlinkat_chk(int dirfd,const char * path,char * buf,size_t size,size_t buf_size)207  ssize_t __readlinkat_chk(int dirfd, const char* path, char* buf, size_t size, size_t buf_size) {
208    __check_count("readlinkat", "size", size);
209    __check_buffer_access("readlinkat", "write into", size, buf_size);
210    return readlinkat(dirfd, path, buf, size);
211  }
212  
__readlink_chk(const char * path,char * buf,size_t size,size_t buf_size)213  ssize_t __readlink_chk(const char* path, char* buf, size_t size, size_t buf_size) {
214    __check_count("readlink", "size", size);
215    __check_buffer_access("readlink", "write into", size, buf_size);
216    return readlink(path, buf, size);
217  }
218  
__recvfrom_chk(int socket,void * buf,size_t len,size_t buf_size,int flags,sockaddr * src_addr,socklen_t * addrlen)219  ssize_t __recvfrom_chk(int socket, void* buf, size_t len, size_t buf_size,
220                         int flags, sockaddr* src_addr, socklen_t* addrlen) {
221    __check_buffer_access("recvfrom", "write into", len, buf_size);
222    return recvfrom(socket, buf, len, flags, src_addr, addrlen);
223  }
224  
__sendto_chk(int socket,const void * buf,size_t len,size_t buflen,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)225  ssize_t __sendto_chk(int socket, const void* buf, size_t len, size_t buflen,
226                       int flags, const struct sockaddr* dest_addr,
227                       socklen_t addrlen) {
228    __check_buffer_access("sendto", "read from", len, buflen);
229    return sendto(socket, buf, len, flags, dest_addr, addrlen);
230  }
231  
232  // Runtime implementation of __builtin____stpcpy_chk (used directly by compiler, not in headers)..
__stpcpy_chk(char * dst,const char * src,size_t dst_len)233  extern "C" char* __stpcpy_chk(char* dst, const char* src, size_t dst_len) {
234    // TODO: optimize so we don't scan src twice.
235    size_t src_len = strlen(src) + 1;
236    __check_buffer_access("stpcpy", "write into", src_len, dst_len);
237    return stpcpy(dst, src);
238  }
239  
240  // Runtime implementation of __builtin____stpncpy_chk (used directly by compiler, not in headers).
__stpncpy_chk(char * dst,const char * src,size_t len,size_t dst_len)241  extern "C" char* __stpncpy_chk(char* dst, const char* src, size_t len, size_t dst_len) {
242    __check_buffer_access("stpncpy", "write into", len, dst_len);
243    return stpncpy(dst, src, len);
244  }
245  
246  // This is a variant of __stpncpy_chk, but it also checks to make
247  // sure we don't read beyond the end of "src". The code for this is
248  // based on the original version of stpncpy, but modified to check
249  // how much we read from "src" during the copy operation.
__stpncpy_chk2(char * dst,const char * src,size_t n,size_t dst_len,size_t src_len)250  char* __stpncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_t src_len) {
251    __check_buffer_access("stpncpy", "write into", n, dst_len);
252    if (n != 0) {
253      char* d = dst;
254      const char* s = src;
255  
256      do {
257        size_t s_copy_len = static_cast<size_t>(s - src);
258        if (__predict_false(s_copy_len >= src_len)) {
259          __fortify_fatal("stpncpy: detected read past end of %zu-byte buffer", src_len);
260        }
261  
262        if ((*d++ = *s++) == 0) {
263          // NUL pad the remaining n-1 bytes.
264          while (--n != 0) {
265            *d++ = 0;
266          }
267          break;
268        }
269      } while (--n != 0);
270    }
271  
272    return dst;
273  }
274  
275  // strcat is performance-critical enough that we have assembler __strcat_chk implementations.
276  // This function is used to give better diagnostics than we can easily do from assembler.
__strcat_chk_fail(size_t dst_buf_size)277  extern "C" void __strcat_chk_fail(size_t dst_buf_size) {
278    __fortify_fatal("strcat: prevented write past end of %zu-byte buffer", dst_buf_size);
279  }
280  
__strchr_chk(const char * p,int ch,size_t s_len)281  char* __strchr_chk(const char* p, int ch, size_t s_len) {
282    for (;; ++p, s_len--) {
283      if (__predict_false(s_len == 0)) {
284        __fortify_fatal("strchr: prevented read past end of buffer");
285      }
286      if (*p == static_cast<char>(ch)) {
287        return const_cast<char*>(p);
288      }
289      if (*p == '\0') {
290        return nullptr;
291      }
292    }
293  }
294  
295  // strcpy is performance-critical enough that we have assembler __strcpy_chk implementations.
296  // This function is used to give better diagnostics than we can easily do from assembler.
__strcpy_chk_fail(size_t dst_buf_size)297  extern "C" void __strcpy_chk_fail(size_t dst_buf_size) {
298    __fortify_fatal("strcpy: prevented write past end of %zu-byte buffer", dst_buf_size);
299  }
300  
__strlcat_chk(char * dst,const char * src,size_t supplied_size,size_t dst_len_from_compiler)301  size_t __strlcat_chk(char* dst, const char* src,
302                       size_t supplied_size, size_t dst_len_from_compiler) {
303    __check_buffer_access("strlcat", "write into", supplied_size, dst_len_from_compiler);
304    return strlcat(dst, src, supplied_size);
305  }
306  
__strlcpy_chk(char * dst,const char * src,size_t supplied_size,size_t dst_len_from_compiler)307  size_t __strlcpy_chk(char* dst, const char* src,
308                       size_t supplied_size, size_t dst_len_from_compiler) {
309    __check_buffer_access("strlcpy", "write into", supplied_size, dst_len_from_compiler);
310    return strlcpy(dst, src, supplied_size);
311  }
312  
__strlen_chk(const char * s,size_t s_len)313  size_t __strlen_chk(const char* s, size_t s_len) {
314    // TODO: "prevented" here would be a lie because this strlen can run off the end.
315    // strlen is too important to be expensive, so we wanted to be able to call the optimized
316    // implementation, but I think we need to implement optimized assembler __strlen_chk routines.
317    size_t ret = strlen(s);
318    if (__predict_false(ret >= s_len)) {
319      __fortify_fatal("strlen: detected read past end of buffer");
320    }
321    return ret;
322  }
323  
324  // Runtime implementation of __builtin____strncat_chk (used directly by compiler, not in headers).
__strncat_chk(char * dst,const char * src,size_t len,size_t dst_buf_size)325  extern "C" char* __strncat_chk(char* dst, const char* src, size_t len, size_t dst_buf_size) {
326    if (len == 0) {
327      return dst;
328    }
329  
330    size_t dst_len = __strlen_chk(dst, dst_buf_size);
331    char* d = dst + dst_len;
332    dst_buf_size -= dst_len;
333  
334    while (*src != '\0') {
335      *d++ = *src++;
336      len--; dst_buf_size--;
337  
338      if (__predict_false(dst_buf_size == 0)) {
339        __fortify_fatal("strncat: prevented write past end of buffer");
340      }
341  
342      if (len == 0) {
343        break;
344      }
345    }
346  
347    *d = '\0';
348    return dst;
349  }
350  
351  // Runtime implementation of __builtin____strncpy_chk (used directly by compiler, not in headers).
__strncpy_chk(char * dst,const char * src,size_t len,size_t dst_len)352  extern "C" char* __strncpy_chk(char* dst, const char* src, size_t len, size_t dst_len) {
353    __check_buffer_access("strncpy", "write into", len, dst_len);
354    return strncpy(dst, src, len);
355  }
356  
357  // This is a variant of __strncpy_chk, but it also checks to make
358  // sure we don't read beyond the end of "src". The code for this is
359  // based on the original version of strncpy, but modified to check
360  // how much we read from "src" during the copy operation.
__strncpy_chk2(char * dst,const char * src,size_t n,size_t dst_len,size_t src_len)361  char* __strncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_t src_len) {
362    __check_buffer_access("strncpy", "write into", n, dst_len);
363    if (n != 0) {
364      char* d = dst;
365      const char* s = src;
366  
367      do {
368        size_t s_copy_len = static_cast<size_t>(s - src);
369        if (__predict_false(s_copy_len >= src_len)) {
370          __fortify_fatal("strncpy: detected read past end of %zu-byte buffer", src_len);
371        }
372  
373        if ((*d++ = *s++) == 0) {
374          // NUL pad the remaining n-1 bytes.
375          while (--n != 0) {
376            *d++ = 0;
377          }
378          break;
379        }
380      } while (--n != 0);
381    }
382  
383    return dst;
384  }
385  
__strrchr_chk(const char * p,int ch,size_t s_len)386  char* __strrchr_chk(const char* p, int ch, size_t s_len) {
387    for (const char* save = nullptr;; ++p, s_len--) {
388      if (s_len == 0) {
389        __fortify_fatal("strrchr: prevented read past end of buffer");
390      }
391      if (*p == static_cast<char>(ch)) {
392        save = p;
393      }
394      if (!*p) {
395        return const_cast<char*>(save);
396      }
397    }
398  }
399  
__umask_chk(mode_t mode)400  mode_t __umask_chk(mode_t mode) {
401    if (__predict_false((mode & 0777) != mode)) {
402      __fortify_fatal("umask: called with invalid mask %o", mode);
403    }
404  
405    return umask(mode);
406  }
407  
408  // Runtime implementation of __builtin____vsnprintf_chk (used directly by compiler, not in headers).
__vsnprintf_chk(char * dst,size_t supplied_size,int,size_t dst_len_from_compiler,const char * format,va_list va)409  extern "C" int __vsnprintf_chk(char* dst, size_t supplied_size, int /*flags*/,
410                                 size_t dst_len_from_compiler, const char* format, va_list va) {
411    __check_buffer_access("vsnprintf", "write into", supplied_size, dst_len_from_compiler);
412    return vsnprintf(dst, supplied_size, format, va);
413  }
414  
415  // Runtime implementation of __builtin____snprintf_chk (used directly by compiler, not in headers).
__snprintf_chk(char * dst,size_t supplied_size,int flags,size_t dst_len_from_compiler,const char * format,...)416  extern "C" int __snprintf_chk(char* dst, size_t supplied_size, int flags,
417                                size_t dst_len_from_compiler, const char* format, ...) {
418    va_list va;
419    va_start(va, format);
420    int result = __vsnprintf_chk(dst, supplied_size, flags, dst_len_from_compiler, format, va);
421    va_end(va);
422    return result;
423  }
424  
425  // Runtime implementation of __builtin____vsprintf_chk (used directly by compiler, not in headers).
__vsprintf_chk(char * dst,int,size_t dst_len_from_compiler,const char * format,va_list va)426  extern "C" int __vsprintf_chk(char* dst, int /*flags*/,
427                                size_t dst_len_from_compiler, const char* format, va_list va) {
428    // The compiler uses SIZE_MAX to mean "no idea", but our vsnprintf rejects sizes that large.
429    int result = vsnprintf(dst,
430                           dst_len_from_compiler == SIZE_MAX ? SSIZE_MAX : dst_len_from_compiler,
431                           format, va);
432  
433    // Try to catch failures after the fact...
434    __check_buffer_access("vsprintf", "write into", result + 1, dst_len_from_compiler);
435    return result;
436  }
437  
438  // Runtime implementation of __builtin____sprintf_chk (used directly by compiler, not in headers).
__sprintf_chk(char * dst,int flags,size_t dst_len_from_compiler,const char * format,...)439  extern "C" int __sprintf_chk(char* dst, int flags, size_t dst_len_from_compiler,
440                               const char* format, ...) {
441    va_list va;
442    va_start(va, format);
443    int result = __vsprintf_chk(dst, flags, dst_len_from_compiler, format, va);
444    va_end(va);
445    return result;
446  }
447  
__write_chk(int fd,const void * buf,size_t count,size_t buf_size)448  ssize_t __write_chk(int fd, const void* buf, size_t count, size_t buf_size) {
449    __check_count("write", "count", count);
450    __check_buffer_access("write", "read from", count, buf_size);
451    return write(fd, buf, count);
452  }
453  
454  #if defined(RENAME___STRCAT_CHK)
455  #define __STRCAT_CHK __strcat_chk_generic
456  #else
457  #define __STRCAT_CHK __strcat_chk
458  #endif // RENAME___STRCAT_CHK
459  
460  // Runtime implementation of __builtin____strcat_chk (used directly by compiler, not in headers).
__STRCAT_CHK(char * dst,const char * src,size_t dst_buf_size)461  extern "C" char* __STRCAT_CHK(char* dst, const char* src, size_t dst_buf_size) {
462    char* save = dst;
463    size_t dst_len = __strlen_chk(dst, dst_buf_size);
464  
465    dst += dst_len;
466    dst_buf_size -= dst_len;
467  
468    while ((*dst++ = *src++) != '\0') {
469      dst_buf_size--;
470      if (__predict_false(dst_buf_size == 0)) {
471        __fortify_fatal("strcat: prevented write past end of %zu-byte buffer", dst_buf_size);
472      }
473    }
474  
475    return save;
476  }
477  
478  #if defined(RENAME___STRCPY_CHK)
479  #define __STRCPY_CHK __strcpy_chk_generic
480  #else
481  #define __STRCPY_CHK __strcpy_chk
482  #endif // RENAME___STRCPY_CHK
483  
484  // Runtime implementation of __builtin____strcpy_chk (used directly by compiler, not in headers).
__STRCPY_CHK(char * dst,const char * src,size_t dst_len)485  extern "C" char* __STRCPY_CHK(char* dst, const char* src, size_t dst_len) {
486    // TODO: optimize so we don't scan src twice.
487    size_t src_len = strlen(src) + 1;
488    __check_buffer_access("strcpy", "write into", src_len, dst_len);
489    return strcpy(dst, src);
490  }
491  
492  #if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv)
493  // Runtime implementation of __memcpy_chk (used directly by compiler, not in headers).
494  // arm32,arm64,riscv have assembler implementations, and don't need this C fallback.
__memcpy_chk(void * dst,const void * src,size_t count,size_t dst_len)495  extern "C" void* __memcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
496    __check_count("memcpy", "count", count);
497    __check_buffer_access("memcpy", "write into", count, dst_len);
498    return memcpy(dst, src, count);
499  }
500  #endif
501  
502  // Runtime implementation of __mempcpy_chk (used directly by compiler, not in headers).
__mempcpy_chk(void * dst,const void * src,size_t count,size_t dst_len)503  extern "C" void* __mempcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
504    __check_count("mempcpy", "count", count);
505    __check_buffer_access("mempcpy", "write into", count, dst_len);
506    return mempcpy(dst, src, count);
507  }
508