diff options
author | Todd C. Miller <Todd.Miller@sudo.ws> | 2022-06-08 08:33:16 -0600 |
---|---|---|
committer | Todd C. Miller <Todd.Miller@sudo.ws> | 2022-06-08 08:33:16 -0600 |
commit | a781a5b2506e120a059bce2a64664a93fa1004a5 (patch) | |
tree | 3c04ab07531840f8ee3bf2f4f4aa403db371b433 | |
parent | 58656bda244b5815a9a21dcb23344cf58dd42403 (diff) | |
parent | 1466a4c8dc712e3c710e36d28e4cb52418b87aa4 (diff) | |
download | sudo-a781a5b2506e120a059bce2a64664a93fa1004a5.tar.gz |
Merge sudo 1.9.11p1 from tip.SUDO_1_9_11p1
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | config.h.in | 6 | ||||
-rwxr-xr-x | configure | 26 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | docs/sudoers.man.in | 12 | ||||
-rw-r--r-- | docs/sudoers.mdoc.in | 12 | ||||
-rw-r--r-- | include/sudo_event.h | 8 | ||||
-rw-r--r-- | lib/protobuf-c/protobuf-c.c | 38 | ||||
-rw-r--r-- | lib/util/event_select.c | 16 | ||||
-rw-r--r-- | logsrvd/logsrvd.c | 9 | ||||
-rw-r--r-- | logsrvd/logsrvd_relay.c | 4 | ||||
-rw-r--r-- | logsrvd/sendlog.c | 4 | ||||
-rw-r--r-- | plugins/sudoers/sudoers.in | 2 | ||||
-rw-r--r-- | src/exec_ptrace.h | 1 | ||||
-rw-r--r-- | src/exec_pty.c | 36 | ||||
-rw-r--r-- | src/sudo_exec.h | 4 | ||||
-rw-r--r-- | src/sudo_noexec.c | 6 |
17 files changed, 117 insertions, 89 deletions
@@ -1,3 +1,19 @@ +What's new in Sudo 1.9.11p1 + + * Correctly handle EAGAIN in the I/O read/right events. This fixes + a hang seen on some systems when piping a large amount of data + through sudo, such as via rsync. Bug #963. + + * Changes to avoid implementation or unspecified behavior when + bit shifting signed values in the protobuf library. + + * Fixed a compilation error on Linux/aarch64. + + * Fixed the configure check for seccomp(2) support on Linux. + + * Corrected the EBNF specification for tags in the sudoers manual + page. GitHub issue #153. + What's new in Sudo 1.9.11 * Fixed a crash in the Python module with Python 3.9.10 on some diff --git a/config.h.in b/config.h.in index d0be95822..c9c024a15 100644 --- a/config.h.in +++ b/config.h.in @@ -175,9 +175,9 @@ don't. */ #undef HAVE_DECL_QUAD_MIN -/* Define to 1 if you have the declaration of `SECCOMP_SET_MODE_FILTER', and - to 0 if you don't. */ -#undef HAVE_DECL_SECCOMP_SET_MODE_FILTER +/* Define to 1 if you have the declaration of `SECCOMP_MODE_FILTER', and to 0 + if you don't. */ +#undef HAVE_DECL_SECCOMP_MODE_FILTER /* Define to 1 if you have the declaration of `setauthdb', and to 0 if you don't. */ @@ -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.11. +# Generated by GNU Autoconf 2.71 for sudo 1.9.11p1. # # Report bugs to <https://bugzilla.sudo.ws/>. # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.9.11' -PACKAGE_STRING='sudo 1.9.11' +PACKAGE_VERSION='1.9.11p1' +PACKAGE_STRING='sudo 1.9.11p1' 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.11 to adapt to many kinds of systems. +\`configure' configures sudo 1.9.11p1 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.11:";; + short | recursive ) echo "Configuration of sudo 1.9.11p1:";; 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.11 +sudo configure 1.9.11p1 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.11, which was +It was created by sudo $as_me 1.9.11p1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -17821,8 +17821,8 @@ fi *-*-linux*|*-*-k*bsd*-gnu) shadow_funcs="getspnam" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" - # Check for SECCOMP_SET_MODE_FILTER in linux/seccomp.h - ac_fn_check_decl "$LINENO" "SECCOMP_SET_MODE_FILTER" "ac_cv_have_decl_SECCOMP_SET_MODE_FILTER" " + # Check for SECCOMP_MODE_FILTER in linux/seccomp.h + ac_fn_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" " #include <sys/types.h> #include <sys/prctl.h> #include <asm/unistd.h> @@ -17830,13 +17830,13 @@ fi #include <linux/filter.h> " "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_SECCOMP_SET_MODE_FILTER" = xyes +if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes then : ac_have_decl=1 else $as_nop ac_have_decl=0 fi -printf "%s\n" "#define HAVE_DECL_SECCOMP_SET_MODE_FILTER $ac_have_decl" >>confdefs.h +printf "%s\n" "#define HAVE_DECL_SECCOMP_MODE_FILTER $ac_have_decl" >>confdefs.h # We call getrandom via syscall(3) in case it is not in libc ac_fn_c_check_header_compile "$LINENO" "linux/random.h" "ac_cv_header_linux_random_h" "$ac_includes_default" @@ -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.11, which was +This file was extended by sudo $as_me 1.9.11p1, 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" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -sudo config.status 1.9.11 +sudo config.status 1.9.11p1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 4d4278f81..fc4abf8a5 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF dnl OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl AC_PREREQ([2.70]) -AC_INIT([sudo], [1.9.11], [https://bugzilla.sudo.ws/], [sudo]) +AC_INIT([sudo], [1.9.11p1], [https://bugzilla.sudo.ws/], [sudo]) AC_CONFIG_HEADERS([config.h pathnames.h]) AC_CONFIG_SRCDIR([src/sudo.c]) AC_CONFIG_AUX_DIR([scripts]) @@ -2065,8 +2065,8 @@ case "$host" in *-*-linux*|*-*-k*bsd*-gnu) shadow_funcs="getspnam" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" - # Check for SECCOMP_SET_MODE_FILTER in linux/seccomp.h - AC_CHECK_DECLS([SECCOMP_SET_MODE_FILTER], [], [], [ + # Check for SECCOMP_MODE_FILTER in linux/seccomp.h + AC_CHECK_DECLS([SECCOMP_MODE_FILTER], [], [], [ #include <sys/types.h> #include <sys/prctl.h> #include <asm/unistd.h> diff --git a/docs/sudoers.man.in b/docs/sudoers.man.in index e12462665..5f73f7ca2 100644 --- a/docs/sudoers.man.in +++ b/docs/sudoers.man.in @@ -1273,7 +1273,7 @@ User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e Cmnd_Spec_List ::= Cmnd_Spec | Cmnd_Spec ',' Cmnd_Spec_List -Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd +Cmnd_Spec ::= Runas_Spec? Option_Spec* (Tag_Spec ':')* Cmnd Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')' @@ -1304,11 +1304,11 @@ Chdir_Spec ::= 'CWD=directory' Chroot_Spec ::= 'CHROOT=directory' -Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' | - 'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' | - 'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'INTERCEPT:' | - 'NOINTERCEPT:' | 'PASSWD:' | 'NOPASSWD:' | 'SETENV:' | - 'NOSETENV:') +Tag_Spec ::= ('EXEC' | 'NOEXEC' | 'FOLLOW' | 'NOFOLLOW' | + 'LOG_INPUT' | 'NOLOG_INPUT' | 'LOG_OUTPUT' | + 'NOLOG_OUTPUT' | 'MAIL' | 'NOMAIL' | 'INTERCEPT' | + 'NOINTERCEPT' | 'PASSWD' | 'NOPASSWD' | 'SETENV' | + 'NOSETENV') .RE .fi .PP diff --git a/docs/sudoers.mdoc.in b/docs/sudoers.mdoc.in index 9211fbe9e..29aeacfdd 100644 --- a/docs/sudoers.mdoc.in +++ b/docs/sudoers.mdoc.in @@ -1223,7 +1223,7 @@ User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e Cmnd_Spec_List ::= Cmnd_Spec | Cmnd_Spec ',' Cmnd_Spec_List -Cmnd_Spec ::= Runas_Spec? Option_Spec* Tag_Spec* Cmnd +Cmnd_Spec ::= Runas_Spec? Option_Spec* (Tag_Spec ':')* Cmnd Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')' @@ -1262,11 +1262,11 @@ Chdir_Spec ::= 'CWD=directory' Chroot_Spec ::= 'CHROOT=directory' -Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' | - 'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' | - 'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'INTERCEPT:' | - 'NOINTERCEPT:' | 'PASSWD:' | 'NOPASSWD:' | 'SETENV:' | - 'NOSETENV:') +Tag_Spec ::= ('EXEC' | 'NOEXEC' | 'FOLLOW' | 'NOFOLLOW' | + 'LOG_INPUT' | 'NOLOG_INPUT' | 'LOG_OUTPUT' | + 'NOLOG_OUTPUT' | 'MAIL' | 'NOMAIL' | 'INTERCEPT' | + 'NOINTERCEPT' | 'PASSWD' | 'NOPASSWD' | 'SETENV' | + 'NOSETENV') .Ed .Pp A diff --git a/include/sudo_event.h b/include/sudo_event.h index 2bb7bb2be..12bb89478 100644 --- a/include/sudo_event.h +++ b/include/sudo_event.h @@ -102,10 +102,10 @@ struct sudo_event_base { int pfd_high; /* highest slot used */ int pfd_free; /* idx of next free entry or pfd_max if full */ #else - fd_set *readfds_in; /* read I/O descriptor set (in) */ - fd_set *writefds_in; /* write I/O descriptor set (in) */ - fd_set *readfds_out; /* read I/O descriptor set (out) */ - fd_set *writefds_out; /* write I/O descriptor set (out) */ + void *readfds_in; /* read I/O descriptor set (in) */ + void *writefds_in; /* write I/O descriptor set (in) */ + void *readfds_out; /* read I/O descriptor set (out) */ + void *writefds_out; /* write I/O descriptor set (out) */ int maxfd; /* max fd we can store in readfds/writefds */ int highfd; /* highest fd to pass as 1st arg to select */ #endif /* HAVE_POLL */ diff --git a/lib/protobuf-c/protobuf-c.c b/lib/protobuf-c/protobuf-c.c index 96b750650..9d56e1fec 100644 --- a/lib/protobuf-c/protobuf-c.c +++ b/lib/protobuf-c/protobuf-c.c @@ -331,9 +331,8 @@ int32_size(int32_t v) static inline uint32_t zigzag32(int32_t v) { - // Note: the right-shift must be arithmetic - // Note: left shift must be unsigned because of overflow - return ((uint32_t)(v) << 1) ^ (uint32_t)(v >> 31); + // Note: Using unsigned types prevents undefined behavior + return ((uint32_t)v << 1) ^ -((uint32_t)v >> 31); } /** @@ -395,9 +394,8 @@ uint64_size(uint64_t v) static inline uint64_t zigzag64(int64_t v) { - // Note: the right-shift must be arithmetic - // Note: left shift must be unsigned because of overflow - return ((uint64_t)(v) << 1) ^ (uint64_t)(v >> 63); + // Note: Using unsigned types prevents undefined behavior + return ((uint64_t)v << 1) ^ -((uint64_t)v >> 63); } /** @@ -817,7 +815,8 @@ uint32_pack(uint32_t value, uint8_t *out) } /** - * Pack a signed 32-bit integer and return the number of bytes written. + * Pack a signed 32-bit integer and return the number of bytes written, + * passed as unsigned to avoid implementation-specific behavior. * Negative numbers are encoded as two's complement 64-bit integers. * * \param value @@ -828,14 +827,14 @@ uint32_pack(uint32_t value, uint8_t *out) * Number of bytes written to `out`. */ static inline size_t -int32_pack(int32_t value, uint8_t *out) +int32_pack(uint32_t value, uint8_t *out) { - if (value < 0) { + if ((int32_t)value < 0) { out[0] = value | 0x80; out[1] = (value >> 7) | 0x80; out[2] = (value >> 14) | 0x80; out[3] = (value >> 21) | 0x80; - out[4] = (value >> 28) | 0x80; + out[4] = (value >> 28) | 0xf0; out[5] = out[6] = out[7] = out[8] = 0xff; out[9] = 0x01; return 10; @@ -2440,7 +2439,7 @@ static inline int32_t unzigzag32(uint32_t v) { // Note: Using unsigned types prevents undefined behavior - return (int32_t)((v >> 1) ^ (~(v & 1) + 1)); + return (int32_t)((v >> 1) ^ -(v & 1)); } static inline uint32_t @@ -2482,7 +2481,7 @@ static inline int64_t unzigzag64(uint64_t v) { // Note: Using unsigned types prevents undefined behavior - return (int64_t)((v >> 1) ^ (~(v & 1) + 1)); + return (int64_t)((v >> 1) ^ -(v & 1)); } static inline uint64_t @@ -2619,11 +2618,14 @@ parse_required_member(ScannedMember *scanned_member, return FALSE; def_mess = scanned_member->field->default_value; - subm = protobuf_c_message_unpack(scanned_member->field->descriptor, - allocator, - len - pref_len, - data + pref_len); - + if (len > pref_len) { + subm = protobuf_c_message_unpack(scanned_member->field->descriptor, + allocator, + len - pref_len, + data + pref_len); + } else { + subm = NULL; + } if (maybe_clear && *pmessage != NULL && *pmessage != def_mess) @@ -3553,7 +3555,7 @@ protobuf_c_service_generated_init(ProtobufCService *service, service->descriptor = descriptor; service->destroy = destroy; service->invoke = protobuf_c_service_invoke_internal; - memset(service + 1, 0, descriptor->n_methods * sizeof(GenericHandler)); + memset(&service[1], 0, descriptor->n_methods * sizeof(GenericHandler)); } void protobuf_c_service_destroy(ProtobufCService *service) diff --git a/lib/util/event_select.c b/lib/util/event_select.c index a2ee9d1b3..8d3e8a9b2 100644 --- a/lib/util/event_select.c +++ b/lib/util/event_select.c @@ -120,12 +120,12 @@ sudo_ev_add_impl(struct sudo_event_base *base, struct sudo_event *ev) if (ISSET(ev->events, SUDO_EV_READ)) { sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to readfs", __func__, ev->fd); - FD_SET(ev->fd, base->readfds_in); + FD_SET(ev->fd, (fd_set *)base->readfds_in); } if (ISSET(ev->events, SUDO_EV_WRITE)) { sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: added fd %d to writefds", __func__, ev->fd); - FD_SET(ev->fd, base->writefds_in); + FD_SET(ev->fd, (fd_set *)base->writefds_in); } if (ev->fd > base->highfd) base->highfd = ev->fd; @@ -142,17 +142,17 @@ sudo_ev_del_impl(struct sudo_event_base *base, struct sudo_event *ev) if (ISSET(ev->events, SUDO_EV_READ)) { sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: removed fd %d from readfds", __func__, ev->fd); - FD_CLR(ev->fd, base->readfds_in); + FD_CLR(ev->fd, (fd_set *)base->readfds_in); } if (ISSET(ev->events, SUDO_EV_WRITE)) { sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: removed fd %d from writefds", __func__, ev->fd); - FD_CLR(ev->fd, base->writefds_in); + FD_CLR(ev->fd, (fd_set *)base->writefds_in); } if (base->highfd == ev->fd) { for (;;) { - if (FD_ISSET(base->highfd, base->readfds_in) || - FD_ISSET(base->highfd, base->writefds_in)) + if (FD_ISSET(base->highfd, (fd_set *)base->readfds_in) || + FD_ISSET(base->highfd, (fd_set *)base->writefds_in)) break; if (--base->highfd < 0) break; @@ -230,9 +230,9 @@ sudo_ev_scan_impl(struct sudo_event_base *base, int flags) TAILQ_FOREACH(ev, &base->events, entries) { if (ev->fd >= 0) { int what = 0; - if (FD_ISSET(ev->fd, base->readfds_out)) + if (FD_ISSET(ev->fd, (fd_set *)base->readfds_out)) what |= (ev->events & SUDO_EV_READ); - if (FD_ISSET(ev->fd, base->writefds_out)) + if (FD_ISSET(ev->fd, (fd_set *)base->writefds_out)) what |= (ev->events & SUDO_EV_WRITE); if (what != 0) { /* Make event active. */ diff --git a/logsrvd/logsrvd.c b/logsrvd/logsrvd.c index 4eba07e07..4bf739ff5 100644 --- a/logsrvd/logsrvd.c +++ b/logsrvd/logsrvd.c @@ -929,6 +929,8 @@ server_msg_cb(int fd, int what, void *v) } if (nwritten == -1) { + if (errno == EAGAIN || errno == EINTR) + debug_return; sudo_warn("%s: write", closure->ipaddr); goto finished; } @@ -1043,7 +1045,7 @@ client_msg_cb(int fd, int what, void *v) __func__, nread, closure->ipaddr); switch (nread) { case -1: - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EINTR) debug_return; sudo_warn("%s: read", closure->ipaddr); goto close_connection; @@ -1519,9 +1521,10 @@ listener_cb(int fd, int what, void *v) "unable to start new connection"); } } else { - if (errno != EAGAIN) - sudo_warn("accept"); + if (errno == EAGAIN || errno == EINTR) + debug_return; /* TODO: pause accepting on ENFILE and EMFILE */ + sudo_warn("accept"); } debug_return; diff --git a/logsrvd/logsrvd_relay.c b/logsrvd/logsrvd_relay.c index f23b88f90..6937ed82c 100644 --- a/logsrvd/logsrvd_relay.c +++ b/logsrvd/logsrvd_relay.c @@ -799,7 +799,7 @@ relay_server_msg_cb(int fd, int what, void *v) relay_closure->relay_name.name, relay_closure->relay_name.ipaddr); switch (nread) { case -1: - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EINTR) debug_return; sudo_warn("%s: read", relay_closure->relay_name.ipaddr); closure->errstr = _("unable to read from relay"); @@ -970,6 +970,8 @@ relay_client_msg_cb(int fd, int what, void *v) { nwritten = write(fd, buf->data + buf->off, buf->len - buf->off); if (nwritten == -1) { + if (errno == EAGAIN || errno == EINTR) + debug_return; sudo_warn("%s: write", relay_closure->relay_name.ipaddr); closure->errstr = _("error writing to relay"); goto send_error; diff --git a/logsrvd/sendlog.c b/logsrvd/sendlog.c index 094bd369d..50d7f59c1 100644 --- a/logsrvd/sendlog.c +++ b/logsrvd/sendlog.c @@ -1359,7 +1359,7 @@ server_msg_cb(int fd, int what, void *v) __func__, nread); switch (nread) { case -1: - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EINTR) debug_return; sudo_warn("recv"); goto bad; @@ -1479,6 +1479,8 @@ client_msg_cb(int fd, int what, void *v) nwritten = send(fd, buf->data + buf->off, buf->len - buf->off, 0); } if (nwritten == -1) { + if (errno == EAGAIN || errno == EINTR) + debug_return; sudo_warn("send"); goto bad; } diff --git a/plugins/sudoers/sudoers.in b/plugins/sudoers/sudoers.in index a0d293409..5efda5d23 100644 --- a/plugins/sudoers/sudoers.in +++ b/plugins/sudoers/sudoers.in @@ -64,7 +64,7 @@ ## ## Uncomment to enable logging of a command's output, except for ## sudoreplay and reboot. Use sudoreplay to play back logged sessions. -## Sudo will create up to 2,176,782,336 I/O logs before recycing them. +## Sudo will create up to 2,176,782,336 I/O logs before recycling them. ## Set maxseq to a smaller number if you don't have unlimited disk space. # Defaults log_output # Defaults!/usr/bin/sudoreplay !log_output diff --git a/src/exec_ptrace.h b/src/exec_ptrace.h index 7f26283a8..4a5a86581 100644 --- a/src/exec_ptrace.h +++ b/src/exec_ptrace.h @@ -76,6 +76,7 @@ # define reg_arg4(x) (x).r10 #elif defined(__aarch64__) # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64 +# define sudo_pt_regs struct user_pt_regs # define reg_syscall(x) (x).regs[8] /* w8 */ # define reg_retval(x) (x).regs[0] /* x0 */ # define reg_sp(x) (x).sp /* sp */ diff --git a/src/exec_pty.c b/src/exec_pty.c index 326d8318a..e2fd9c60e 100644 --- a/src/exec_pty.c +++ b/src/exec_pty.c @@ -676,9 +676,11 @@ read_callback(int fd, int what, void *v) /* Schedule SIGTTIN to be forwarded to the command. */ schedule_signal(iob->ec, SIGTTIN); } - if (errno == EAGAIN || errno == EINTR) + if (errno == EAGAIN || errno == EINTR) { + /* Not an error, retry later. */ break; - /* treat read error as fatal and close the fd */ + } + /* Treat read error as fatal and close the fd. */ sudo_debug_printf(SUDO_DEBUG_ERROR, "error reading fd %d: %s", fd, strerror(errno)); FALLTHROUGH; @@ -705,18 +707,18 @@ read_callback(int fd, int what, void *v) iob->ec->cmnd_pid = -1; } iob->len += n; - /* Enable writer now that there is data in the buffer. */ + /* Disable reader if buffer is full. */ + if (iob->len == sizeof(iob->buf)) + sudo_ev_del(evbase, iob->revent); + /* Enable writer now that there is new data in the buffer. */ if (iob->wevent != NULL) { if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) sudo_fatal("%s", U_("unable to add event to queue")); } - /* Re-enable reader if buffer is not full. */ - if (iob->len != sizeof(iob->buf)) { - if (sudo_ev_add(evbase, iob->revent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); - } break; } + + debug_return; } /* @@ -783,7 +785,7 @@ write_callback(int fd, int what, void *v) } FALLTHROUGH; case EAGAIN: - /* not an error */ + /* Not an error, retry later. */ break; default: /* XXX - need a way to distinguish non-exec error. */ @@ -798,20 +800,16 @@ write_callback(int fd, int what, void *v) sudo_debug_printf(SUDO_DEBUG_INFO, "wrote %zd bytes to fd %d", n, fd); iob->off += n; - /* Reset buffer if fully consumed. */ + /* Disable writer and reset the buffer if fully consumed. */ if (iob->off == iob->len) { iob->off = iob->len = 0; + sudo_ev_del(evbase, iob->wevent); /* Forward the EOF from reader to writer. */ if (iob->revent == NULL) { safe_close(fd); ev_free_by_fd(evbase, fd); } } - /* Re-enable writer if buffer is not empty. */ - if (iob->len > iob->off) { - if (sudo_ev_add(evbase, iob->wevent, NULL, false) == -1) - sudo_fatal("%s", U_("unable to add event to queue")); - } /* Enable reader if buffer is not full. */ if (iob->revent != NULL && (ttymode == TERM_RAW || !USERTTY_EVENT(iob->revent))) { @@ -821,6 +819,8 @@ write_callback(int fd, int what, void *v) } } } + + debug_return; } static void @@ -844,8 +844,10 @@ io_buf_new(int rfd, int wfd, if ((iob = malloc(sizeof(*iob))) == NULL) sudo_fatalx(U_("%s: %s"), __func__, U_("unable to allocate memory")); iob->ec = ec; - iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ, read_callback, iob); - iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE, write_callback, iob); + iob->revent = sudo_ev_alloc(rfd, SUDO_EV_READ|SUDO_EV_PERSIST, + read_callback, iob); + iob->wevent = sudo_ev_alloc(wfd, SUDO_EV_WRITE|SUDO_EV_PERSIST, + write_callback, iob); iob->len = 0; iob->off = 0; iob->action = action; diff --git a/src/sudo_exec.h b/src/sudo_exec.h index d225524d5..2f099a332 100644 --- a/src/sudo_exec.h +++ b/src/sudo_exec.h @@ -95,13 +95,13 @@ union sudo_token_un { * On MIPS we can't change the syscall return and only support log_subcmds. */ #if defined(_PATH_SUDO_INTERCEPT) && defined(__linux__) -# if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER +# if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER # if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__arm__) || defined(__mips__) || defined(__powerpc__) || (defined(__riscv) && __riscv_xlen == 64) || defined(__s390__) # ifndef HAVE_PTRACE_INTERCEPT # define HAVE_PTRACE_INTERCEPT 1 # endif /* HAVE_PTRACE_INTERCEPT */ # endif /* __amd64__ || __i386__ || __aarch64__ || __riscv || __s390__ */ -# endif /* HAVE_DECL_SECCOMP_SET_MODE_FILTER */ +# endif /* HAVE_DECL_SECCOMP_MODE_FILTER */ #endif /* _PATH_SUDO_INTERCEPT && __linux__ */ /* diff --git a/src/sudo_noexec.c b/src/sudo_noexec.c index 3a2abdfdd..fd8117226 100644 --- a/src/sudo_noexec.c +++ b/src/sudo_noexec.c @@ -25,7 +25,7 @@ #include <sys/types.h> -#if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER +#if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER # include <sys/prctl.h> # include <asm/unistd.h> # include <linux/filter.h> @@ -213,7 +213,7 @@ INTERPOSE(wordexp) /* * On Linux we can use a seccomp() filter to disable exec. */ -#if defined(HAVE_DECL_SECCOMP_SET_MODE_FILTER) && HAVE_DECL_SECCOMP_SET_MODE_FILTER +#if defined(HAVE_DECL_SECCOMP_MODE_FILTER) && HAVE_DECL_SECCOMP_MODE_FILTER /* Older systems may not support execveat(2). */ #ifndef __NR_execveat @@ -248,4 +248,4 @@ noexec_ctor(void) if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) (void)prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &exec_fprog); } -#endif /* HAVE_DECL_SECCOMP_SET_MODE_FILTER */ +#endif /* HAVE_DECL_SECCOMP_MODE_FILTER */ |