diff -urNap sudo-1.9.11p2/ChangeLog sudo-1.9.11p3/ChangeLog --- sudo-1.9.11p2/ChangeLog Sun Jun 12 12:47:49 2022 +++ sudo-1.9.11p3/ChangeLog Mon Jun 20 17:00:34 2022 @@ -1,8 +1,56 @@ +2022-06-20 Todd C. Miller + + * .hgtags: + Added tag SUDO_1_9_11p3 for changeset 6e671475b373 + [59e5766213e9] [tip] <1.9> + + * NEWS, configure, configure.ac: + Merge sudo 1.9.11p3 from tip. + [6e671475b373] [SUDO_1_9_11p3] <1.9> + + * NEWS, configure, configure.ac: + Sudo 1.9.11p3 + [c96ded63ae46] + + * src/exec_intercept.c, src/sudo_intercept_common.c: + Set TCP_NODELAY on the socket used for intercept IPC to reduce + latency. On some systems, Nagle's algorithm was delaying receipt of + the data, causing commands with intercept or log_subcmds to run + slowly. Related to Bug #1034. + [11b129850ac1] + + * src/sudo_intercept_common.c: + Use blocking I/O when talking to the sudo process. Also check for + EAGAIN/EINTR when reading the message size. Fixes a problem seen on + AIX where recv_intercept_response() could fail unexpectedly. Bug + #1034. + [8554618665a2] + + * src/exec_intercept.c: + Add debug printfs when send/recv return EAGAIN or EINTR. These are + not actually errors but can help gain insight into what is going on + and, in the case of EAGAIN, whether or not there may be a kernel + resource starvation problem. + [fd2dee906d2f] + +2022-06-14 Todd C. Miller + + * plugins/sudoers/logging.c: + log_exit_status: make local variables match struct evlog members. + [f93d5141e818] + +2022-06-13 Todd C. Miller + + * lib/util/getgrouplist.c: + Quiet a compiler warning on macOS. The getgrouplist() groups array + on macOS is int * instead of gid_t *. + [c64bf72a1416] + 2022-06-12 Todd C. Miller * .hgtags: Added tag SUDO_1_9_11p2 for changeset 9e4705cb1db5 - [2a4b6b814432] [tip] <1.9> + [2a4b6b814432] <1.9> * NEWS, configure, configure.ac, include/sudo_compat.h: Merge sudo 1.9.11p2 from tip. diff -urNap sudo-1.9.11p2/NEWS sudo-1.9.11p3/NEWS --- sudo-1.9.11p2/NEWS Sun Jun 12 12:46:56 2022 +++ sudo-1.9.11p3/NEWS Mon Jun 20 16:58:38 2022 @@ -1,3 +1,14 @@ +What's new in Sudo 1.9.11p3 + + * Fixed "connection reset" errors on AIX when running shell scripts + with the "intercept" or "log_subcmds" sudoers options enabled. + Bug #1034. + + * Fixed very slow execution of shell scripts when the "intercept" + or "log_subcmds" sudoers options are set on systems that enable + Nagle's algorithm on the loopback device, such as AIX. + Bug #1034. + What's new in Sudo 1.9.11p2 * Fixed a compilation error on Linux/x86_64 with the x32 ABI. diff -urNap sudo-1.9.11p2/configure sudo-1.9.11p3/configure --- sudo-1.9.11p2/configure Sun Jun 12 12:46:56 2022 +++ sudo-1.9.11p3/configure Mon Jun 20 16:58:38 2022 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for sudo 1.9.11p2. +# Generated by GNU Autoconf 2.71 for sudo 1.9.11p3. # # Report bugs to . # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.9.11p2' -PACKAGE_STRING='sudo 1.9.11p2' +PACKAGE_VERSION='1.9.11p3' +PACKAGE_STRING='sudo 1.9.11p3' PACKAGE_BUGREPORT='https://bugzilla.sudo.ws/' PACKAGE_URL='' @@ -1640,7 +1640,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sudo 1.9.11p2 to adapt to many kinds of systems. +\`configure' configures sudo 1.9.11p3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1706,7 +1706,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.9.11p2:";; + short | recursive ) echo "Configuration of sudo 1.9.11p3:";; esac cat <<\_ACEOF @@ -1996,7 +1996,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.9.11p2 +sudo configure 1.9.11p3 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2653,7 +2653,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sudo $as_me 1.9.11p2, which was +It was created by sudo $as_me 1.9.11p3, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -33050,7 +33050,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sudo $as_me 1.9.11p2, which was +This file was extended by sudo $as_me 1.9.11p3, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -33118,7 +33118,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -sudo config.status 1.9.11p2 +sudo config.status 1.9.11p3 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urNap sudo-1.9.11p2/configure.ac sudo-1.9.11p3/configure.ac --- sudo-1.9.11p2/configure.ac Sun Jun 12 12:46:56 2022 +++ sudo-1.9.11p3/configure.ac Mon Jun 20 16:58:38 2022 @@ -18,7 +18,7 @@ dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS A dnl OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl AC_PREREQ([2.70]) -AC_INIT([sudo], [1.9.11p2], [https://bugzilla.sudo.ws/], [sudo]) +AC_INIT([sudo], [1.9.11p3], [https://bugzilla.sudo.ws/], [sudo]) AC_CONFIG_HEADERS([config.h pathnames.h]) AC_CONFIG_SRCDIR([src/sudo.c]) AC_CONFIG_AUX_DIR([scripts]) diff -urNap sudo-1.9.11p2/lib/util/getgrouplist.c sudo-1.9.11p3/lib/util/getgrouplist.c --- sudo-1.9.11p2/lib/util/getgrouplist.c Sun Jun 12 12:46:45 2022 +++ sudo-1.9.11p3/lib/util/getgrouplist.c Mon Jun 20 16:58:38 2022 @@ -66,7 +66,11 @@ int sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid, GETGROUPS_T **groupsp, int *ngroupsp) { +#ifdef __APPLE__ + int *groups = (int *)*groupsp; +#else GETGROUPS_T *groups = *groupsp; +#endif int ngroups; #ifndef HAVE_GETGROUPLIST_2 int grpsize, tries; diff -urNap sudo-1.9.11p2/plugins/sudoers/logging.c sudo-1.9.11p3/plugins/sudoers/logging.c --- sudo-1.9.11p2/plugins/sudoers/logging.c Sun Jun 12 12:46:56 2022 +++ sudo-1.9.11p3/plugins/sudoers/logging.c Mon Jun 20 16:58:38 2022 @@ -573,15 +573,15 @@ log_allowed(struct eventlog *evlog) } bool -log_exit_status(int exit_status) +log_exit_status(int status) { struct eventlog evlog; int evl_flags = 0; - int ecode = 0; + int exit_value = 0; int oldlocale; struct timespec run_time; char sigbuf[SIG2STR_MAX]; - char *signame = NULL; + char *signal_name = NULL; bool dumped_core = false; bool ret = true; debug_decl(log_exit_status, SUDOERS_DEBUG_LOGGING); @@ -594,17 +594,17 @@ log_exit_status(int exit_status) } sudo_timespecsub(&run_time, &sudo_user.submit_time, &run_time); - if (WIFEXITED(exit_status)) { - ecode = WEXITSTATUS(exit_status); - } else if (WIFSIGNALED(exit_status)) { - int signo = WTERMSIG(exit_status); + if (WIFEXITED(status)) { + exit_value = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + int signo = WTERMSIG(status); if (signo <= 0 || sig2str(signo, sigbuf) == -1) (void)snprintf(sigbuf, sizeof(sigbuf), "%d", signo); - signame = sigbuf; - ecode = signo | 128; - dumped_core = WCOREDUMP(exit_status); + signal_name = sigbuf; + exit_value = signo | 128; + dumped_core = WCOREDUMP(status); } else { - sudo_warnx("invalid exit status 0x%x", exit_status); + sudo_warnx("invalid exit status 0x%x", status); ret = false; goto done; } @@ -619,8 +619,8 @@ log_exit_status(int exit_status) SET(evl_flags, EVLOG_MAIL_ONLY); } evlog.run_time = run_time; - evlog.exit_value = ecode; - evlog.signal_name = signame; + evlog.exit_value = exit_value; + evlog.signal_name = signal_name; evlog.dumped_core = dumped_core; if (!eventlog_exit(&evlog, evl_flags)) ret = false; diff -urNap sudo-1.9.11p2/src/exec_intercept.c sudo-1.9.11p3/src/exec_intercept.c --- sudo-1.9.11p2/src/exec_intercept.c Sun Jun 12 12:46:46 2022 +++ sudo-1.9.11p3/src/exec_intercept.c Mon Jun 20 16:58:38 2022 @@ -25,6 +25,7 @@ #include #include +#include #if defined(HAVE_STDINT_H) # include @@ -560,8 +561,12 @@ intercept_read(int fd, struct intercept_closure *closu case false: goto done; default: - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) { debug_return_bool(true); + sudo_debug_printf( + SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, + "reading intercept token"); + } sudo_warn("recv"); goto done; } @@ -574,8 +579,12 @@ intercept_read(int fd, struct intercept_closure *closu nread = recv(fd, &req_len, sizeof(req_len), 0); if (nread != sizeof(req_len)) { if (nread == -1) { - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) { + sudo_debug_printf( + SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, + "reading intercept message size"); debug_return_bool(true); + } sudo_warn("recv"); } goto done; @@ -605,8 +614,12 @@ intercept_read(int fd, struct intercept_closure *closu /* EOF, other side must have exited. */ goto done; case -1: - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) { + sudo_debug_printf( + SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, + "reading intercept message"); debug_return_bool(true); + } sudo_warn("recv"); goto done; default: @@ -835,8 +848,12 @@ intercept_write(int fd, struct intercept_closure *clos nwritten = send(fd, closure->buf + closure->off, closure->len - closure->off, 0); if (nwritten == -1) { - if (errno == EINTR || errno == EAGAIN) + if (errno == EINTR || errno == EAGAIN) { + sudo_debug_printf( + SUDO_DEBUG_WARN|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO, + "writing intercept message"); debug_return_bool(true); + } sudo_warn("send"); goto done; } @@ -930,7 +947,7 @@ intercept_accept_cb(int fd, int what, void *v) struct sudo_event_base *evbase = sudo_ev_get_base(&closure->ev); struct sockaddr_in sin; socklen_t sin_len = sizeof(sin); - int client_sock, flags; + int client_sock, flags, on = 1; debug_decl(intercept_accept_cb, SUDO_DEBUG_EXEC); if (closure->state != RECV_CONNECTION) { @@ -950,6 +967,9 @@ intercept_accept_cb(int fd, int what, void *v) flags = fcntl(client_sock, F_GETFL, 0); if (flags != -1) (void)fcntl(client_sock, F_SETFL, flags | O_NONBLOCK); + + /* Send data immediately, we need low latency IPC. */ + (void)setsockopt(client_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); /* * Create a new intercept closure and register an event for client_sock. diff -urNap sudo-1.9.11p2/src/sudo_intercept_common.c sudo-1.9.11p3/src/sudo_intercept_common.c --- sudo-1.9.11p2/src/sudo_intercept_common.c Sun Jun 12 12:46:46 2022 +++ sudo-1.9.11p3/src/sudo_intercept_common.c Mon Jun 20 16:58:38 2022 @@ -26,6 +26,7 @@ #include #include #include +#include #if defined(HAVE_STDINT_H) # include @@ -136,16 +137,29 @@ recv_intercept_response(int fd) debug_decl(recv_intercept_response, SUDO_DEBUG_EXEC); /* Read message size (uint32_t in host byte order). */ - nread = recv(fd, &res_len, sizeof(res_len), 0); - if ((size_t)nread != sizeof(res_len)) { - if (nread == 0) { + for (;;) { + nread = recv(fd, &res_len, sizeof(res_len), 0); + if (nread == ssizeof(res_len)) + break; + switch (nread) { + case 0: sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "unexpected EOF reading response size"); - } else { - sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + break; + case -1: + if (errno == EINTR) + continue; + sudo_debug_printf( + SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "error reading response size"); + break; + default: + sudo_debug_printf( + SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "error reading response size: short read"); + break; } - goto done; + goto done; } if (res_len > MESSAGE_SIZE_MAX) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, @@ -169,7 +183,8 @@ recv_intercept_response(int fd) case -1: if (errno == EINTR) continue; - sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, + sudo_debug_printf( + SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "error reading response"); goto done; default: @@ -199,7 +214,7 @@ sudo_interposer_init(void) { InterceptResponse *res = NULL; static bool initialized; - int fd = -1; + int flags, fd = -1; char **p; debug_decl(sudo_interposer_init, SUDO_DEBUG_EXEC); @@ -240,6 +255,13 @@ sudo_interposer_init(void) } /* + * We don't want to use non-blocking I/O. + */ + flags = fcntl(fd, F_GETFL, 0); + if (flags != -1) + (void)fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + + /* * Send InterceptHello message to over the fd. */ if (!send_client_hello(fd)) @@ -334,6 +356,7 @@ static int intercept_connect(void) { int sock = -1; + int on = 1; struct sockaddr_in sin; debug_decl(command_allowed, SUDO_DEBUG_EXEC); @@ -352,6 +375,9 @@ intercept_connect(void) sudo_warn("socket"); goto done; } + + /* Send data immediately, we need low latency IPC. */ + (void)setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) { sudo_warn("connect");