1 /* 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2011-2017 Todd C. Miller <Todd.Miller@sudo.ws> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef SUDO_DEBUG_H 20 #define SUDO_DEBUG_H 21 22 #include <sys/types.h> /* for id_t, size_t, ssize_t, time_t */ 23 #include <stdarg.h> 24 #ifdef HAVE_STDBOOL_H 25 # include <stdbool.h> 26 #else 27 # include "compat/stdbool.h" 28 #endif 29 #include "sudo_queue.h" 30 31 /* 32 * List of debug files and flags for use in registration. 33 */ 34 struct sudo_debug_file { 35 TAILQ_ENTRY(sudo_debug_file) entries; 36 char *debug_file; 37 char *debug_flags; 38 }; 39 struct sudo_conf_debug_file_list; 40 41 /* 42 * The priority and subsystem are encoded in a single 32-bit value. 43 * The lower 4 bits are the priority and the top 26 bits are the subsystem. 44 * This allows for 16 priorities and a very large number of subsystems. 45 * Bit 5 is used as a flag to specify whether to log the errno value. 46 * Bit 6 specifies whether to log the function, file and line number data. 47 */ 48 49 /* 50 * Sudo debug priorities, ordered least to most verbose, 51 * in other words, highest to lowest priority. Max pri is 15. 52 * Note: order must match sudo_debug_priorities[] 53 */ 54 #define SUDO_DEBUG_CRIT 1 /* critical errors */ 55 #define SUDO_DEBUG_ERROR 2 /* non-critical errors */ 56 #define SUDO_DEBUG_WARN 3 /* non-fatal warnings */ 57 #define SUDO_DEBUG_NOTICE 4 /* non-error condition notices */ 58 #define SUDO_DEBUG_DIAG 5 /* diagnostic messages */ 59 #define SUDO_DEBUG_INFO 6 /* informational message */ 60 #define SUDO_DEBUG_TRACE 7 /* log function enter/exit */ 61 #define SUDO_DEBUG_DEBUG 8 /* very verbose debugging */ 62 63 /* Flag to include string version of errno in debug info. */ 64 #define SUDO_DEBUG_ERRNO (1<<4) 65 66 /* Flag to include function, file and line number in debug info. */ 67 #define SUDO_DEBUG_LINENO (1<<5) 68 69 /* 70 * Sudo debug subsystems. 71 * This includes subsystems in the sudoers plugin. 72 * Note: order must match sudo_debug_subsystems[] 73 */ 74 #define SUDO_DEBUG_ARGS ( 1<<6) /* command line argument handling */ 75 #define SUDO_DEBUG_CONV ( 2<<6) /* user conversation */ 76 #define SUDO_DEBUG_EDIT ( 3<<6) /* sudoedit */ 77 #define SUDO_DEBUG_EVENT ( 4<<6) /* event handling */ 78 #define SUDO_DEBUG_EXEC ( 5<<6) /* command execution */ 79 #define SUDO_DEBUG_HOOKS ( 6<<6) /* hook functions */ 80 #define SUDO_DEBUG_MAIN ( 7<<6) /* sudo main() */ 81 #define SUDO_DEBUG_NETIF ( 8<<6) /* network interface functions */ 82 #define SUDO_DEBUG_PCOMM ( 9<<6) /* plugin communications */ 83 #define SUDO_DEBUG_PLUGIN (10<<6) /* main plugin functions */ 84 #define SUDO_DEBUG_PTY (11<<6) /* pseudo-tty */ 85 #define SUDO_DEBUG_SELINUX (12<<6) /* selinux */ 86 #define SUDO_DEBUG_UTIL (13<<6) /* utility functions */ 87 #define SUDO_DEBUG_UTMP (14<<6) /* utmp file ops */ 88 #define SUDO_DEBUG_ALL 0xffff0000 /* all subsystems */ 89 90 /* Error return for sudo_debug_register(). */ 91 #define SUDO_DEBUG_INSTANCE_ERROR -2 92 93 /* Initializer for instance index to indicate that debugging is not setup. */ 94 #define SUDO_DEBUG_INSTANCE_INITIALIZER -1 95 96 /* Extract priority number and convert to an index. */ 97 #define SUDO_DEBUG_PRI(n) (((n) & 0x0f) - 1) 98 99 /* Extract subsystem number and convert to an index. */ 100 #define SUDO_DEBUG_SUBSYS(n) (((n) >> 6) - 1) 101 102 /* 103 * Wrapper for sudo_debug_enter() that declares __func__ as needed 104 * and sets sudo_debug_subsys for sudo_debug_exit(). 105 */ 106 #ifdef HAVE___FUNC__ 107 # define debug_decl_func(funcname) 108 # define debug_decl_vars(funcname, subsys) \ 109 const int sudo_debug_subsys = (subsys) 110 #else 111 # define debug_decl_func(funcname) \ 112 const char __func__[] = #funcname; 113 # define debug_decl_vars(funcname, subsys) \ 114 debug_decl_func(funcname) \ 115 const int sudo_debug_subsys = (subsys) 116 #endif 117 #define debug_decl(funcname, subsys) \ 118 debug_decl_vars((funcname), (subsys)); \ 119 sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys) 120 121 /* 122 * Wrappers for sudo_debug_exit() and friends. 123 */ 124 #define debug_return \ 125 do { \ 126 sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys); \ 127 return; \ 128 } while (0) 129 130 #define debug_return_int(ret) \ 131 do { \ 132 int sudo_debug_ret = (ret); \ 133 sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 134 sudo_debug_ret); \ 135 return sudo_debug_ret; \ 136 } while (0) 137 138 #define debug_return_id_t(ret) \ 139 do { \ 140 id_t sudo_debug_ret = (ret); \ 141 sudo_debug_exit_id_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\ 142 sudo_debug_ret); \ 143 return sudo_debug_ret; \ 144 } while (0) 145 146 #define debug_return_size_t(ret) \ 147 do { \ 148 size_t sudo_debug_ret = (ret); \ 149 sudo_debug_exit_size_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\ 150 sudo_debug_ret); \ 151 return sudo_debug_ret; \ 152 } while (0) 153 154 #define debug_return_ssize_t(ret) \ 155 do { \ 156 ssize_t sudo_debug_ret = (ret); \ 157 sudo_debug_exit_ssize_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\ 158 sudo_debug_ret); \ 159 return sudo_debug_ret; \ 160 } while (0) 161 162 #define debug_return_time_t(ret) \ 163 do { \ 164 time_t sudo_debug_ret = (ret); \ 165 sudo_debug_exit_time_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\ 166 sudo_debug_ret); \ 167 return sudo_debug_ret; \ 168 } while (0) 169 170 #define debug_return_long(ret) \ 171 do { \ 172 long sudo_debug_ret = (ret); \ 173 sudo_debug_exit_long(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 174 sudo_debug_ret); \ 175 return sudo_debug_ret; \ 176 } while (0) 177 178 #define debug_return_bool(ret) \ 179 do { \ 180 bool sudo_debug_ret = (ret); \ 181 sudo_debug_exit_bool(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 182 sudo_debug_ret); \ 183 return sudo_debug_ret; \ 184 } while (0) 185 186 #define debug_return_str(ret) \ 187 do { \ 188 char *sudo_debug_ret = (ret); \ 189 sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 190 sudo_debug_ret); \ 191 return sudo_debug_ret; \ 192 } while (0) 193 194 #define debug_return_const_str(ret) \ 195 do { \ 196 const char *sudo_debug_ret = (ret); \ 197 sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 198 sudo_debug_ret); \ 199 return sudo_debug_ret; \ 200 } while (0) 201 202 #define debug_return_str_masked(ret) \ 203 do { \ 204 char *sudo_debug_ret = (ret); \ 205 sudo_debug_exit_str_masked(__func__, __FILE__, __LINE__, \ 206 sudo_debug_subsys, sudo_debug_ret); \ 207 return sudo_debug_ret; \ 208 } while (0) 209 210 #define debug_return_ptr(ret) \ 211 do { \ 212 void *sudo_debug_ret = (ret); \ 213 sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 214 sudo_debug_ret); \ 215 return sudo_debug_ret; \ 216 } while (0) 217 218 #define debug_return_const_ptr(ret) \ 219 do { \ 220 const void *sudo_debug_ret = (ret); \ 221 sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys, \ 222 sudo_debug_ret); \ 223 return sudo_debug_ret; \ 224 } while (0) 225 226 /* 227 * Variadic macros are a C99 feature but GNU cpp has supported 228 * a (different) version of them for a long time. 229 */ 230 #if defined(NO_VARIADIC_MACROS) 231 # define sudo_debug_printf sudo_debug_printf_nvm 232 #elif defined(__GNUC__) && __GNUC__ == 2 233 # define sudo_debug_printf(pri, fmt...) \ 234 sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \ 235 fmt) 236 #else 237 # define sudo_debug_printf(pri, ...) \ 238 sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \ 239 __VA_ARGS__) 240 #endif 241 242 #define sudo_debug_execve(pri, path, argv, envp) \ 243 sudo_debug_execve2((pri)|sudo_debug_subsys, (path), (argv), (envp)) 244 245 #define sudo_debug_write(fd, str, len, errnum) \ 246 sudo_debug_write2(fd, NULL, NULL, 0, (str), (len), (errnum)) 247 248 sudo_dso_public int sudo_debug_deregister_v1(int instance_id); 249 sudo_dso_public void sudo_debug_enter_v1(const char *func, const char *file, int line, int subsys); 250 sudo_dso_public void sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *const envp[]); 251 sudo_dso_public void sudo_debug_exit_v1(const char *func, const char *file, int line, int subsys); 252 sudo_dso_public void sudo_debug_exit_bool_v1(const char *func, const char *file, int line, int subsys, bool ret); 253 sudo_dso_public void sudo_debug_exit_int_v1(const char *func, const char *file, int line, int subsys, int ret); 254 sudo_dso_public void sudo_debug_exit_long_v1(const char *func, const char *file, int line, int subsys, long ret); 255 sudo_dso_public void sudo_debug_exit_ptr_v1(const char *func, const char *file, int line, int subsys, const void *ret); 256 sudo_dso_public void sudo_debug_exit_id_t_v1(const char *func, const char *file, int line, int subsys, id_t ret); 257 sudo_dso_public void sudo_debug_exit_size_t_v1(const char *func, const char *file, int line, int subsys, size_t ret); 258 sudo_dso_public void sudo_debug_exit_ssize_t_v1(const char *func, const char *file, int line, int subsys, ssize_t ret); 259 sudo_dso_public void sudo_debug_exit_str_v1(const char *func, const char *file, int line, int subsys, const char *ret); 260 sudo_dso_public void sudo_debug_exit_str_masked_v1(const char *func, const char *file, int line, int subsys, const char *ret); 261 sudo_dso_public void sudo_debug_exit_time_t_v1(const char *func, const char *file, int line, int subsys, time_t ret); 262 sudo_dso_public pid_t sudo_debug_fork_v1(void); 263 sudo_dso_public int sudo_debug_get_active_instance_v1(void); 264 sudo_dso_public int sudo_debug_get_fds_v1(unsigned char **fds); 265 sudo_dso_public int sudo_debug_get_instance_v1(const char *program); 266 sudo_dso_public int sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files, const char *entry); 267 sudo_dso_public void sudo_debug_printf2_v1(const char *func, const char *file, int line, int level, const char *fmt, ...) __printf0like(5, 6); 268 sudo_dso_public void sudo_debug_printf_nvm_v1(int pri, const char *fmt, ...) __printf0like(2, 3); 269 sudo_dso_public int sudo_debug_register_v1(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files); 270 sudo_dso_public int sudo_debug_register_v2(const char *program, const char *const subsystems[], unsigned int ids[], struct sudo_conf_debug_file_list *debug_files, int minfd); 271 sudo_dso_public int sudo_debug_set_active_instance_v1(int inst); 272 sudo_dso_public void sudo_debug_update_fd_v1(int ofd, int nfd); 273 sudo_dso_public void sudo_debug_vprintf2_v1(const char *func, const char *file, int line, int level, const char *fmt, va_list ap) __printf0like(5, 0); 274 sudo_dso_public void sudo_debug_write2_v1(int fd, const char *func, const char *file, int line, const char *str, int len, int errnum); 275 sudo_dso_public bool sudo_debug_needed_v1(int level); 276 277 #define sudo_debug_needed(level) sudo_debug_needed_v1((level)|sudo_debug_subsys) 278 #define sudo_debug_deregister(_a) sudo_debug_deregister_v1((_a)) 279 #define sudo_debug_enter(_a, _b, _c, _d) sudo_debug_enter_v1((_a), (_b), (_c), (_d)) 280 #define sudo_debug_execve2(_a, _b, _c, _d) sudo_debug_execve2_v1((_a), (_b), (_c), (_d)) 281 #define sudo_debug_exit(_a, _b, _c, _d) sudo_debug_exit_v1((_a), (_b), (_c), (_d)) 282 #define sudo_debug_exit_bool(_a, _b, _c, _d, _e) sudo_debug_exit_bool_v1((_a), (_b), (_c), (_d), (_e)) 283 #define sudo_debug_exit_int(_a, _b, _c, _d, _e) sudo_debug_exit_int_v1((_a), (_b), (_c), (_d), (_e)) 284 #define sudo_debug_exit_long(_a, _b, _c, _d, _e) sudo_debug_exit_long_v1((_a), (_b), (_c), (_d), (_e)) 285 #define sudo_debug_exit_ptr(_a, _b, _c, _d, _e) sudo_debug_exit_ptr_v1((_a), (_b), (_c), (_d), (_e)) 286 #define sudo_debug_exit_id_t(_a, _b, _c, _d, _e) sudo_debug_exit_id_t_v1((_a), (_b), (_c), (_d), (_e)) 287 #define sudo_debug_exit_size_t(_a, _b, _c, _d, _e) sudo_debug_exit_size_t_v1((_a), (_b), (_c), (_d), (_e)) 288 #define sudo_debug_exit_ssize_t(_a, _b, _c, _d, _e) sudo_debug_exit_ssize_t_v1((_a), (_b), (_c), (_d), (_e)) 289 #define sudo_debug_exit_str(_a, _b, _c, _d, _e) sudo_debug_exit_str_v1((_a), (_b), (_c), (_d), (_e)) 290 #define sudo_debug_exit_str_masked(_a, _b, _c, _d, _e) sudo_debug_exit_str_masked_v1((_a), (_b), (_c), (_d), (_e)) 291 #define sudo_debug_exit_time_t(_a, _b, _c, _d, _e) sudo_debug_exit_time_t_v1((_a), (_b), (_c), (_d), (_e)) 292 #define sudo_debug_fork() sudo_debug_fork_v1() 293 #define sudo_debug_get_active_instance() sudo_debug_get_active_instance_v1() 294 #define sudo_debug_get_fds(_a) sudo_debug_get_fds_v1((_a)) 295 #define sudo_debug_get_instance(_a) sudo_debug_get_instance_v1((_a)) 296 #define sudo_debug_parse_flags(_a, _b) sudo_debug_parse_flags_v1((_a), (_b)) 297 #define sudo_debug_printf2 sudo_debug_printf2_v1 298 #define sudo_debug_printf_nvm sudo_debug_printf_nvm_v1 299 #define sudo_debug_register(_a, _b, _c, _d, _e) sudo_debug_register_v2((_a), (_b), (_c), (_d), (_e)) 300 #define sudo_debug_set_active_instance(_a) sudo_debug_set_active_instance_v1((_a)) 301 #define sudo_debug_update_fd(_a, _b) sudo_debug_update_fd_v1((_a), (_b)) 302 #define sudo_debug_vprintf2(_a, _b, _c, _d, _e, _f) sudo_debug_vprintf2_v1((_a), (_b), (_c), (_d), (_e), (_f)) 303 #define sudo_debug_write2(_a, _b, _c, _d, _e, _f, _g) sudo_debug_write2_v1((_a), (_b), (_c), (_d), (_e), (_f), (_g)) 304 305 #endif /* SUDO_DEBUG_H */ 306