From 06bfbecd64e91153662c02731e7cef9e5a80621d Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 2 Jan 2021 10:43:34 -0700 Subject: [PATCH] Add emulation of pread(3) and pwrite(3) for systems without them. This makes it possible to remove some ugly #ifdefs and only affects very old systems. --- MANIFEST | 2 ++ configure | 58 ++++++++++++++++++++++++++++++++++++++----- configure.ac | 10 +++++++- include/sudo_compat.h | 10 ++++++++ lib/util/Makefile.in | 12 +++++++++ lib/util/pread.c | 48 +++++++++++++++++++++++++++++++++++ lib/util/pwrite.c | 48 +++++++++++++++++++++++++++++++++++ scripts/mkdep.pl | 2 +- 8 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 lib/util/pread.c create mode 100644 lib/util/pwrite.c diff --git a/MANIFEST b/MANIFEST index a04ca9826..623e9c452 100644 --- a/MANIFEST +++ b/MANIFEST @@ -182,8 +182,10 @@ lib/util/nanosleep.c lib/util/openat.c lib/util/parseln.c lib/util/pipe2.c +lib/util/pread.c lib/util/progname.c lib/util/pw_dup.c +lib/util/pwrite.c lib/util/reallocarray.c lib/util/regress/fnmatch/fnm_test.c lib/util/regress/fnmatch/fnm_test.in diff --git a/configure b/configure index 192a22af1..7ea34399a 100755 --- a/configure +++ b/configure @@ -2928,8 +2928,6 @@ as_fn_append ac_header_list " sys/statvfs.h" as_fn_append ac_func_list " fexecve" as_fn_append ac_func_list " killpg" as_fn_append ac_func_list " nl_langinfo" -as_fn_append ac_func_list " pread" -as_fn_append ac_func_list " pwrite" as_fn_append ac_func_list " faccessat" as_fn_append ac_func_list " wordexp" as_fn_append ac_func_list " getauxval" @@ -19437,10 +19435,6 @@ done - - - - case "$host_os" in hpux*) if test X"$ac_cv_func_pread" = X"yes"; then @@ -19466,6 +19460,58 @@ done fi ;; esac +for ac_func in pread +do : + ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread" +if test "x$ac_cv_func_pread" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PREAD 1 +_ACEOF + +else + + case " $LIBOBJS " in + *" pread.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS pread.$ac_objext" + ;; +esac + + + for _sym in sudo_pread; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + +fi +done + +for ac_func in pwrite +do : + ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite" +if test "x$ac_cv_func_pwrite" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PWRITE 1 +_ACEOF + +else + + case " $LIBOBJS " in + *" pwrite.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS pwrite.$ac_objext" + ;; +esac + + + for _sym in sudo_pwrite; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + +fi +done + for ac_func in cfmakeraw do : ac_fn_c_check_func "$LINENO" "cfmakeraw" "ac_cv_func_cfmakeraw" diff --git a/configure.ac b/configure.ac index 8af315d9d..7c1503fdd 100644 --- a/configure.ac +++ b/configure.ac @@ -2641,7 +2641,7 @@ dnl dnl Function checks dnl AC_FUNC_GETGROUPS -AC_CHECK_FUNCS_ONCE([fexecve killpg nl_langinfo pread pwrite faccessat wordexp getauxval fseeko]) +AC_CHECK_FUNCS_ONCE([fexecve killpg nl_langinfo faccessat wordexp getauxval fseeko]) case "$host_os" in hpux*) if test X"$ac_cv_func_pread" = X"yes"; then @@ -2654,6 +2654,14 @@ case "$host_os" in fi ;; esac +AC_CHECK_FUNCS([pread], [], [ + AC_LIBOBJ(pread) + SUDO_APPEND_COMPAT_EXP(sudo_pread) +]) +AC_CHECK_FUNCS([pwrite], [], [ + AC_LIBOBJ(pwrite) + SUDO_APPEND_COMPAT_EXP(sudo_pwrite) +]) AC_CHECK_FUNCS([cfmakeraw], [], [ AC_LIBOBJ(cfmakeraw) SUDO_APPEND_COMPAT_EXP(sudo_cfmakeraw) diff --git a/include/sudo_compat.h b/include/sudo_compat.h index 019a8206e..095dd04d0 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -595,6 +595,16 @@ sudo_dso_public int sudo_pipe2(int fildes[2], int flags); # undef pipe2 # define pipe2(_a, _b) sudo_pipe2((_a), (_b)) #endif /* HAVE_PIPE2 */ +#ifndef HAVE_PREAD +sudo_dso_public int sudo_pread(int fd, void *buf, size_t nbytes, off_t offset); +# undef pread +# define pread(_a, _b, _c, _d) sudo_pread((_a), (_b), (_c), (_d)) +#endif /* HAVE_PREAD */ +#ifndef HAVE_PWRITE +sudo_dso_public int sudo_pwrite(int fd, const void *buf, size_t nbytes, off_t offset); +# undef pwrite +# define pwrite(_a, _b, _c, _d) sudo_pwrite((_a), (_b), (_c), (_d)) +#endif /* HAVE_PWRITE */ #ifndef HAVE_UNLINKAT sudo_dso_public int sudo_unlinkat(int dfd, const char *path, int flag); # undef unlinkat diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in index 7c2200964..a94bfc36b 100644 --- a/lib/util/Makefile.in +++ b/lib/util/Makefile.in @@ -985,6 +985,12 @@ pipe2.i: $(srcdir)/pipe2.c $(incdir)/sudo_compat.h $(top_builddir)/config.h $(CC) -E -o $@ $(CPPFLAGS) $< pipe2.plog: pipe2.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pipe2.c --i-file $< --output-file $@ +pread.lo: $(srcdir)/pread.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)/pread.c +pread.i: $(srcdir)/pread.c $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(CC) -E -o $@ $(CPPFLAGS) $< +pread.plog: pread.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pread.c --i-file $< --output-file $@ progname.lo: $(srcdir)/progname.c $(incdir)/compat/stdbool.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_util.h \ $(top_builddir)/config.h @@ -1011,6 +1017,12 @@ pw_dup.i: $(srcdir)/pw_dup.c $(incdir)/sudo_compat.h $(top_builddir)/config.h $(CC) -E -o $@ $(CPPFLAGS) $< pw_dup.plog: pw_dup.i rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pw_dup.c --i-file $< --output-file $@ +pwrite.lo: $(srcdir)/pwrite.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)/pwrite.c +pwrite.i: $(srcdir)/pwrite.c $(incdir)/sudo_compat.h $(top_builddir)/config.h + $(CC) -E -o $@ $(CPPFLAGS) $< +pwrite.plog: pwrite.i + rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/pwrite.c --i-file $< --output-file $@ reallocarray.lo: $(srcdir)/reallocarray.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)/reallocarray.c diff --git a/lib/util/pread.c b/lib/util/pread.c new file mode 100644 index 000000000..9328c543a --- /dev/null +++ b/lib/util/pread.c @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/* + * 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 + +#include +#include + +#include "sudo_compat.h" + +#if !defined(HAVE_PREAD) && !defined(HAVE_PREAD64) +ssize_t +sudo_pread(int fd, void *buf, size_t nbytes, off_t offset) +{ + ssize_t nread; + off_t old_offset; + + old_offset = lseek(fd, (off_t)0, SEEK_CUR); + if (old_offset == -1 || lseek(fd, offset, SEEK_SET) == -1) + return -1; + + nread = read(fd, buf, nbytes); + if (lseek(fd, old_offset, SEEK_SET) == -1) + return -1; + + return nread; +} +#endif /* !HAVE_PREAD && !HAVE_PREAD64 */ diff --git a/lib/util/pwrite.c b/lib/util/pwrite.c new file mode 100644 index 000000000..48f8cbf8e --- /dev/null +++ b/lib/util/pwrite.c @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/* + * 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 + +#include +#include + +#include "sudo_compat.h" + +#if !defined(HAVE_PWRITE) && !defined(HAVE_PWRITE64) +ssize_t +sudo_pwrite(int fd, const void *buf, size_t nbytes, off_t offset) +{ + ssize_t nwritten; + off_t old_offset; + + old_offset = lseek(fd, (off_t)0, SEEK_CUR); + if (old_offset == -1 || lseek(fd, offset, SEEK_SET) == -1) + return -1; + + nwritten = write(fd, buf, nbytes); + if (lseek(fd, old_offset, SEEK_SET) == -1) + return -1; + + return nwritten; +} +#endif /* HAVE_PWRITE && !HAVE_PWRITE64 */ diff --git a/scripts/mkdep.pl b/scripts/mkdep.pl index 042342109..1d7d53de1 100755 --- a/scripts/mkdep.pl +++ b/scripts/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 cfmakeraw.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo freezero.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.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 cfmakeraw.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo freezero.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pread.lo pwrite.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;