diff --git a/MANIFEST b/MANIFEST index 300d76bf3..3e4908528 100644 --- a/MANIFEST +++ b/MANIFEST @@ -107,6 +107,7 @@ lib/util/closefrom.c lib/util/digest.c lib/util/digest_gcrypt.c lib/util/digest_openssl.c +lib/util/dup3.c lib/util/event.c lib/util/event_poll.c lib/util/event_select.c diff --git a/config.h.in b/config.h.in index 06acdcae5..536416f88 100644 --- a/config.h.in +++ b/config.h.in @@ -227,6 +227,9 @@ /* Define to 1 if the compiler supports the __visibility__ attribute. */ #undef HAVE_DSO_VISIBILITY +/* Define to 1 if you have the `dup3' function. */ +#undef HAVE_DUP3 + /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H diff --git a/configure b/configure index c9b2c8ddb..1806966b0 100755 --- a/configure +++ b/configure @@ -20560,6 +20560,32 @@ esac done +fi +done + +for ac_func in dup3 +do : + ac_fn_c_check_func "$LINENO" "dup3" "ac_cv_func_dup3" +if test "x$ac_cv_func_dup3" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DUP3 1 +_ACEOF + +else + + case " $LIBOBJS " in + *" dup3.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS dup3.$ac_objext" + ;; +esac + + + for _sym in sudo_dup3; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + fi done diff --git a/configure.ac b/configure.ac index 7c83bedd2..f0912d175 100644 --- a/configure.ac +++ b/configure.ac @@ -2740,6 +2740,10 @@ AC_CHECK_FUNCS([fstatat], [], [ AC_LIBOBJ(fstatat) SUDO_APPEND_COMPAT_EXP(sudo_fstatat) ]) +AC_CHECK_FUNCS([dup3], [], [ + AC_LIBOBJ(dup3) + SUDO_APPEND_COMPAT_EXP(sudo_dup3) +]) AC_CHECK_FUNCS([pipe2], [], [ AC_LIBOBJ(pipe2) SUDO_APPEND_COMPAT_EXP(sudo_pipe2) diff --git a/include/sudo_compat.h b/include/sudo_compat.h index 9e07543d2..e1723657b 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -221,10 +221,12 @@ # endif #endif -/* For pipe2() emulation. */ -#if !defined(HAVE_PIPE2) && defined(O_NONBLOCK) && (!defined(O_CLOEXEC) || O_CLOEXEC > 0xffffffff) -# undef O_CLOEXEC -# define O_CLOEXEC 0x80000000 +/* For dup3() and pipe2() emulation. */ +#if (!defined(HAVE_PIPE2) || !defined(HAVE_DUP3)) && defined(O_NONBLOCK) +# if !defined(O_CLOEXEC) || O_CLOEXEC > 0xffffffff +# undef O_CLOEXEC +# define O_CLOEXEC 0x80000000 +# endif #endif /* @@ -544,6 +546,11 @@ __dso_public void sudo_vsyslog(int pri, const char *fmt, va_list ap); # undef vsyslog # define vsyslog(_a, _b, _c) sudo_vsyslog((_a), (_b), (_c)) #endif /* HAVE_VSYSLOG */ +#ifndef HAVE_DUP3 +__dso_public int sudo_dup3(int oldd, int newd, int flags); +# undef dup3 +# define dup3(_a, _b, _c) sudo_dup3((_a), (_b), (_c)) +#endif /* HAVE_DUP3 */ #ifndef HAVE_PIPE2 __dso_public int sudo_pipe2(int fildes[2], int flags); # undef pipe2 diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in index e9bc0872e..a6fbcb983 100644 --- a/lib/util/Makefile.in +++ b/lib/util/Makefile.in @@ -510,6 +510,12 @@ digest_openssl.i: $(srcdir)/digest_openssl.c $(incdir)/compat/stdbool.h \ $(CC) -E -o $@ $(CPPFLAGS) $< digest_openssl.plog: digest_openssl.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/digest_openssl.c --i-file $< --output-file $@ +dup3.lo: $(srcdir)/dup3.c $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/dup3.c +dup3.i: $(srcdir)/dup3.c $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(CC) -E -o $@ $(CPPFLAGS) $< +dup3.plog: dup3.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/dup3.c --i-file $< --output-file $@ event.lo: $(srcdir)/event.c $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/sudo_debug.h $(incdir)/sudo_event.h $(incdir)/sudo_fatal.h \ $(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h diff --git a/lib/util/dup3.c b/lib/util/dup3.c new file mode 100644 index 000000000..2c44ca040 --- /dev/null +++ b/lib/util/dup3.c @@ -0,0 +1,76 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2013 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. + */ + +/* + * This is an open source non-commercial project. Dear PVS-Studio, please check it. + * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + */ + +#include + +#ifndef HAVE_DUP3 + +#include + +#include +#include +#include + +#include "sudo_compat.h" + +int +sudo_dup3(int oldd, int newd, int flags) +{ + int oflags; + + if (oldd == newd) { + errno = EINVAL; + return -1; + } + + if (dup2(oldd, newd) == -1) + return -1; + + oflags = fcntl(newd, F_GETFL, 0); + if (oflags == -1) + goto bad; + + if (ISSET(flags, O_NONBLOCK)) { + if (!ISSET(oflags, O_NONBLOCK)) { + SET(oflags, O_NONBLOCK); + if (fcntl(newd, F_SETFL, oflags) == -1) + goto bad; + } + } else { + if (ISSET(oflags, O_NONBLOCK)) { + CLR(oflags, O_NONBLOCK); + if (fcntl(newd, F_SETFL, oflags) == -1) + goto bad; + } + } + if (ISSET(flags, O_CLOEXEC)) { + if (fcntl(newd, F_SETFD, FD_CLOEXEC) == -1) + goto bad; + } + return 0; +bad: + close(newd); + return -1; +} + +#endif /* HAVE_DUP3 */ diff --git a/mkdep.pl b/mkdep.pl index cfe5a2f9e..100d1dc14 100755 --- a/mkdep.pl +++ b/mkdep.pl @@ -116,7 +116,7 @@ sub mkdep { # 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:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:; - $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo fchmodat.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.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 nanosleep.lo openat.lo pipe2.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo unlinkat.lo utimens.lo vsyslog.lo:; + $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo dup3.lo fchmodat.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.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 nanosleep.lo openat.lo pipe2.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo unlinkat.lo utimens.lo vsyslog.lo:; # Parse OBJS lines my %objs;