summaryrefslogtreecommitdiffstats
path: root/include/sudo_debug.h
blob: 5ee5cc18d821fa3350d14046465b521db967477c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
/*
 * SPDX-License-Identifier: ISC
 *
 * Copyright (c) 2011-2017 Todd C. Miller <Todd.Miller@sudo.ws>
 *
 * 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.
 */

#ifndef SUDO_DEBUG_H
#define SUDO_DEBUG_H

#include <sys/types.h>		/* for id_t, size_t, ssize_t, time_t */
#include <stdarg.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif
#include "sudo_queue.h"

/*
 * List of debug files and flags for use in registration.
 */
struct sudo_debug_file {
    TAILQ_ENTRY(sudo_debug_file) entries;
    char *debug_file;
    char *debug_flags;
};
struct sudo_conf_debug_file_list;

/*
 * The priority and subsystem are encoded in a single 32-bit value.
 * The lower 4 bits are the priority and the top 26 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.
 * Bit 6 specifies whether to log the function, file and line number data.
 */

/*
 * Sudo debug priorities, ordered least to most verbose,
 * in other words, highest to lowest priority.  Max pri is 15.
 * Note: order must match sudo_debug_priorities[]
 */
#define SUDO_DEBUG_CRIT		1	/* critical errors */
#define SUDO_DEBUG_ERROR	2	/* non-critical errors */
#define SUDO_DEBUG_WARN		3	/* non-fatal warnings */
#define SUDO_DEBUG_NOTICE	4	/* non-error condition notices */
#define SUDO_DEBUG_DIAG		5	/* diagnostic messages */
#define SUDO_DEBUG_INFO		6	/* informational message */
#define SUDO_DEBUG_TRACE	7	/* log function enter/exit */
#define SUDO_DEBUG_DEBUG	8	/* very verbose debugging */

/* Flag to include string version of errno in debug info. */
#define SUDO_DEBUG_ERRNO	(1<<4)

/* Flag to include function, file and line number in debug info. */
#define SUDO_DEBUG_LINENO	(1<<5)

/*
 * Sudo debug subsystems.
 * This includes subsystems in the sudoers plugin.
 * Note: order must match sudo_debug_subsystems[]
 */
#define SUDO_DEBUG_ARGS		( 1<<6)    /* command line argument handling */
#define SUDO_DEBUG_CONV		( 2<<6)    /* user conversation */
#define SUDO_DEBUG_EDIT		( 3<<6)    /* sudoedit */
#define SUDO_DEBUG_EVENT	( 4<<6)    /* event handling */
#define SUDO_DEBUG_EXEC		( 5<<6)    /* command execution */
#define SUDO_DEBUG_HOOKS	( 6<<6)    /* hook functions */
#define SUDO_DEBUG_MAIN		( 7<<6)    /* sudo main() */
#define SUDO_DEBUG_NETIF	( 8<<6)    /* network interface functions */
#define SUDO_DEBUG_PCOMM	( 9<<6)    /* plugin communications */
#define SUDO_DEBUG_PLUGIN	(10<<6)    /* main plugin functions */
#define SUDO_DEBUG_PTY		(11<<6)    /* pseudo-tty */
#define SUDO_DEBUG_SELINUX	(12<<6)    /* selinux */
#define SUDO_DEBUG_UTIL		(13<<6)    /* utility functions */
#define SUDO_DEBUG_UTMP		(14<<6)    /* utmp file ops */
#define SUDO_DEBUG_APPARMOR     (15<<6)    /* AppArmor */
#define SUDO_DEBUG_ALL		0xffff0000 /* all subsystems */

/* Error return for sudo_debug_register().  */
#define SUDO_DEBUG_INSTANCE_ERROR	-2

/* Initializer for instance index to indicate that debugging is not setup. */
#define SUDO_DEBUG_INSTANCE_INITIALIZER	-1

/* Extract priority number and convert to an index. */
#define SUDO_DEBUG_PRI(n) (((n) & 0x0f) - 1)

/* Extract subsystem number and convert to an index. */
#define SUDO_DEBUG_SUBSYS(n) (((n) >> 6) - 1)

/*
 * Wrapper for sudo_debug_enter() that declares __func__ as needed
 * and sets sudo_debug_subsys for sudo_debug_exit().
 */
#ifdef HAVE___FUNC__
# define debug_decl_func(funcname)
# define debug_decl_vars(funcname, subsys)				       \
    const int sudo_debug_subsys = (subsys)
#else
# define debug_decl_func(funcname)					       \
    const char __func__[] = #funcname;
# define debug_decl_vars(funcname, subsys)				       \
    debug_decl_func(funcname)						       \
    const int sudo_debug_subsys = (subsys)
#endif
#define debug_decl(funcname, subsys)					       \
    debug_decl_vars((funcname), (subsys));				       \
    sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys)

/*
 * Wrappers for sudo_debug_exit() and friends.
 */
#define debug_return							       \
    do {								       \
	sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);      \
	return;								       \
    } while (0)

#define debug_return_int(ret)						       \
    do {								       \
	int sudo_debug_ret = (ret);					       \
	sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys,   \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_id_t(ret)					       \
    do {								       \
	id_t sudo_debug_ret = (ret);				       \
	sudo_debug_exit_id_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_size_t(ret)					       \
    do {								       \
	size_t sudo_debug_ret = (ret);				       \
	sudo_debug_exit_size_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_ssize_t(ret)					       \
    do {								       \
	ssize_t sudo_debug_ret = (ret);				       \
	sudo_debug_exit_ssize_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_time_t(ret)					       \
    do {								       \
	time_t sudo_debug_ret = (ret);				       \
	sudo_debug_exit_time_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_long(ret)						       \
    do {								       \
	long sudo_debug_ret = (ret);					       \
	sudo_debug_exit_long(__func__, __FILE__, __LINE__, sudo_debug_subsys,  \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_bool(ret)						       \
    do {								       \
	bool sudo_debug_ret = (ret);					       \
	sudo_debug_exit_bool(__func__, __FILE__, __LINE__, sudo_debug_subsys,  \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_str(ret)						       \
    do {								       \
	char *sudo_debug_ret = (ret);					       \
	sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys,   \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_const_str(ret)					       \
    do {								       \
	const char *sudo_debug_ret = (ret);				       \
	sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys,   \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_str_masked(ret)					       \
    do {								       \
	char *sudo_debug_ret = (ret);					       \
	sudo_debug_exit_str_masked(__func__, __FILE__, __LINE__,	       \
	    sudo_debug_subsys, sudo_debug_ret);			       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_ptr(ret)						       \
    do {								       \
	void *sudo_debug_ret = (ret);					       \
	sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys,   \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

#define debug_return_const_ptr(ret)					       \
    do {								       \
	const void *sudo_debug_ret = (ret);				       \
	sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys,   \
	    sudo_debug_ret);						       \
	return sudo_debug_ret;						       \
    } while (0)

/*
 * Variadic macros are a C99 feature but GNU cpp has supported
 * a (different) version of them for a long time.
 */
#if defined(NO_VARIADIC_MACROS)
# define sudo_debug_printf sudo_debug_printf_nvm
#elif defined(__GNUC__) && __GNUC__ == 2
# define sudo_debug_printf(pri, fmt...) \
    sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \
    fmt)
#else
# define sudo_debug_printf(pri, ...) \
    sudo_debug_printf2(__func__, __FILE__, __LINE__, (pri)|sudo_debug_subsys, \
    __VA_ARGS__)
#endif

#define sudo_debug_execve(pri, path, argv, envp) \
    sudo_debug_execve2((pri)|sudo_debug_subsys, (path), (argv), (envp))

#define sudo_debug_write(fd, str, len, errnum) \
    sudo_debug_write2(fd, NULL, NULL, 0, (str), (len), (errnum))

sudo_dso_public int sudo_debug_deregister_v1(int instance_id);
sudo_dso_public void sudo_debug_enter_v1(const char *func, const char *file, int line, int subsys);
sudo_dso_public void sudo_debug_execve2_v1(int level, const char *path, char *const argv[], char *const envp[]);
sudo_dso_public void sudo_debug_exit_v1(const char *func, const char *file, int line, int subsys);
sudo_dso_public void sudo_debug_exit_bool_v1(const char *func, const char *file, int line, int subsys, bool ret);
sudo_dso_public void sudo_debug_exit_int_v1(const char *func, const char *file, int line, int subsys, int ret);
sudo_dso_public void sudo_debug_exit_long_v1(const char *func, const char *file, int line, int subsys, long ret);
sudo_dso_public void sudo_debug_exit_ptr_v1(const char *func, const char *file, int line, int subsys, const void *ret);
sudo_dso_public void sudo_debug_exit_id_t_v1(const char *func, const char *file, int line, int subsys, id_t ret);
sudo_dso_public void sudo_debug_exit_size_t_v1(const char *func, const char *file, int line, int subsys, size_t ret);
sudo_dso_public void sudo_debug_exit_ssize_t_v1(const char *func, const char *file, int line, int subsys, ssize_t ret);
sudo_dso_public void sudo_debug_exit_str_v1(const char *func, const char *file, int line, int subsys, const char *ret);
sudo_dso_public void sudo_debug_exit_str_masked_v1(const char *func, const char *file, int line, int subsys, const char *ret);
sudo_dso_public void sudo_debug_exit_time_t_v1(const char *func, const char *file, int line, int subsys, time_t ret);
sudo_dso_public pid_t sudo_debug_fork_v1(void);
sudo_dso_public int sudo_debug_get_active_instance_v1(void);
sudo_dso_public int sudo_debug_get_fds_v1(unsigned char **fds);
sudo_dso_public int sudo_debug_get_instance_v1(const char *program);
sudo_dso_public int sudo_debug_parse_flags_v1(struct sudo_conf_debug_file_list *debug_files, const char *entry);
sudo_dso_public void sudo_debug_printf2_v1(const char *func, const char *file, int line, int level, const char *fmt, ...) sudo_printf0like(5, 6);
sudo_dso_public void sudo_debug_printf_nvm_v1(int pri, const char *fmt, ...) sudo_printf0like(2, 3);
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);
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);
sudo_dso_public int sudo_debug_set_active_instance_v1(int inst);
sudo_dso_public void sudo_debug_update_fd_v1(int ofd, int nfd);
sudo_dso_public void sudo_debug_vprintf2_v1(const char *func, const char *file, int line, int level, const char *fmt, va_list ap) sudo_printf0like(5, 0);
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);
sudo_dso_public bool sudo_debug_needed_v1(int level);

#define sudo_debug_needed(level) sudo_debug_needed_v1((level)|sudo_debug_subsys)
#define sudo_debug_deregister(_a) sudo_debug_deregister_v1((_a))
#define sudo_debug_enter(_a, _b, _c, _d) sudo_debug_enter_v1((_a), (_b), (_c), (_d))
#define sudo_debug_execve2(_a, _b, _c, _d) sudo_debug_execve2_v1((_a), (_b), (_c), (_d))
#define sudo_debug_exit(_a, _b, _c, _d) sudo_debug_exit_v1((_a), (_b), (_c), (_d))
#define sudo_debug_exit_bool(_a, _b, _c, _d, _e) sudo_debug_exit_bool_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_int(_a, _b, _c, _d, _e) sudo_debug_exit_int_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_long(_a, _b, _c, _d, _e) sudo_debug_exit_long_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_ptr(_a, _b, _c, _d, _e) sudo_debug_exit_ptr_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_id_t(_a, _b, _c, _d, _e) sudo_debug_exit_id_t_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_size_t(_a, _b, _c, _d, _e) sudo_debug_exit_size_t_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_ssize_t(_a, _b, _c, _d, _e) sudo_debug_exit_ssize_t_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_str(_a, _b, _c, _d, _e) sudo_debug_exit_str_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_str_masked(_a, _b, _c, _d, _e) sudo_debug_exit_str_masked_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_exit_time_t(_a, _b, _c, _d, _e) sudo_debug_exit_time_t_v1((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_fork() sudo_debug_fork_v1()
#define sudo_debug_get_active_instance() sudo_debug_get_active_instance_v1()
#define sudo_debug_get_fds(_a) sudo_debug_get_fds_v1((_a))
#define sudo_debug_get_instance(_a) sudo_debug_get_instance_v1((_a))
#define sudo_debug_parse_flags(_a, _b) sudo_debug_parse_flags_v1((_a), (_b))
#define sudo_debug_printf2 sudo_debug_printf2_v1
#define sudo_debug_printf_nvm sudo_debug_printf_nvm_v1
#define sudo_debug_register(_a, _b, _c, _d, _e) sudo_debug_register_v2((_a), (_b), (_c), (_d), (_e))
#define sudo_debug_set_active_instance(_a) sudo_debug_set_active_instance_v1((_a))
#define sudo_debug_update_fd(_a, _b) sudo_debug_update_fd_v1((_a), (_b))
#define sudo_debug_vprintf2(_a, _b, _c, _d, _e, _f) sudo_debug_vprintf2_v1((_a), (_b), (_c), (_d), (_e), (_f))
#define sudo_debug_write2(_a, _b, _c, _d, _e, _f, _g) sudo_debug_write2_v1((_a), (_b), (_c), (_d), (_e), (_f), (_g))

#endif /* SUDO_DEBUG_H */