2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 01:49:11 +00:00

Add regress for mkdtemp and mkstemps from OpenBSD

This commit is contained in:
Todd C. Miller 2015-02-20 14:37:02 -07:00
parent bd8eebd6f7
commit 49128a79e3
7 changed files with 231 additions and 8 deletions

View File

@ -119,6 +119,7 @@ lib/util/regress/fnmatch/fnm_test.in
lib/util/regress/glob/files lib/util/regress/glob/files
lib/util/regress/glob/globtest.c lib/util/regress/glob/globtest.c
lib/util/regress/glob/globtest.in lib/util/regress/glob/globtest.in
lib/util/regress/mktemp/mktemp_test.c
lib/util/regress/progname/progname_test.c lib/util/regress/progname/progname_test.c
lib/util/regress/sudo_conf/conf_test.c lib/util/regress/sudo_conf/conf_test.c
lib/util/regress/sudo_conf/test1.in lib/util/regress/sudo_conf/test1.in

1
configure vendored
View File

@ -19651,6 +19651,7 @@ esac
" "
done done
COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }mktemp_test"
fi fi
for ac_func in snprintf vsnprintf for ac_func in snprintf vsnprintf
do : do :

View File

@ -2571,6 +2571,7 @@ if test X"$ac_cv_func_mkstemps$ac_cv_func_mkdtemp" != X"yesyes"; then
AC_LIBOBJ(mktemp) AC_LIBOBJ(mktemp)
# If either mkdtemp() or mkstemps() is missing, replace both. # If either mkdtemp() or mkstemps() is missing, replace both.
SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkstemps) SUDO_APPEND_COMPAT_EXP(sudo_mkdtemp sudo_mkstemps)
COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }mktemp_test"
fi fi
AX_FUNC_SNPRINTF AX_FUNC_SNPRINTF
if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"; then if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"; then

View File

@ -103,6 +103,8 @@ LTOBJS = alloc.lo event.lo fatal.lo key_val.lo gethostname.lo gidlist.lo \
ATOFOO_TEST_OBJS = atofoo_test.lo locale_stub.lo ATOFOO_TEST_OBJS = atofoo_test.lo locale_stub.lo
MKTEMP_TEST_OBJS = mktemp_test.lo locale_stub.lo
PARSELN_TEST_OBJS = parseln_test.lo locale_stub.lo PARSELN_TEST_OBJS = parseln_test.lo locale_stub.lo
PROGNAME_TEST_OBJS = progname_test.lo progname.lo PROGNAME_TEST_OBJS = progname_test.lo progname.lo
@ -176,6 +178,9 @@ globtest: $(GLOBTEST_OBJS) libsudo_util.la
hltq_test: $(HLTQ_TEST_OBJS) libsudo_util.la hltq_test: $(HLTQ_TEST_OBJS) libsudo_util.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libsudo_util.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) $(LIBTOOL) --mode=link $(CC) -o $@ $(HLTQ_TEST_OBJS) libsudo_util.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
mktemp_test: $(MKTEMP_TEST_OBJS) libsudo_util.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(MKTEMP_TEST_OBJS) libsudo_util.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
parseln_test: $(PARSELN_TEST_OBJS) libsudo_util.la parseln_test: $(PARSELN_TEST_OBJS) libsudo_util.la
$(LIBTOOL) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libsudo_util.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) $(LIBTOOL) --mode=link $(CC) -o $@ $(PARSELN_TEST_OBJS) libsudo_util.la $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
@ -225,6 +230,9 @@ check: $(TEST_PROGS)
./globtest $(srcdir)/regress/glob/globtest.in || rval=`expr $$rval + $$?`; \ ./globtest $(srcdir)/regress/glob/globtest.in || rval=`expr $$rval + $$?`; \
rm -rf fake; \ rm -rf fake; \
fi; \ fi; \
if test -f mktemp_test; then \
./mktemp_test || rval=`expr $$rval + $$?`; \
fi; \
./atofoo_test || rval=`expr $$rval + $$?`; \ ./atofoo_test || rval=`expr $$rval + $$?`; \
./hltq_test || rval=`expr $$rval + $$?`; \ ./hltq_test || rval=`expr $$rval + $$?`; \
./progname_test || rval=`expr $$rval + $$?`; \ ./progname_test || rval=`expr $$rval + $$?`; \
@ -347,7 +355,6 @@ fatal.lo: $(srcdir)/fatal.c $(incdir)/compat/stdbool.h $(incdir)/sudo_alloc.h \
fnm_test.lo: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \ fnm_test.lo: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \
$(incdir)/sudo_compat.h $(top_builddir)/config.h $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/fnmatch/fnm_test.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/fnmatch/fnm_test.c
fnm_test.o: fnm_test.lo
fnmatch.lo: $(srcdir)/fnmatch.c $(incdir)/compat/charclass.h \ fnmatch.lo: $(srcdir)/fnmatch.c $(incdir)/compat/charclass.h \
$(incdir)/compat/fnmatch.h $(incdir)/sudo_compat.h \ $(incdir)/compat/fnmatch.h $(incdir)/sudo_compat.h \
$(top_builddir)/config.h $(top_builddir)/config.h
@ -383,12 +390,14 @@ glob.lo: $(srcdir)/glob.c $(incdir)/compat/charclass.h $(incdir)/compat/glob.h \
globtest.lo: $(srcdir)/regress/glob/globtest.c $(incdir)/compat/glob.h \ globtest.lo: $(srcdir)/regress/glob/globtest.c $(incdir)/compat/glob.h \
$(incdir)/sudo_compat.h $(top_builddir)/config.h $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/glob/globtest.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/glob/globtest.c
globtest.o: globtest.lo
hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(incdir)/compat/stdbool.h \ hltq_test.lo: $(srcdir)/regress/tailq/hltq_test.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_fatal.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/tailq/hltq_test.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/tailq/hltq_test.c
inet_pton.lo: $(srcdir)/inet_pton.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/inet_pton.c
isblank.lo: $(srcdir)/isblank.c $(incdir)/sudo_compat.h $(top_builddir)/config.h isblank.lo: $(srcdir)/isblank.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/isblank.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/isblank.c
key_val.lo: $(srcdir)/key_val.c $(incdir)/compat/stdbool.h \ key_val.lo: $(srcdir)/key_val.c $(incdir)/compat/stdbool.h \
@ -426,6 +435,11 @@ mksigname.lo: $(srcdir)/mksigname.c $(incdir)/sudo_compat.h \
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/mksigname.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/mksigname.c
mktemp.lo: $(srcdir)/mktemp.c $(incdir)/sudo_compat.h $(top_builddir)/config.h mktemp.lo: $(srcdir)/mktemp.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/mktemp.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/mktemp.c
mktemp_test.lo: $(srcdir)/regress/mktemp/mktemp_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/regress/mktemp/mktemp_test.c
parseln.lo: $(srcdir)/parseln.c $(incdir)/compat/stdbool.h \ parseln.lo: $(srcdir)/parseln.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2003, 2004, 2008-2011, 2013, 2014 * Copyright (c) 2001, 2003, 2004, 2008-2011, 2013, 2015
* Todd C. Miller <Todd.Miller@courtesan.com> * Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@ -30,6 +30,12 @@
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
# include <stdlib.h> # include <stdlib.h>
#endif /* HAVE_STDLIB_H */ #endif /* HAVE_STDLIB_H */
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <ctype.h> #include <ctype.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
@ -45,6 +51,7 @@
#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
#define NUM_CHARS (sizeof(TEMPCHARS) - 1) #define NUM_CHARS (sizeof(TEMPCHARS) - 1)
#define MIN_X 6
#ifndef INT_MAX #ifndef INT_MAX
#define INT_MAX 0x7fffffff #define INT_MAX 0x7fffffff
@ -122,15 +129,15 @@ mktemp_internal(char *path, int slen, int mode)
char *start, *cp, *ep; char *start, *cp, *ep;
const char tempchars[] = TEMPCHARS; const char tempchars[] = TEMPCHARS;
unsigned int r, tries; unsigned int r, tries;
size_t len;
int fd; int fd;
for (ep = path; *ep; ep++) len = strlen(path);
; if (len < MIN_X || slen < 0 || (size_t)slen > len - MIN_X) {
if (path + slen >= ep) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ep -= slen; ep = path + len - slen;
tries = 1; tries = 1;
for (start = ep; start > path && start[-1] == 'X'; start--) { for (start = ep; start > path && start[-1] == 'X'; start--) {
@ -138,6 +145,10 @@ mktemp_internal(char *path, int slen, int mode)
tries *= NUM_CHARS; tries *= NUM_CHARS;
} }
tries *= 2; tries *= 2;
if (ep - start < MIN_X) {
errno = EINVAL;
return -1;
}
do { do {
for (cp = start; cp != ep; cp++) { for (cp = start; cp != ep; cp++) {

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2010 Philip Guenther <guenther@openbsd.org>
*
* Public domain.
*
* Verify that mkdtemp() and mkstemps() doesn't overrun or underrun
* the template buffer and that it can generate names that don't
* contain any X's
*/
#include <config.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <unistd.h>
#define SUDO_ERROR_WRAP 0
#include "sudo_compat.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#ifndef MAP_ANON
# if defined(MAP_ANONYMOUS)
# define MAP_ANON MAP_ANONYMOUS
# endif
#endif
#define MAX_TEMPLATE_LEN 10
#define MAX_TRIES 100
#define MIN_Xs 6
#define SUFFIX ".suff"
#define SLEN (sizeof SUFFIX - 1)
__dso_public int main(int argc, char *argv[]);
/*
* verify that a path generated by mkdtemp() or mkstemp() looks like a
* reasonable expansion of the template and matches the fd. Returns true
* if all the X's were replaced with non-X's
*/
int
check(int fd, char const *kind, char const *path, char const *prefix,
size_t plen, char const *suffix, size_t slen, int tlen)
{
struct stat sb, fsb;
char const *p;
if (tlen < MIN_Xs) {
if (fd != -1)
sudo_fatalx("%s(%s) succeed with too few Xs", kind, path);
if (errno != EINVAL)
sudo_fatal("%s(%s) failed with wrong errno: %d", kind, path, errno);
return 1;
}
if (fd == -1)
sudo_fatal("%s(%s)", kind, path);
if (stat(path, &sb))
sudo_fatal("%s: stat(%s)", kind, path);
if (fd >= 0) {
if (fstat(fd, &fsb))
sudo_fatal("%s: fstat(%d==%s)", kind, fd, path);
if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino)
sudo_fatalx("%s: stat mismatch", kind);
}
if (memcmp(path, prefix, plen) != 0)
sudo_fatalx("%s: prefix changed! %s vs %s", kind, prefix, path);
if (memcmp(path + plen + tlen, suffix, slen + 1) != 0)
sudo_fatalx("%s: suffix changed! %s vs %s", kind, suffix, path);
for (p = path + plen; p < path + plen + tlen; p++)
if (*p == '\0')
sudo_fatalx("%s: unexpected truncation", kind);
else if (*p == 'X')
return 0;
return 1;
}
void
try_mkdtemp(char *p, char const *prefix, int len)
{
size_t plen = strlen(prefix);
int fd, tries, ok;
for (tries = 0; tries < MAX_TRIES; tries++) {
memcpy(p, prefix, plen);
memset(p + plen, 'X', len);
p[plen + len] = '\0';
fd = mkdtemp(p) ? -2 : -1;
ok = check(fd, "mkdtemp", p, prefix, plen, "", 0, len);
rmdir(p);
if (ok)
return;
}
sudo_fatalx("mkdtemp: exceeded MAX_TRIES");
}
void
try_mkstemps(char *p, char const *prefix, int len, char const *suffix)
{
size_t plen = strlen(prefix);
size_t slen = strlen(suffix);
int tries, fd, ok;
for (tries = 0; tries < MAX_TRIES; tries++) {
memcpy(p, prefix, plen);
memset(p + plen, 'X', len);
memcpy(p + plen + len, suffix, slen + 1);
fd = mkstemps(p, slen);
ok = check(fd, "mkstemp", p, prefix, plen, suffix, slen, len);
close(fd);
unlink(p);
if (ok)
return;
}
sudo_fatalx("mkstemps: exceeded MAX_TRIES");
}
int
main(int argc, char *argv[])
{
char cwd[PATH_MAX + 1];
char *p;
size_t clen;
long pg;
int i;
initprogname(argc > 0 ? argv[0] : "mktemp_test");
pg = sysconf(_SC_PAGESIZE);
if (getcwd(cwd, sizeof cwd - 1) == NULL)
sudo_fatal("getcwd");
clen = strlen(cwd);
cwd[clen++] = '/';
cwd[clen] = '\0';
#ifdef MAP_ANON
p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
#else
i = open("/dev/zero", O_RDWR);
if (i == -1)
sudo_fatal("/dev/zero");
p = mmap(NULL, pg * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE, i, 0);
#endif
if (p == MAP_FAILED)
sudo_fatal("mmap");
if (mprotect(p, pg, PROT_NONE) || mprotect(p + pg * 2, pg, PROT_NONE))
sudo_fatal("mprotect");
p += pg;
i = MAX_TEMPLATE_LEN + 1;
while (i-- > 0) {
/* try first at the start of a page, no prefix */
try_mkdtemp(p, "", i);
/* now at the end of the page, no prefix */
try_mkdtemp(p + pg - i - 1, "", i);
/* start of the page, prefixed with the cwd */
try_mkdtemp(p, cwd, i);
/* how about at the end of the page, prefixed with cwd? */
try_mkdtemp(p + pg - clen - i - 1, cwd, i);
/* again, with mkstemps() and an empty suffix */
/* try first at the start of a page, no prefix */
try_mkstemps(p, "", i, "");
/* now at the end of the page, no prefix */
try_mkstemps(p + pg - i - 1, "", i, "");
/* start of the page, prefixed with the cwd */
try_mkstemps(p, cwd, i, "");
/* how about at the end of the page, prefixed with cwd? */
try_mkstemps(p + pg - clen - i - 1, cwd, i, "");
/* mkstemps() and a non-empty suffix */
/* try first at the start of a page, no prefix */
try_mkstemps(p, "", i, SUFFIX);
/* now at the end of the page, no prefix */
try_mkstemps(p + pg - i - SLEN - 1, "", i, SUFFIX);
/* start of the page, prefixed with the cwd */
try_mkstemps(p, cwd, i, SUFFIX);
/* how about at the end of the page, prefixed with cwd? */
try_mkstemps(p + pg - clen - i - SLEN - 1, cwd, i, SUFFIX);
}
return 0;
}

View File

@ -70,7 +70,7 @@ sub mkdep {
$makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo solaris_audit.lo sssd.lo:; $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo solaris_audit.lo sssd.lo:;
# XXX - fill in AUTH_OBJS from contents of the auth dir instead # XXX - fill in AUTH_OBJS from contents of the auth dir instead
$makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
$makefile =~ s:\@LTLIBOBJS\@:clock_gettime.lo closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo strtonum.lo utimes.lo globtest.o fnm_test.o inet_pton:; $makefile =~ s:\@LTLIBOBJS\@:clock_gettime.lo closefrom.lo fnmatch.lo getaddrinfo.lo getcwd.lo getgrouplist.lo getline.lo getopt_long.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo pw_dup.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo strtonum.lo utimes.lo:;
# Parse OBJS lines # Parse OBJS lines
my %objs; my %objs;