diff options
Diffstat (limited to 'libc')
-rw-r--r-- | libc/Android.mk | 4 | ||||
-rw-r--r-- | libc/bionic/__stpcpy_chk.cpp | 55 | ||||
-rw-r--r-- | libc/bionic/__stpncpy_chk.cpp | 92 | ||||
-rw-r--r-- | libc/bionic/__strcpy_chk.cpp | 4 | ||||
-rw-r--r-- | libc/include/string.h | 44 | ||||
-rw-r--r-- | libc/private/libc_events.h | 2 | ||||
-rw-r--r-- | libc/upstream-openbsd/lib/libc/string/stpcpy.c | 44 | ||||
-rw-r--r-- | libc/upstream-openbsd/lib/libc/string/stpncpy.c | 56 |
8 files changed, 295 insertions, 6 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index 44bf3881e..3eaff2f60 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -96,6 +96,8 @@ libc_common_src_files += \ bionic/__memmove_chk.cpp \ bionic/__read_chk.cpp \ bionic/__recvfrom_chk.cpp \ + bionic/__stpcpy_chk.cpp \ + bionic/__stpncpy_chk.cpp \ bionic/__strchr_chk.cpp \ bionic/__strlcat_chk.cpp \ bionic/__strlcpy_chk.cpp \ @@ -383,6 +385,8 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdlib/strtoull.c \ upstream-openbsd/lib/libc/stdlib/strtoumax.c \ upstream-openbsd/lib/libc/stdlib/system.c \ + upstream-openbsd/lib/libc/string/stpcpy.c \ + upstream-openbsd/lib/libc/string/stpncpy.c \ upstream-openbsd/lib/libc/string/strcasecmp.c \ upstream-openbsd/lib/libc/string/strcspn.c \ upstream-openbsd/lib/libc/string/strdup.c \ diff --git a/libc/bionic/__stpcpy_chk.cpp b/libc/bionic/__stpcpy_chk.cpp new file mode 100644 index 000000000..3ce81eeba --- /dev/null +++ b/libc/bionic/__stpcpy_chk.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#undef _FORTIFY_SOURCE + +#include <string.h> +#include <stdlib.h> +#include "private/libc_logging.h" + +/* + * Runtime implementation of __builtin____stpcpy_chk. + * + * See + * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html + * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html + * for details. + * + * This stpcpy check is called if _FORTIFY_SOURCE is defined and + * greater than 0. + */ +extern "C" char* __stpcpy_chk(char* dest, const char* src, size_t dest_len) { + // TODO: optimize so we don't scan src twice. + size_t src_len = strlen(src) + 1; + if (__predict_false(src_len > dest_len)) { + __fortify_chk_fail("stpcpy: prevented write past end of buffer", + BIONIC_EVENT_STPCPY_BUFFER_OVERFLOW); + } + + return stpcpy(dest, src); +} diff --git a/libc/bionic/__stpncpy_chk.cpp b/libc/bionic/__stpncpy_chk.cpp new file mode 100644 index 000000000..6c9215c70 --- /dev/null +++ b/libc/bionic/__stpncpy_chk.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#undef _FORTIFY_SOURCE + +#include <string.h> +#include <stdlib.h> +#include "private/libc_logging.h" + +/* + * Runtime implementation of __builtin____stpncpy_chk. + * + * See + * http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html + * http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html + * for details. + * + * This stpncpy check is called if _FORTIFY_SOURCE is defined and + * greater than 0. + */ +extern "C" char* __stpncpy_chk(char* __restrict dest, const char* __restrict src, + size_t len, size_t dest_len) { + if (__predict_false(len > dest_len)) { + __fortify_chk_fail("stpncpy: prevented write past end of buffer", + BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW); + } + + return stpncpy(dest, src, len); +} + +/* + * __stpncpy_chk2 + * + * This is a variant of __stpncpy_chk, but it also checks to make + * sure we don't read beyond the end of "src". The code for this is + * based on the original version of stpncpy, but modified to check + * how much we read from "src" at the end of the copy operation. + */ +extern "C" char* __stpncpy_chk2(char* __restrict dst, const char* __restrict src, + size_t n, size_t dest_len, size_t src_len) +{ + if (__predict_false(n > dest_len)) { + __fortify_chk_fail("stpncpy: prevented write past end of buffer", + BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW); + } + if (n != 0) { + char* d = dst; + const char* s = src; + + do { + if ((*d++ = *s++) == 0) { + /* NUL pad the remaining n-1 bytes */ + while (--n != 0) { + *d++ = 0; + } + break; + } + } while (--n != 0); + + size_t s_copy_len = static_cast<size_t>(s - src); + if (__predict_false(s_copy_len > src_len)) { + __fortify_chk_fail("stpncpy: prevented read past end of buffer", 0); + } + } + + return dst; +} diff --git a/libc/bionic/__strcpy_chk.cpp b/libc/bionic/__strcpy_chk.cpp index 1f6bc8085..ad3ef5024 100644 --- a/libc/bionic/__strcpy_chk.cpp +++ b/libc/bionic/__strcpy_chk.cpp @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#undef _FORTIFY_SOURCE + #include <string.h> #include <stdlib.h> #include "private/libc_logging.h" @@ -41,7 +43,7 @@ * This strcpy check is called if _FORTIFY_SOURCE is defined and * greater than 0. */ -extern "C" char* __strcpy_chk (char* dest, const char* src, size_t dest_len) { +extern "C" char* __strcpy_chk(char* dest, const char* src, size_t dest_len) { // TODO: optimize so we don't scan src twice. size_t src_len = strlen(src) + 1; if (__predict_false(src_len > dest_len)) { diff --git a/libc/include/string.h b/libc/include/string.h index ec998ed35..c9ae03bce 100644 --- a/libc/include/string.h +++ b/libc/include/string.h @@ -53,6 +53,7 @@ extern char* __strrchr_chk(const char *, int, size_t); extern size_t strlen(const char *) __purefunc; extern size_t __strlen_chk(const char *, size_t); extern int strcmp(const char *, const char *) __purefunc; +extern char* stpcpy(char* __restrict, const char* __restrict); extern char* strcpy(char* __restrict, const char* __restrict); extern char* strcat(char* __restrict, const char* __restrict); @@ -72,6 +73,7 @@ extern size_t strnlen(const char *, size_t) __purefunc; extern char* strncat(char* __restrict, const char* __restrict, size_t); extern char* strndup(const char *, size_t); extern int strncmp(const char *, const char *, size_t) __purefunc; +extern char* stpncpy(char* __restrict, const char* __restrict, size_t); extern char* strncpy(char* __restrict, const char* __restrict, size_t); extern size_t strlcat(char* __restrict, const char* __restrict, size_t); @@ -89,8 +91,8 @@ extern size_t strxfrm(char* __restrict, const char* __restrict, size_t); #if defined(__BIONIC_FORTIFY) -__errordecl(__memcpy_dest_size_error, "memcpy called with size bigger than destination"); -__errordecl(__memcpy_src_size_error, "memcpy called with size bigger than source"); +__errordecl(__memcpy_dest_size_error, "memcpy: prevented write past end of buffer"); +__errordecl(__memcpy_src_size_error, "memcpy: prevented read past end of buffer"); __BIONIC_FORTIFY_INLINE void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) { @@ -116,11 +118,43 @@ void* memmove(void *dest, const void *src, size_t len) { } __BIONIC_FORTIFY_INLINE +char* stpcpy(char* __restrict dest, const char* __restrict src) { + return __builtin___stpcpy_chk(dest, src, __bos(dest)); +} + +__BIONIC_FORTIFY_INLINE char* strcpy(char* __restrict dest, const char* __restrict src) { return __builtin___strcpy_chk(dest, src, __bos(dest)); } -__errordecl(__strncpy_error, "strncpy called with size bigger than buffer"); +__errordecl(__stpncpy_error, "stpncpy: prevented write past end of buffer"); +extern char* __stpncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t); + +__BIONIC_FORTIFY_INLINE +char* stpncpy(char* __restrict dest, const char* __restrict src, size_t n) { + size_t bos_dest = __bos(dest); + size_t bos_src = __bos(src); + if (__builtin_constant_p(n) && (n > bos_dest)) { + __stpncpy_error(); + } + + if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) { + return __builtin___stpncpy_chk(dest, src, n, bos_dest); + } + + if (__builtin_constant_p(n) && (n <= bos_src)) { + return __builtin___stpncpy_chk(dest, src, n, bos_dest); + } + + size_t slen = __builtin_strlen(src); + if (__builtin_constant_p(slen)) { + return __builtin___stpncpy_chk(dest, src, n, bos_dest); + } + + return __stpncpy_chk2(dest, src, n, bos_dest, bos_src); +} + +__errordecl(__strncpy_error, "strncpy: prevented write past end of buffer"); extern char* __strncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t); __BIONIC_FORTIFY_INLINE @@ -164,7 +198,7 @@ void* memset(void *s, int c, size_t n) { extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t) __asm__(__USER_LABEL_PREFIX__ "strlcpy"); -__errordecl(__strlcpy_error, "strlcpy called with size bigger than buffer"); +__errordecl(__strlcpy_error, "strlcpy: prevented write past end of buffer"); extern size_t __strlcpy_chk(char *, const char *, size_t, size_t); __BIONIC_FORTIFY_INLINE @@ -195,7 +229,7 @@ size_t strlcpy(char* __restrict dest, const char* __restrict src, size_t size) { extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t) __asm__(__USER_LABEL_PREFIX__ "strlcat"); -__errordecl(__strlcat_error, "strlcat called with size bigger than buffer"); +__errordecl(__strlcat_error, "strlcat: prevented write past end of buffer"); extern size_t __strlcat_chk(char* __restrict, const char* __restrict, size_t, size_t); diff --git a/libc/private/libc_events.h b/libc/private/libc_events.h index 5d20f4b81..f2b973d08 100644 --- a/libc/private/libc_events.h +++ b/libc/private/libc_events.h @@ -40,6 +40,8 @@ #define BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW 80120 #define BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 80125 #define BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW 80130 +#define BIONIC_EVENT_STPCPY_BUFFER_OVERFLOW 80135 +#define BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW 80140 #define BIONIC_EVENT_RESOLVER_OLD_RESPONSE 80300 #define BIONIC_EVENT_RESOLVER_WRONG_SERVER 80305 diff --git a/libc/upstream-openbsd/lib/libc/string/stpcpy.c b/libc/upstream-openbsd/lib/libc/string/stpcpy.c new file mode 100644 index 000000000..d3d61e0f1 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/string/stpcpy.c @@ -0,0 +1,44 @@ +/* $OpenBSD: stpcpy.c,v 1.1 2012/01/17 02:48:01 guenther Exp $ */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <string.h> + +#if defined(APIWARN) +__warn_references(stpcpy, + "warning: stpcpy() is dangerous GNU crap; don't use it"); +#endif + +char * +stpcpy(char *to, const char *from) +{ + for (; (*to = *from) != '\0'; ++from, ++to); + return(to); +} diff --git a/libc/upstream-openbsd/lib/libc/string/stpncpy.c b/libc/upstream-openbsd/lib/libc/string/stpncpy.c new file mode 100644 index 000000000..c7c2a57c4 --- /dev/null +++ b/libc/upstream-openbsd/lib/libc/string/stpncpy.c @@ -0,0 +1,56 @@ +/* $OpenBSD: stpncpy.c,v 1.2 2012/07/11 10:44:59 naddy Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <string.h> + +char * +stpncpy(char *dst, const char *src, size_t n) +{ + if (n != 0) { + char *d = dst; + const char *s = src; + + dst = &dst[n]; + do { + if ((*d++ = *s++) == 0) { + dst = d - 1; + /* NUL pad the remaining n-1 bytes */ + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + return (dst); +} |