2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 09:57:41 +00:00

Add fchmodat() and fstatat() emulation.

Note that fchmodat() emulation does not support AT_SYMLINK_NOFOLLOW
This commit is contained in:
Todd C. Miller 2019-10-24 20:04:33 -06:00
parent 13e3eaad5f
commit dbf78d0716
9 changed files with 256 additions and 3 deletions

View File

@ -111,7 +111,9 @@ lib/util/event.c
lib/util/event_poll.c
lib/util/event_select.c
lib/util/fatal.c
lib/util/fchmodat.c
lib/util/fnmatch.c
lib/util/fstatat.c
lib/util/getaddrinfo.c
lib/util/getcwd.c
lib/util/getdelim.c

View File

@ -242,6 +242,9 @@
/* Define to 1 if you have the `faccessat' function. */
#undef HAVE_FACCESSAT
/* Define to 1 if you have the `fchmodat' function. */
#undef HAVE_FCHMODAT
/* Define to 1 if your system has the F_CLOSEM fcntl. */
#undef HAVE_FCNTL_CLOSEM
@ -257,6 +260,9 @@
/* Define to 1 if you have the `fseeko' function. */
#undef HAVE_FSEEKO
/* Define to 1 if you have the `fstatat' function. */
#undef HAVE_FSTATAT
/* Define to 1 if you have the `futime' function. */
#undef HAVE_FUTIME

52
configure vendored
View File

@ -20508,6 +20508,58 @@ esac
done
fi
done
for ac_func in fchmodat
do :
ac_fn_c_check_func "$LINENO" "fchmodat" "ac_cv_func_fchmodat"
if test "x$ac_cv_func_fchmodat" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FCHMODAT 1
_ACEOF
else
case " $LIBOBJS " in
*" fchmodat.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS fchmodat.$ac_objext"
;;
esac
for _sym in sudo_fchmodat; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
fi
done
for ac_func in fstatat
do :
ac_fn_c_check_func "$LINENO" "fstatat" "ac_cv_func_fstatat"
if test "x$ac_cv_func_fstatat" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FSTATAT 1
_ACEOF
else
case " $LIBOBJS " in
*" fstatat.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS fstatat.$ac_objext"
;;
esac
for _sym in sudo_fstatat; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
fi
done

View File

@ -2732,6 +2732,14 @@ AC_CHECK_FUNCS([unlinkat], [], [
AC_LIBOBJ(unlinkat)
SUDO_APPEND_COMPAT_EXP(sudo_unlinkat)
])
AC_CHECK_FUNCS([fchmodat], [], [
AC_LIBOBJ(fchmodat)
SUDO_APPEND_COMPAT_EXP(sudo_fchmodat)
])
AC_CHECK_FUNCS([fstatat], [], [
AC_LIBOBJ(fstatat)
SUDO_APPEND_COMPAT_EXP(sudo_fstatat)
])
AC_CHECK_FUNCS([pipe2], [], [
AC_LIBOBJ(pipe2)
SUDO_APPEND_COMPAT_EXP(sudo_pipe2)

View File

@ -212,10 +212,13 @@
# define UTIME_NOW -2L
# endif
#endif
#if !defined(HAVE_OPENAT) || (!defined(HAVE_FUTIMENS) && !defined(HAVE_UTIMENSAT))
#if !defined(HAVE_OPENAT) || (!defined(HAVE_FUTIMENS) && !defined(HAVE_UTIMENSAT)) || !defined(HAVE_FCHMODAT) || !defined(HAVE_FSTATAT) || !defined(HAVE_UNLINKAT)
# ifndef AT_FDCWD
# define AT_FDCWD -100
# endif
# ifndef AT_SYMLINK_NOFOLLOW
# define AT_SYMLINK_NOFOLLOW 0x02
# endif
#endif
/* For pipe2() emulation. */
@ -385,6 +388,7 @@ int getdomainname(char *, size_t);
*/
struct passwd;
struct stat;
struct timespec;
#ifndef HAVE_CLOSEFROM
@ -412,6 +416,16 @@ __dso_public int sudo_utimensat(int fd, const char *file, const struct timespec
# undef utimensat
# define utimensat(_a, _b, _c, _d) sudo_utimensat((_a), (_b), (_c), (_d))
#endif /* HAVE_UTIMENSAT */
#ifndef HAVE_FCHMODAT
__dso_public int sudo_fchmodat(int dfd, const char *path, mode_t mode, int flag);
# undef fchmodat
# define fchmodat(_a, _b, _c, _d) sudo_fchmodat((_a), (_b), (_c), (_d))
#endif /* HAVE_FCHMODAT */
#ifndef HAVE_FSTATAT
__dso_public int sudo_fstatat(int dfd, const char *path, struct stat *sb, int flag);
# undef fstatat
# define fstatat(_a, _b, _c, _d) sudo_fstatat((_a), (_b), (_c), (_d))
#endif /* HAVE_FSTATAT */
#ifndef HAVE_FUTIMENS
__dso_public int sudo_futimens(int fd, const struct timespec *times);
# undef futimens

View File

@ -562,6 +562,14 @@ fatal.i: $(srcdir)/fatal.c $(incdir)/compat/getaddrinfo.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
fatal.plog: fatal.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fatal.c --i-file $< --output-file $@
fchmodat.lo: $(srcdir)/fchmodat.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)/fchmodat.c
fchmodat.i: $(srcdir)/fchmodat.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
fchmodat.plog: fchmodat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fchmodat.c --i-file $< --output-file $@
fnm_test.lo: $(srcdir)/regress/fnmatch/fnm_test.c $(incdir)/compat/fnmatch.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
@ -582,6 +590,12 @@ fnmatch.i: $(srcdir)/fnmatch.c $(incdir)/compat/charclass.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
fnmatch.plog: fnmatch.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fnmatch.c --i-file $< --output-file $@
fstatat.lo: $(srcdir)/fstatat.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)/fstatat.c
fstatat.i: $(srcdir)/fstatat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
fstatat.plog: fstatat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/fstatat.c --i-file $< --output-file $@
getaddrinfo.lo: $(srcdir)/getaddrinfo.c $(incdir)/compat/getaddrinfo.h \
$(incdir)/sudo_compat.h $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/getaddrinfo.c
@ -866,6 +880,12 @@ nanosleep.i: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
nanosleep.plog: nanosleep.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/nanosleep.c --i-file $< --output-file $@
openat.lo: $(srcdir)/openat.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)/openat.c
openat.i: $(srcdir)/openat.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
openat.plog: openat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/openat.c --i-file $< --output-file $@
parse_gids_test.lo: $(srcdir)/regress/parse_gids/parse_gids_test.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \
@ -1246,6 +1266,14 @@ ttysize.i: $(srcdir)/ttysize.c $(incdir)/compat/stdbool.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
ttysize.plog: ttysize.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/ttysize.c --i-file $< --output-file $@
unlinkat.lo: $(srcdir)/unlinkat.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)/unlinkat.c
unlinkat.i: $(srcdir)/unlinkat.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
unlinkat.plog: unlinkat.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/unlinkat.c --i-file $< --output-file $@
utimens.lo: $(srcdir)/utimens.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_util.h \
$(top_builddir)/config.h

71
lib/util/fchmodat.c Normal file
View File

@ -0,0 +1,71 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2019 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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 <config.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "sudo_compat.h"
#ifndef HAVE_FCHMODAT
int
sudo_fchmodat(int dfd, const char *path, mode_t mode, int flag)
{
int odfd, ret = -1;
if (ISSET(flag, AT_SYMLINK_NOFOLLOW)) {
errno = ENOTSUP;
return -1;
}
if (dfd == (int)AT_FDCWD)
return chmod(path, mode);
/* Save cwd */
if ((odfd = open(".", O_RDONLY)) == -1)
goto done;
if (fchdir(dfd) == -1)
goto done;
ret = chmod(path, mode);
/* Restore cwd */
if (fchdir(odfd) == -1) {
/* Should not happen */
ret = -1;
}
done:
if (odfd != -1)
close(odfd);
return ret;
}
#endif /* HAVE_FCHMODAT */

72
lib/util/fstatat.c Normal file
View File

@ -0,0 +1,72 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2019 Todd C. Miller <Todd.Miller@sudo.ws>
*
* 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 <config.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include "sudo_compat.h"
#ifndef HAVE_FSTATAT
int
sudo_fstatat(int dfd, const char *path, struct stat *sb, int flag)
{
int odfd, ret = -1;
if (dfd == (int)AT_FDCWD) {
if (ISSET(flag, AT_SYMLINK_NOFOLLOW))
return lstat(path, sb);
else
return stat(path, sb);
}
/* Save cwd */
if ((odfd = open(".", O_RDONLY)) == -1)
goto done;
if (fchdir(dfd) == -1)
goto done;
if (ISSET(flag, AT_SYMLINK_NOFOLLOW))
ret = lstat(path, sb);
else
ret = stat(path, sb);
/* Restore cwd */
if (fchdir(odfd) == -1) {
/* Should not happen */
ret = -1;
}
done:
if (odfd != -1)
close(odfd);
return ret;
}
#endif /* HAVE_FSTATAT */

View File

@ -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 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 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 utimens.lo vsyslog.lo pipe2.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:;
# Parse OBJS lines
my %objs;