From d4739533fd055a59b1a68094e59ade2f635bdf21 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 18 Jun 2020 15:14:00 -0600 Subject: [PATCH] Add regress test to catch swapids() bug when called by iolog_mkdtemp() --- MANIFEST | 1 + lib/iolog/Makefile.in | 28 +++++- .../regress/iolog_mkpath/check_iolog_mkpath.c | 91 +++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c diff --git a/MANIFEST b/MANIFEST index e4851ce9a..23e0d9e63 100644 --- a/MANIFEST +++ b/MANIFEST @@ -115,6 +115,7 @@ lib/iolog/regress/iolog_json/test1.in lib/iolog/regress/iolog_json/test2.in lib/iolog/regress/iolog_json/test2.out.ok lib/iolog/regress/iolog_json/test3.in +lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c lib/iolog/regress/iolog_path/check_iolog_path.c lib/iolog/regress/iolog_path/data lib/iolog/regress/iolog_util/check_iolog_util.c diff --git a/lib/iolog/Makefile.in b/lib/iolog/Makefile.in index e7cd14711..b8979251e 100644 --- a/lib/iolog/Makefile.in +++ b/lib/iolog/Makefile.in @@ -75,7 +75,7 @@ PVS_IGNORE = 'V707,V011,V002,V536' PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE) # Regression tests -TEST_PROGS = check_iolog_json check_iolog_path check_iolog_util host_port_test +TEST_PROGS = check_iolog_json check_iolog_mkpath check_iolog_path check_iolog_util host_port_test TEST_LIBS = @LIBS@ TEST_LDFLAGS = @LDFLAGS@ @@ -93,6 +93,8 @@ IOBJS = $(LIBIOLOG_OBJS:.lo=.i) POBJS = $(IOBJS:.i=.plog) +CHECK_IOLOG_MKPATH_OBJS = check_iolog_mkpath.lo iolog_fileio.lo + CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo iolog_path.lo CHECK_IOLOG_UTIL_OBJS = check_iolog_util.lo iolog_json.lo iolog_util.lo @@ -133,6 +135,9 @@ libsudo_iolog.la: $(LIBIOLOG_OBJS) check_iolog_path: $(CHECK_IOLOG_PATH_OBJS) libsudo_iolog.la $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) +check_iolog_mkpath: $(CHECK_IOLOG_MKPATH_OBJS) libsudo_iolog.la + $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_MKPATH_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) + check_iolog_util: $(CHECK_IOLOG_UTIL_OBJS) libsudo_iolog.la $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_UTIL_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS) @@ -171,6 +176,7 @@ check: $(TEST_PROGS) rval=0; \ ./check_iolog_json $(srcdir)/regress/iolog_json/*.in || rval=`expr $$rval + $$?`; \ ./check_iolog_path $(srcdir)/regress/iolog_path/data || rval=`expr $$rval + $$?`; \ + ./check_iolog_mkpath || rval=`expr $$rval + $$?`; \ ./check_iolog_util || rval=`expr $$rval + $$?`; \ ./host_port_test || rval=`expr $$rval + $$?`; \ exit $$rval; \ @@ -208,6 +214,18 @@ check_iolog_json.i: $(srcdir)/regress/iolog_json/check_iolog_json.c \ $(CC) -E -o $@ $(CPPFLAGS) $< check_iolog_json.plog: check_iolog_json.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_json/check_iolog_json.c --i-file $< --output-file $@ +check_iolog_mkpath.lo: $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c +check_iolog_mkpath.i: $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c \ + $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ + $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h + $(CC) -E -o $@ $(CPPFLAGS) $< +check_iolog_mkpath.plog: check_iolog_mkpath.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_mkpath/check_iolog_mkpath.c --i-file $< --output-file $@ check_iolog_path.lo: $(srcdir)/regress/iolog_path/check_iolog_path.c \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \ @@ -246,13 +264,13 @@ host_port.plog: host_port.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/host_port.c --i-file $< --output-file $@ host_port_test.lo: $(srcdir)/regress/host_port/host_port_test.c \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ - $(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \ - $(top_builddir)/config.h + $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/host_port/host_port_test.c host_port_test.i: $(srcdir)/regress/host_port/host_port_test.c \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ - $(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \ - $(top_builddir)/config.h + $(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \ + $(incdir)/sudo_util.h $(top_builddir)/config.h $(CC) -E -o $@ $(CPPFLAGS) $< host_port_test.plog: host_port_test.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/host_port/host_port_test.c --i-file $< --output-file $@ diff --git a/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c b/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c new file mode 100644 index 000000000..70be07e72 --- /dev/null +++ b/lib/iolog/regress/iolog_mkpath/check_iolog_mkpath.c @@ -0,0 +1,91 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2020 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#define SUDO_ERROR_WRAP 0 + +#include "sudo_compat.h" +#include "sudo_util.h" +#include "sudo_fatal.h" +#include "sudo_iolog.h" + +__dso_public int main(int argc, char *argv[]); + +static const char *test_paths[] = { + "testdir/a/b/c/user", /* create new */ + "testdir/a/b/c/user", /* open existing */ + "testdir/a/b/c/user.XXXXXX", /* mkdtemp new */ + NULL +}; + +static void +test_iolog_mkpath(const char *testdir, int *ntests, int *nerrors) +{ + const char **tp; + char *path; + + iolog_set_owner(geteuid(), getegid()); + + for (tp = test_paths; *tp != NULL; tp++) { + if (asprintf(&path, "%s/%s", testdir, *tp) == -1) + sudo_fatalx("unable to allocate memory"); + + (*ntests)++; + if (!iolog_mkpath(path)) { + sudo_warnx("unable to mkpath %s", path); + (*nerrors)++; + } + free(path); + } +} + +int +main(int argc, char *argv[]) +{ + char testdir[] = "mkpath.XXXXXX"; + char *rmargs[] = { "rm", "-rf", NULL, NULL }; + int status, tests = 0, errors = 0; + + initprogname(argc > 0 ? argv[0] : "check_iolog_mkpath"); + + if (mkdtemp(testdir) == NULL) + sudo_fatal("unable to create test dir"); + rmargs[2] = testdir; + + test_iolog_mkpath(testdir, &tests, &errors); + + if (tests != 0) { + printf("iolog_mkpath: %d test%s run, %d errors, %d%% success rate\n", + tests, tests == 1 ? "" : "s", errors, + (tests - errors) * 100 / tests); + } + + /* Clean up (avoid running via shell) */ + execvp("rm", rmargs); + wait(&status); + + exit(errors); +}