From: Todd C. Miller Date: Wed, 4 Apr 2012 20:59:31 +0000 (-0400) Subject: Add SUDO_DEBUG_ERRNO flag to debug functions so we can log errno. X-Git-Tag: SUDO_1_8_5~1^2~86 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2fe41248acc61880653eb6fb8d4e5b7cfc7e987f;p=sudo Add SUDO_DEBUG_ERRNO flag to debug functions so we can log errno. Use this flag when wrapping error() and warning() so the debug output includes the error string. --- diff --git a/common/sudo_debug.c b/common/sudo_debug.c index 84b1ad1ae..2b2a12355 100644 --- a/common/sudo_debug.c +++ b/common/sudo_debug.c @@ -252,12 +252,13 @@ void sudo_debug_exit_ptr(const char *func, const char *file, int line, } void -sudo_debug_write(const char *str, int len) +sudo_debug_write(const char *str, int len, int errno_val) { char *timestr; time_t now; - struct iovec iov[5]; + struct iovec iov[7]; int iovcnt = 4; + bool need_newline = false; if (len <= 0) return; @@ -266,14 +267,22 @@ sudo_debug_write(const char *str, int len) case SUDO_DEBUG_MODE_CONV: /* Call conversation function */ if (sudo_conv != NULL) { - struct sudo_conv_message msg; - struct sudo_conv_reply repl; - - memset(&msg, 0, sizeof(msg)); - memset(&repl, 0, sizeof(repl)); - msg.msg_type = SUDO_CONV_DEBUG_MSG; - msg.msg = str; - sudo_conv(1, &msg, &repl); + struct sudo_conv_message msg[3]; + struct sudo_conv_reply repl[3]; + int msgcnt = 1; + + memset(msg, 0, sizeof(msg)); + memset(repl, 0, sizeof(repl)); + msg[0].msg_type = SUDO_CONV_DEBUG_MSG; + msg[0].msg = str; + if (errno_val) { + msgcnt = 3; + msg[1].msg_type = SUDO_CONV_DEBUG_MSG; + msg[1].msg = ": "; + msg[2].msg_type = SUDO_CONV_DEBUG_MSG; + msg[2].msg = strerror(errno_val); + } + sudo_conv(msgcnt, msg, repl); } break; case SUDO_DEBUG_MODE_FILE: @@ -286,10 +295,30 @@ sudo_debug_write(const char *str, int len) /* Add string along with newline if it doesn't have one. */ iov[3].iov_base = (char *)str; iov[3].iov_len = len; - if (str[len - 1] != '\n') { + if (str[len - 1] != '\n') + need_newline = true; + + /* Append error string if errno is specified. */ + if (errno_val) { + iov[iovcnt].iov_base = ": "; + iov[iovcnt].iov_len = 2; + iovcnt++; + iov[iovcnt].iov_base = strerror(errno_val); + iov[iovcnt].iov_len = strlen(iov[iovcnt].iov_base); + iovcnt++; + + /* Move newline to the end. */ + if (!need_newline) { + need_newline = true; + iov[3].iov_len--; + } + } + + /* Append newline as needed. */ + if (need_newline) { /* force newline */ - iov[4].iov_base = "\n"; - iov[4].iov_len = 1; + iov[iovcnt].iov_base = "\n"; + iov[iovcnt].iov_len = 1; iovcnt++; } @@ -310,7 +339,7 @@ sudo_debug_write(const char *str, int len) void sudo_debug_printf2(int level, const char *fmt, ...) { - int buflen, pri, subsys; + int buflen, pri, subsys, saved_errno = errno; va_list ap; char *buf; @@ -322,16 +351,20 @@ sudo_debug_printf2(int level, const char *fmt, ...) subsys = SUDO_DEBUG_SUBSYS(level); /* Make sure we want debug info at this level. */ - if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri) - return; - - va_start(ap, fmt); - buflen = vasprintf(&buf, fmt, ap); - va_end(ap); - if (buflen != -1) { - sudo_debug_write(buf, buflen); - free(buf); + if (subsys < NUM_SUBSYSTEMS && sudo_debug_settings[subsys] >= pri) { + va_start(ap, fmt); + buflen = vasprintf(&buf, fmt, ap); + va_end(ap); + if (buflen != -1) { + if (ISSET(level, SUDO_DEBUG_ERRNO)) + sudo_debug_write(buf, buflen, saved_errno); + else + sudo_debug_write(buf, buflen, 0); + free(buf); + } } + + errno = saved_errno; } void @@ -411,7 +444,7 @@ sudo_debug_execve2(int level, const char *path, char *const argv[], char *const *cp = '\0'; - sudo_debug_write(buf, buflen); + sudo_debug_write(buf, buflen, 0); free(buf); } diff --git a/include/error.h b/include/error.h index fdc1e08bf..17cc0697c 100644 --- a/include/error.h +++ b/include/error.h @@ -38,7 +38,7 @@ #else /* SUDO_ERROR_WRAP */ # if defined(__GNUC__) && __GNUC__ == 2 # define error(rval, fmt...) do { \ - sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, (fmt)); \ + sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, (fmt));\ error2((rval), (fmt)); \ } while (0) # define errorx(rval, fmt...) do { \ @@ -46,7 +46,7 @@ errorx2((rval), (fmt)); \ } while (0) # define warning(fmt...) do { \ - sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, (fmt)); \ + sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, (fmt));\ warning2((fmt)); \ } while (0) # define warningx(fmt...) do { \ @@ -55,7 +55,7 @@ } while (0) # else # define error(rval, ...) do { \ - sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, __VA_ARGS__); \ + sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, __VA_ARGS__);\ error2((rval), __VA_ARGS__); \ } while (0) # define errorx(rval, ...) do { \ @@ -63,7 +63,7 @@ errorx2((rval), __VA_ARGS__); \ } while (0) # define warning(...) do { \ - sudo_debug_printf2(SUDO_DEBUG_ERROR|sudo_debug_subsys, __VA_ARGS__); \ + sudo_debug_printf2(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|sudo_debug_subsys, __VA_ARGS__);\ warning2(__VA_ARGS__); \ } while (0) # define warningx(...) do { \ diff --git a/include/sudo_debug.h b/include/sudo_debug.h index e2896f7e8..41389c798 100644 --- a/include/sudo_debug.h +++ b/include/sudo_debug.h @@ -21,8 +21,9 @@ /* * The priority and subsystem are encoded in a single 32-bit value. - * The lower 4 bits are the priority and the top 28 bits are the subsystem. + * The lower 4 bits are the priority and the top 27 bits are the subsystem. * This allows for 16 priorities and a very large number of subsystems. + * Bit 5 is used as a flag to specify whether to log the errno value. */ /* @@ -44,38 +45,41 @@ * This includes subsystems in the sudoers plugin. * Note: order must match sudo_debug_subsystems[] */ -#define SUDO_DEBUG_MAIN (1<<4) /* sudo main() */ -#define SUDO_DEBUG_ARGS (2<<4) /* command line argument processing */ -#define SUDO_DEBUG_EXEC (3<<4) /* command execution */ -#define SUDO_DEBUG_PTY (4<<4) /* pseudo-tty */ -#define SUDO_DEBUG_UTMP (5<<4) /* utmp file ops */ -#define SUDO_DEBUG_CONV (6<<4) /* user conversation */ -#define SUDO_DEBUG_PCOMM (7<<4) /* plugin communications */ -#define SUDO_DEBUG_UTIL (8<<4) /* utility functions */ -#define SUDO_DEBUG_NETIF (9<<4) /* network interface functions */ -#define SUDO_DEBUG_AUDIT (10<<4) /* audit */ -#define SUDO_DEBUG_EDIT (11<<4) /* sudoedit */ -#define SUDO_DEBUG_SELINUX (12<<4) /* selinux */ -#define SUDO_DEBUG_LDAP (13<<4) /* sudoers LDAP */ -#define SUDO_DEBUG_MATCH (14<<4) /* sudoers matching */ -#define SUDO_DEBUG_PARSER (15<<4) /* sudoers parser */ -#define SUDO_DEBUG_ALIAS (16<<4) /* sudoers alias functions */ -#define SUDO_DEBUG_DEFAULTS (17<<4) /* sudoers defaults settings */ -#define SUDO_DEBUG_AUTH (18<<4) /* authentication functions */ -#define SUDO_DEBUG_ENV (19<<4) /* environment handling */ -#define SUDO_DEBUG_LOGGING (20<<4) /* logging functions */ -#define SUDO_DEBUG_NSS (21<<4) /* network service switch */ -#define SUDO_DEBUG_RBTREE (22<<4) /* red-black tree functions */ -#define SUDO_DEBUG_PERMS (23<<4) /* uid/gid swapping functions */ -#define SUDO_DEBUG_PLUGIN (24<<4) /* main plugin functions */ -#define SUDO_DEBUG_HOOKS (25<<4) /* hook functions */ +#define SUDO_DEBUG_MAIN ( 1<<5) /* sudo main() */ +#define SUDO_DEBUG_ARGS ( 2<<5) /* command line argument processing */ +#define SUDO_DEBUG_EXEC ( 3<<5) /* command execution */ +#define SUDO_DEBUG_PTY ( 4<<5) /* pseudo-tty */ +#define SUDO_DEBUG_UTMP ( 5<<5) /* utmp file ops */ +#define SUDO_DEBUG_CONV ( 6<<5) /* user conversation */ +#define SUDO_DEBUG_PCOMM ( 7<<5) /* plugin communications */ +#define SUDO_DEBUG_UTIL ( 8<<5) /* utility functions */ +#define SUDO_DEBUG_NETIF ( 9<<5) /* network interface functions */ +#define SUDO_DEBUG_AUDIT (10<<5) /* audit */ +#define SUDO_DEBUG_EDIT (11<<5) /* sudoedit */ +#define SUDO_DEBUG_SELINUX (12<<5) /* selinux */ +#define SUDO_DEBUG_LDAP (13<<5) /* sudoers LDAP */ +#define SUDO_DEBUG_MATCH (14<<5) /* sudoers matching */ +#define SUDO_DEBUG_PARSER (15<<5) /* sudoers parser */ +#define SUDO_DEBUG_ALIAS (16<<5) /* sudoers alias functions */ +#define SUDO_DEBUG_DEFAULTS (17<<5) /* sudoers defaults settings */ +#define SUDO_DEBUG_AUTH (18<<5) /* authentication functions */ +#define SUDO_DEBUG_ENV (19<<5) /* environment handling */ +#define SUDO_DEBUG_LOGGING (20<<5) /* logging functions */ +#define SUDO_DEBUG_NSS (21<<5) /* network service switch */ +#define SUDO_DEBUG_RBTREE (22<<5) /* red-black tree functions */ +#define SUDO_DEBUG_PERMS (23<<5) /* uid/gid swapping functions */ +#define SUDO_DEBUG_PLUGIN (24<<5) /* main plugin functions */ +#define SUDO_DEBUG_HOOKS (25<<5) /* hook functions */ #define SUDO_DEBUG_ALL 0xfff0 /* all subsystems */ +/* Flag to include string version of errno in debug info. */ +#define SUDO_DEBUG_ERRNO (1<<4) + /* Extract priority and convert to an index. */ #define SUDO_DEBUG_PRI(n) (((n) & 0xf) - 1) /* Extract subsystem and convert to an index. */ -#define SUDO_DEBUG_SUBSYS(n) (((n) >> 4) - 1) +#define SUDO_DEBUG_SUBSYS(n) (((n) >> 5) - 1) /* * Wrapper for sudo_debug_enter() that declares __func__ as needed @@ -191,6 +195,6 @@ void sudo_debug_exit_ptr(const char *func, const char *file, int line, int subsy int sudo_debug_fd_set(int fd); int sudo_debug_init(const char *debugfile, const char *settings); void sudo_debug_printf2(int level, const char *format, ...) __printflike(2, 3); -void sudo_debug_write(const char *str, int len); +void sudo_debug_write(const char *str, int len, int errno_val); #endif /* _SUDO_DEBUG_H */ diff --git a/src/conversation.c b/src/conversation.c index a2dab5a7c..737335eb8 100644 --- a/src/conversation.c +++ b/src/conversation.c @@ -98,7 +98,7 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], break; case SUDO_CONV_DEBUG_MSG: if (msg->msg) - sudo_debug_write(msg->msg, strlen(msg->msg)); + sudo_debug_write(msg->msg, strlen(msg->msg), 0); break; default: goto err;