diff --git a/src/libc/secure/memccpy_chk.c b/src/libc/secure/memccpy_chk.c new file mode 100644 index 000000000..5f472c098 --- /dev/null +++ b/src/libc/secure/memccpy_chk.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012-2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include "secure.h" + +void * +__memccpy_chk (void *dest, const void *src, int c, size_t len, size_t dstlen) +{ + void *retval; + + if (__builtin_expect (dstlen < len, 0)) + __chk_fail_overflow (); + + /* retval is NULL if len was copied, otherwise retval is the + * byte *after* the last one written. + */ + retval = memccpy (dest, src, c, len); + + if (retval != NULL) { + len = (uintptr_t)retval - (uintptr_t)dest; + } + + __chk_overlap(dest, len, src, len); + + return retval; +} diff --git a/src/libc/secure/secure.c b/src/libc/secure/secure.c new file mode 100644 index 000000000..a88f524e0 --- /dev/null +++ b/src/libc/secure/secure.c @@ -0,0 +1,30 @@ +#include "secure.h" +#include +#include +#include +#include +#include + +extern void __abort(void) __dead2; +extern void __chk_fail (void) __attribute__((__noreturn__)); + +void __chk_fail_overflow (void) __attribute__((__noreturn__)) +{ + __chk_fail(); +} + +void __chk_fail_overlap (void) __attribute__((__noreturn__)) +{ + const char message[] = "[%d] detected illegal buffer overlap"; + + syslog(LOG_CRIT, message, getpid()); + + __abort(); +} + +void __chk_overlap (const void *a, size_t an, const void *b, size_t bn) +{ + if (((uintptr_t)a) <= ((uintptr_t)b)+bn && ((uintptr_t)b) <= ((uintptr_t)a)+an) + __chk_fail_overlap(); +} + diff --git a/src/libc/secure/secure.h b/src/libc/secure/secure.h new file mode 100644 index 000000000..07bafc614 --- /dev/null +++ b/src/libc/secure/secure.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef _SECURE_H_ + +#include + +extern void __chk_fail_overflow (void) __attribute__((__noreturn__)); +extern void __chk_fail_overlap (void) __attribute__((__noreturn__)); + +/* Assert if a -> a+an and b -> b+bn overlap. + * 0-lengths don't overlap anything. + */ +extern void __chk_overlap (const void *a, size_t an, const void *b, size_t bn); + +/* Do we avoid the overlap check for older APIs? */ +extern int __chk_assert_no_overlap; + +#endif diff --git a/src/libc/secure/strlcat_chk.c b/src/libc/secure/strlcat_chk.c new file mode 100644 index 000000000..5eb434ee9 --- /dev/null +++ b/src/libc/secure/strlcat_chk.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012-2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include "secure.h" + +size_t +__strlcat_chk (char *restrict dest, char *restrict src, + size_t len, size_t dstlen) +{ + size_t initial_srclen; + size_t initial_dstlen; + + if (__builtin_expect (dstlen < len, 0)) + __chk_fail_overflow (); + + initial_srclen = strlen(src); + initial_dstlen = strnlen(dest, len); + + if (initial_dstlen == len) + return len+initial_srclen; + + if (initial_srclen < len - initial_dstlen) { + __chk_overlap(dest, initial_srclen + initial_dstlen + 1, src, initial_srclen + 1); + memcpy(dest+initial_dstlen, src, initial_srclen + 1); + } else { + __chk_overlap(dest, initial_srclen + initial_dstlen + 1, src, len - initial_dstlen - 1); + memcpy(dest+initial_dstlen, src, len - initial_dstlen - 1); + dest[len-1] = '\0'; + } + + return initial_srclen + initial_dstlen; +} diff --git a/src/libc/secure/strlcpy_chk.c b/src/libc/secure/strlcpy_chk.c new file mode 100644 index 000000000..504e7662c --- /dev/null +++ b/src/libc/secure/strlcpy_chk.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012-2013 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include "secure.h" + +size_t +__strlcpy_chk (char *restrict dest, char *restrict src, + size_t len, size_t dstlen) +{ + size_t retval; + if (__builtin_expect (dstlen < len, 0)) + __chk_fail_overflow (); + + retval = strlcpy (dest, src, len); + + if (retval < len) + len = retval + 1; + + __chk_overlap(dest, len, src, len); + + return retval; +}