From: Todd C. Miller Date: Thu, 12 Jan 2017 17:44:26 +0000 (-0700) Subject: When waiting for the parent to grant us the tty, use nanosleep X-Git-Tag: SUDO_1_8_19p2^2~8 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f0295373ad5dc1d1eee685e49ad969cd05eeaca;p=sudo When waiting for the parent to grant us the tty, use nanosleep instead of spinning to avoid hogging the CPU. --- diff --git a/MANIFEST b/MANIFEST index db59f4292..ea8f458b1 100644 --- a/MANIFEST +++ b/MANIFEST @@ -107,6 +107,7 @@ lib/util/mksiglist.h lib/util/mksigname.c lib/util/mksigname.h lib/util/mktemp.c +lib/util/nanosleep.c lib/util/parseln.c lib/util/progname.c lib/util/pw_dup.c diff --git a/config.h.in b/config.h.in index 61462e4b5..14275b252 100644 --- a/config.h.in +++ b/config.h.in @@ -470,6 +470,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MPS_LDAP_SSL_H +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H diff --git a/configure b/configure index ae14da306..892fc28d7 100755 --- a/configure +++ b/configure @@ -19688,6 +19688,68 @@ esac done +fi +done + +for ac_func in nanosleep +do : + ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" +if test "x$ac_cv_func_nanosleep" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NANOSLEEP 1 +_ACEOF + +else + + # On Solaris, nanosleep is in librt + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5 +$as_echo_n "checking for nanosleep in -lrt... " >&6; } +if ${ac_cv_lib_rt_nanosleep+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char nanosleep (); +int +main () +{ +return nanosleep (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_nanosleep=yes +else + ac_cv_lib_rt_nanosleep=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5 +$as_echo "$ac_cv_lib_rt_nanosleep" >&6; } +if test "x$ac_cv_lib_rt_nanosleep" = xyes; then : + REPLAY_LIBS="${REPLAY_LIBS} -lrt" +else + case " $LIBOBJS " in + *" nanosleep.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS nanosleep.$ac_objext" + ;; +esac + +fi + + fi done diff --git a/configure.ac b/configure.ac index 9d09eea7d..c3f85cad3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl dnl Use the top-level autogen.sh script to generate configure and config.h.in dnl -dnl Copyright (c) 1994-1996,1998-2016 Todd C. Miller +dnl Copyright (c) 1994-1996,1998-2017 Todd C. Miller dnl AC_PREREQ([2.59]) AC_INIT([sudo], [1.8.19p1], [https://bugzilla.sudo.ws/], [sudo]) @@ -2578,6 +2578,10 @@ AC_CHECK_FUNCS([memset_s], [], [ AC_LIBOBJ(memset_s) SUDO_APPEND_COMPAT_EXP(sudo_memset_s) ]) +AC_CHECK_FUNCS(nanosleep, [], [ + # On Solaris, nanosleep is in librt + AC_CHECK_LIB(rt, nanosleep, [REPLAY_LIBS="${REPLAY_LIBS} -lrt"], [AC_LIBOBJ(nanosleep)]) +]) AC_CHECK_FUNCS([pw_dup], [], [ AC_LIBOBJ(pw_dup) SUDO_APPEND_COMPAT_EXP(sudo_pw_dup) diff --git a/include/sudo_compat.h b/include/sudo_compat.h index 3642a3465..311c4440a 100644 --- a/include/sudo_compat.h +++ b/include/sudo_compat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2008, 2009-2016 + * Copyright (c) 1996, 1998-2005, 2008, 2009-2017 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -220,6 +220,13 @@ #undef ISSET #define ISSET(t, f) ((t) & (f)) +/* + * Some systems define this in but we don't include that anymore. + */ +#ifndef howmany +# define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif + /* * Simple isblank() macro and function for systems without it. */ @@ -468,6 +475,11 @@ __dso_public int sudo_mkstemps(char *path, int slen); # undef mkstemps # define mkstemps(_a, _b) sudo_mkstemps((_a), (_b)) #endif /* !HAVE_MKDTEMP || !HAVE_MKSTEMPS */ +#ifndef HAVE_NANOSLEEP +__dso_public int sudo_nanosleep(const struct timespec *timeout, struct timespec *remainder); +#undef nanosleep +# define nanosleep(_a, _b) sudo_nanosleep((_a), (_b)) +#endif #ifndef HAVE_PW_DUP __dso_public struct passwd *sudo_pw_dup(const struct passwd *pw); # undef pw_dup diff --git a/lib/util/Makefile.in b/lib/util/Makefile.in index eb3ebdb7d..3eecc2410 100644 --- a/lib/util/Makefile.in +++ b/lib/util/Makefile.in @@ -463,6 +463,10 @@ mktemp_test.lo: $(srcdir)/regress/mktemp/mktemp_test.c \ $(incdir)/sudo_fatal.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/mktemp/mktemp_test.c +nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/compat/stdbool.h \ + $(incdir)/sudo_compat.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)/nanosleep.c 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 \ diff --git a/lib/util/nanosleep.c b/lib/util/nanosleep.c new file mode 100644 index 000000000..02fb5619a --- /dev/null +++ b/lib/util/nanosleep.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2009-2011, 2013, 2017 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 + +#ifndef HAVE_NANOSLEEP + +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif /* HAVE_SYS_SELECT_H */ +#if TIME_WITH_SYS_TIME +# include +#endif +#include + +#include "sudo_compat.h" +#include "sudo_util.h" + +int +sudo_nanosleep(const struct timespec *ts, struct timespec *rts) +{ + struct timeval timeout, endtime, now; + int rval; + + if (ts->tv_sec == 0 && ts->tv_nsec < 1000) { + timeout.tv_sec = 0; + timeout.tv_usec = 1; + } else { + TIMESPEC_TO_TIMEVAL(&timeout, ts); + } + if (rts != NULL) { + if (gettimeofday(&endtime, NULL) == -1) + return -1; + sudo_timevaladd(&endtime, &timeout, &endtime); + } + rval = select(0, NULL, NULL, NULL, &timeout); + if (rts != NULL && rval == -1 && errno == EINTR) { + if (gettimeofday(&now, NULL) == -1) + return -1; + sudo_timevalsub(&endtime, &now, &endtime); + TIMEVAL_TO_TIMESPEC(&endtime, rts); + } + return rval; +} +#endif /* HAVE_NANOSLEEP */ diff --git a/mkdep.pl b/mkdep.pl index 6c8f55b47..5a83c7f92 100755 --- a/mkdep.pl +++ b/mkdep.pl @@ -1,6 +1,6 @@ #!/usr/bin/env perl # -# Copyright (c) 2011-2014 Todd C. Miller +# Copyright (c) 2011-2017 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 @@ -70,7 +70,7 @@ sub mkdep { $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 $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\@: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 reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo strtonum.lo utimens.lo vsyslog.lo:; + $makefile =~ s:\@LTLIBOBJS\@: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 nanosleep.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo strtonum.lo utimens.lo vsyslog.lo:; # Parse OBJS lines my %objs; diff --git a/src/exec_pty.c b/src/exec_pty.c index f317146bf..740350638 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -1556,8 +1556,9 @@ exec_pty(struct command_details *details, /* Wait for parent to grant us the tty if we are foreground. */ if (foreground && !ISSET(details->flags, CD_EXEC_BG)) { + struct timespec ts = { 0, 1000 }; /* 1us */ while (tcgetpgrp(io_fds[SFD_SLAVE]) != self) - continue; /* spin */ + nanosleep(&ts, NULL); } /* We have guaranteed that the slave fd is > 2 */