diff --git a/include/ssp/ssp.h b/include/ssp/ssp.h index de109da4959e..6ebc23288391 100644 --- a/include/ssp/ssp.h +++ b/include/ssp/ssp.h @@ -1,105 +1,109 @@ /* $NetBSD: ssp.h,v 1.13 2015/09/03 20:43:47 plunky Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006, 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_SSP_H_ #define _SSP_SSP_H_ #include #if !defined(__cplusplus) # if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && \ (__OPTIMIZE__ > 0 || defined(__clang__)) # if _FORTIFY_SOURCE > 1 # define __SSP_FORTIFY_LEVEL 2 # else # define __SSP_FORTIFY_LEVEL 1 # endif # else # define __SSP_FORTIFY_LEVEL 0 # endif #else # define __SSP_FORTIFY_LEVEL 0 #endif #define __ssp_var(type) __CONCAT(__ssp_ ## type, __COUNTER__) /* __ssp_real is used by the implementation in libc */ #if __SSP_FORTIFY_LEVEL == 0 #define __ssp_real_(fun) fun #else #define __ssp_real_(fun) __ssp_real_ ## fun #endif #define __ssp_real(fun) __ssp_real_(fun) #define __ssp_inline static __inline __attribute__((__always_inline__)) #define __ssp_bos(ptr) __builtin_object_size(ptr, __SSP_FORTIFY_LEVEL > 1) #define __ssp_bos0(ptr) __builtin_object_size(ptr, 0) #define __ssp_check(buf, len, bos) \ - if (bos(buf) != (size_t)-1 && len > bos(buf)) \ + if (bos(buf) != (size_t)-1 && (size_t)len > bos(buf)) \ __chk_fail() -#define __ssp_redirect_raw(rtype, fun, symbol, args, call, cond, bos) \ + +#define __ssp_redirect_raw_impl(rtype, fun, symbol, args) \ rtype __ssp_real_(fun) args __RENAME(symbol); \ __ssp_inline rtype fun args __RENAME(__ssp_protected_ ## fun); \ -__ssp_inline rtype fun args { \ +__ssp_inline rtype fun args + +#define __ssp_redirect_raw(rtype, fun, symbol, args, call, cond, bos, len) \ +__ssp_redirect_raw_impl(rtype, fun, symbol, args) { \ if (cond) \ - __ssp_check(__buf, __len, bos); \ + __ssp_check(__buf, len, bos); \ return __ssp_real_(fun) call; \ } #define __ssp_redirect(rtype, fun, args, call) \ - __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos) + __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos, __len) #define __ssp_redirect0(rtype, fun, args, call) \ - __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0) + __ssp_redirect_raw(rtype, fun, fun, args, call, 1, __ssp_bos0, __len) #include static inline int __ssp_overlap(const void *leftp, const void *rightp, __size_t sz) { __uintptr_t left = (__uintptr_t)leftp; __uintptr_t right = (__uintptr_t)rightp; if (left <= right) return (SIZE_MAX - sz < left || right < left + sz); return (SIZE_MAX - sz < right || left < right + sz); } __BEGIN_DECLS void __stack_chk_fail(void) __dead2; void __chk_fail(void) __dead2; __END_DECLS #endif /* _SSP_SSP_H_ */ diff --git a/include/ssp/stdio.h b/include/ssp/stdio.h index 4bca1de7d4f9..f7a390f315a4 100644 --- a/include/ssp/stdio.h +++ b/include/ssp/stdio.h @@ -1,87 +1,105 @@ /* $NetBSD: stdio.h,v 1.5 2011/07/17 20:54:34 joerg Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_STDIO_H_ #define _SSP_STDIO_H_ #include __BEGIN_DECLS +#if __SSP_FORTIFY_LEVEL > 0 +#if __POSIX_VISIBLE +__ssp_redirect_raw(char *, ctermid, ctermid, (char *__buf), (__buf), + __buf != NULL, __ssp_bos, L_ctermid); +#if __BSD_VISIBLE +__ssp_redirect_raw(char *, ctermid_r, ctermid_r, (char *__buf), (__buf), + __buf != NULL, __ssp_bos, L_ctermid); +#endif /* __BSD_VISIBLE */ +#endif /* __POSIX_VISIBLE */ +__ssp_redirect(size_t, fread, (void *__restrict __buf, size_t __len, + size_t __nmemb, FILE *__restrict __fp), (__buf, __len, __nmemb, __fp)); +__ssp_redirect(size_t, fread_unlocked, (void *__restrict __buf, size_t __len, + size_t __nmemb, FILE *__restrict __fp), (__buf, __len, __nmemb, __fp)); +__ssp_redirect(char *, gets_s, (char *__buf, rsize_t __len), (__buf, __len)); +__ssp_redirect_raw(char *, tmpnam, tmpnam, (char *__buf), (__buf), 1, + __ssp_bos, L_tmpnam); +#endif + int __sprintf_chk(char *__restrict, int, size_t, const char *__restrict, ...) __printflike(4, 5); int __vsprintf_chk(char *__restrict, int, size_t, const char *__restrict, __va_list) __printflike(4, 0); int __snprintf_chk(char *__restrict, size_t, int, size_t, const char *__restrict, ...) __printflike(5, 6); int __vsnprintf_chk(char *__restrict, size_t, int, size_t, const char *__restrict, __va_list) __printflike(5, 0); char *__fgets_chk(char *, int, size_t, FILE *); __END_DECLS #if __SSP_FORTIFY_LEVEL > 0 #define sprintf(str, ...) __extension__ ({ \ char *_ssp_str = (str); \ __builtin___sprintf_chk(_ssp_str, 0, __ssp_bos(_ssp_str), \ __VA_ARGS__); \ }) #define vsprintf(str, fmt, ap) __extension__ ({ \ char *_ssp_str = (str); \ __builtin___vsprintf_chk(_ssp_str, 0, __ssp_bos(_ssp_str), fmt, \ ap); \ }) #define snprintf(str, len, ...) __extension__ ({ \ char *_ssp_str = (str); \ __builtin___snprintf_chk(_ssp_str, len, 0, __ssp_bos(_ssp_str), \ __VA_ARGS__); \ }) #define vsnprintf(str, len, fmt, ap) __extension__ ({ \ char *_ssp_str = (str); \ __builtin___vsnprintf_chk(_ssp_str, len, 0, __ssp_bos(_ssp_str), \ fmt, ap); \ }) #define fgets(str, len, fp) __extension__ ({ \ char *_ssp_str = (str); \ __fgets_chk(_ssp_str, len, __ssp_bos(_ssp_str), fp); \ }) #endif /* __SSP_FORTIFY_LEVEL > 0 */ #endif /* _SSP_STDIO_H_ */ diff --git a/include/ssp/string.h b/include/ssp/string.h index ceb4ba2a2174..b9f2dceb1df5 100644 --- a/include/ssp/string.h +++ b/include/ssp/string.h @@ -1,129 +1,151 @@ /* $NetBSD: string.h,v 1.14 2020/09/05 13:37:59 mrg Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_STRING_H_ #define _SSP_STRING_H_ #include __BEGIN_DECLS void *__memcpy_chk(void *, const void *, size_t, size_t); void *__memmove_chk(void *, const void *, size_t, size_t); void *__memset_chk(void *, int, size_t, size_t); char *__stpcpy_chk(char *, const char *, size_t); char *__stpncpy_chk(char *, const char *, size_t, size_t); char *__strcat_chk(char *, const char *, size_t); char *__strcpy_chk(char *, const char *, size_t); char *__strncat_chk(char *, const char *, size_t, size_t); +size_t __strlcat_chk(char *, const char *, size_t, size_t); char *__strncpy_chk(char *, const char *, size_t, size_t); +size_t __strlcpy_chk(char *, const char *, size_t, size_t); __END_DECLS #if __SSP_FORTIFY_LEVEL > 0 #define __ssp_bos_check3_typed_var(fun, dsttype, dsrvar, dst, srctype, srcvar, \ src, lenvar, len) __extension__ ({ \ srctype srcvar = (src); \ dsttype dstvar = (dst); \ size_t lenvar = (len); \ ((__ssp_bos0(dstvar) != (size_t)-1) ? \ __builtin___ ## fun ## _chk(dstvar, srcvar, lenvar, \ __ssp_bos0(dstvar)) : \ __ ## fun ## _ichk(dstvar, srcvar, lenvar)); \ }) #define __ssp_bos_check3_typed(fun, dsttype, dst, srctype, src, len) \ __ssp_bos_check3_typed_var(fun, dsttype, __ssp_var(dstv), dst, \ srctype, __ssp_var(srcv), src, __ssp_var(lenv), len) #define __ssp_bos_check3(fun, dst, src, len) \ __ssp_bos_check3_typed_var(fun, void *, __ssp_var(dstv), dst, \ const void *, __ssp_var(srcv), src, __ssp_var(lenv), len) #define __ssp_bos_check2_var(fun, dstvar, dst, srcvar, src) __extension__ ({ \ const void *srcvar = (src); \ void *dstvar = (dst); \ ((__ssp_bos0(dstvar) != (size_t)-1) ? \ __builtin___ ## fun ## _chk(dstvar, srcvar, \ __ssp_bos0(dstvar)) : \ __ ## fun ## _ichk(dstvar, srcvar)); \ }) #define __ssp_bos_check2(fun, dst, src) \ __ssp_bos_check2_var(fun, __ssp_var(dstv), dst, __ssp_var(srcv), src) #define __ssp_bos_icheck3_restrict(fun, type1, type2) \ static __inline type1 __ ## fun ## _ichk(type1 __restrict, type2 __restrict, size_t); \ static __inline __attribute__((__always_inline__)) type1 \ __ ## fun ## _ichk(type1 __restrict dst, type2 __restrict src, size_t len) { \ return __builtin___ ## fun ## _chk(dst, src, len, __ssp_bos0(dst)); \ } #define __ssp_bos_icheck3(fun, type1, type2) \ static __inline type1 __ ## fun ## _ichk(type1, type2, size_t); \ static __inline __attribute__((__always_inline__)) type1 \ __ ## fun ## _ichk(type1 dst, type2 src, size_t len) { \ return __builtin___ ## fun ## _chk(dst, src, len, __ssp_bos0(dst)); \ } #define __ssp_bos_icheck2_restrict(fun, type1, type2) \ static __inline type1 __ ## fun ## _ichk(type1, type2); \ static __inline __attribute__((__always_inline__)) type1 \ __ ## fun ## _ichk(type1 __restrict dst, type2 __restrict src) { \ return __builtin___ ## fun ## _chk(dst, src, __ssp_bos0(dst)); \ } __BEGIN_DECLS __ssp_bos_icheck3_restrict(memcpy, void *, const void *) __ssp_bos_icheck3(memmove, void *, const void *) __ssp_bos_icheck3(memset, void *, int) __ssp_bos_icheck2_restrict(stpcpy, char *, const char *) __ssp_bos_icheck3_restrict(stpncpy, char *, const char *) __ssp_bos_icheck2_restrict(strcpy, char *, const char *) __ssp_bos_icheck2_restrict(strcat, char *, const char *) +__ssp_redirect0(int, strerror_r, (int __errnum, char *__buf, size_t __len), + (__errnum, __buf, __len)); __ssp_bos_icheck3_restrict(strncpy, char *, const char *) __ssp_bos_icheck3_restrict(strncat, char *, const char *) + +__ssp_redirect_raw_impl(void *, mempcpy, mempcpy, + (void *__restrict buf, const void *__restrict src, size_t len)) +{ + const size_t slen = __ssp_bos(buf); + + if (len > slen) + __chk_fail(); + + if (__ssp_overlap(src, buf, len)) + __chk_fail(); + + return (__ssp_real(mempcpy)(buf, src, len)); +} __END_DECLS #define memcpy(dst, src, len) __ssp_bos_check3(memcpy, dst, src, len) #define memmove(dst, src, len) __ssp_bos_check3(memmove, dst, src, len) #define memset(dst, val, len) \ __ssp_bos_check3_typed(memset, void *, dst, int, val, len) #define stpcpy(dst, src) __ssp_bos_check2(stpcpy, dst, src) #define stpncpy(dst, src, len) __ssp_bos_check3(stpncpy, dst, src, len) #define strcpy(dst, src) __ssp_bos_check2(strcpy, dst, src) #define strcat(dst, src) __ssp_bos_check2(strcat, dst, src) +#define strlcpy(dst, src, dstlen) \ + __strlcpy_chk(dst, src, dstlen, __ssp_bos(dst)) #define strncpy(dst, src, len) __ssp_bos_check3(strncpy, dst, src, len) +#define strlcat(dst, src, dstlen) \ + __strlcat_chk(dst, src, dstlen, __ssp_bos(dst)) #define strncat(dst, src, len) __ssp_bos_check3(strncat, dst, src, len) #endif /* __SSP_FORTIFY_LEVEL > 0 */ #endif /* _SSP_STRING_H_ */ diff --git a/include/ssp/strings.h b/include/ssp/strings.h index 51b11a14ee87..79b70eba1c5c 100644 --- a/include/ssp/strings.h +++ b/include/ssp/strings.h @@ -1,67 +1,72 @@ /* $NetBSD: strings.h,v 1.3 2008/04/28 20:22:54 martin Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_STRINGS_H_ #define _SSP_STRINGS_H_ #include #include #if __SSP_FORTIFY_LEVEL > 0 #define _ssp_bcopy(srcvar, src, dstvar, dst, lenvar, len) __extension__ ({ \ const void *srcvar = (src); \ void *dstvar = (dst); \ size_t lenvar = (len); \ ((__ssp_bos0(dstvar) != (size_t)-1) ? \ __builtin___memmove_chk(dstvar, srcvar, lenvar, \ __ssp_bos0(dstvar)) : \ __memmove_ichk(dstvar, srcvar, lenvar)); \ }) #define bcopy(src, dst, len) \ _ssp_bcopy(__ssp_var(srcv), src, __ssp_var(dstv), dst, __ssp_var(lenv), len) #define _ssp_bzero(dstvar, dst, lenvar, len) __extension__ ({ \ void *dstvar = (dst); \ size_t lenvar = (len); \ ((__ssp_bos0(dstvar) != (size_t)-1) ? \ __builtin___memset_chk(dstvar, 0, lenvar, \ __ssp_bos0(dstvar)) : \ __memset_ichk(dstvar, 0, lenvar)); \ }) #define bzero(dst, len) _ssp_bzero(__ssp_var(dstv), dst, __ssp_var(lenv), len) +__BEGIN_DECLS +__ssp_redirect(void, explicit_bzero, (void *__buf, size_t __len), + (__buf, __len)); +__END_DECLS + #endif /* __SSP_FORTIFY_LEVEL > 0 */ #endif /* _SSP_STRINGS_H_ */ diff --git a/include/ssp/unistd.h b/include/ssp/unistd.h index bcd3664116cc..7e9d72343dde 100644 --- a/include/ssp/unistd.h +++ b/include/ssp/unistd.h @@ -1,58 +1,90 @@ /* $NetBSD: unistd.h,v 1.7 2015/06/25 18:41:03 joerg Exp $ */ /*- * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Christos Zoulas. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ #ifndef _SSP_UNISTD_H_ #define _SSP_UNISTD_H_ #include #if __SSP_FORTIFY_LEVEL > 0 __BEGIN_DECLS #ifndef _FORTIFY_SOURCE_read #define _FORTIFY_SOURCE_read read #endif -__ssp_redirect0(ssize_t, _FORTIFY_SOURCE_read, (int __fd, void *__buf, +__ssp_inline size_t +__ssp_gid_bos(const void *ptr) +{ + size_t ptrsize = __ssp_bos(ptr); + + if (ptrsize == (size_t)-1) + return (ptrsize); + + return (ptrsize / sizeof(gid_t)); +} + +__ssp_redirect_raw(int, getgrouplist, getgrouplist, + (const char *__name, gid_t __base, gid_t *__buf, int *__lenp), + (__name, __base, __buf, __lenp), 1, __ssp_gid_bos, *__lenp); + +__ssp_redirect_raw(int, getgroups, getgroups, (int __len, gid_t *__buf), + (__len, __buf), 1, __ssp_gid_bos, __len); + +__ssp_redirect(int, getloginclass, (char *__buf, size_t __len), + (__buf, __len)); + +__ssp_redirect(ssize_t, _FORTIFY_SOURCE_read, (int __fd, void *__buf, size_t __len), (__fd, __buf, __len)); +__ssp_redirect(ssize_t, pread, (int __fd, void *__buf, size_t __len, + off_t __offset), (__fd, __buf, __len, __offset)); __ssp_redirect(ssize_t, readlink, (const char *__restrict __path, \ char *__restrict __buf, size_t __len), (__path, __buf, __len)); +__ssp_redirect(ssize_t, readlinkat, (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len), (__fd, __path, __buf, __len)); __ssp_redirect_raw(char *, getcwd, getcwd, (char *__buf, size_t __len), - (__buf, __len), __buf != 0, __ssp_bos); + (__buf, __len), __buf != 0, __ssp_bos, __len); + +__ssp_redirect(int, getdomainname, (char *__buf, int __len), (__buf, __len)); +__ssp_redirect(int, getentropy, (void *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, gethostname, (char *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, getlogin_r, (char *__buf, size_t __len), (__buf, __len)); +__ssp_redirect(int, ttyname_r, (int __fd, char *__buf, size_t __len), + (__fd, __buf, __len)); __END_DECLS #endif /* __SSP_FORTIFY_LEVEL > 0 */ #endif /* _SSP_UNISTD_H_ */ diff --git a/include/stdio.h b/include/stdio.h index ea53816cf1d4..b0190d25eb4f 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -1,536 +1,539 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * 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. */ #ifndef _STDIO_H_ #define _STDIO_H_ #include #include #include __NULLABILITY_PRAGMA_PUSH typedef __off_t fpos_t; #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif #ifndef _RSIZE_T_DEFINED #define _RSIZE_T_DEFINED typedef size_t rsize_t; #endif #if __POSIX_VISIBLE >= 200809 #ifndef _OFF_T_DECLARED #define _OFF_T_DECLARED typedef __off_t off_t; #endif #ifndef _SSIZE_T_DECLARED #define _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #endif #endif #ifndef _OFF64_T_DECLARED #define _OFF64_T_DECLARED typedef __off64_t off64_t; #endif #if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE #ifndef _VA_LIST_DECLARED typedef __va_list va_list; #define _VA_LIST_DECLARED #endif #endif #define _FSTDIO /* Define for new stdio with functions. */ /* * NB: to fit things in six character monocase externals, the stdio * code uses the prefix `__s' for stdio objects, typically followed * by a three-character attempt at a mnemonic. */ /* stdio buffers */ struct __sbuf { unsigned char *_base; int _size; }; /* * stdio state variables. * * The following always hold: * * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR), * _lbfsize is -_bf._size, else _lbfsize is 0 * if _flags&__SRD, _w is 0 * if _flags&__SWR, _r is 0 * * This ensures that the getc and putc macros (or inline functions) never * try to write or read from a file that is in `read' or `write' mode. * (Moreover, they can, and do, automatically switch from read mode to * write mode, and back, on "r+" and "w+" files.) * * _lbfsize is used only to make the inline line-buffered output stream * code as compact as possible. * * _ub, _up, and _ur are used when ungetc() pushes back more characters * than fit in the current _bf, or when ungetc() pushes back a character * that does not match the previous one in _bf. When this happens, * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. * * Certain members of __sFILE are accessed directly via macros or * inline functions. To preserve ABI compat, these members must not * be disturbed. These members are marked below with (*). */ struct __sFILE { unsigned char *_p; /* (*) current position in (some) buffer */ int _r; /* (*) read space left for getc() */ int _w; /* (*) write space left for putc() */ short _flags; /* (*) flags, below; this FILE is free if 0 */ short _file; /* (*) fileno, if Unix descriptor, else -1 */ struct __sbuf _bf; /* (*) the buffer (at least 1 byte, if !NULL) */ int _lbfsize; /* (*) 0 or -_bf._size, for inline putc */ /* operations */ void *_cookie; /* (*) cookie passed to io functions */ int (* _Nullable _close)(void *); int (* _Nullable _read)(void *, char *, int); fpos_t (* _Nullable _seek)(void *, fpos_t, int); int (* _Nullable _write)(void *, const char *, int); /* separate buffer for long sequences of ungetc() */ struct __sbuf _ub; /* ungetc buffer */ unsigned char *_up; /* saved _p when _p is doing ungetc data */ int _ur; /* saved _r when _r is counting ungetc data */ /* tricks to meet minimum requirements even when malloc() fails */ unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ unsigned char _nbuf[1]; /* guarantee a getc() buffer */ /* separate buffer for fgetln() when line crosses buffer boundary */ struct __sbuf _lb; /* buffer for fgetln() */ /* Unix stdio files get aligned to block boundaries on fseek() */ int _blksize; /* stat.st_blksize (may be != _bf._size) */ fpos_t _offset; /* current lseek offset */ struct pthread_mutex *_fl_mutex; /* used for MT-safety */ struct pthread *_fl_owner; /* current owner */ int _fl_count; /* recursive lock count */ int _orientation; /* orientation for fwide() */ __mbstate_t _mbstate; /* multibyte conversion state */ int _flags2; /* additional flags */ }; #ifndef _STDFILE_DECLARED #define _STDFILE_DECLARED typedef struct __sFILE FILE; #endif #ifndef _STDSTREAM_DECLARED __BEGIN_DECLS extern FILE *__stdinp; extern FILE *__stdoutp; extern FILE *__stderrp; __END_DECLS #define _STDSTREAM_DECLARED #endif #define __SLBF 0x0001 /* line buffered */ #define __SNBF 0x0002 /* unbuffered */ #define __SRD 0x0004 /* OK to read */ #define __SWR 0x0008 /* OK to write */ /* RD and WR are never simultaneously asserted */ #define __SRW 0x0010 /* open for reading & writing */ #define __SEOF 0x0020 /* found EOF */ #define __SERR 0x0040 /* found error */ #define __SMBF 0x0080 /* _bf._base is from malloc */ #define __SAPP 0x0100 /* fdopen()ed in append mode */ #define __SSTR 0x0200 /* this is an sprintf/snprintf string */ #define __SOPT 0x0400 /* do fseek() optimization */ #define __SNPT 0x0800 /* do not do fseek() optimization */ #define __SOFF 0x1000 /* set iff _offset is in fact correct */ #define __SMOD 0x2000 /* true => fgetln modified _p text */ #define __SALC 0x4000 /* allocate string space dynamically */ #define __SIGN 0x8000 /* ignore this file in _fwalk */ #define __S2OAP 0x0001 /* O_APPEND mode is set */ /* * The following three definitions are for ANSI C, which took them * from System V, which brilliantly took internal interface macros and * made them official arguments to setvbuf(), without renaming them. * Hence, these ugly _IOxxx names are *supposed* to appear in user code. * * Although numbered as their counterparts above, the implementation * does not rely on this. */ #define _IOFBF 0 /* setvbuf should set fully buffered */ #define _IOLBF 1 /* setvbuf should set line buffered */ #define _IONBF 2 /* setvbuf should set unbuffered */ #define BUFSIZ 1024 /* size of buffer used by setbuf */ #define EOF (-1) /* * FOPEN_MAX is a minimum maximum, and is the number of streams that * stdio can provide without attempting to allocate further resources * (which could fail). Do not use this for anything. */ /* must be == _POSIX_STREAM_MAX */ #ifndef FOPEN_MAX #define FOPEN_MAX 20 /* must be <= OPEN_MAX */ #endif #define FILENAME_MAX 1024 /* must be <= PATH_MAX */ /* System V/ANSI C; this is the wrong way to do this, do *not* use these. */ #if __XSI_VISIBLE #define P_tmpdir "/tmp/" #endif #define L_tmpnam 1024 /* XXX must be == PATH_MAX */ #define TMP_MAX 308915776 #ifndef SEEK_SET #define SEEK_SET 0 /* set file offset to offset */ #endif #ifndef SEEK_CUR #define SEEK_CUR 1 /* set file offset to current plus offset */ #endif #ifndef SEEK_END #define SEEK_END 2 /* set file offset to EOF plus offset */ #endif #define stdin __stdinp #define stdout __stdoutp #define stderr __stderrp +/* + * Functions defined in all versions of POSIX 1003.1. + */ +#if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 199506) +#define L_cuserid 17 /* size for cuserid(3); MAXLOGNAME, legacy */ +#endif + +#if __POSIX_VISIBLE +#define L_ctermid 1024 /* size for ctermid(3); PATH_MAX */ +#endif /* __POSIX_VISIBLE */ + +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #ifdef _XLOCALE_H_ #include #endif /* * Functions defined in ANSI C standard. */ void clearerr(FILE *); int fclose(FILE *); int feof(FILE *); int ferror(FILE *); int fflush(FILE *); int fgetc(FILE *); int fgetpos(FILE * __restrict, fpos_t * __restrict); -char *fgets(char * __restrict, int, FILE * __restrict); +char *(fgets)(char * __restrict, int, FILE * __restrict); FILE *fopen(const char * __restrict, const char * __restrict); int fprintf(FILE * __restrict, const char * __restrict, ...); int fputc(int, FILE *); int fputs(const char * __restrict, FILE * __restrict); size_t fread(void * __restrict, size_t, size_t, FILE * __restrict); FILE *freopen(const char * __restrict, const char * __restrict, FILE * __restrict); int fscanf(FILE * __restrict, const char * __restrict, ...); int fseek(FILE *, long, int); int fsetpos(FILE *, const fpos_t *); long ftell(FILE *); size_t fwrite(const void * __restrict, size_t, size_t, FILE * __restrict); int getc(FILE *); int getchar(void); #if __EXT1_VISIBLE char *gets_s(char *, rsize_t); #endif void perror(const char *); int printf(const char * __restrict, ...); int putc(int, FILE *); int putchar(int); int puts(const char *); int remove(const char *); int rename(const char *, const char *); void rewind(FILE *); int scanf(const char * __restrict, ...); void setbuf(FILE * __restrict, char * __restrict); int setvbuf(FILE * __restrict, char * __restrict, int, size_t); -int sprintf(char * __restrict, const char * __restrict, ...); +int (sprintf)(char * __restrict, const char * __restrict, ...); int sscanf(const char * __restrict, const char * __restrict, ...); FILE *tmpfile(void); char *tmpnam(char *); int ungetc(int, FILE *); int vfprintf(FILE * __restrict, const char * __restrict, __va_list); int vprintf(const char * __restrict, __va_list); -int vsprintf(char * __restrict, const char * __restrict, +int (vsprintf)(char * __restrict, const char * __restrict, __va_list); #if __ISO_C_VISIBLE >= 1999 || __POSIX_VISIBLE >= 199506 -int snprintf(char * __restrict, size_t, const char * __restrict, +int (snprintf)(char * __restrict, size_t, const char * __restrict, ...) __printflike(3, 4); -int vsnprintf(char * __restrict, size_t, const char * __restrict, +int (vsnprintf)(char * __restrict, size_t, const char * __restrict, __va_list) __printflike(3, 0); #endif #if __ISO_C_VISIBLE >= 1999 int vfscanf(FILE * __restrict, const char * __restrict, __va_list) __scanflike(2, 0); int vscanf(const char * __restrict, __va_list) __scanflike(1, 0); int vsscanf(const char * __restrict, const char * __restrict, __va_list) __scanflike(2, 0); #endif -/* - * Functions defined in all versions of POSIX 1003.1. - */ -#if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 199506) -#define L_cuserid 17 /* size for cuserid(3); MAXLOGNAME, legacy */ -#endif - #if __POSIX_VISIBLE -#define L_ctermid 1024 /* size for ctermid(3); PATH_MAX */ - char *ctermid(char *); FILE *fdopen(int, const char *); int fileno(FILE *); #endif /* __POSIX_VISIBLE */ #if __POSIX_VISIBLE >= 199209 int pclose(FILE *); FILE *popen(const char *, const char *); #endif #if __POSIX_VISIBLE >= 199506 int ftrylockfile(FILE *); void flockfile(FILE *); void funlockfile(FILE *); /* * These are normally used through macros as defined below, but POSIX * requires functions as well. */ int getc_unlocked(FILE *); int getchar_unlocked(void); int putc_unlocked(int, FILE *); int putchar_unlocked(int); #endif #if __BSD_VISIBLE void clearerr_unlocked(FILE *); int feof_unlocked(FILE *); int ferror_unlocked(FILE *); int fflush_unlocked(FILE *); int fileno_unlocked(FILE *); int fputc_unlocked(int, FILE *); int fputs_unlocked(const char * __restrict, FILE * __restrict); size_t fread_unlocked(void * __restrict, size_t, size_t, FILE * __restrict); size_t fwrite_unlocked(const void * __restrict, size_t, size_t, FILE * __restrict); #endif #if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 int fseeko(FILE *, __off_t, int); __off_t ftello(FILE *); #endif #if __BSD_VISIBLE || __XSI_VISIBLE > 0 && __XSI_VISIBLE < 600 int getw(FILE *); int putw(int, FILE *); #endif /* BSD or X/Open before issue 6 */ #if __XSI_VISIBLE char *tempnam(const char *, const char *); #endif #if __POSIX_VISIBLE >= 200809 FILE *fmemopen(void * __restrict, size_t, const char * __restrict); ssize_t getdelim(char ** __restrict, size_t * __restrict, int, FILE * __restrict); FILE *open_memstream(char **, size_t *); int renameat(int, const char *, int, const char *); int vdprintf(int, const char * __restrict, __va_list) __printflike(2, 0); /* _WITH_GETLINE to allow pre 11 sources to build on 11+ systems */ ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict); int dprintf(int, const char * __restrict, ...) __printflike(2, 3); #endif /* __POSIX_VISIBLE >= 200809 */ /* * Routines that are purely local. */ #if __BSD_VISIBLE int asprintf(char **, const char *, ...) __printflike(2, 3); char *ctermid_r(char *); void fcloseall(void); int fdclose(FILE *, int *); char *fgetln(FILE *, size_t *); const char *fmtcheck(const char *, const char *) __format_arg(2); int fpurge(FILE *); void setbuffer(FILE *, char *, int); int setlinebuf(FILE *); int vasprintf(char **, const char *, __va_list) __printflike(2, 0); /* * The system error table contains messages for the first sys_nerr * positive errno values. Use strerror() or strerror_r() from * instead. */ extern const int sys_nerr; extern const char * const sys_errlist[]; /* * Stdio function-access interface. */ FILE *funopen(const void *, int (* _Nullable)(void *, char *, int), int (* _Nullable)(void *, const char *, int), fpos_t (* _Nullable)(void *, fpos_t, int), int (* _Nullable)(void *)); #define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0) #define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0) #if __BSD_VISIBLE typedef __ssize_t cookie_read_function_t(void *, char *, size_t); typedef __ssize_t cookie_write_function_t(void *, const char *, size_t); typedef int cookie_seek_function_t(void *, off64_t *, int); typedef int cookie_close_function_t(void *); typedef struct { cookie_read_function_t *read; cookie_write_function_t *write; cookie_seek_function_t *seek; cookie_close_function_t *close; } cookie_io_functions_t; FILE *fopencookie(void *, const char *, cookie_io_functions_t); #endif /* * Portability hacks. See . */ #ifndef _FTRUNCATE_DECLARED #define _FTRUNCATE_DECLARED int ftruncate(int, __off_t); #endif #ifndef _LSEEK_DECLARED #define _LSEEK_DECLARED __off_t lseek(int, __off_t, int); #endif #ifndef _MMAP_DECLARED #define _MMAP_DECLARED void *mmap(void *, size_t, int, int, int, __off_t); #endif #ifndef _TRUNCATE_DECLARED #define _TRUNCATE_DECLARED int truncate(const char *, __off_t); #endif #endif /* __BSD_VISIBLE */ /* * Functions internal to the implementation. */ int __srget(FILE *); int __swbuf(int, FILE *); /* * The __sfoo macros are here so that we can * define function versions in the C library. */ #define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++)) #if defined(__GNUC__) && defined(__STDC__) static __inline int __sputc(int _c, FILE *_p) { if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) return (*_p->_p++ = _c); else return (__swbuf(_c, _p)); } #else /* * This has been tuned to generate reasonable code on the vax using pcc. */ #define __sputc(c, p) \ (--(p)->_w < 0 ? \ (p)->_w >= (p)->_lbfsize ? \ (*(p)->_p = (c)), *(p)->_p != '\n' ? \ (int)*(p)->_p++ : \ __swbuf('\n', p) : \ __swbuf((int)(c), p) : \ (*(p)->_p = (c), (int)*(p)->_p++)) #endif #ifndef __LIBC_ISTHREADED_DECLARED #define __LIBC_ISTHREADED_DECLARED extern int __isthreaded; #endif #ifndef __cplusplus #define __sfeof(p) (((p)->_flags & __SEOF) != 0) #define __sferror(p) (((p)->_flags & __SERR) != 0) #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) #define __sfileno(p) ((p)->_file) #define feof(p) (!__isthreaded ? __sfeof(p) : (feof)(p)) #define ferror(p) (!__isthreaded ? __sferror(p) : (ferror)(p)) #define clearerr(p) (!__isthreaded ? __sclearerr(p) : (clearerr)(p)) #if __POSIX_VISIBLE #define fileno(p) (!__isthreaded ? __sfileno(p) : (fileno)(p)) #endif #define getc(fp) (!__isthreaded ? __sgetc(fp) : (getc)(fp)) #define putc(x, fp) (!__isthreaded ? __sputc(x, fp) : (putc)(x, fp)) #define getchar() getc(stdin) #define putchar(x) putc(x, stdout) #if __BSD_VISIBLE /* * See ISO/IEC 9945-1 ANSI/IEEE Std 1003.1 Second Edition 1996-07-12 * B.8.2.7 for the rationale behind the *_unlocked() macros. */ #define clearerr_unlocked(p) __sclearerr(p) #define feof_unlocked(p) __sfeof(p) #define ferror_unlocked(p) __sferror(p) #define fileno_unlocked(p) __sfileno(p) #define fputc_unlocked(s, p) __sputc(s, p) #endif #if __POSIX_VISIBLE >= 199506 #define getc_unlocked(fp) __sgetc(fp) #define putc_unlocked(x, fp) __sputc(x, fp) #define getchar_unlocked() getc_unlocked(stdin) #define putchar_unlocked(x) putc_unlocked(x, stdout) #endif #endif /* __cplusplus */ __END_DECLS __NULLABILITY_PRAGMA_POP -#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 -#include -#endif #endif /* !_STDIO_H_ */ diff --git a/include/string.h b/include/string.h index ce605117daa6..c9d3e1add1a1 100644 --- a/include/string.h +++ b/include/string.h @@ -1,174 +1,175 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * The 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. */ #ifndef _STRING_H_ #define _STRING_H_ #include #include #include /* * Prototype functions which were historically defined in , but * are required by POSIX to be prototyped in . */ #if __BSD_VISIBLE #include #endif #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #if __XSI_VISIBLE >= 600 void *memccpy(void * __restrict, const void * __restrict, int, size_t); #endif void *memchr(const void *, int, size_t) __pure; #if __BSD_VISIBLE void *memrchr(const void *, int, size_t) __pure; #endif int memcmp(const void *, const void *, size_t) __pure; -void *memcpy(void * __restrict, const void * __restrict, size_t); +void *(memcpy)(void * __restrict, const void * __restrict, size_t); #if __BSD_VISIBLE void *memmem(const void *, size_t, const void *, size_t) __pure; #endif -void *memmove(void *, const void *, size_t); +void *(memmove)(void *, const void *, size_t); #if __BSD_VISIBLE void *mempcpy(void * __restrict, const void * __restrict, size_t); #endif -void *memset(void *, int, size_t); +void *(memset)(void *, int, size_t); #if __POSIX_VISIBLE >= 200809 -char *stpcpy(char * __restrict, const char * __restrict); -char *stpncpy(char * __restrict, const char * __restrict, size_t); +char *(stpcpy)(char * __restrict, const char * __restrict); +char *(stpncpy)(char * __restrict, const char * __restrict, size_t); #endif #if __BSD_VISIBLE char *strcasestr(const char *, const char *) __pure; #endif -char *strcat(char * __restrict, const char * __restrict); +char *(strcat)(char * __restrict, const char * __restrict); char *strchr(const char *, int) __pure; #if __BSD_VISIBLE char *strchrnul(const char*, int) __pure; int strverscmp(const char *, const char *) __pure; #endif int strcmp(const char *, const char *) __pure; int strcoll(const char *, const char *); -char *strcpy(char * __restrict, const char * __restrict); +char *(strcpy)(char * __restrict, const char * __restrict); size_t strcspn(const char *, const char *) __pure; #if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE char *strdup(const char *) __malloc_like; #endif char *strerror(int); #if __POSIX_VISIBLE >= 200112 int strerror_r(int, char *, size_t); #endif #if __BSD_VISIBLE -size_t strlcat(char * __restrict, const char * __restrict, size_t); -size_t strlcpy(char * __restrict, const char * __restrict, size_t); +size_t (strlcat)(char * __restrict, const char * __restrict, size_t); +size_t (strlcpy)(char * __restrict, const char * __restrict, size_t); #endif size_t strlen(const char *) __pure; #if __BSD_VISIBLE #ifndef _MODE_T_DECLARED typedef __mode_t mode_t; #define _MODE_T_DECLARED #endif void strmode(mode_t, char *); #endif -char *strncat(char * __restrict, const char * __restrict, size_t); +char *(strncat)(char * __restrict, const char * __restrict, size_t); int strncmp(const char *, const char *, size_t) __pure; -char *strncpy(char * __restrict, const char * __restrict, size_t); +char *(strncpy)(char * __restrict, const char * __restrict, size_t); #if __POSIX_VISIBLE >= 200809 char *strndup(const char *, size_t) __malloc_like; size_t strnlen(const char *, size_t) __pure; #endif #if __BSD_VISIBLE char *strnstr(const char *, const char *, size_t) __pure; #endif char *strpbrk(const char *, const char *) __pure; char *strrchr(const char *, int) __pure; #if __BSD_VISIBLE char *strsep(char **, const char *); #endif #if __POSIX_VISIBLE >= 200809 char *strsignal(int); #endif size_t strspn(const char *, const char *) __pure; char *strstr(const char *, const char *) __pure; char *strtok(char * __restrict, const char * __restrict); #if __POSIX_VISIBLE >= 199506 || __XSI_VISIBLE >= 500 char *strtok_r(char *, const char *, char **); #endif size_t strxfrm(char * __restrict, const char * __restrict, size_t); #if __BSD_VISIBLE #ifndef _SWAB_DECLARED #define _SWAB_DECLARED #ifndef _SSIZE_T_DECLARED typedef __ssize_t ssize_t; #define _SSIZE_T_DECLARED #endif /* _SIZE_T_DECLARED */ void swab(const void * __restrict, void * __restrict, ssize_t); #endif /* _SWAB_DECLARED */ int timingsafe_bcmp(const void *, const void *, size_t); int timingsafe_memcmp(const void *, const void *, size_t); #endif /* __BSD_VISIBLE */ #if __POSIX_VISIBLE >= 200112 || defined(_XLOCALE_H_) #include #endif #if __EXT1_VISIBLE #ifndef _RSIZE_T_DEFINED #define _RSIZE_T_DEFINED typedef size_t rsize_t; #endif #ifndef _ERRNO_T_DEFINED #define _ERRNO_T_DEFINED typedef int errno_t; #endif /* ISO/IEC 9899:2011 K.3.7.4.1.1 */ errno_t memset_s(void *, rsize_t, int, rsize_t); #endif /* __EXT1_VISIBLE */ __END_DECLS -#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 -#include -#endif #endif /* _STRING_H_ */ diff --git a/include/strings.h b/include/strings.h index 511f7c03cb3c..889f43bd2311 100644 --- a/include/strings.h +++ b/include/strings.h @@ -1,74 +1,75 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2002 Mike Barcroft * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. */ #ifndef _STRINGS_H_ #define _STRINGS_H_ #include #include #ifndef _SIZE_T_DECLARED typedef __size_t size_t; #define _SIZE_T_DECLARED #endif +#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#include +#endif + __BEGIN_DECLS #if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112 int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */ -void bcopy(const void *, void *, size_t); /* LEGACY */ -void bzero(void *, size_t); /* LEGACY */ +void (bcopy)(const void *, void *, size_t); /* LEGACY */ +void (bzero)(void *, size_t); /* LEGACY */ #endif #if __BSD_VISIBLE void explicit_bzero(void *, size_t); #endif #if __XSI_VISIBLE int ffs(int) __pure2; #endif #if __BSD_VISIBLE int ffsl(long) __pure2; int ffsll(long long) __pure2; int fls(int) __pure2; int flsl(long) __pure2; int flsll(long long) __pure2; #endif #if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112 char *index(const char *, int) __pure; /* LEGACY */ char *rindex(const char *, int) __pure; /* LEGACY */ #endif int strcasecmp(const char *, const char *) __pure; int strncasecmp(const char *, const char *, size_t) __pure; #if __POSIX_VISIBLE >= 200809 || defined(_XLOCALE_H_) #include #endif __END_DECLS -#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 -#include -#endif #endif /* _STRINGS_H_ */ diff --git a/lib/libc/amd64/string/strlcat.c b/lib/libc/amd64/string/strlcat.c index 0c1e1c5d05f7..94fdc0963dc3 100644 --- a/lib/libc/amd64/string/strlcat.c +++ b/lib/libc/amd64/string/strlcat.c @@ -1,25 +1,27 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2023 Robert Clausecker */ #include #include +#undef strlcat /* FORTIFY_SOURCE */ + void *__memchr(const void *, int, size_t); size_t __strlcpy(char *restrict, const char *restrict, size_t); size_t strlcat(char *restrict dst, const char *restrict src, size_t dstsize) { char *loc = __memchr(dst, '\0', dstsize); if (loc != NULL) { size_t dstlen = (size_t)(loc - dst); return (dstlen + __strlcpy(loc, src, dstsize - dstlen)); } else return (dstsize + strlen(src)); } diff --git a/lib/libc/gen/ctermid.c b/lib/libc/gen/ctermid.c index 9265d402930c..fb117b3c8ded 100644 --- a/lib/libc/gen/ctermid.c +++ b/lib/libc/gen/ctermid.c @@ -1,69 +1,70 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2011 Ed Schouten * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 #include #include #include #include #include #include +#include #define LEN_PATH_DEV (sizeof(_PATH_DEV) - 1) char * -ctermid(char *s) +__ssp_real(ctermid)(char *s) { static char def[sizeof(_PATH_DEV) + SPECNAMELEN]; struct stat sb; size_t dlen; int sverrno; if (s == NULL) { s = def; dlen = sizeof(def) - LEN_PATH_DEV; } else dlen = L_ctermid - LEN_PATH_DEV; strcpy(s, _PATH_TTY); /* Attempt to perform a lookup of the actual TTY pathname. */ sverrno = errno; if (stat(_PATH_TTY, &sb) == 0 && S_ISCHR(sb.st_mode)) (void)sysctlbyname("kern.devname", s + LEN_PATH_DEV, &dlen, &sb.st_rdev, sizeof(sb.st_rdev)); errno = sverrno; return (s); } char * -ctermid_r(char *s) +__ssp_real(ctermid_r)(char *s) { return (s != NULL ? ctermid(s) : NULL); } diff --git a/lib/libc/gen/getdomainname.c b/lib/libc/gen/getdomainname.c index a9527b36a247..c0be7465f967 100644 --- a/lib/libc/gen/getdomainname.c +++ b/lib/libc/gen/getdomainname.c @@ -1,49 +1,50 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993 * The 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 #include #include +#include int -getdomainname(char *name, int namelen) +__ssp_real(getdomainname)(char *name, int namelen) { int mib[2]; size_t size; mib[0] = CTL_KERN; mib[1] = KERN_NISDOMAINNAME; size = namelen; if (sysctl(mib, 2, name, &size, NULL, 0) == -1) return (-1); return (0); } diff --git a/lib/libc/gen/getentropy.c b/lib/libc/gen/getentropy.c index 38cd515e74d7..40b84af65f83 100644 --- a/lib/libc/gen/getentropy.c +++ b/lib/libc/gen/getentropy.c @@ -1,156 +1,157 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2018 Conrad Meyer * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 #include #include #include #include #include #include #include +#include #include "libc_private.h" /* First __FreeBSD_version bump after introduction of getrandom(2) (r331279) */ #define GETRANDOM_FIRST 1200061 extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t); static inline void _getentropy_fail(void) { raise(SIGKILL); } static size_t arnd_sysctl(u_char *buf, size_t size) { int mib[2]; size_t len, done; mib[0] = CTL_KERN; mib[1] = KERN_ARND; done = 0; do { len = size; if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1) return (done); done += len; buf += len; size -= len; } while (size > 0); return (done); } /* * If a newer libc is accidentally installed on an older kernel, provide high * quality random data anyway. The sysctl interface is not as fast and does * not block by itself, but is provided by even very old kernels. */ static int getentropy_fallback(void *buf, size_t buflen) { /* * oldp (buf) == NULL has a special meaning for sysctl that results in * no EFAULT. For compatibility with the kernel getrandom(2), detect * this case and return the appropriate error. */ if (buf == NULL && buflen > 0) { errno = EFAULT; return (-1); } if (arnd_sysctl(buf, buflen) != buflen) { if (errno == EFAULT) return (-1); /* * This cannot happen. arnd_sysctl() spins until the random * device is seeded and then repeatedly reads until the full * request is satisfied. The only way for this to return a zero * byte or short read is if sysctl(2) on the kern.arandom MIB * fails. In this case, excepting the user-provided-a-bogus- * buffer EFAULT, give up (like for arc4random(3)'s arc4_stir). */ _getentropy_fail(); } return (0); } int -getentropy(void *buf, size_t buflen) +__ssp_real(getentropy)(void *buf, size_t buflen) { ssize_t rd; bool have_getrandom; if (buflen > 256) { errno = EIO; return (-1); } have_getrandom = (__getosreldate() >= GETRANDOM_FIRST); while (buflen > 0) { if (have_getrandom) { rd = getrandom(buf, buflen, 0); if (rd == -1) { switch (errno) { case ECAPMODE: /* * Kernel >= r331280 and < r337999 * will return ECAPMODE when the * caller is already in capability * mode, fallback to traditional * method in this case. */ have_getrandom = false; continue; case EINTR: continue; case EFAULT: return (-1); default: _getentropy_fail(); } } } else { return (getentropy_fallback(buf, buflen)); } /* This cannot happen. */ if (rd == 0) _getentropy_fail(); buf = (char *)buf + rd; buflen -= rd; } return (0); } diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c index 1c29b249f8c4..5bd06bc5121f 100644 --- a/lib/libc/gen/getgrouplist.c +++ b/lib/libc/gen/getgrouplist.c @@ -1,48 +1,49 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The 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. */ /* * get credential */ #include #include #include #include +#include extern int __getgroupmembership(const char *, gid_t, gid_t *, int, int *); int -getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) +__ssp_real(getgrouplist)(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt) { return __getgroupmembership(uname, agroup, groups, *grpcnt, grpcnt); } diff --git a/lib/libc/gen/gethostname.c b/lib/libc/gen/gethostname.c index 36e988c91ecc..66d401fad846 100644 --- a/lib/libc/gen/gethostname.c +++ b/lib/libc/gen/gethostname.c @@ -1,51 +1,52 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993 * The 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 #include #include #include +#include int -gethostname(char *name, size_t namelen) +__ssp_real(gethostname)(char *name, size_t namelen) { int mib[2]; mib[0] = CTL_KERN; mib[1] = KERN_HOSTNAME; if (sysctl(mib, 2, name, &namelen, NULL, 0) == -1) { if (errno == ENOMEM) errno = ENAMETOOLONG; return (-1); } return (0); } diff --git a/lib/libc/gen/getlogin.c b/lib/libc/gen/getlogin.c index 55ed83795f7d..f8a3fb079067 100644 --- a/lib/libc/gen/getlogin.c +++ b/lib/libc/gen/getlogin.c @@ -1,83 +1,84 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 1993 * The 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 #include #include #include #include #include #include "namespace.h" #include +#include #include "un-namespace.h" #include "libc_private.h" extern int _getlogin(char *, int); char * getlogin(void) { static char logname[MAXLOGNAME]; if (_getlogin(logname, sizeof(logname)) < 0) return (NULL); return (logname[0] != '\0' ? logname : NULL); } int -getlogin_r(char *logname, size_t namelen) +__ssp_real(getlogin_r)(char *logname, size_t namelen) { char tmpname[MAXLOGNAME]; int len; if (namelen < 1) return (ERANGE); logname[0] = '\0'; if (_getlogin(tmpname, sizeof(tmpname)) < 0) return (errno); len = strlen(tmpname) + 1; if (len > namelen) return (ERANGE); strlcpy(logname, tmpname, len); return (0); } /* FreeBSD 12 and earlier compat. */ int __getlogin_r_fbsd12(char *logname, int namelen) { if (namelen < 1) return (ERANGE); return (getlogin_r(logname, namelen)); } __sym_compat(getlogin_r, __getlogin_r_fbsd12, FBSD_1.0); diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c index 268b2e0f7b65..f1e2f401fe5d 100644 --- a/lib/libc/gen/ttyname.c +++ b/lib/libc/gen/ttyname.c @@ -1,110 +1,111 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 1993 * The 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 "namespace.h" #include #include #include #include #include #include #include #include #include #include #include #include "reentrant.h" +#include #include "un-namespace.h" #include "libc_private.h" static char ttyname_buf[sizeof(_PATH_DEV) + MAXNAMLEN]; static once_t ttyname_init_once = ONCE_INITIALIZER; static thread_key_t ttyname_key; static int ttyname_keycreated = 0; int -ttyname_r(int fd, char *buf, size_t len) +__ssp_real(ttyname_r)(int fd, char *buf, size_t len) { size_t used; /* Don't write off the end of a zero-length buffer. */ if (len < 1) return (ERANGE); *buf = '\0'; /* Must be a terminal. */ if (!isatty(fd)) return (errno); /* Must have enough room */ if (len <= sizeof(_PATH_DEV)) return (ERANGE); strcpy(buf, _PATH_DEV); used = strlen(buf); if (fdevname_r(fd, buf + used, len - used) == NULL) return (errno == EINVAL ? ERANGE : errno); return (0); } static void ttyname_keycreate(void) { ttyname_keycreated = (thr_keycreate(&ttyname_key, free) == 0); } char * ttyname(int fd) { char *buf; if (thr_main() != 0) buf = ttyname_buf; else { if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 || !ttyname_keycreated) return (NULL); if ((buf = thr_getspecific(ttyname_key)) == NULL) { if ((buf = malloc(sizeof ttyname_buf)) == NULL) return (NULL); if (thr_setspecific(ttyname_key, buf) != 0) { free(buf); return (NULL); } } } if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0) return (NULL); return (buf); } diff --git a/lib/libc/secure/Makefile.inc b/lib/libc/secure/Makefile.inc index 28289127c7a6..5d10612e67a8 100644 --- a/lib/libc/secure/Makefile.inc +++ b/lib/libc/secure/Makefile.inc @@ -1,21 +1,21 @@ # # libc sources related to security .PATH: ${LIBC_SRCTOP}/secure # _FORTIFY_SOURCE SRCS+= fgets_chk.c memcpy_chk.c memmove_chk.c memset_chk.c \ snprintf_chk.c sprintf_chk.c stpcpy_chk.c stpncpy_chk.c \ - strcat_chk.c strcpy_chk.c strncat_chk.c strncpy_chk.c \ - vsnprintf_chk.c vsprintf_chk.c + strcat_chk.c strcpy_chk.c strlcat_chk.c strncat_chk.c strlcpy_chk.c \ + strncpy_chk.c vsnprintf_chk.c vsprintf_chk.c CFLAGS.snprintf_chk.c+= -Wno-unused-parameter CFLAGS.sprintf_chk.c+= -Wno-unused-parameter CFLAGS.vsnprintf_chk.c+= -Wno-unused-parameter CFLAGS.vsprintf_chk.c+= -Wno-unused-parameter # Sources common to both syscall interfaces: SRCS+= stack_protector.c \ stack_protector_compat.c SYM_MAPS+= ${LIBC_SRCTOP}/secure/Symbol.map diff --git a/lib/libc/secure/Symbol.map b/lib/libc/secure/Symbol.map index 0d854039955f..1f12fe059367 100644 --- a/lib/libc/secure/Symbol.map +++ b/lib/libc/secure/Symbol.map @@ -1,22 +1,24 @@ FBSD_1.0 { __chk_fail; __stack_chk_fail; __stack_chk_guard; }; FBSD_1.8 { __fgets_chk; __memcpy_chk; __memmove_chk; __memset_chk; __snprintf_chk; __sprintf_chk; __stpcpy_chk; __stpncpy_chk; __strcat_chk; __strcpy_chk; + __strlcat_chk; __strncat_chk; + __strlcpy_chk; __strncpy_chk; __vsnprintf_chk; __vsprintf_chk; }; diff --git a/lib/libc/string/strlcat.c b/lib/libc/secure/strlcat_chk.c similarity index 78% copy from lib/libc/string/strlcat.c copy to lib/libc/secure/strlcat_chk.c index bdb302def7b0..26448bd37af0 100644 --- a/lib/libc/string/strlcat.c +++ b/lib/libc/secure/strlcat_chk.c @@ -1,55 +1,70 @@ /* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */ /* + * SPDX-License-Identifier: ISC + * * Copyright (c) 1998, 2015 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include #include +#include + /* * Appends src to string dst of size dsize (unlike strncat, dsize is the * full size of dst, not space left). At most dsize-1 characters * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). * Returns strlen(src) + MIN(dsize, strlen(initial dst)). * If retval >= dsize, truncation occurred. */ size_t -strlcat(char * __restrict dst, const char * __restrict src, size_t dsize) +__strlcat_chk(char * __restrict dst, const char * __restrict src, size_t dsize, + size_t dbufsize) { const char *odst = dst; const char *osrc = src; size_t n = dsize; size_t dlen; + if (dsize > dbufsize) + __chk_fail(); + /* Find the end of dst and adjust bytes left but don't go past end. */ - while (n-- != 0 && *dst != '\0') + while (n-- != 0 && *dst != '\0') { dst++; + } + dlen = dst - odst; n = dsize - dlen; if (n-- == 0) - return(dlen + strlen(src)); + return (dlen + strlen(src)); while (*src != '\0') { if (n != 0) { + if (dbufsize-- == 0) + __chk_fail(); *dst++ = *src; n--; } + src++; } - *dst = '\0'; - return(dlen + (src - osrc)); /* count does not include NUL */ + if (dbufsize-- == 0) + __chk_fail(); + *dst = '\0'; + return (dlen + (src - osrc)); /* count does not include NUL */ } diff --git a/include/ssp/unistd.h b/lib/libc/secure/strlcpy_chk.c similarity index 61% copy from include/ssp/unistd.h copy to lib/libc/secure/strlcpy_chk.c index bcd3664116cc..8c11ee3e07eb 100644 --- a/include/ssp/unistd.h +++ b/lib/libc/secure/strlcpy_chk.c @@ -1,58 +1,43 @@ -/* $NetBSD: unistd.h,v 1.7 2015/06/25 18:41:03 joerg Exp $ */ - /*- - * * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2006 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. + * Copyright (c) 2024, Klara, Inc. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ -#ifndef _SSP_UNISTD_H_ -#define _SSP_UNISTD_H_ - -#include - -#if __SSP_FORTIFY_LEVEL > 0 -__BEGIN_DECLS - -#ifndef _FORTIFY_SOURCE_read -#define _FORTIFY_SOURCE_read read -#endif -__ssp_redirect0(ssize_t, _FORTIFY_SOURCE_read, (int __fd, void *__buf, - size_t __len), (__fd, __buf, __len)); +#include +#include -__ssp_redirect(ssize_t, readlink, (const char *__restrict __path, \ - char *__restrict __buf, size_t __len), (__path, __buf, __len)); +#include +#undef strlcpy -__ssp_redirect_raw(char *, getcwd, getcwd, (char *__buf, size_t __len), - (__buf, __len), __buf != 0, __ssp_bos); +size_t +__strlcpy_chk(char * __restrict dst, const char * __restrict src, size_t dsize, + size_t dbufsize) +{ -__END_DECLS + if (dsize > dbufsize) + __chk_fail(); -#endif /* __SSP_FORTIFY_LEVEL > 0 */ -#endif /* _SSP_UNISTD_H_ */ + return (strlcpy(dst, src, dsize)); +} diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c index bf943fdd1d0d..65d9ecf94366 100644 --- a/lib/libc/stdio/fread.c +++ b/lib/libc/stdio/fread.c @@ -1,144 +1,146 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * 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 "namespace.h" #include #include #include #include +#include #include "un-namespace.h" #include "local.h" #include "libc_private.h" /* * MT-safe version */ size_t -fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp) +__ssp_real(fread)(void * __restrict buf, size_t size, size_t count, + FILE * __restrict fp) { size_t ret; FLOCKFILE_CANCELSAFE(fp); ret = __fread(buf, size, count, fp); FUNLOCKFILE_CANCELSAFE(); return (ret); } size_t __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp) { size_t resid; char *p; int r; size_t total; /* * ANSI and SUSv2 require a return value of 0 if size or count are 0. */ if ((count == 0) || (size == 0)) return (0); /* * Check for integer overflow. As an optimization, first check that * at least one of {count, size} is at least 2^16, since if both * values are less than that, their product can't possible overflow * (size_t is always at least 32 bits on FreeBSD). */ if (((count | size) > 0xFFFF) && (count > SIZE_MAX / size)) { errno = EINVAL; fp->_flags |= __SERR; return (0); } /* * Compute the (now required to not overflow) number of bytes to * read and actually do the work. */ resid = count * size; ORIENT(fp, -1); if (fp->_r < 0) fp->_r = 0; total = resid; p = buf; /* * If we're unbuffered we know that the buffer in fp is empty so * we can read directly into buf. This is much faster than a * series of one byte reads into fp->_nbuf. */ if ((fp->_flags & __SNBF) != 0 && buf != NULL) { while (resid > 0) { /* set up the buffer */ fp->_bf._base = fp->_p = p; fp->_bf._size = resid; if (__srefill(fp)) { /* no more input: return partial result */ count = (total - resid) / size; break; } p += fp->_r; resid -= fp->_r; } /* restore the old buffer (see __smakebuf) */ fp->_bf._base = fp->_p = fp->_nbuf; fp->_bf._size = 1; fp->_r = 0; return (count); } while (resid > (r = fp->_r)) { if (r != 0) { (void)memcpy((void *)p, (void *)fp->_p, (size_t)r); fp->_p += r; /* fp->_r = 0 ... done in __srefill */ p += r; resid -= r; } if (__srefill(fp)) { /* no more input: return partial result */ return ((total - resid) / size); } } (void)memcpy((void *)p, (void *)fp->_p, resid); fp->_r -= resid; fp->_p += resid; return (count); } __weak_reference(__fread, fread_unlocked); diff --git a/lib/libc/stdio/gets_s.c b/lib/libc/stdio/gets_s.c index 9a8cf34916fb..41e379507483 100644 --- a/lib/libc/stdio/gets_s.c +++ b/lib/libc/stdio/gets_s.c @@ -1,99 +1,100 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2017, 2018 * Cyril S. E. Schubert * * 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 "namespace.h" #include #include #include #include +#include #include "un-namespace.h" #include "libc_private.h" #include "local.h" static inline char * _gets_s(char *buf, rsize_t n) { int c; char *s; ORIENT(stdin, -1); for (s = buf, n--; (c = __sgetc(stdin)) != '\n' && n > 0 ; n--) { if (c == EOF) { if (s == buf) { return (NULL); } else break; } else *s++ = c; } /* * If end of buffer reached, discard until \n or eof. * Then throw an error. */ if (n == 0) { /* discard */ while ((c = __sgetc(stdin)) != '\n' && c != EOF); /* throw the error after lock released prior to exit */ __throw_constraint_handler_s("gets_s : end of buffer", E2BIG); return (NULL); } *s = 0; return (buf); } /* ISO/IEC 9899:2011 K.3.7.4.1 */ char * -gets_s(char *buf, rsize_t n) +__ssp_real(gets_s)(char *buf, rsize_t n) { char *ret; if (buf == NULL) { __throw_constraint_handler_s("gets_s : str is NULL", EINVAL); return(NULL); } else if (n > RSIZE_MAX) { __throw_constraint_handler_s("gets_s : n > RSIZE_MAX", EINVAL); return(NULL); } else if (n == 0) { __throw_constraint_handler_s("gets_s : n == 0", EINVAL); return(NULL); } FLOCKFILE_CANCELSAFE(stdin); ret = _gets_s(buf, n); FUNLOCKFILE_CANCELSAFE(); return (ret); } diff --git a/lib/libc/stdio/tmpnam.c b/lib/libc/stdio/tmpnam.c index d7c436928cd7..fab4253e2834 100644 --- a/lib/libc/stdio/tmpnam.c +++ b/lib/libc/stdio/tmpnam.c @@ -1,56 +1,57 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993, 1994 * 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 #include #include +#include __warn_references(tmpnam, "warning: tmpnam() possibly used unsafely; consider using mkstemp()"); extern char *_mktemp(char *); char * -tmpnam(char *s) +__ssp_real(tmpnam)(char *s) { static u_long tmpcount; static char buf[L_tmpnam]; if (s == NULL) s = buf; (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXX", P_tmpdir, tmpcount); ++tmpcount; return (_mktemp(s)); } diff --git a/lib/libc/string/mempcpy.c b/lib/libc/string/mempcpy.c index 619371632922..86e44cdebb85 100644 --- a/lib/libc/string/mempcpy.c +++ b/lib/libc/string/mempcpy.c @@ -1,37 +1,39 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2021 The FreeBSD Foundation * * This software was developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +#include void * -mempcpy(void *__restrict dst, const void *__restrict src, size_t len) +__ssp_real(mempcpy)(void *__restrict dst, const void *__restrict src, + size_t len) { return ((char *)memcpy(dst, src, len) + len); } diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c index ecad55caa673..922bb0284497 100644 --- a/lib/libc/string/strerror.c +++ b/lib/libc/string/strerror.c @@ -1,140 +1,142 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 1993 * The 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. */ #if defined(NLS) #include #endif #include #include #include #include +#include + #include "errlst.h" #include "../locale/xlocale_private.h" #include "libc_private.h" /* * Define buffer big enough to contain delimiter (": ", 2 bytes), * 64-bit signed integer converted to ASCII decimal (19 bytes) with * optional leading sign (1 byte), and a trailing NUL. */ #define EBUFSIZE (2 + 19 + 1 + 1) /* * Doing this by hand instead of linking with stdio(3) avoids bloat for * statically linked binaries. */ static void errstr(int num, const char *uprefix, char *buf, size_t len) { char *t; unsigned int uerr; char tmp[EBUFSIZE]; t = tmp + sizeof(tmp); *--t = '\0'; uerr = (num >= 0) ? num : -num; do { *--t = "0123456789"[uerr % 10]; } while (uerr /= 10); if (num < 0) *--t = '-'; *--t = ' '; *--t = ':'; strlcpy(buf, uprefix, len); strlcat(buf, t, len); } int __strerror_rl(int errnum, char *strerrbuf, size_t buflen, locale_t locale) { int retval = 0; #if defined(NLS) int saved_errno = errno; nl_catd catd; catd = __catopen_l("libc", NL_CAT_LOCALE, locale); #endif if (errnum < 0 || errnum >= __hidden_sys_nerr) { errstr(errnum, #if defined(NLS) catgets(catd, 1, 0xffff, __uprefix), #else __uprefix, #endif strerrbuf, buflen); retval = EINVAL; } else { if (strlcpy(strerrbuf, #if defined(NLS) catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]), #else __hidden_sys_errlist[errnum], #endif buflen) >= buflen) retval = ERANGE; } #if defined(NLS) catclose(catd); errno = saved_errno; #endif return (retval); } int -strerror_r(int errnum, char *strerrbuf, size_t buflen) +__ssp_real(strerror_r)(int errnum, char *strerrbuf, size_t buflen) { return (__strerror_rl(errnum, strerrbuf, buflen, __get_locale())); } char * strerror_l(int num, locale_t locale) { static _Thread_local char ebuf[NL_TEXTMAX]; if (__strerror_rl(num, ebuf, sizeof(ebuf), locale) != 0) errno = EINVAL; return (ebuf); } char * strerror(int num) { static char ebuf[NL_TEXTMAX]; if (__strerror_rl(num, ebuf, sizeof(ebuf), __get_locale()) != 0) errno = EINVAL; return (ebuf); } diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c index bdb302def7b0..fc18fad179db 100644 --- a/lib/libc/string/strlcat.c +++ b/lib/libc/string/strlcat.c @@ -1,55 +1,57 @@ /* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */ /* * Copyright (c) 1998, 2015 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include +#undef strlcat /* FORTIFY_SOURCE */ + /* * Appends src to string dst of size dsize (unlike strncat, dsize is the * full size of dst, not space left). At most dsize-1 characters * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). * Returns strlen(src) + MIN(dsize, strlen(initial dst)). * If retval >= dsize, truncation occurred. */ size_t strlcat(char * __restrict dst, const char * __restrict src, size_t dsize) { const char *odst = dst; const char *osrc = src; size_t n = dsize; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end. */ while (n-- != 0 && *dst != '\0') dst++; dlen = dst - odst; n = dsize - dlen; if (n-- == 0) return(dlen + strlen(src)); while (*src != '\0') { if (n != 0) { *dst++ = *src; n--; } src++; } *dst = '\0'; return(dlen + (src - osrc)); /* count does not include NUL */ } diff --git a/lib/libc/string/strlcpy.c b/lib/libc/string/strlcpy.c index 58a42e321f6a..79f7ab19cdfd 100644 --- a/lib/libc/string/strlcpy.c +++ b/lib/libc/string/strlcpy.c @@ -1,50 +1,52 @@ /* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */ /* * Copyright (c) 1998, 2015 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include +#undef strlcpy /* FORTIFY_SOURCE */ + /* * Copy string src to buffer dst of size dsize. At most dsize-1 * chars will be copied. Always NUL terminates (unless dsize == 0). * Returns strlen(src); if retval >= dsize, truncation occurred. */ size_t strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize) { const char *osrc = src; size_t nleft = dsize; /* Copy as many bytes as will fit. */ if (nleft != 0) { while (--nleft != 0) { if ((*dst++ = *src++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src. */ if (nleft == 0) { if (dsize != 0) *dst = '\0'; /* NUL-terminate dst */ while (*src++) ; } return(src - osrc - 1); /* count does not include NUL */ } diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c index b1df82a2dbf8..67240a855196 100644 --- a/lib/libc/string/strncpy.c +++ b/lib/libc/string/strncpy.c @@ -1,67 +1,69 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993 * 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 +#undef strncpy /* FORTIFY_SOURCE */ + /* * Copy src to dst, truncating or null-padding to always copy n bytes. * Return dst. */ #ifdef WEAK_STRNCPY __weak_reference(__strncpy, strncpy); #endif char * #ifdef WEAK_STRNCPY __strncpy #else strncpy #endif (char * __restrict dst, const char * __restrict src, size_t n) { 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); } return (dst); } diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c index 20ecdab89a8b..fe0f14acd988 100644 --- a/lib/libc/tests/secure/fortify_stdio_test.c +++ b/lib/libc/tests/secure/fortify_stdio_test.c @@ -1,383 +1,1373 @@ /* @generated by `generate-fortify-tests.lua "stdio"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + /* * Create a new symlink to use for readlink(2) style tests, we'll just use a * random target name to have something interesting to look at. */ static const char * __unused new_symlink(size_t __len) { static const char linkname[] = "link"; char target[MAXNAMLEN]; int error; ATF_REQUIRE(__len <= sizeof(target)); arc4random_buf(target, sizeof(target)); error = unlink(linkname); ATF_REQUIRE(error == 0 || errno == ENOENT); error = symlink(target, linkname); ATF_REQUIRE(error == 0); return (linkname); } /* * Constructs a tmpfile that we can use for testing read(2) and friends. */ static int __unused new_tmpfile(void) { char buf[1024]; ssize_t rv; size_t written; int fd; - fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); - ATF_REQUIRE(fd >= 0); + fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd >= 0); + + written = 0; + while (written < TMPFILE_SIZE) { + rv = write(fd, buf, sizeof(buf)); + ATF_REQUIRE(rv > 0); + + written += rv; + } + + ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); + return (fd); +} + +static void +disable_coredumps(void) +{ + struct rlimit rl = { 0 }; + + if (setrlimit(RLIMIT_CORE, &rl) == -1) + _exit(EX_OSERR); +} + +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + +ATF_TC_WITHOUT_HEAD(ctermid_before_end); +ATF_TC_BODY(ctermid_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_end); +ATF_TC_BODY(ctermid_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_heap_before_end); +ATF_TC_BODY(ctermid_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid + 1); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_heap_end); +ATF_TC_BODY(ctermid_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_heap_after_end); +ATF_TC_BODY(ctermid_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid - 1); + const size_t __len = L_ctermid - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ctermid(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_r_before_end); +ATF_TC_BODY(ctermid_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_r_end); +ATF_TC_BODY(ctermid_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_ctermid]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_r_heap_before_end); +ATF_TC_BODY(ctermid_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid + 1); + const size_t __len = L_ctermid + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_r_heap_end); +ATF_TC_BODY(ctermid_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid); + const size_t __len = L_ctermid; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ctermid_r_heap_after_end); +ATF_TC_BODY(ctermid_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_ctermid - 1); + const size_t __len = L_ctermid - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ctermid_r(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_before_end); +ATF_TC_BODY(fread_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_end); +ATF_TC_BODY(fread_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_heap_before_end); +ATF_TC_BODY(fread_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_heap_end); +ATF_TC_BODY(fread_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_heap_after_end); +ATF_TC_BODY(fread_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread(__stack.__buf, __len, 1, stdin); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_unlocked_before_end); +ATF_TC_BODY(fread_unlocked_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_unlocked_end); +ATF_TC_BODY(fread_unlocked_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_unlocked_heap_before_end); +ATF_TC_BODY(fread_unlocked_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_unlocked_heap_end); +ATF_TC_BODY(fread_unlocked_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fread_unlocked_heap_after_end); +ATF_TC_BODY(fread_unlocked_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + fread_unlocked(__stack.__buf, __len, 1, stdin); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gets_s_before_end); +ATF_TC_BODY(gets_s_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gets_s_end); +ATF_TC_BODY(gets_s_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gets_s_heap_before_end); +ATF_TC_BODY(gets_s_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gets_s_heap_end); +ATF_TC_BODY(gets_s_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + replace_stdin(); + + gets_s(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gets_s_heap_after_end); +ATF_TC_BODY(gets_s_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + replace_stdin(); - written = 0; - while (written < TMPFILE_SIZE) { - rv = write(fd, buf, sizeof(buf)); - ATF_REQUIRE(rv > 0); + gets_s(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ - written += rv; +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); } - ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); - return (fd); -} - -static void -disable_coredumps(void) -{ - struct rlimit rl = { 0 }; + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF - if (setrlimit(RLIMIT_CORE, &rl) == -1) - _exit(EX_OSERR); } ATF_TC_WITHOUT_HEAD(sprintf_before_end); ATF_TC_BODY(sprintf_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(sprintf_end); ATF_TC_BODY(sprintf_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(sprintf_heap_before_end); ATF_TC_BODY(sprintf_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(sprintf_heap_end); ATF_TC_BODY(sprintf_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(sprintf_heap_after_end); ATF_TC_BODY(sprintf_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char srcvar[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; sprintf(__stack.__buf, "%.*s", (int)__len - 1, srcvar); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(snprintf_before_end); ATF_TC_BODY(snprintf_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(snprintf_end); ATF_TC_BODY(snprintf_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(snprintf_heap_before_end); ATF_TC_BODY(snprintf_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(snprintf_heap_end); ATF_TC_BODY(snprintf_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char srcvar[__len + 10]; __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); #undef BUF } ATF_TC_WITHOUT_HEAD(snprintf_heap_after_end); ATF_TC_BODY(snprintf_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char srcvar[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; snprintf(__stack.__buf, __len, "%.*s", (int)__len - 1, srcvar); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } +ATF_TC_WITHOUT_HEAD(tmpnam_before_end); +ATF_TC_BODY(tmpnam_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_tmpnam + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_tmpnam + 1; + const size_t __idx __unused = __len - 1; + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(tmpnam_end); +ATF_TC_BODY(tmpnam_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[L_tmpnam]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = L_tmpnam; + const size_t __idx __unused = __len - 1; + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(tmpnam_heap_before_end); +ATF_TC_BODY(tmpnam_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam + 1); + const size_t __len = L_tmpnam + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(tmpnam_heap_end); +ATF_TC_BODY(tmpnam_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam); + const size_t __len = L_tmpnam; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(tmpnam_heap_after_end); +ATF_TC_BODY(tmpnam_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (L_tmpnam - 1); + const size_t __len = L_tmpnam - 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + tmpnam(__stack.__buf); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fgets_before_end); +ATF_TC_BODY(fgets_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + FILE *fp; + + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fgets_end); +ATF_TC_BODY(fgets_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + FILE *fp; + + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fgets_heap_before_end); +ATF_TC_BODY(fgets_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + FILE *fp; + + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fgets_heap_end); +ATF_TC_BODY(fgets_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + FILE *fp; + + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(fgets_heap_after_end); +ATF_TC_BODY(fgets_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + FILE *fp; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fp = new_fp(__len); + + fgets(__stack.__buf, __len, fp); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, ctermid_before_end); + ATF_TP_ADD_TC(tp, ctermid_end); + ATF_TP_ADD_TC(tp, ctermid_heap_before_end); + ATF_TP_ADD_TC(tp, ctermid_heap_end); + ATF_TP_ADD_TC(tp, ctermid_heap_after_end); + ATF_TP_ADD_TC(tp, ctermid_r_before_end); + ATF_TP_ADD_TC(tp, ctermid_r_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_before_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_end); + ATF_TP_ADD_TC(tp, ctermid_r_heap_after_end); + ATF_TP_ADD_TC(tp, fread_before_end); + ATF_TP_ADD_TC(tp, fread_end); + ATF_TP_ADD_TC(tp, fread_heap_before_end); + ATF_TP_ADD_TC(tp, fread_heap_end); + ATF_TP_ADD_TC(tp, fread_heap_after_end); + ATF_TP_ADD_TC(tp, fread_unlocked_before_end); + ATF_TP_ADD_TC(tp, fread_unlocked_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_before_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_end); + ATF_TP_ADD_TC(tp, fread_unlocked_heap_after_end); + ATF_TP_ADD_TC(tp, gets_s_before_end); + ATF_TP_ADD_TC(tp, gets_s_end); + ATF_TP_ADD_TC(tp, gets_s_heap_before_end); + ATF_TP_ADD_TC(tp, gets_s_heap_end); + ATF_TP_ADD_TC(tp, gets_s_heap_after_end); ATF_TP_ADD_TC(tp, sprintf_before_end); ATF_TP_ADD_TC(tp, sprintf_end); ATF_TP_ADD_TC(tp, sprintf_heap_before_end); ATF_TP_ADD_TC(tp, sprintf_heap_end); ATF_TP_ADD_TC(tp, sprintf_heap_after_end); ATF_TP_ADD_TC(tp, snprintf_before_end); ATF_TP_ADD_TC(tp, snprintf_end); ATF_TP_ADD_TC(tp, snprintf_heap_before_end); ATF_TP_ADD_TC(tp, snprintf_heap_end); ATF_TP_ADD_TC(tp, snprintf_heap_after_end); + ATF_TP_ADD_TC(tp, tmpnam_before_end); + ATF_TP_ADD_TC(tp, tmpnam_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_before_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_end); + ATF_TP_ADD_TC(tp, tmpnam_heap_after_end); + ATF_TP_ADD_TC(tp, fgets_before_end); + ATF_TP_ADD_TC(tp, fgets_end); + ATF_TP_ADD_TC(tp, fgets_heap_before_end); + ATF_TP_ADD_TC(tp, fgets_heap_end); + ATF_TP_ADD_TC(tp, fgets_heap_after_end); return (atf_no_error()); } diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c index 109ef40fd62d..8306abb5f9e2 100644 --- a/lib/libc/tests/secure/fortify_string_test.c +++ b/lib/libc/tests/secure/fortify_string_test.c @@ -1,1415 +1,1893 @@ /* @generated by `generate-fortify-tests.lua "string"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + /* * Create a new symlink to use for readlink(2) style tests, we'll just use a * random target name to have something interesting to look at. */ static const char * __unused new_symlink(size_t __len) { static const char linkname[] = "link"; char target[MAXNAMLEN]; int error; ATF_REQUIRE(__len <= sizeof(target)); arc4random_buf(target, sizeof(target)); error = unlink(linkname); ATF_REQUIRE(error == 0 || errno == ENOENT); error = symlink(target, linkname); ATF_REQUIRE(error == 0); return (linkname); } /* * Constructs a tmpfile that we can use for testing read(2) and friends. */ static int __unused new_tmpfile(void) { char buf[1024]; ssize_t rv; size_t written; int fd; fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); ATF_REQUIRE(fd >= 0); written = 0; while (written < TMPFILE_SIZE) { rv = write(fd, buf, sizeof(buf)); ATF_REQUIRE(rv > 0); written += rv; } ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); return (fd); } static void disable_coredumps(void) { struct rlimit rl = { 0 }; if (setrlimit(RLIMIT_CORE, &rl) == -1) _exit(EX_OSERR); } +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + ATF_TC_WITHOUT_HEAD(memcpy_before_end); ATF_TC_BODY(memcpy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; memcpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memcpy_end); ATF_TC_BODY(memcpy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; memcpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memcpy_heap_before_end); ATF_TC_BODY(memcpy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); memcpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memcpy_heap_end); ATF_TC_BODY(memcpy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); memcpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memcpy_heap_after_end); ATF_TC_BODY(memcpy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memcpy(__stack.__buf, src, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } +ATF_TC_WITHOUT_HEAD(mempcpy_before_end); +ATF_TC_BODY(mempcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(mempcpy_end); +ATF_TC_BODY(mempcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(mempcpy_heap_before_end); +ATF_TC_BODY(mempcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(mempcpy_heap_end); +ATF_TC_BODY(mempcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len + 10]; + + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(mempcpy_heap_after_end); +ATF_TC_BODY(mempcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len + 10]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + mempcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TC_WITHOUT_HEAD(memmove_before_end); ATF_TC_BODY(memmove_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; memmove(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memmove_end); ATF_TC_BODY(memmove_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; memmove(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memmove_heap_before_end); ATF_TC_BODY(memmove_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); memmove(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memmove_heap_end); ATF_TC_BODY(memmove_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); memmove(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memmove_heap_after_end); ATF_TC_BODY(memmove_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memmove(__stack.__buf, src, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(memset_before_end); ATF_TC_BODY(memset_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; memset(__stack.__buf, 0, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memset_end); ATF_TC_BODY(memset_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; memset(__stack.__buf, 0, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memset_heap_before_end); ATF_TC_BODY(memset_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memset_heap_end); ATF_TC_BODY(memset_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(memset_heap_after_end); ATF_TC_BODY(memset_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(stpcpy_before_end); ATF_TC_BODY(stpcpy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(stpcpy_end); ATF_TC_BODY(stpcpy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(stpcpy_heap_before_end); ATF_TC_BODY(stpcpy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(stpcpy_heap_end); ATF_TC_BODY(stpcpy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(stpcpy_heap_after_end); ATF_TC_BODY(stpcpy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpcpy(__stack.__buf, src); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(stpncpy_before_end); ATF_TC_BODY(stpncpy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(stpncpy_end); ATF_TC_BODY(stpncpy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(stpncpy_heap_before_end); ATF_TC_BODY(stpncpy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(stpncpy_heap_end); ATF_TC_BODY(stpncpy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(stpncpy_heap_after_end); ATF_TC_BODY(stpncpy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; stpncpy(__stack.__buf, src, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(strcat_before_end); ATF_TC_BODY(strcat_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcat(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcat_end); ATF_TC_BODY(strcat_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcat(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcat_heap_before_end); ATF_TC_BODY(strcat_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcat(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcat_heap_end); ATF_TC_BODY(strcat_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcat(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcat_heap_after_end); ATF_TC_BODY(strcat_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcat(__stack.__buf, src); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } +ATF_TC_WITHOUT_HEAD(strlcat_before_end); +ATF_TC_BODY(strlcat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcat_end); +ATF_TC_BODY(strlcat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcat_heap_before_end); +ATF_TC_BODY(strlcat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcat_heap_end); +ATF_TC_BODY(strlcat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcat_heap_after_end); +ATF_TC_BODY(strlcat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcat(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TC_WITHOUT_HEAD(strncat_before_end); ATF_TC_BODY(strncat_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncat(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncat_end); ATF_TC_BODY(strncat_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncat(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncat_heap_before_end); ATF_TC_BODY(strncat_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncat(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncat_heap_end); ATF_TC_BODY(strncat_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncat(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncat_heap_after_end); ATF_TC_BODY(strncat_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncat(__stack.__buf, src, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(strcpy_before_end); ATF_TC_BODY(strcpy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcpy_end); ATF_TC_BODY(strcpy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcpy_heap_before_end); ATF_TC_BODY(strcpy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcpy_heap_end); ATF_TC_BODY(strcpy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcpy(__stack.__buf, src); #undef BUF } ATF_TC_WITHOUT_HEAD(strcpy_heap_after_end); ATF_TC_BODY(strcpy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strcpy(__stack.__buf, src); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } +ATF_TC_WITHOUT_HEAD(strlcpy_before_end); +ATF_TC_BODY(strlcpy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcpy_end); +ATF_TC_BODY(strlcpy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcpy_heap_before_end); +ATF_TC_BODY(strlcpy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcpy_heap_end); +ATF_TC_BODY(strlcpy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + char src[__len]; + + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(strlcpy_heap_after_end); +ATF_TC_BODY(strlcpy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char src[__len]; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + memset(__stack.__buf, 0, __len); + memset(src, 'A', __len - 1); + src[__len - 1] = '\0'; + + strlcpy(__stack.__buf, src, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TC_WITHOUT_HEAD(strncpy_before_end); ATF_TC_BODY(strncpy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncpy_end); ATF_TC_BODY(strncpy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncpy_heap_before_end); ATF_TC_BODY(strncpy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncpy_heap_end); ATF_TC_BODY(strncpy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len]; __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncpy(__stack.__buf, src, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(strncpy_heap_after_end); ATF_TC_BODY(strncpy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; strncpy(__stack.__buf, src, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, memcpy_before_end); ATF_TP_ADD_TC(tp, memcpy_end); ATF_TP_ADD_TC(tp, memcpy_heap_before_end); ATF_TP_ADD_TC(tp, memcpy_heap_end); ATF_TP_ADD_TC(tp, memcpy_heap_after_end); + ATF_TP_ADD_TC(tp, mempcpy_before_end); + ATF_TP_ADD_TC(tp, mempcpy_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_before_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_end); + ATF_TP_ADD_TC(tp, mempcpy_heap_after_end); ATF_TP_ADD_TC(tp, memmove_before_end); ATF_TP_ADD_TC(tp, memmove_end); ATF_TP_ADD_TC(tp, memmove_heap_before_end); ATF_TP_ADD_TC(tp, memmove_heap_end); ATF_TP_ADD_TC(tp, memmove_heap_after_end); ATF_TP_ADD_TC(tp, memset_before_end); ATF_TP_ADD_TC(tp, memset_end); ATF_TP_ADD_TC(tp, memset_heap_before_end); ATF_TP_ADD_TC(tp, memset_heap_end); ATF_TP_ADD_TC(tp, memset_heap_after_end); ATF_TP_ADD_TC(tp, stpcpy_before_end); ATF_TP_ADD_TC(tp, stpcpy_end); ATF_TP_ADD_TC(tp, stpcpy_heap_before_end); ATF_TP_ADD_TC(tp, stpcpy_heap_end); ATF_TP_ADD_TC(tp, stpcpy_heap_after_end); ATF_TP_ADD_TC(tp, stpncpy_before_end); ATF_TP_ADD_TC(tp, stpncpy_end); ATF_TP_ADD_TC(tp, stpncpy_heap_before_end); ATF_TP_ADD_TC(tp, stpncpy_heap_end); ATF_TP_ADD_TC(tp, stpncpy_heap_after_end); ATF_TP_ADD_TC(tp, strcat_before_end); ATF_TP_ADD_TC(tp, strcat_end); ATF_TP_ADD_TC(tp, strcat_heap_before_end); ATF_TP_ADD_TC(tp, strcat_heap_end); ATF_TP_ADD_TC(tp, strcat_heap_after_end); + ATF_TP_ADD_TC(tp, strlcat_before_end); + ATF_TP_ADD_TC(tp, strlcat_end); + ATF_TP_ADD_TC(tp, strlcat_heap_before_end); + ATF_TP_ADD_TC(tp, strlcat_heap_end); + ATF_TP_ADD_TC(tp, strlcat_heap_after_end); ATF_TP_ADD_TC(tp, strncat_before_end); ATF_TP_ADD_TC(tp, strncat_end); ATF_TP_ADD_TC(tp, strncat_heap_before_end); ATF_TP_ADD_TC(tp, strncat_heap_end); ATF_TP_ADD_TC(tp, strncat_heap_after_end); ATF_TP_ADD_TC(tp, strcpy_before_end); ATF_TP_ADD_TC(tp, strcpy_end); ATF_TP_ADD_TC(tp, strcpy_heap_before_end); ATF_TP_ADD_TC(tp, strcpy_heap_end); ATF_TP_ADD_TC(tp, strcpy_heap_after_end); + ATF_TP_ADD_TC(tp, strlcpy_before_end); + ATF_TP_ADD_TC(tp, strlcpy_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_before_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_end); + ATF_TP_ADD_TC(tp, strlcpy_heap_after_end); ATF_TP_ADD_TC(tp, strncpy_before_end); ATF_TP_ADD_TC(tp, strncpy_end); ATF_TP_ADD_TC(tp, strncpy_heap_before_end); ATF_TP_ADD_TC(tp, strncpy_heap_end); ATF_TP_ADD_TC(tp, strncpy_heap_after_end); return (atf_no_error()); } diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c index f9e628bbcd38..f9cb1e4917f7 100644 --- a/lib/libc/tests/secure/fortify_strings_test.c +++ b/lib/libc/tests/secure/fortify_strings_test.c @@ -1,354 +1,519 @@ /* @generated by `generate-fortify-tests.lua "strings"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + /* * Create a new symlink to use for readlink(2) style tests, we'll just use a * random target name to have something interesting to look at. */ static const char * __unused new_symlink(size_t __len) { static const char linkname[] = "link"; char target[MAXNAMLEN]; int error; ATF_REQUIRE(__len <= sizeof(target)); arc4random_buf(target, sizeof(target)); error = unlink(linkname); ATF_REQUIRE(error == 0 || errno == ENOENT); error = symlink(target, linkname); ATF_REQUIRE(error == 0); return (linkname); } /* * Constructs a tmpfile that we can use for testing read(2) and friends. */ static int __unused new_tmpfile(void) { char buf[1024]; ssize_t rv; size_t written; int fd; fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); ATF_REQUIRE(fd >= 0); written = 0; while (written < TMPFILE_SIZE) { rv = write(fd, buf, sizeof(buf)); ATF_REQUIRE(rv > 0); written += rv; } ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); return (fd); } static void disable_coredumps(void) { struct rlimit rl = { 0 }; if (setrlimit(RLIMIT_CORE, &rl) == -1) _exit(EX_OSERR); } +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + ATF_TC_WITHOUT_HEAD(bcopy_before_end); ATF_TC_BODY(bcopy_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; bcopy(src, __stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bcopy_end); ATF_TC_BODY(bcopy_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; bcopy(src, __stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bcopy_heap_before_end); ATF_TC_BODY(bcopy_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); bcopy(src, __stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bcopy_heap_end); ATF_TC_BODY(bcopy_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; char src[__len + 10]; __stack.__buf = malloc(__bufsz); bcopy(src, __stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bcopy_heap_after_end); ATF_TC_BODY(bcopy_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; char src[__len + 10]; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); bcopy(src, __stack.__buf, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TC_WITHOUT_HEAD(bzero_before_end); ATF_TC_BODY(bzero_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; bzero(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bzero_end); ATF_TC_BODY(bzero_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; bzero(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bzero_heap_before_end); ATF_TC_BODY(bzero_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); bzero(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bzero_heap_end); ATF_TC_BODY(bzero_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); bzero(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(bzero_heap_after_end); ATF_TC_BODY(bzero_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); bzero(__stack.__buf, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } +ATF_TC_WITHOUT_HEAD(explicit_bzero_before_end); +ATF_TC_BODY(explicit_bzero_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(explicit_bzero_end); +ATF_TC_BODY(explicit_bzero_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_before_end); +ATF_TC_BODY(explicit_bzero_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_end); +ATF_TC_BODY(explicit_bzero_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(explicit_bzero_heap_after_end); +ATF_TC_BODY(explicit_bzero_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + explicit_bzero(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, bcopy_before_end); ATF_TP_ADD_TC(tp, bcopy_end); ATF_TP_ADD_TC(tp, bcopy_heap_before_end); ATF_TP_ADD_TC(tp, bcopy_heap_end); ATF_TP_ADD_TC(tp, bcopy_heap_after_end); ATF_TP_ADD_TC(tp, bzero_before_end); ATF_TP_ADD_TC(tp, bzero_end); ATF_TP_ADD_TC(tp, bzero_heap_before_end); ATF_TP_ADD_TC(tp, bzero_heap_end); ATF_TP_ADD_TC(tp, bzero_heap_after_end); + ATF_TP_ADD_TC(tp, explicit_bzero_before_end); + ATF_TP_ADD_TC(tp, explicit_bzero_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_before_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_end); + ATF_TP_ADD_TC(tp, explicit_bzero_heap_after_end); return (atf_no_error()); } diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c index 69e70124ca5f..76702321676a 100644 --- a/lib/libc/tests/secure/fortify_unistd_test.c +++ b/lib/libc/tests/secure/fortify_unistd_test.c @@ -1,505 +1,1967 @@ /* @generated by `generate-fortify-tests.lua "unistd"` */ #define _FORTIFY_SOURCE 2 #define TMPFILE_SIZE (1024 * 32) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + /* * Create a new symlink to use for readlink(2) style tests, we'll just use a * random target name to have something interesting to look at. */ static const char * __unused new_symlink(size_t __len) { static const char linkname[] = "link"; char target[MAXNAMLEN]; int error; ATF_REQUIRE(__len <= sizeof(target)); arc4random_buf(target, sizeof(target)); error = unlink(linkname); ATF_REQUIRE(error == 0 || errno == ENOENT); error = symlink(target, linkname); ATF_REQUIRE(error == 0); return (linkname); } /* * Constructs a tmpfile that we can use for testing read(2) and friends. */ static int __unused new_tmpfile(void) { char buf[1024]; ssize_t rv; size_t written; int fd; fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); ATF_REQUIRE(fd >= 0); written = 0; while (written < TMPFILE_SIZE) { rv = write(fd, buf, sizeof(buf)); ATF_REQUIRE(rv > 0); written += rv; } ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); return (fd); } static void disable_coredumps(void) { struct rlimit rl = { 0 }; if (setrlimit(RLIMIT_CORE, &rl) == -1) _exit(EX_OSERR); } +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + ATF_TC_WITHOUT_HEAD(getcwd_before_end); ATF_TC_BODY(getcwd_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[8]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 8 - 1; const size_t __idx __unused = __len - 1; getcwd(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getcwd_end); ATF_TC_BODY(getcwd_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[8]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 8; const size_t __idx __unused = __len - 1; getcwd(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getcwd_heap_before_end); ATF_TC_BODY(getcwd_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); const size_t __len = 8 - 1; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); getcwd(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getcwd_heap_end); ATF_TC_BODY(getcwd_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); const size_t __len = 8; const size_t __idx __unused = __len - 1; __stack.__buf = malloc(__bufsz); getcwd(__stack.__buf, __len); #undef BUF } ATF_TC_WITHOUT_HEAD(getcwd_heap_after_end); ATF_TC_BODY(getcwd_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (8); const size_t __len = 8 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); getcwd(__stack.__buf, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } -ATF_TC_WITHOUT_HEAD(read_before_end); -ATF_TC_BODY(read_before_end, tc) +ATF_TC_WITHOUT_HEAD(getgrouplist_before_end); +ATF_TC_BODY(getgrouplist_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[41]; + gid_t __buf[4]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); - const size_t __len = 41 - 1; + const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; - int fd; + int intlen = (int)__len; - fd = new_tmpfile(); /* Cannot fail */ + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF - read(fd, __stack.__buf, __len); +} + +ATF_TC_WITHOUT_HEAD(getgrouplist_end); +ATF_TC_BODY(getgrouplist_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + getgrouplist("root", 0, __stack.__buf, &intlen); #undef BUF } -ATF_TC_WITHOUT_HEAD(read_end); -ATF_TC_BODY(read_end, tc) +ATF_TC_WITHOUT_HEAD(getgrouplist_heap_before_end); +ATF_TC_BODY(getgrouplist_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getgrouplist_heap_end); +ATF_TC_BODY(getgrouplist_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + int intlen = (int)__len; + + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getgrouplist_heap_after_end); +ATF_TC_BODY(getgrouplist_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + gid_t * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int intlen = (int)__len; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getgrouplist("root", 0, __stack.__buf, &intlen); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getgroups_before_end); +ATF_TC_BODY(getgroups_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; - unsigned char __buf[41]; + gid_t __buf[4]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); - const size_t __len = 41; + const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; - int fd; - fd = new_tmpfile(); /* Cannot fail */ + getgroups(__len, __stack.__buf); +#undef BUF - read(fd, __stack.__buf, __len); +} + +ATF_TC_WITHOUT_HEAD(getgroups_end); +ATF_TC_BODY(getgroups_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + gid_t __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + + getgroups(__len, __stack.__buf); #undef BUF } -ATF_TC_WITHOUT_HEAD(read_heap_before_end); -ATF_TC_BODY(read_heap_before_end, tc) +ATF_TC_WITHOUT_HEAD(getgroups_heap_before_end); +ATF_TC_BODY(getgroups_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + gid_t * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); - const size_t __len = 41 - 1; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; const size_t __idx __unused = __len - 1; - int fd; __stack.__buf = malloc(__bufsz); - fd = new_tmpfile(); /* Cannot fail */ - read(fd, __stack.__buf, __len); + getgroups(__len, __stack.__buf); #undef BUF } -ATF_TC_WITHOUT_HEAD(read_heap_end); -ATF_TC_BODY(read_heap_end, tc) +ATF_TC_WITHOUT_HEAD(getgroups_heap_end); +ATF_TC_BODY(getgroups_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + gid_t * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); - const size_t __len = 41; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; const size_t __idx __unused = __len - 1; - int fd; __stack.__buf = malloc(__bufsz); - fd = new_tmpfile(); /* Cannot fail */ - read(fd, __stack.__buf, __len); + getgroups(__len, __stack.__buf); #undef BUF } -ATF_TC_WITHOUT_HEAD(read_heap_after_end); -ATF_TC_BODY(read_heap_after_end, tc) +ATF_TC_WITHOUT_HEAD(getgroups_heap_after_end); +ATF_TC_BODY(getgroups_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; - unsigned char * __buf; + gid_t * __buf; uint8_t padding_r; } __stack; - const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); - const size_t __len = 41 + 1; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; - int fd; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); - fd = new_tmpfile(); /* Cannot fail */ - read(fd, __stack.__buf, __len); + getgroups(__len, __stack.__buf); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } -ATF_TC_WITHOUT_HEAD(readlink_before_end); -ATF_TC_BODY(readlink_before_end, tc) +ATF_TC_WITHOUT_HEAD(getloginclass_before_end); +ATF_TC_BODY(getloginclass_before_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; - const char *path; - - path = new_symlink(__len); /* Cannot fail */ - readlink(path, __stack.__buf, __len); + getloginclass(__stack.__buf, __len); #undef BUF } -ATF_TC_WITHOUT_HEAD(readlink_end); -ATF_TC_BODY(readlink_end, tc) +ATF_TC_WITHOUT_HEAD(getloginclass_end); +ATF_TC_BODY(getloginclass_end, tc) { #define BUF &__stack.__buf struct { uint8_t padding_l; unsigned char __buf[42]; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(__stack.__buf); const size_t __len = 42; const size_t __idx __unused = __len - 1; - const char *path; - - path = new_symlink(__len); /* Cannot fail */ - readlink(path, __stack.__buf, __len); + getloginclass(__stack.__buf, __len); #undef BUF } -ATF_TC_WITHOUT_HEAD(readlink_heap_before_end); -ATF_TC_BODY(readlink_heap_before_end, tc) +ATF_TC_WITHOUT_HEAD(getloginclass_heap_before_end); +ATF_TC_BODY(getloginclass_heap_before_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 - 1; const size_t __idx __unused = __len - 1; - const char *path; __stack.__buf = malloc(__bufsz); - path = new_symlink(__len); /* Cannot fail */ - readlink(path, __stack.__buf, __len); + getloginclass(__stack.__buf, __len); #undef BUF } -ATF_TC_WITHOUT_HEAD(readlink_heap_end); -ATF_TC_BODY(readlink_heap_end, tc) +ATF_TC_WITHOUT_HEAD(getloginclass_heap_end); +ATF_TC_BODY(getloginclass_heap_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42; const size_t __idx __unused = __len - 1; - const char *path; __stack.__buf = malloc(__bufsz); - path = new_symlink(__len); /* Cannot fail */ - readlink(path, __stack.__buf, __len); + getloginclass(__stack.__buf, __len); #undef BUF } -ATF_TC_WITHOUT_HEAD(readlink_heap_after_end); -ATF_TC_BODY(readlink_heap_after_end, tc) +ATF_TC_WITHOUT_HEAD(getloginclass_heap_after_end); +ATF_TC_BODY(getloginclass_heap_after_end, tc) { #define BUF __stack.__buf struct { uint8_t padding_l; unsigned char * __buf; uint8_t padding_r; } __stack; const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); const size_t __len = 42 + 1; const size_t __idx __unused = __len - 1; pid_t __child; int __status; - const char *path; __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); __stack.__buf = malloc(__bufsz); - path = new_symlink(__len); /* Cannot fail */ - readlink(path, __stack.__buf, __len); + getloginclass(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(pread_before_end); +ATF_TC_BODY(pread_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(pread_end); +ATF_TC_BODY(pread_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(pread_heap_before_end); +ATF_TC_BODY(pread_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(pread_heap_end); +ATF_TC_BODY(pread_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(pread_heap_after_end); +ATF_TC_BODY(pread_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + pread(fd, __stack.__buf, __len, 0); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(read_before_end); +ATF_TC_BODY(read_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(read_end); +ATF_TC_BODY(read_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[41]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(read_heap_before_end); +ATF_TC_BODY(read_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(read_heap_end); +ATF_TC_BODY(read_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41; + const size_t __idx __unused = __len - 1; + int fd; + + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(read_heap_after_end); +ATF_TC_BODY(read_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (41); + const size_t __len = 41 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + fd = new_tmpfile(); /* Cannot fail */ + + read(fd, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlink_before_end); +ATF_TC_BODY(readlink_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlink_end); +ATF_TC_BODY(readlink_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlink_heap_before_end); +ATF_TC_BODY(readlink_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlink_heap_end); +ATF_TC_BODY(readlink_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlink_heap_after_end); +ATF_TC_BODY(readlink_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + const char *path; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlink(path, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlinkat_before_end); +ATF_TC_BODY(readlinkat_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlinkat_end); +ATF_TC_BODY(readlinkat_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlinkat_heap_before_end); +ATF_TC_BODY(readlinkat_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlinkat_heap_end); +ATF_TC_BODY(readlinkat_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + const char *path; + + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(readlinkat_heap_after_end); +ATF_TC_BODY(readlinkat_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + const char *path; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + path = new_symlink(__len); /* Cannot fail */ + + readlinkat(AT_FDCWD, path, __stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getdomainname_before_end); +ATF_TC_BODY(getdomainname_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + char sysdomain[256]; + + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getdomainname_end); +ATF_TC_BODY(getdomainname_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + char sysdomain[256]; + + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getdomainname_heap_before_end); +ATF_TC_BODY(getdomainname_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + char sysdomain[256]; + + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); + + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getdomainname_heap_end); +ATF_TC_BODY(getdomainname_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + char sysdomain[256]; + + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); + + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getdomainname_heap_after_end); +ATF_TC_BODY(getdomainname_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char sysdomain[256]; + + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getdomainname(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getentropy_before_end); +ATF_TC_BODY(getentropy_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getentropy_end); +ATF_TC_BODY(getentropy_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getentropy_heap_before_end); +ATF_TC_BODY(getentropy_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getentropy_heap_end); +ATF_TC_BODY(getentropy_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getentropy_heap_after_end); +ATF_TC_BODY(getentropy_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getentropy(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gethostname_before_end); +ATF_TC_BODY(gethostname_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + char syshost[256]; + int error; + + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gethostname_end); +ATF_TC_BODY(gethostname_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[4]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + char syshost[256]; + int error; + + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gethostname_heap_before_end); +ATF_TC_BODY(gethostname_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 - 1; + const size_t __idx __unused = __len - 1; + char syshost[256]; + int error; + + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); + + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gethostname_heap_end); +ATF_TC_BODY(gethostname_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4; + const size_t __idx __unused = __len - 1; + char syshost[256]; + int error; + + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); + + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(gethostname_heap_after_end); +ATF_TC_BODY(gethostname_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (4); + const size_t __len = 4 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + char syshost[256]; + int error; + + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + gethostname(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getlogin_r_before_end); +ATF_TC_BODY(getlogin_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[MAXLOGNAME + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = MAXLOGNAME + 1 - 1; + const size_t __idx __unused = __len - 1; + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getlogin_r_end); +ATF_TC_BODY(getlogin_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[MAXLOGNAME + 1]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = MAXLOGNAME + 1; + const size_t __idx __unused = __len - 1; + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getlogin_r_heap_before_end); +ATF_TC_BODY(getlogin_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1 - 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getlogin_r_heap_end); +ATF_TC_BODY(getlogin_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1; + const size_t __idx __unused = __len - 1; + + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(getlogin_r_heap_after_end); +ATF_TC_BODY(getlogin_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (MAXLOGNAME + 1); + const size_t __len = MAXLOGNAME + 1 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + getlogin_r(__stack.__buf, __len); + _exit(EX_SOFTWARE); /* Should have aborted. */ + +monitor: + while (waitpid(__child, &__status, 0) != __child) { + ATF_REQUIRE_EQ(EINTR, errno); + } + + if (!WIFSIGNALED(__status)) { + switch (WEXITSTATUS(__status)) { + case EX_SOFTWARE: + atf_tc_fail("FORTIFY_SOURCE failed to abort"); + break; + case EX_OSERR: + atf_tc_fail("setrlimit(2) failed"); + break; + default: + atf_tc_fail("child exited with status %d", + WEXITSTATUS(__status)); + } + } else { + ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); + } +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ttyname_r_before_end); +ATF_TC_BODY(ttyname_r_before_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ttyname_r_end); +ATF_TC_BODY(ttyname_r_end, tc) +{ +#define BUF &__stack.__buf + struct { + uint8_t padding_l; + unsigned char __buf[42]; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(__stack.__buf); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ttyname_r_heap_before_end); +ATF_TC_BODY(ttyname_r_heap_before_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 - 1; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ttyname_r_heap_end); +ATF_TC_BODY(ttyname_r_heap_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42; + const size_t __idx __unused = __len - 1; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); +#undef BUF + +} + +ATF_TC_WITHOUT_HEAD(ttyname_r_heap_after_end); +ATF_TC_BODY(ttyname_r_heap_after_end, tc) +{ +#define BUF __stack.__buf + struct { + uint8_t padding_l; + unsigned char * __buf; + uint8_t padding_r; + } __stack; + const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42); + const size_t __len = 42 + 1; + const size_t __idx __unused = __len - 1; + pid_t __child; + int __status; + int fd; + + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); + + __child = fork(); + ATF_REQUIRE(__child >= 0); + if (__child > 0) + goto monitor; + + /* Child */ + disable_coredumps(); + __stack.__buf = malloc(__bufsz); + + ttyname_r(fd, __stack.__buf, __len); _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } #undef BUF } ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, getcwd_before_end); ATF_TP_ADD_TC(tp, getcwd_end); ATF_TP_ADD_TC(tp, getcwd_heap_before_end); ATF_TP_ADD_TC(tp, getcwd_heap_end); ATF_TP_ADD_TC(tp, getcwd_heap_after_end); + ATF_TP_ADD_TC(tp, getgrouplist_before_end); + ATF_TP_ADD_TC(tp, getgrouplist_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_before_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_end); + ATF_TP_ADD_TC(tp, getgrouplist_heap_after_end); + ATF_TP_ADD_TC(tp, getgroups_before_end); + ATF_TP_ADD_TC(tp, getgroups_end); + ATF_TP_ADD_TC(tp, getgroups_heap_before_end); + ATF_TP_ADD_TC(tp, getgroups_heap_end); + ATF_TP_ADD_TC(tp, getgroups_heap_after_end); + ATF_TP_ADD_TC(tp, getloginclass_before_end); + ATF_TP_ADD_TC(tp, getloginclass_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_before_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_end); + ATF_TP_ADD_TC(tp, getloginclass_heap_after_end); + ATF_TP_ADD_TC(tp, pread_before_end); + ATF_TP_ADD_TC(tp, pread_end); + ATF_TP_ADD_TC(tp, pread_heap_before_end); + ATF_TP_ADD_TC(tp, pread_heap_end); + ATF_TP_ADD_TC(tp, pread_heap_after_end); ATF_TP_ADD_TC(tp, read_before_end); ATF_TP_ADD_TC(tp, read_end); ATF_TP_ADD_TC(tp, read_heap_before_end); ATF_TP_ADD_TC(tp, read_heap_end); ATF_TP_ADD_TC(tp, read_heap_after_end); ATF_TP_ADD_TC(tp, readlink_before_end); ATF_TP_ADD_TC(tp, readlink_end); ATF_TP_ADD_TC(tp, readlink_heap_before_end); ATF_TP_ADD_TC(tp, readlink_heap_end); ATF_TP_ADD_TC(tp, readlink_heap_after_end); + ATF_TP_ADD_TC(tp, readlinkat_before_end); + ATF_TP_ADD_TC(tp, readlinkat_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_before_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_end); + ATF_TP_ADD_TC(tp, readlinkat_heap_after_end); + ATF_TP_ADD_TC(tp, getdomainname_before_end); + ATF_TP_ADD_TC(tp, getdomainname_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_before_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_end); + ATF_TP_ADD_TC(tp, getdomainname_heap_after_end); + ATF_TP_ADD_TC(tp, getentropy_before_end); + ATF_TP_ADD_TC(tp, getentropy_end); + ATF_TP_ADD_TC(tp, getentropy_heap_before_end); + ATF_TP_ADD_TC(tp, getentropy_heap_end); + ATF_TP_ADD_TC(tp, getentropy_heap_after_end); + ATF_TP_ADD_TC(tp, gethostname_before_end); + ATF_TP_ADD_TC(tp, gethostname_end); + ATF_TP_ADD_TC(tp, gethostname_heap_before_end); + ATF_TP_ADD_TC(tp, gethostname_heap_end); + ATF_TP_ADD_TC(tp, gethostname_heap_after_end); + ATF_TP_ADD_TC(tp, getlogin_r_before_end); + ATF_TP_ADD_TC(tp, getlogin_r_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_before_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_end); + ATF_TP_ADD_TC(tp, getlogin_r_heap_after_end); + ATF_TP_ADD_TC(tp, ttyname_r_before_end); + ATF_TP_ADD_TC(tp, ttyname_r_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_before_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_end); + ATF_TP_ADD_TC(tp, ttyname_r_heap_after_end); return (atf_no_error()); } diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua index 8734fcfa4e2e..bff1162c7d83 100755 --- a/lib/libc/tests/secure/generate-fortify-tests.lua +++ b/lib/libc/tests/secure/generate-fortify-tests.lua @@ -1,706 +1,977 @@ #!/usr/libexec/flua -- -- SPDX-License-Identifier: BSD-2-Clause -- -- Copyright (c) 2024, Klara, Inc. -- -- 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. -- -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. -- -- THEORY OF OPERATION -- -- generate-fortify-tests.lua is intended to test fortified functions as found -- mostly in the various headers in /usr/include/ssp. Each fortified function -- gets three basic tests: -- -- 1. Write just before the end of the buffer, -- 2. Write right at the end of the buffer, -- 3. Write just after the end of the buffer. -- -- Each test is actually generated twice: once with a buffer on the stack, and -- again with a buffer on the heap, to confirm that __builtin_object_size(3) can -- deduce the buffer size in both scenarios. The tests work by setting up the -- stack with our buffer (and some padding on either side to avoid tripping any -- other stack or memory protection), doing any initialization as described by -- the test definition, then calling the fortified function with the buffer as -- outlined by the test definition. -- -- For the 'before' and 'at' the end tests, we're ensuring that valid writes -- that are on the verge of being invalid aren't accidentally being detected as -- invalid. -- -- The 'after' test is the one that actually tests the functional benefit of -- _FORTIFY_SOURCE by violating a boundary that should trigger an abort. As -- such, this test differs more from the other two in that it has to fork() off -- the fortified function call so that we can monitor for a SIGABRT and -- pass/fail the test at function end appropriately. -- Some tests, like the FD_*() macros, may define these differently. For -- instance, for fd sets we're varying the index we pass and not using arbitrary -- buffers. Other tests that don't use the length in any way may physically -- vary the buffer size for each test case when we'd typically vary the length -- we're requesting a write for. local includes = { "sys/param.h", "sys/resource.h", "sys/time.h", "sys/wait.h", "dirent.h", "errno.h", "fcntl.h", "limits.h", "signal.h", "stdio.h", "stdlib.h", "string.h", "strings.h", "sysexits.h", "unistd.h", "atf-c.h", } local tests_added = {} -- Some of these will need to be excluded because clang sees the wrong size when -- an array is embedded inside a struct, we'll get something that looks more -- like __builtin_object_size(ptr, 0) than it does the correct -- __builtin_object_size(ptr, 1) (i.e., includes the padding after). This is -- almost certainly a bug in llvm. local function excludes_stack_overflow(disposition, is_heap) return (not is_heap) and disposition > 0 end local printf_stackvars = "\tchar srcvar[__len + 10];\n" local printf_init = [[ memset(srcvar, 'A', sizeof(srcvar) - 1); srcvar[sizeof(srcvar) - 1] = '\0'; ]] +local stdio_init = [[ + replace_stdin(); +]] + local string_stackvars = "\tchar src[__len];\n" local string_init = [[ memset(__stack.__buf, 0, __len); memset(src, 'A', __len - 1); src[__len - 1] = '\0'; ]] -- Each test entry describes how to test a given function. We need to know how -- to construct the buffer, we need to know the argument set we're dealing with, -- and we need to know what we're passing to each argument. We could be passing -- fixed values, or we could be passing the __buf under test. -- -- definition: -- func: name of the function under test to call -- bufsize: size of buffer to generate, defaults to 42 -- buftype: type of buffer to generate, defaults to unsigned char[] -- arguments: __buf, __len, or the name of a variable placed on the stack -- exclude: a function(disposition, is_heap) that returns true if this combo -- should be excluded. -- stackvars: extra variables to be placed on the stack, should be a string -- optionally formatted with tabs and newlines -- init: extra code to inject just before the function call for initialization -- of the buffer or any of the above-added stackvars; also a string -- uses_len: bool-ish, necessary if arguments doesn't include either __idx or -- or __len so that the test generator doesn't try to vary the size of the -- buffer instead of just manipulating __idx/__len to try and induce an -- overflow. -- -- Most tests will just use the default bufsize/buftype, but under some -- circumstances it's useful to use a different type (e.g., for alignment -- requirements). local all_tests = { stdio = { -- + { + func = "ctermid", + bufsize = "L_ctermid", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "ctermid_r", + bufsize = "L_ctermid", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "fread", + arguments = { + "__buf", + "__len", + "1", + "stdin", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, + { + func = "fread_unlocked", + arguments = { + "__buf", + "__len", + "1", + "stdin", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, + { + func = "gets_s", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + init = stdio_init, + }, { func = "sprintf", arguments = { "__buf", "\"%.*s\"", "(int)__len - 1", -- - 1 for NUL terminator "srcvar", }, exclude = excludes_stack_overflow, stackvars = printf_stackvars, init = printf_init, }, { func = "snprintf", arguments = { "__buf", "__len", "\"%.*s\"", "(int)__len - 1", -- - 1 for NUL terminator "srcvar", }, exclude = excludes_stack_overflow, stackvars = printf_stackvars, init = printf_init, }, + { + func = "tmpnam", + bufsize = "L_tmpnam", + arguments = { + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "fgets", + arguments = { + "__buf", + "__len", + "fp", + }, + exclude = excludes_stack_overflow, + stackvars = "\tFILE *fp;\n", + init = [[ + fp = new_fp(__len); +]], + }, }, string = { -- { func = "memcpy", arguments = { "__buf", "src", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tchar src[__len + 10];\n", }, + { + func = "mempcpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar src[__len + 10];\n", + }, { func = "memmove", arguments = { "__buf", "src", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tchar src[__len + 10];\n", }, { func = "memset", arguments = { "__buf", "0", "__len", }, exclude = excludes_stack_overflow, }, { func = "stpcpy", arguments = { "__buf", "src", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, uses_len = true, }, { func = "stpncpy", arguments = { "__buf", "src", "__len", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, }, { func = "strcat", arguments = { "__buf", "src", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, uses_len = true, }, + { + func = "strlcat", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, { func = "strncat", arguments = { "__buf", "src", "__len", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, }, { func = "strcpy", arguments = { "__buf", "src", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, uses_len = true, }, + { + func = "strlcpy", + arguments = { + "__buf", + "src", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = string_stackvars, + init = string_init, + }, { func = "strncpy", arguments = { "__buf", "src", "__len", }, exclude = excludes_stack_overflow, stackvars = string_stackvars, init = string_init, }, }, strings = { -- { func = "bcopy", arguments = { "src", "__buf", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tchar src[__len + 10];\n", }, { func = "bzero", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, }, + { + func = "explicit_bzero", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, }, unistd = { -- { func = "getcwd", bufsize = "8", arguments = { "__buf", "__len", }, exclude = excludes_stack_overflow, }, + { + func = "getgrouplist", + bufsize = "4", + buftype = "gid_t[]", + arguments = { + "\"root\"", + "0", + "__buf", + "&intlen", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint intlen = (int)__len;\n", + uses_len = true, + }, + { + func = "getgroups", + bufsize = "4", + buftype = "gid_t[]", + arguments = { + "__len", + "__buf", + }, + exclude = excludes_stack_overflow, + }, + { + func = "getloginclass", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "pread", + bufsize = "41", + arguments = { + "fd", + "__buf", + "__len", + "0", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint fd;\n", + init = [[ + fd = new_tmpfile(); /* Cannot fail */ +]], + }, { func = "read", bufsize = "41", arguments = { "fd", "__buf", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tint fd;\n", init = [[ fd = new_tmpfile(); /* Cannot fail */ ]], }, { func = "readlink", arguments = { "path", "__buf", "__len", }, exclude = excludes_stack_overflow, stackvars = "\tconst char *path;\n", init = [[ path = new_symlink(__len); /* Cannot fail */ ]], }, + { + func = "readlinkat", + arguments = { + "AT_FDCWD", + "path", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tconst char *path;\n", + init = [[ + path = new_symlink(__len); /* Cannot fail */ +]], + }, + { + func = "getdomainname", + bufsize = "4", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tchar sysdomain[256];\n", + early_init = [[ + (void)getdomainname(sysdomain, __len); + if (strlen(sysdomain) <= __len) + atf_tc_skip("domain name too short for testing"); +]] + }, + { + func = "getentropy", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "gethostname", + bufsize = "4", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = [[ + char syshost[256]; + int error; +]], + early_init = [[ + error = gethostname(syshost, __len); + if (error != 0 || strlen(syshost) <= __len) + atf_tc_skip("hostname too short for testing"); +]] + }, + { + func = "getlogin_r", + bufsize = "MAXLOGNAME + 1", + arguments = { + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + }, + { + func = "ttyname_r", + arguments = { + "fd", + "__buf", + "__len", + }, + exclude = excludes_stack_overflow, + stackvars = "\tint fd;\n", + early_init = [[ + fd = STDIN_FILENO; + if (!isatty(fd)) + atf_tc_skip("stdin is not an fd"); +]] + }, }, } local function write_test_boilerplate(fh, name, body) fh:write("ATF_TC_WITHOUT_HEAD(" .. name .. ");\n") fh:write("ATF_TC_BODY(" .. name .. ", tc)\n") fh:write("{\n" .. body .. "\n}\n\n") return name end local function generate_test_name(func, variant, disposition, heap) local basename = func if variant then basename = basename .. "_" .. variant end if heap then basename = basename .. "_heap" end if disposition < 0 then return basename .. "_before_end" elseif disposition == 0 then return basename .. "_end" else return basename .. "_after_end" end end local function array_type(buftype) if not buftype:match("%[%]") then return nil end return buftype:gsub("%[%]", "") end local function configurable(def, idx) local cfgitem = def[idx] if not cfgitem then return nil end if type(cfgitem) == "function" then return cfgitem() end return cfgitem end local function generate_stackframe(buftype, bufsize, disposition, heap, def) local function len_offset(inverted, disposition) -- Tests that don't use __len in their arguments may use an -- inverted sense because we can't just specify a length that -- would induce an access just after the end. Instead, we have -- to manipulate the buffer size to be too short so that the -- function under test would write one too many. if disposition < 0 then return ((inverted and " + ") or " - ") .. "1" elseif disposition == 0 then return "" else return ((inverted and " - ") or " + ") .. "1" end end local function test_uses_len(def) if def.uses_len then return true end for _, arg in ipairs(def.arguments) do if arg:match("__len") or arg:match("__idx") then return true end end return false end -- This is perhaps a little convoluted, but we toss the buffer into a -- struct on the stack to guarantee that we have at least one valid -- byte on either side of the buffer -- a measure to make sure that -- we're tripping _FORTIFY_SOURCE specifically in the buffer + 1 case, -- rather than some other stack or memory protection. local vars = "\tstruct {\n" vars = vars .. "\t\tuint8_t padding_l;\n" local uses_len = test_uses_len(def) local bufsize_offset = len_offset(not uses_len, disposition) local buftype_elem = array_type(buftype) local size_expr = bufsize if not uses_len then -- If the length isn't in use, we have to vary the buffer size -- since the fortified function likely has some internal size -- constraint that it's supposed to be checking. size_expr = size_expr .. bufsize_offset end if not heap and buftype_elem then -- Array type: size goes after identifier vars = vars .. "\t\t" .. buftype_elem .. " __buf[" .. size_expr .. "];\n" else local basic_type = buftype_elem or buftype -- Heap tests obviously just put a pointer on the stack that -- points to our new allocation, but we leave it in the padded -- struct just to simplify our generator. if heap then basic_type = basic_type .. " *" end vars = vars .. "\t\t" .. basic_type .. " __buf;\n" end -- padding_r is our just-past-the-end padding that we use to make sure -- that there's a valid portion after the buffer that isn't being -- included in our function calls. If we didn't have it, then we'd have -- a hard time feeling confident that an abort on the just-after tests -- isn't maybe from some other memory or stack protection. vars = vars .. "\t\tuint8_t padding_r;\n" vars = vars .. "\t} __stack;\n" -- Not all tests will use __bufsz, but some do for, e.g., clearing -- memory.. vars = vars .. "\tconst size_t __bufsz __unused = " if heap then local scalar = 1 if buftype_elem then scalar = size_expr end vars = vars .. "sizeof(*__stack.__buf) * (" .. scalar .. ");\n" else vars = vars .. "sizeof(__stack.__buf);\n" end vars = vars .. "\tconst size_t __len = " .. bufsize .. bufsize_offset .. ";\n" vars = vars .. "\tconst size_t __idx __unused = __len - 1;\n" -- For overflow testing, we need to fork() because we're expecting the -- test to ultimately abort()/_exit(). Then we can collect the exit -- status and report appropriately. if disposition > 0 then vars = vars .. "\tpid_t __child;\n" vars = vars .. "\tint __status;\n" end -- Any other stackvars defined by the test get placed after everything -- else. vars = vars .. (configurable(def, "stackvars") or "") return vars end local function write_test(fh, func, disposition, heap, def) local testname = generate_test_name(func, def.variant, disposition, heap) local buftype = def.buftype or "unsigned char[]" local bufsize = def.bufsize or 42 local body = "" if def.exclude and def.exclude(disposition, heap) then return end local function need_addr(buftype) return not (buftype:match("%[%]") or buftype:match("%*")) end if heap then body = body .. "#define BUF __stack.__buf\n" else body = body .. "#define BUF &__stack.__buf\n" end -- Setup the buffer body = body .. generate_stackframe(buftype, bufsize, disposition, heap, def) .. "\n" -- Any early initialization goes before we would fork for the just-after -- tests, because they may want to skip the test based on some criteria -- and we can't propagate that up very easily once we're forked. local early_init = configurable(def, "early_init") body = body .. (early_init or "") if early_init then body = body .. "\n" end -- Fork off, iff we're testing some access past the end of the buffer. if disposition > 0 then body = body .. [[ __child = fork(); ATF_REQUIRE(__child >= 0); if (__child > 0) goto monitor; /* Child */ disable_coredumps(); ]] end local bufvar = "__stack.__buf" if heap then -- Buffer needs to be initialized because it's a heap allocation. body = body .. "\t" .. bufvar .. " = malloc(__bufsz);\n" end -- Non-early init happens just after the fork in the child, not the -- monitor. This is used to setup any other buffers we may need, for -- instance. local extra_init = configurable(def, "init") body = body .. (extra_init or "") if heap or extra_init then body = body .. "\n" end -- Setup the function call with arguments as described in the test -- definition. body = body .. "\t" .. func .. "(" for idx, arg in ipairs(def.arguments) do if idx > 1 then body = body .. ", " end if arg == "__buf" then if not heap and need_addr(buftype) then body = body .. "&" end body = body .. bufvar else local argname = arg if def.value_of then argname = argname or def.value_of(arg) end body = body .. argname end end body = body .. ");\n" -- Monitor stuff follows, for OOB access. if disposition <= 0 then goto skip end body = body .. [[ _exit(EX_SOFTWARE); /* Should have aborted. */ monitor: while (waitpid(__child, &__status, 0) != __child) { ATF_REQUIRE_EQ(EINTR, errno); } if (!WIFSIGNALED(__status)) { switch (WEXITSTATUS(__status)) { case EX_SOFTWARE: atf_tc_fail("FORTIFY_SOURCE failed to abort"); break; case EX_OSERR: atf_tc_fail("setrlimit(2) failed"); break; default: atf_tc_fail("child exited with status %d", WEXITSTATUS(__status)); } } else { ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status)); } ]] ::skip:: body = body .. "#undef BUF\n" return write_test_boilerplate(fh, testname, body) end -- main() local tests local tcat = assert(arg[1], "usage: generate-fortify-tests.lua ") for k, defs in pairs(all_tests) do if k == tcat then tests = defs break end end assert(tests, "category " .. tcat .. " not found") local fh = io.stdout fh:write("/* @" .. "generated" .. " by `generate-fortify-tests.lua \"" .. tcat .. "\"` */\n\n") fh:write("#define _FORTIFY_SOURCE 2\n") fh:write("#define TMPFILE_SIZE (1024 * 32)\n") fh:write("\n") for _, inc in ipairs(includes) do fh:write("#include <" .. inc .. ">\n") end fh:write([[ +static FILE * __unused +new_fp(size_t __len) +{ + static char fpbuf[LINE_MAX]; + FILE *fp; + + ATF_REQUIRE(__len <= sizeof(fpbuf)); + + memset(fpbuf, 'A', sizeof(fpbuf) - 1); + fpbuf[sizeof(fpbuf) - 1] = '\0'; + + fp = fmemopen(fpbuf, sizeof(fpbuf), "rb"); + ATF_REQUIRE(fp != NULL); + + return (fp); +} + /* * Create a new symlink to use for readlink(2) style tests, we'll just use a * random target name to have something interesting to look at. */ static const char * __unused new_symlink(size_t __len) { static const char linkname[] = "link"; char target[MAXNAMLEN]; int error; ATF_REQUIRE(__len <= sizeof(target)); arc4random_buf(target, sizeof(target)); error = unlink(linkname); ATF_REQUIRE(error == 0 || errno == ENOENT); error = symlink(target, linkname); ATF_REQUIRE(error == 0); return (linkname); } /* * Constructs a tmpfile that we can use for testing read(2) and friends. */ static int __unused new_tmpfile(void) { char buf[1024]; ssize_t rv; size_t written; int fd; fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644); ATF_REQUIRE(fd >= 0); written = 0; while (written < TMPFILE_SIZE) { rv = write(fd, buf, sizeof(buf)); ATF_REQUIRE(rv > 0); written += rv; } ATF_REQUIRE_EQ(0, lseek(fd, 0, SEEK_SET)); return (fd); } static void disable_coredumps(void) { struct rlimit rl = { 0 }; if (setrlimit(RLIMIT_CORE, &rl) == -1) _exit(EX_OSERR); } +/* + * Replaces stdin with a file that we can actually read from, for tests where + * we want a FILE * or fd that we can get data from. + */ +static void __unused +replace_stdin(void) +{ + int fd; + + fd = new_tmpfile(); + + (void)dup2(fd, STDIN_FILENO); + if (fd != STDIN_FILENO) + close(fd); +} + ]]) for _, def in pairs(tests) do local func = def.func local function write_tests(heap) -- Dispositions here are relative to the buffer size prescribed -- by the test definition. local dispositions = def.dispositions or { -1, 0, 1 } for _, disposition in ipairs(dispositions) do tests_added[#tests_added + 1] = write_test(fh, func, disposition, heap, def) end end write_tests(false) write_tests(true) end fh:write("ATF_TP_ADD_TCS(tp)\n") fh:write("{\n") for idx = 1, #tests_added do fh:write("\tATF_TP_ADD_TC(tp, " .. tests_added[idx] .. ");\n") end fh:write("\treturn (atf_no_error());\n") fh:write("}\n") diff --git a/lib/libutil/tests/trimdomain-nodomain_test.c b/lib/libutil/tests/trimdomain-nodomain_test.c index 7e549533996f..b2dfaa4ae9af 100644 --- a/lib/libutil/tests/trimdomain-nodomain_test.c +++ b/lib/libutil/tests/trimdomain-nodomain_test.c @@ -1,88 +1,90 @@ /* * Copyright (C) 2005 Brooks Davis. 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. * * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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 #include #include #include #include #include #include #include +#include + #define TESTDOMAIN "" #define TESTHOST "testhost" #define TESTFQDN "testhost" TESTDOMAIN int failures = 0; int tests = 0; /* * Evily override gethostname(3) so trimdomain always gets the same result. * This makes the tests much easier to write and less likely to fail on * oddly configured systems. */ int -gethostname(char *name, size_t namelen) +__ssp_real(gethostname)(char *name, size_t namelen) { if (strlcpy(name, TESTFQDN, namelen) > namelen) { errno = ENAMETOOLONG; return (-1); } return (0); } void testit(const char *input, int hostsize, const char *output, const char *test) { char *testhost; const char *expected = (output == NULL) ? input : output; testhost = strdup(input); trimdomain(testhost, hostsize < 0 ? (int)strlen(testhost) : hostsize); tests++; if (strcmp(testhost, expected) != 0) { printf("not ok %d - %s\n", tests, test); printf("# %s -> %s (expected %s)\n", input, testhost, expected); } else printf("ok %d - %s\n", tests, test); free(testhost); return; } int main(void) { printf("1..5\n"); testit(TESTFQDN, -1, TESTHOST, "self"); testit("XXX" TESTDOMAIN, -1, "XXX", "different host, same domain"); testit("XXX" TESTDOMAIN, 1, NULL, "short hostsize"); testit("bogus.example.net", -1, NULL, "arbitrary host"); testit("XXX." TESTFQDN, -1, NULL, "domain is local hostname"); return (0); } diff --git a/lib/libutil/tests/trimdomain_test.c b/lib/libutil/tests/trimdomain_test.c index 772cca6aacf6..ad5b92b0ce1e 100644 --- a/lib/libutil/tests/trimdomain_test.c +++ b/lib/libutil/tests/trimdomain_test.c @@ -1,88 +1,90 @@ /* * Copyright (C) 2005 Brooks Davis. 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. * * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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 #include #include #include #include #include #include #include +#include + #define TESTDOMAIN ".domain.example.com" #define TESTHOST "testhost" #define TESTFQDN "testhost" TESTDOMAIN int failures = 0; int tests = 0; /* * Evily override gethostname(3) so trimdomain always gets the same result. * This makes the tests much easier to write and less likely to fail on * oddly configured systems. */ int -gethostname(char *name, size_t namelen) +__ssp_real(gethostname)(char *name, size_t namelen) { if (strlcpy(name, TESTFQDN, namelen) > namelen) { errno = ENAMETOOLONG; return (-1); } return (0); } void testit(const char *input, int hostsize, const char *output, const char *test) { char *testhost; const char *expected = (output == NULL) ? input : output; testhost = strdup(input); trimdomain(testhost, hostsize < 0 ? (int)strlen(testhost) : hostsize); tests++; if (strcmp(testhost, expected) != 0) { printf("not ok %d - %s\n", tests, test); printf("# %s -> %s (expected %s)\n", input, testhost, expected); } else printf("ok %d - %s\n", tests, test); free(testhost); return; } int main(void) { printf("1..5\n"); testit(TESTFQDN, -1, TESTHOST, "self"); testit("XXX" TESTDOMAIN, -1, "XXX", "different host, same domain"); testit("XXX" TESTDOMAIN, 1, NULL, "short hostsize"); testit("bogus.example.net", -1, NULL, "arbitrary host"); testit("XXX." TESTFQDN, -1, NULL, "domain is local hostname"); return (0); } diff --git a/sys/libkern/explicit_bzero.c b/sys/libkern/explicit_bzero.c index 618828008ab7..97a7b71540bc 100644 --- a/sys/libkern/explicit_bzero.c +++ b/sys/libkern/explicit_bzero.c @@ -1,26 +1,27 @@ /* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ /* * Public domain. * Written by Matthew Dempsky. */ #include #ifdef _KERNEL #include #else #include +#include #endif /* _KERNEL */ __attribute__((weak)) void __explicit_bzero_hook(void *, size_t); __attribute__((weak)) void __explicit_bzero_hook(void *buf, size_t len) { } void -explicit_bzero(void *buf, size_t len) +__ssp_real(explicit_bzero)(void *buf, size_t len) { memset(buf, 0, len); __explicit_bzero_hook(buf, len); } diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h index 7d2e24f1263b..64744f57b5c3 100644 --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -1,340 +1,346 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1992, 1993 * The 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. */ #ifndef _SYS_LIBKERN_H_ #define _SYS_LIBKERN_H_ #include #ifdef _KERNEL #include #endif #include #ifndef LIBKERN_INLINE #define LIBKERN_INLINE static __inline #define LIBKERN_BODY #endif /* BCD conversions. */ extern u_char const bcd2bin_data[]; extern u_char const bin2bcd_data[]; extern char const hex2ascii_data[]; #define LIBKERN_LEN_BCD2BIN 154 #define LIBKERN_LEN_BIN2BCD 100 #define LIBKERN_LEN_HEX2ASCII 36 static inline u_char bcd2bin(int bcd) { KASSERT(bcd >= 0 && bcd < LIBKERN_LEN_BCD2BIN, ("invalid bcd %d", bcd)); return (bcd2bin_data[bcd]); } static inline u_char bin2bcd(int bin) { KASSERT(bin >= 0 && bin < LIBKERN_LEN_BIN2BCD, ("invalid bin %d", bin)); return (bin2bcd_data[bin]); } static inline char hex2ascii(int hex) { KASSERT(hex >= 0 && hex < LIBKERN_LEN_HEX2ASCII, ("invalid hex %d", hex)); return (hex2ascii_data[hex]); } static inline bool validbcd(int bcd) { return (bcd == 0 || (bcd > 0 && bcd <= 0x99 && bcd2bin_data[bcd] != 0)); } static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); } static __inline long lmax(long a, long b) { return (a > b ? a : b); } static __inline long lmin(long a, long b) { return (a < b ? a : b); } static __inline u_int max(u_int a, u_int b) { return (a > b ? a : b); } static __inline u_int min(u_int a, u_int b) { return (a < b ? a : b); } static __inline quad_t qmax(quad_t a, quad_t b) { return (a > b ? a : b); } static __inline quad_t qmin(quad_t a, quad_t b) { return (a < b ? a : b); } static __inline u_quad_t uqmax(u_quad_t a, u_quad_t b) { return (a > b ? a : b); } static __inline u_quad_t uqmin(u_quad_t a, u_quad_t b) { return (a < b ? a : b); } static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); } static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); } static __inline __uintmax_t ummax(__uintmax_t a, __uintmax_t b) { return (a > b ? a : b); } static __inline __uintmax_t ummin(__uintmax_t a, __uintmax_t b) { return (a < b ? a : b); } static __inline off_t omax(off_t a, off_t b) { return (a > b ? a : b); } static __inline off_t omin(off_t a, off_t b) { return (a < b ? a : b); } static __inline int abs(int a) { return (a < 0 ? -a : a); } static __inline long labs(long a) { return (a < 0 ? -a : a); } static __inline int64_t abs64(int64_t a) { return (a < 0 ? -a : a); } static __inline quad_t qabs(quad_t a) { return (a < 0 ? -a : a); } #ifndef RANDOM_FENESTRASX #define ARC4_ENTR_NONE 0 /* Don't have entropy yet. */ #define ARC4_ENTR_HAVE 1 /* Have entropy. */ #define ARC4_ENTR_SEED 2 /* Reseeding. */ extern int arc4rand_iniseed_state; #endif /* Prototypes for non-quad routines. */ struct malloc_type; uint32_t arc4random(void); void arc4random_buf(void *, size_t); uint32_t arc4random_uniform(uint32_t); void arc4rand(void *, u_int, int); int timingsafe_bcmp(const void *, const void *, size_t); void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); /* * MHTODO: remove the 'HAVE_INLINE_FOO' defines once use of these flags has * been purged everywhere. For now we provide them unconditionally. */ #define HAVE_INLINE_FFS #define HAVE_INLINE_FFSL #define HAVE_INLINE_FFSLL #define HAVE_INLINE_FLS #define HAVE_INLINE_FLSL #define HAVE_INLINE_FLSLL static __inline __pure2 int ffs(int mask) { return (__builtin_ffs((u_int)mask)); } static __inline __pure2 int ffsl(long mask) { return (__builtin_ffsl((u_long)mask)); } static __inline __pure2 int ffsll(long long mask) { return (__builtin_ffsll((unsigned long long)mask)); } static __inline __pure2 int fls(int mask) { return (mask == 0 ? 0 : 8 * sizeof(mask) - __builtin_clz((u_int)mask)); } static __inline __pure2 int flsl(long mask) { return (mask == 0 ? 0 : 8 * sizeof(mask) - __builtin_clzl((u_long)mask)); } static __inline __pure2 int flsll(long long mask) { return (mask == 0 ? 0 : 8 * sizeof(mask) - __builtin_clzll((unsigned long long)mask)); } static __inline __pure2 int ilog2_int(int n) { KASSERT(n != 0, ("ilog argument must be nonzero")); return (8 * sizeof(n) - 1 - __builtin_clz((u_int)n)); } static __inline __pure2 int ilog2_long(long n) { KASSERT(n != 0, ("ilog argument must be nonzero")); return (8 * sizeof(n) - 1 - __builtin_clzl((u_long)n)); } static __inline __pure2 int ilog2_long_long(long long n) { KASSERT(n != 0, ("ilog argument must be nonzero")); return (8 * sizeof(n) - 1 - __builtin_clzll((unsigned long long)n)); } #define ilog2_var(n) \ _Generic((n), \ default: ilog2_int, \ long: ilog2_long, \ unsigned long: ilog2_long, \ long long: ilog2_long_long, \ unsigned long long: ilog2_long_long \ )(n) #define ilog2_const(n) \ (8 * (int)sizeof(unsigned long long) - 1 - \ __builtin_clzll(n)) #define ilog2(n) (__builtin_constant_p(n) ? ilog2_const(n) : ilog2_var(n)) #define rounddown_pow_of_two(n) ((__typeof(n))1 << ilog2(n)) #define order_base_2(n) ({ \ __typeof(n) _n = (n); \ _n == 1 ? 0 : 1 + ilog2(_n - 1); \ }) #define roundup_pow_of_two(n) ((__typeof(n))1 << order_base_2(n)) #define bitcount64(x) __bitcount64((uint64_t)(x)) #define bitcount32(x) __bitcount32((uint32_t)(x)) #define bitcount16(x) __bitcount16((uint16_t)(x)) #define bitcountl(x) __bitcountl((u_long)(x)) #define bitcount(x) __bitcount((u_int)(x)) int fnmatch(const char *, const char *, int); int locc(int, char *, u_int); void *memchr(const void *s, int c, size_t n); void *memcchr(const void *s, int c, size_t n); void *memmem(const void *l, size_t l_len, const void *s, size_t s_len); void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *thunk); u_long random(void); int scanc(u_int, const u_char *, const u_char *, int); int strcasecmp(const char *, const char *); char *strcasestr(const char *, const char *); char *strcat(char * __restrict, const char * __restrict); char *strchr(const char *, int); char *strchrnul(const char *, int); int strcmp(const char *, const char *); char *strcpy(char * __restrict, const char * __restrict); char *strdup_flags(const char *__restrict, struct malloc_type *, int); size_t strcspn(const char *, const char *) __pure; char *strdup(const char *__restrict, struct malloc_type *); char *strncat(char *, const char *, size_t); char *strndup(const char *__restrict, size_t, struct malloc_type *); size_t strlcat(char *, const char *, size_t); size_t strlcpy(char *, const char *, size_t); size_t strlen(const char *); int strncasecmp(const char *, const char *, size_t); int strncmp(const char *, const char *, size_t); char *strncpy(char * __restrict, const char * __restrict, size_t); size_t strnlen(const char *, size_t); char *strnstr(const char *, const char *, size_t); char *strrchr(const char *, int); char *strsep(char **, const char *delim); size_t strspn(const char *, const char *); char *strstr(const char *, const char *); int strvalid(const char *, size_t); #ifdef SAN_NEEDS_INTERCEPTORS #ifndef SAN_INTERCEPTOR #define SAN_INTERCEPTOR(func) \ __CONCAT(SAN_INTERCEPTOR_PREFIX, __CONCAT(_, func)) #endif char *SAN_INTERCEPTOR(strcpy)(char *, const char *); int SAN_INTERCEPTOR(strcmp)(const char *, const char *); size_t SAN_INTERCEPTOR(strlen)(const char *); #ifndef SAN_RUNTIME #define strcpy(d, s) SAN_INTERCEPTOR(strcpy)((d), (s)) #define strcmp(s1, s2) SAN_INTERCEPTOR(strcmp)((s1), (s2)) #define strlen(s) SAN_INTERCEPTOR(strlen)(s) #endif /* !SAN_RUNTIME */ #else /* !SAN_NEEDS_INTERCEPTORS */ #define strcpy(d, s) __builtin_strcpy((d), (s)) #define strcmp(s1, s2) __builtin_strcmp((s1), (s2)) #define strlen(s) __builtin_strlen((s)) #endif /* SAN_NEEDS_INTERCEPTORS */ static __inline char * index(const char *p, int ch) { return (strchr(p, ch)); } static __inline char * rindex(const char *p, int ch) { return (strrchr(p, ch)); } static __inline int64_t signed_extend64(uint64_t bitmap, int lsb, int width) { return ((int64_t)(bitmap << (63 - lsb - (width - 1)))) >> (63 - (width - 1)); } static __inline int32_t signed_extend32(uint32_t bitmap, int lsb, int width) { return ((int32_t)(bitmap << (31 - lsb - (width - 1)))) >> (31 - (width - 1)); } /* fnmatch() return values. */ #define FNM_NOMATCH 1 /* Match failed. */ /* fnmatch() flags. */ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ #define FNM_PERIOD 0x04 /* Period must be matched by period. */ #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ #define FNM_IGNORECASE FNM_CASEFOLD #define FNM_FILE_NAME FNM_PATHNAME +#if __has_include() +#include /* __ssp_real */ +#else +#define __ssp_real(fun) fun +#endif + #endif /* !_SYS_LIBKERN_H_ */