1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "config.h"
21 
22 #ifdef HAVE_SIGNAL_H
23 #	if !defined(_GNU_SOURCE)
24 #		define _GNU_SOURCE	/* required for getting at program counter */
25 #	endif
26 #	include <signal.h>
27 #endif
28 
29 #ifdef HAVE_SYS_UCONTEXT_H
30 #	if !defined(_GNU_SOURCE)
31 #		define _GNU_SOURCE	/* required for getting at program counter */
32 #	endif
33 #	include <sys/ucontext.h>
34 #endif
35 
36 #ifdef	HAVE_EXECINFO_H
37 #	include <execinfo.h>
38 #endif
39 
40 #include "common.h"
41 #include "log.h"
42 
43 #include "fatal.h"
44 
get_signal_name(int sig)45 const char	*get_signal_name(int sig)
46 {
47 	/* either strsignal() or sys_siglist[] could be used to */
48 	/* get signal name, but these methods are not portable */
49 
50 	/* not all POSIX signals are available on all platforms, */
51 	/* so we list only signals that we react to in our handlers */
52 
53 	switch (sig)
54 	{
55 		case SIGALRM:	return "SIGALRM";
56 		case SIGILL:	return "SIGILL";
57 		case SIGFPE:	return "SIGFPE";
58 		case SIGSEGV:	return "SIGSEGV";
59 		case SIGBUS:	return "SIGBUS";
60 		case SIGQUIT:	return "SIGQUIT";
61 		case SIGHUP:	return "SIGHUP";
62 		case SIGINT:	return "SIGINT";
63 		case SIGTERM:	return "SIGTERM";
64 		case SIGPIPE:	return "SIGPIPE";
65 		case SIGUSR1:	return "SIGUSR1";
66 		case SIGUSR2:	return "SIGUSR2";
67 		default:	return "unknown";
68 	}
69 }
70 
71 #if defined(HAVE_SYS_UCONTEXT_H) && (defined(REG_EIP) || defined(REG_RIP))
72 
get_register_name(int reg)73 static const char	*get_register_name(int reg)
74 {
75 	switch (reg)
76 	{
77 
78 /* i386 */
79 
80 #ifdef	REG_GS
81 		case REG_GS:	return "gs";
82 #endif
83 #ifdef	REG_FS
84 		case REG_FS:	return "fs";
85 #endif
86 #ifdef	REG_ES
87 		case REG_ES:	return "es";
88 #endif
89 #ifdef	REG_DS
90 		case REG_DS:	return "ds";
91 #endif
92 #ifdef	REG_EDI
93 		case REG_EDI:	return "edi";
94 #endif
95 #ifdef	REG_ESI
96 		case REG_ESI:	return "esi";
97 #endif
98 #ifdef	REG_EBP
99 		case REG_EBP:	return "ebp";
100 #endif
101 #ifdef	REG_ESP
102 		case REG_ESP:	return "esp";
103 #endif
104 #ifdef	REG_EBX
105 		case REG_EBX:	return "ebx";
106 #endif
107 #ifdef	REG_EDX
108 		case REG_EDX:	return "edx";
109 #endif
110 #ifdef	REG_ECX
111 		case REG_ECX:	return "ecx";
112 #endif
113 #ifdef	REG_EAX
114 		case REG_EAX:	return "eax";
115 #endif
116 #ifdef	REG_EIP
117 		case REG_EIP:	return "eip";
118 #endif
119 #ifdef	REG_CS
120 		case REG_CS:	return "cs";
121 #endif
122 #ifdef	REG_UESP
123 		case REG_UESP:	return "uesp";
124 #endif
125 #ifdef	REG_SS
126 		case REG_SS:	return "ss";
127 #endif
128 
129 /* x86_64 */
130 
131 #ifdef	REG_R8
132 		case REG_R8:	return "r8";
133 #endif
134 #ifdef	REG_R9
135 		case REG_R9:	return "r9";
136 #endif
137 #ifdef	REG_R10
138 		case REG_R10:	return "r10";
139 #endif
140 #ifdef	REG_R11
141 		case REG_R11:	return "r11";
142 #endif
143 #ifdef	REG_R12
144 		case REG_R12:	return "r12";
145 #endif
146 #ifdef	REG_R13
147 		case REG_R13:	return "r13";
148 #endif
149 #ifdef	REG_R14
150 		case REG_R14:	return "r14";
151 #endif
152 #ifdef	REG_R15
153 		case REG_R15:	return "r15";
154 #endif
155 #ifdef	REG_RDI
156 		case REG_RDI:	return "rdi";
157 #endif
158 #ifdef	REG_RSI
159 		case REG_RSI:	return "rsi";
160 #endif
161 #ifdef	REG_RBP
162 		case REG_RBP:	return "rbp";
163 #endif
164 #ifdef	REG_RBX
165 		case REG_RBX:	return "rbx";
166 #endif
167 #ifdef	REG_RDX
168 		case REG_RDX:	return "rdx";
169 #endif
170 #ifdef	REG_RAX
171 		case REG_RAX:	return "rax";
172 #endif
173 #ifdef	REG_RCX
174 		case REG_RCX:	return "rcx";
175 #endif
176 #ifdef	REG_RSP
177 		case REG_RSP:	return "rsp";
178 #endif
179 #ifdef	REG_RIP
180 		case REG_RIP:	return "rip";
181 #endif
182 #ifdef	REG_CSGSFS
183 		case REG_CSGSFS:	return "csgsfs";
184 #endif
185 #ifdef	REG_OLDMASK
186 		case REG_OLDMASK:	return "oldmask";
187 #endif
188 #ifdef	REG_CR2
189 		case REG_CR2:	return "cr2";
190 #endif
191 
192 /* i386 and x86_64 */
193 
194 #ifdef	REG_EFL
195 		case REG_EFL:	return "efl";
196 #endif
197 #ifdef	REG_ERR
198 		case REG_ERR:	return "err";
199 #endif
200 #ifdef	REG_TRAPNO
201 		case REG_TRAPNO:	return "trapno";
202 #endif
203 
204 /* unknown */
205 
206 		default:	return "unknown";
207 	}
208 }
209 
210 #endif	/* defined(HAVE_SYS_UCONTEXT_H) && (defined(REG_EIP) || defined(REG_RIP)) */
211 
zbx_backtrace(void)212 void	zbx_backtrace(void)
213 {
214 #	define	ZBX_BACKTRACE_SIZE	60
215 #ifdef	HAVE_EXECINFO_H
216 	char	**bcktrc_syms;
217 	void	*bcktrc[ZBX_BACKTRACE_SIZE];
218 	int	bcktrc_sz, i;
219 
220 	zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ===");
221 
222 	bcktrc_sz = backtrace(bcktrc, ZBX_BACKTRACE_SIZE);
223 	bcktrc_syms = backtrace_symbols(bcktrc, bcktrc_sz);
224 
225 	if (NULL == bcktrc_syms)
226 	{
227 		zabbix_log(LOG_LEVEL_CRIT, "error in backtrace_symbols(): %s", zbx_strerror(errno));
228 
229 		for (i = 0; i < bcktrc_sz; i++)
230 			zabbix_log(LOG_LEVEL_CRIT, "%d: %p", bcktrc_sz - i - 1, bcktrc[i]);
231 	}
232 	else
233 	{
234 		for (i = 0; i < bcktrc_sz; i++)
235 			zabbix_log(LOG_LEVEL_CRIT, "%d: %s", bcktrc_sz - i - 1, bcktrc_syms[i]);
236 
237 		zbx_free(bcktrc_syms);
238 	}
239 #else
240 	zabbix_log(LOG_LEVEL_CRIT, "backtrace is not available for this platform");
241 #endif	/* HAVE_EXECINFO_H */
242 }
243 
zbx_log_fatal_info(void * context,unsigned int flags)244 void	zbx_log_fatal_info(void *context, unsigned int flags)
245 {
246 #ifdef	HAVE_SYS_UCONTEXT_H
247 
248 #if defined(REG_EIP) || defined(REG_RIP)
249 	ucontext_t	*uctx = (ucontext_t *)context;
250 #endif
251 
252 	/* look for GET_PC() macro in sigcontextinfo.h files */
253 	/* of glibc if you wish to add more CPU architectures */
254 
255 #	if	defined(REG_EIP)	/* i386 */
256 
257 #		define ZBX_GET_REG(uctx, reg)	(uctx)->uc_mcontext.gregs[reg]
258 #		define ZBX_GET_PC(uctx)		ZBX_GET_REG(uctx, REG_EIP)
259 
260 #	elif	defined(REG_RIP)	/* x86_64 */
261 
262 #		define ZBX_GET_REG(uctx, reg)	(uctx)->uc_mcontext.gregs[reg]
263 #		define ZBX_GET_PC(uctx)		ZBX_GET_REG(uctx, REG_RIP)
264 
265 #	endif
266 
267 #endif	/* HAVE_SYS_UCONTEXT_H */
268 	int	i;
269 	FILE	*fd;
270 
271 	zabbix_log(LOG_LEVEL_CRIT, "====== Fatal information: ======");
272 
273 	if (0 != (flags & ZBX_FATAL_LOG_PC_REG_SF))
274 	{
275 #ifdef	HAVE_SYS_UCONTEXT_H
276 
277 #ifdef	ZBX_GET_PC
278 		/* On 64-bit GNU/Linux ZBX_GET_PC() returns 'greg_t' defined as 'long long int' (8 bytes). */
279 		/* On 32-bit GNU/Linux it is defined as 'int' (4 bytes). To print registers in a common way we print */
280 		/* them as 'long int' or 'unsigned long int' which is 8 bytes on 64-bit GNU/Linux and 4 bytes on */
281 		/* 32-bit system. */
282 
283 		zabbix_log(LOG_LEVEL_CRIT, "Program counter: %p", (void *)(ZBX_GET_PC(uctx)));
284 		zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
285 
286 		for (i = 0; i < NGREG; i++)
287 		{
288 			zabbix_log(LOG_LEVEL_CRIT, "%-7s = %16lx = %20lu = %20ld", get_register_name(i),
289 					(unsigned long int)(ZBX_GET_REG(uctx, i)),
290 					(unsigned long int)(ZBX_GET_REG(uctx, i)),
291 					(long int)(ZBX_GET_REG(uctx, i)));
292 		}
293 #ifdef	REG_EBP	/* dump a bit of stack frame for i386 */
294 		zabbix_log(LOG_LEVEL_CRIT, "=== Stack frame: ===");
295 
296 		for (i = 16; i >= 2; i--)
297 		{
298 			unsigned int	offset = (unsigned int)i * ZBX_PTR_SIZE;
299 
300 			zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x = %10u = %11d%s",
301 					offset, (int)offset,
302 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
303 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
304 					*(int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + offset),
305 					i == 2 ? " <--- call arguments" : "");
306 		}
307 		zabbix_log(LOG_LEVEL_CRIT, "+0x%02x(%%ebp) = ebp + %2d = %08x%28s<--- return address",
308 					ZBX_PTR_SIZE, (int)ZBX_PTR_SIZE,
309 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) + ZBX_PTR_SIZE), "");
310 		zabbix_log(LOG_LEVEL_CRIT, "     (%%ebp) = ebp      = %08x%28s<--- saved ebp value",
311 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP)), "");
312 
313 		for (i = 1; i <= 16; i++)
314 		{
315 			unsigned int	offset = (unsigned int)i * ZBX_PTR_SIZE;
316 
317 			zabbix_log(LOG_LEVEL_CRIT, "-0x%02x(%%ebp) = ebp - %2d = %08x = %10u = %11d%s",
318 					offset, (int)offset,
319 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
320 					*(unsigned int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
321 					*(int *)((void *)ZBX_GET_REG(uctx, REG_EBP) - offset),
322 					i == 1 ? " <--- local variables" : "");
323 		}
324 #endif	/* REG_EBP */
325 #else
326 		zabbix_log(LOG_LEVEL_CRIT, "program counter not available for this architecture");
327 		zabbix_log(LOG_LEVEL_CRIT, "=== Registers: ===");
328 		zabbix_log(LOG_LEVEL_CRIT, "register dump not available for this architecture");
329 #endif	/* ZBX_GET_PC */
330 #endif	/* HAVE_SYS_UCONTEXT_H */
331 	}
332 
333 	if (0 != (flags & ZBX_FATAL_LOG_BACKTRACE))
334 		zbx_backtrace();
335 
336 	if (0 != (flags & ZBX_FATAL_LOG_MEM_MAP))
337 	{
338 		zabbix_log(LOG_LEVEL_CRIT, "=== Memory map: ===");
339 
340 		if (NULL != (fd = fopen("/proc/self/maps", "r")))
341 		{
342 			char line[1024];
343 
344 			while (NULL != fgets(line, sizeof(line), fd))
345 			{
346 				if (line[0] != '\0')
347 					line[strlen(line) - 1] = '\0'; /* remove trailing '\n' */
348 
349 				zabbix_log(LOG_LEVEL_CRIT, "%s", line);
350 			}
351 
352 			zbx_fclose(fd);
353 		}
354 		else
355 			zabbix_log(LOG_LEVEL_CRIT, "memory map not available for this platform");
356 	}
357 
358 #ifdef	ZBX_GET_PC
359 	zabbix_log(LOG_LEVEL_CRIT, "================================");
360 	zabbix_log(LOG_LEVEL_CRIT, "Please consider attaching a disassembly listing to your bug report.");
361 	zabbix_log(LOG_LEVEL_CRIT, "This listing can be produced with, e.g., objdump -DSswx %s.", progname);
362 #endif
363 
364 	zabbix_log(LOG_LEVEL_CRIT, "================================");
365 }
366