Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131555538
D45679.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
113 KB
Referenced Files
None
Subscribers
None
D45679.diff
View Options
diff --git a/include/ssp/ssp.h b/include/ssp/ssp.h
--- a/include/ssp/ssp.h
+++ b/include/ssp/ssp.h
@@ -67,21 +67,25 @@
#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 <machine/_stdint.h>
diff --git a/include/ssp/stdio.h b/include/ssp/stdio.h
--- a/include/ssp/stdio.h
+++ b/include/ssp/stdio.h
@@ -37,6 +37,24 @@
#include <ssp/ssp.h>
__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,
diff --git a/include/ssp/string.h b/include/ssp/string.h
--- a/include/ssp/string.h
+++ b/include/ssp/string.h
@@ -45,7 +45,9 @@
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
@@ -110,8 +112,24 @@
__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)
@@ -122,7 +140,11 @@
#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 */
diff --git a/include/ssp/strings.h b/include/ssp/strings.h
--- a/include/ssp/strings.h
+++ b/include/ssp/strings.h
@@ -63,5 +63,10 @@
#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
--- a/include/ssp/unistd.h
+++ b/include/ssp/unistd.h
@@ -43,14 +43,46 @@
#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
diff --git a/include/stdio.h b/include/stdio.h
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -238,6 +238,21 @@
#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 <ssp/stdio.h>
+#endif
+
__BEGIN_DECLS
#ifdef _XLOCALE_H_
#include <xlocale/_stdio.h>
@@ -252,7 +267,7 @@
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 *);
@@ -280,7 +295,7 @@
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 *);
@@ -288,13 +303,13 @@
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
@@ -305,16 +320,7 @@
__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 *);
@@ -530,7 +536,4 @@
__END_DECLS
__NULLABILITY_PRAGMA_POP
-#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#include <ssp/stdio.h>
-#endif
#endif /* !_STDIO_H_ */
diff --git a/include/string.h b/include/string.h
--- a/include/string.h
+++ b/include/string.h
@@ -49,6 +49,10 @@
#define _SIZE_T_DECLARED
#endif
+#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+#include <ssp/string.h>
+#endif
+
__BEGIN_DECLS
#if __XSI_VISIBLE >= 600
void *memccpy(void * __restrict, const void * __restrict, int, size_t);
@@ -58,23 +62,23 @@
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;
@@ -82,7 +86,7 @@
#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;
@@ -92,8 +96,8 @@
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
@@ -105,9 +109,9 @@
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;
@@ -168,7 +172,4 @@
#endif /* __EXT1_VISIBLE */
__END_DECLS
-#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#include <ssp/string.h>
-#endif
#endif /* _STRING_H_ */
diff --git a/include/strings.h b/include/strings.h
--- a/include/strings.h
+++ b/include/strings.h
@@ -37,11 +37,15 @@
#define _SIZE_T_DECLARED
#endif
+#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+#include <ssp/strings.h>
+#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);
@@ -68,7 +72,4 @@
#endif
__END_DECLS
-#if !defined(_STANDALONE) && defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#include <ssp/strings.h>
-#endif
#endif /* _STRINGS_H_ */
diff --git a/lib/libc/amd64/string/strlcat.c b/lib/libc/amd64/string/strlcat.c
--- a/lib/libc/amd64/string/strlcat.c
+++ b/lib/libc/amd64/string/strlcat.c
@@ -8,6 +8,8 @@
#include <string.h>
+#undef strlcat /* FORTIFY_SOURCE */
+
void *__memchr(const void *, int, size_t);
size_t __strlcpy(char *restrict, const char *restrict, size_t);
diff --git a/lib/libc/gen/ctermid.c b/lib/libc/gen/ctermid.c
--- a/lib/libc/gen/ctermid.c
+++ b/lib/libc/gen/ctermid.c
@@ -34,11 +34,12 @@
#include <paths.h>
#include <stdio.h>
#include <string.h>
+#include <ssp/ssp.h>
#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;
@@ -62,7 +63,7 @@
}
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
--- a/lib/libc/gen/getdomainname.c
+++ b/lib/libc/gen/getdomainname.c
@@ -33,9 +33,10 @@
#include <sys/sysctl.h>
#include <unistd.h>
+#include <ssp/ssp.h>
int
-getdomainname(char *name, int namelen)
+__ssp_real(getdomainname)(char *name, int namelen)
{
int mib[2];
size_t size;
diff --git a/lib/libc/gen/getentropy.c b/lib/libc/gen/getentropy.c
--- a/lib/libc/gen/getentropy.c
+++ b/lib/libc/gen/getentropy.c
@@ -35,6 +35,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
+#include <ssp/ssp.h>
#include "libc_private.h"
@@ -105,7 +106,7 @@
}
int
-getentropy(void *buf, size_t buflen)
+__ssp_real(getentropy)(void *buf, size_t buflen)
{
ssize_t rd;
bool have_getrandom;
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
--- a/lib/libc/gen/getgrouplist.c
+++ b/lib/libc/gen/getgrouplist.c
@@ -37,11 +37,12 @@
#include <grp.h>
#include <string.h>
#include <unistd.h>
+#include <ssp/ssp.h>
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
--- a/lib/libc/gen/gethostname.c
+++ b/lib/libc/gen/gethostname.c
@@ -34,9 +34,10 @@
#include <errno.h>
#include <unistd.h>
+#include <ssp/ssp.h>
int
-gethostname(char *name, size_t namelen)
+__ssp_real(gethostname)(char *name, size_t namelen)
{
int mib[2];
diff --git a/lib/libc/gen/getlogin.c b/lib/libc/gen/getlogin.c
--- a/lib/libc/gen/getlogin.c
+++ b/lib/libc/gen/getlogin.c
@@ -37,6 +37,7 @@
#include <unistd.h>
#include "namespace.h"
#include <pthread.h>
+#include <ssp/ssp.h>
#include "un-namespace.h"
#include "libc_private.h"
@@ -54,7 +55,7 @@
}
int
-getlogin_r(char *logname, size_t namelen)
+__ssp_real(getlogin_r)(char *logname, size_t namelen)
{
char tmpname[MAXLOGNAME];
int len;
diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c
--- a/lib/libc/gen/ttyname.c
+++ b/lib/libc/gen/ttyname.c
@@ -42,6 +42,7 @@
#include <paths.h>
#include <errno.h>
#include "reentrant.h"
+#include <ssp/ssp.h>
#include "un-namespace.h"
#include "libc_private.h"
@@ -53,7 +54,7 @@
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;
diff --git a/lib/libc/secure/Makefile.inc b/lib/libc/secure/Makefile.inc
--- a/lib/libc/secure/Makefile.inc
+++ b/lib/libc/secure/Makefile.inc
@@ -6,8 +6,8 @@
# _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
diff --git a/lib/libc/secure/Symbol.map b/lib/libc/secure/Symbol.map
--- a/lib/libc/secure/Symbol.map
+++ b/lib/libc/secure/Symbol.map
@@ -15,7 +15,9 @@
__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
copy from lib/libc/string/strlcat.c
copy to lib/libc/secure/strlcat_chk.c
--- a/lib/libc/string/strlcat.c
+++ b/lib/libc/secure/strlcat_chk.c
@@ -1,6 +1,8 @@
/* $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 <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -16,9 +18,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/types.h>
+#include <stdio.h>
#include <string.h>
+#include <ssp/string.h>
+
/*
* 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
@@ -27,29 +31,40 @@
* 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
copy from include/ssp/unistd.h
copy to lib/libc/secure/strlcpy_chk.c
--- a/include/ssp/unistd.h
+++ b/lib/libc/secure/strlcpy_chk.c
@@ -1,14 +1,7 @@
-/* $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
@@ -31,28 +24,20 @@
* 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 <ssp/ssp.h>
-
-#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 <sys/types.h>
+#include <string.h>
-__ssp_redirect(ssize_t, readlink, (const char *__restrict __path, \
- char *__restrict __buf, size_t __len), (__path, __buf, __len));
+#include <ssp/string.h>
+#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
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -37,6 +37,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <ssp/ssp.h>
#include "un-namespace.h"
#include "local.h"
#include "libc_private.h"
@@ -46,7 +47,8 @@
*/
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;
diff --git a/lib/libc/stdio/gets_s.c b/lib/libc/stdio/gets_s.c
--- a/lib/libc/stdio/gets_s.c
+++ b/lib/libc/stdio/gets_s.c
@@ -39,6 +39,7 @@
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
+#include <ssp/ssp.h>
#include "un-namespace.h"
#include "libc_private.h"
#include "local.h"
@@ -77,7 +78,7 @@
/* 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) {
diff --git a/lib/libc/stdio/tmpnam.c b/lib/libc/stdio/tmpnam.c
--- a/lib/libc/stdio/tmpnam.c
+++ b/lib/libc/stdio/tmpnam.c
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <unistd.h>
+#include <ssp/ssp.h>
__warn_references(tmpnam,
"warning: tmpnam() possibly used unsafely; consider using mkstemp()");
@@ -43,7 +44,7 @@
extern char *_mktemp(char *);
char *
-tmpnam(char *s)
+__ssp_real(tmpnam)(char *s)
{
static u_long tmpcount;
static char buf[L_tmpnam];
diff --git a/lib/libc/string/mempcpy.c b/lib/libc/string/mempcpy.c
--- a/lib/libc/string/mempcpy.c
+++ b/lib/libc/string/mempcpy.c
@@ -29,9 +29,11 @@
*/
#include <string.h>
+#include <ssp/ssp.h>
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
--- a/lib/libc/string/strerror.c
+++ b/lib/libc/string/strerror.c
@@ -38,6 +38,8 @@
#include <string.h>
#include <stdio.h>
+#include <ssp/ssp.h>
+
#include "errlst.h"
#include "../locale/xlocale_private.h"
#include "libc_private.h"
@@ -114,7 +116,7 @@
}
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()));
}
diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c
--- a/lib/libc/string/strlcat.c
+++ b/lib/libc/string/strlcat.c
@@ -19,6 +19,8 @@
#include <sys/types.h>
#include <string.h>
+#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
diff --git a/lib/libc/string/strlcpy.c b/lib/libc/string/strlcpy.c
--- a/lib/libc/string/strlcpy.c
+++ b/lib/libc/string/strlcpy.c
@@ -19,6 +19,8 @@
#include <sys/types.h>
#include <string.h>
+#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).
diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c
--- a/lib/libc/string/strncpy.c
+++ b/lib/libc/string/strncpy.c
@@ -34,6 +34,8 @@
#include <string.h>
+#undef strncpy /* FORTIFY_SOURCE */
+
/*
* Copy src to dst, truncating or null-padding to always copy n bytes.
* Return dst.
diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c
--- a/lib/libc/tests/secure/fortify_stdio_test.c
+++ b/lib/libc/tests/secure/fortify_stdio_test.c
@@ -20,6 +20,23 @@
#include <unistd.h>
#include <atf-c.h>
+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.
@@ -55,28 +72,700 @@
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);
@@ -367,8 +1056,299 @@
}
+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);
@@ -379,5 +1359,15 @@
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
--- a/lib/libc/tests/secure/fortify_string_test.c
+++ b/lib/libc/tests/secure/fortify_string_test.c
@@ -20,6 +20,23 @@
#include <unistd.h>
#include <atf-c.h>
+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.
@@ -79,6 +96,22 @@
_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)
{
@@ -211,6 +244,138 @@
}
+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)
{
@@ -917,6 +1082,155 @@
}
+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)
{
@@ -1215,6 +1529,155 @@
}
+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)
{
@@ -1371,6 +1834,11 @@
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);
@@ -1396,6 +1864,11 @@
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);
@@ -1406,6 +1879,11 @@
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);
diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c
--- a/lib/libc/tests/secure/fortify_strings_test.c
+++ b/lib/libc/tests/secure/fortify_strings_test.c
@@ -20,6 +20,23 @@
#include <unistd.h>
#include <atf-c.h>
+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.
@@ -79,6 +96,22 @@
_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)
{
@@ -338,6 +371,133 @@
}
+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);
@@ -350,5 +510,10 @@
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
--- a/lib/libc/tests/secure/fortify_unistd_test.c
+++ b/lib/libc/tests/secure/fortify_unistd_test.c
@@ -20,6 +20,23 @@
#include <unistd.h>
#include <atf-c.h>
+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.
@@ -79,6 +96,22 @@
_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)
{
@@ -206,107 +239,228 @@
}
-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);
@@ -316,9 +470,8 @@
/* 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:
@@ -345,8 +498,8 @@
}
-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 {
@@ -357,17 +510,14 @@
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 {
@@ -378,17 +528,14 @@
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 {
@@ -399,18 +546,16 @@
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 {
@@ -421,18 +566,16 @@
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 {
@@ -445,7 +588,6 @@
const size_t __idx __unused = __len - 1;
pid_t __child;
int __status;
- const char *path;
__child = fork();
ATF_REQUIRE(__child >= 0);
@@ -455,9 +597,1279 @@
/* 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:
@@ -491,6 +1903,26 @@
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);
@@ -501,5 +1933,35 @@
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
--- a/lib/libc/tests/secure/generate-fortify-tests.lua
+++ b/lib/libc/tests/secure/generate-fortify-tests.lua
@@ -96,6 +96,10 @@
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);
@@ -130,6 +134,53 @@
local all_tests = {
stdio = {
-- <stdio.h>
+ {
+ 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 = {
@@ -155,6 +206,27 @@
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 = {
-- <string.h>
@@ -168,6 +240,16 @@
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 = {
@@ -220,6 +302,17 @@
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 = {
@@ -242,6 +335,17 @@
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 = {
@@ -274,6 +378,14 @@
},
exclude = excludes_stack_overflow,
},
+ {
+ func = "explicit_bzero",
+ arguments = {
+ "__buf",
+ "__len",
+ },
+ exclude = excludes_stack_overflow,
+ },
},
unistd = {
-- <unistd.h>
@@ -286,6 +398,53 @@
},
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",
@@ -313,6 +472,85 @@
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");
+]]
+ },
},
}
@@ -620,6 +858,23 @@
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.
@@ -679,6 +934,22 @@
_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
diff --git a/lib/libutil/tests/trimdomain-nodomain_test.c b/lib/libutil/tests/trimdomain-nodomain_test.c
--- a/lib/libutil/tests/trimdomain-nodomain_test.c
+++ b/lib/libutil/tests/trimdomain-nodomain_test.c
@@ -32,6 +32,8 @@
#include <string.h>
#include <unistd.h>
+#include <ssp/ssp.h>
+
#define TESTDOMAIN ""
#define TESTHOST "testhost"
#define TESTFQDN "testhost" TESTDOMAIN
@@ -45,7 +47,7 @@
* 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;
diff --git a/lib/libutil/tests/trimdomain_test.c b/lib/libutil/tests/trimdomain_test.c
--- a/lib/libutil/tests/trimdomain_test.c
+++ b/lib/libutil/tests/trimdomain_test.c
@@ -32,6 +32,8 @@
#include <string.h>
#include <unistd.h>
+#include <ssp/ssp.h>
+
#define TESTDOMAIN ".domain.example.com"
#define TESTHOST "testhost"
#define TESTFQDN "testhost" TESTDOMAIN
@@ -45,7 +47,7 @@
* 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;
diff --git a/sys/libkern/explicit_bzero.c b/sys/libkern/explicit_bzero.c
--- a/sys/libkern/explicit_bzero.c
+++ b/sys/libkern/explicit_bzero.c
@@ -9,6 +9,7 @@
#include <sys/libkern.h>
#else
#include <string.h>
+#include <ssp/ssp.h>
#endif /* _KERNEL */
__attribute__((weak)) void __explicit_bzero_hook(void *, size_t);
@@ -19,7 +20,7 @@
}
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
--- a/sys/sys/libkern.h
+++ b/sys/sys/libkern.h
@@ -337,4 +337,10 @@
#define FNM_IGNORECASE FNM_CASEFOLD
#define FNM_FILE_NAME FNM_PATHNAME
+#if __has_include(<ssp/ssp.h>)
+#include <ssp/ssp.h> /* __ssp_real */
+#else
+#define __ssp_real(fun) fun
+#endif
+
#endif /* !_SYS_LIBKERN_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Oct 10, 5:39 AM (21 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23520433
Default Alt Text
D45679.diff (113 KB)
Attached To
Mode
D45679: include: ssp: round out fortification of current set of headers
Attached
Detach File
Event Timeline
Log In to Comment