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 "common.h"
21 #include "daemon.h"
22
23 #include "pid.h"
24 #include "cfg.h"
25 #include "log.h"
26 #include "zbxself.h"
27
28 #include "fatal.h"
29 #include "sighandler.h"
30 #include "sigcommon.h"
31
32 char *CONFIG_PID_FILE = NULL;
33 static int parent_pid = -1;
34
35 extern pid_t *threads;
36 extern int threads_num;
37
38 #ifdef HAVE_SIGQUEUE
39 extern unsigned char program_type;
40 #endif
41
42 extern int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type,
43 int *local_process_num);
44
45 static void (*zbx_sigusr_handler)(int flags);
46
47 #ifdef HAVE_SIGQUEUE
48 /******************************************************************************
49 * *
50 * Function: common_sigusr_handler *
51 * *
52 * Purpose: common SIGUSR1 handler for Zabbix processes *
53 * *
54 ******************************************************************************/
common_sigusr_handler(int flags)55 static void common_sigusr_handler(int flags)
56 {
57 switch (ZBX_RTC_GET_MSG(flags))
58 {
59 case ZBX_RTC_LOG_LEVEL_INCREASE:
60 if (SUCCEED != zabbix_increase_log_level())
61 {
62 zabbix_log(LOG_LEVEL_INFORMATION, "cannot increase log level:"
63 " maximum level has been already set");
64 }
65 else
66 {
67 zabbix_log(LOG_LEVEL_INFORMATION, "log level has been increased to %s",
68 zabbix_get_log_level_string());
69 }
70 break;
71 case ZBX_RTC_LOG_LEVEL_DECREASE:
72 if (SUCCEED != zabbix_decrease_log_level())
73 {
74 zabbix_log(LOG_LEVEL_INFORMATION, "cannot decrease log level:"
75 " minimum level has been already set");
76 }
77 else
78 {
79 zabbix_log(LOG_LEVEL_INFORMATION, "log level has been decreased to %s",
80 zabbix_get_log_level_string());
81 }
82 break;
83 default:
84 if (NULL != zbx_sigusr_handler)
85 zbx_sigusr_handler(flags);
86 break;
87 }
88 }
89
zbx_signal_process_by_type(int proc_type,int proc_num,int flags)90 static void zbx_signal_process_by_type(int proc_type, int proc_num, int flags)
91 {
92 int process_num, found = 0, i;
93 union sigval s;
94 unsigned char process_type;
95
96 s.ZBX_SIVAL_INT = flags;
97
98 for (i = 0; i < threads_num; i++)
99 {
100 if (FAIL == get_process_info_by_thread(i + 1, &process_type, &process_num))
101 break;
102
103 if (proc_type != process_type)
104 {
105 /* check if we have already checked processes of target type */
106 if (1 == found)
107 break;
108
109 continue;
110 }
111
112 if (0 != proc_num && proc_num != process_num)
113 continue;
114
115 found = 1;
116
117 if (-1 != sigqueue(threads[i], SIGUSR1, s))
118 {
119 zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to \"%s\" process"
120 " pid:%d", get_process_type_string(process_type), threads[i]);
121 }
122 else
123 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
124 }
125
126 if (0 == found)
127 {
128 if (0 == proc_num)
129 {
130 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
131 " \"%s\" process does not exist",
132 get_process_type_string(proc_type));
133 }
134 else
135 {
136 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal:"
137 " \"%s #%d\" process does not exist",
138 get_process_type_string(proc_type), proc_num);
139 }
140 }
141 }
142
zbx_signal_process_by_pid(int pid,int flags)143 static void zbx_signal_process_by_pid(int pid, int flags)
144 {
145 union sigval s;
146 int i, found;
147
148 s.ZBX_SIVAL_INT = flags;
149
150 for (i = 0; i < threads_num; i++)
151 {
152 if (0 != pid && threads[i] != ZBX_RTC_GET_DATA(flags))
153 continue;
154
155 found = 1;
156
157 if (-1 != sigqueue(threads[i], SIGUSR1, s))
158 {
159 zabbix_log(LOG_LEVEL_DEBUG, "the signal was redirected to process pid:%d",
160 threads[i]);
161 }
162 else
163 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: %s", zbx_strerror(errno));
164 }
165
166 if (0 != ZBX_RTC_GET_DATA(flags) && 0 == found)
167 {
168 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: process pid:%d is not a Zabbix child"
169 " process", ZBX_RTC_GET_DATA(flags));
170 }
171 }
172
173 #endif
174
zbx_set_sigusr_handler(void (* handler)(int flags))175 void zbx_set_sigusr_handler(void (*handler)(int flags))
176 {
177 zbx_sigusr_handler = handler;
178 }
179
180 /******************************************************************************
181 * *
182 * Function: user1_signal_handler *
183 * *
184 * Purpose: handle user signal SIGUSR1 *
185 * *
186 ******************************************************************************/
user1_signal_handler(int sig,siginfo_t * siginfo,void * context)187 static void user1_signal_handler(int sig, siginfo_t *siginfo, void *context)
188 {
189 #ifdef HAVE_SIGQUEUE
190 int flags;
191 #endif
192 SIG_CHECK_PARAMS(sig, siginfo, context);
193
194 zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d,sender_uid:%d,value_int:%d(0x%08x)].",
195 sig, get_signal_name(sig),
196 SIG_CHECKED_FIELD(siginfo, si_pid),
197 SIG_CHECKED_FIELD(siginfo, si_uid),
198 SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT),
199 SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT));
200 #ifdef HAVE_SIGQUEUE
201 flags = SIG_CHECKED_FIELD(siginfo, si_value.ZBX_SIVAL_INT);
202
203 if (!SIG_PARENT_PROCESS)
204 {
205 common_sigusr_handler(flags);
206 return;
207 }
208
209 if (NULL == threads)
210 {
211 zabbix_log(LOG_LEVEL_ERR, "cannot redirect signal: shutdown in progress");
212 return;
213 }
214
215 switch (ZBX_RTC_GET_MSG(flags))
216 {
217 case ZBX_RTC_CONFIG_CACHE_RELOAD:
218 if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
219 {
220 zabbix_log(LOG_LEVEL_WARNING, "forced reloading of the configuration cache"
221 " cannot be performed for a passive proxy");
222 return;
223 }
224
225 zbx_signal_process_by_type(ZBX_PROCESS_TYPE_CONFSYNCER, 1, flags);
226 break;
227 case ZBX_RTC_HOUSEKEEPER_EXECUTE:
228 zbx_signal_process_by_type(ZBX_PROCESS_TYPE_HOUSEKEEPER, 1, flags);
229 break;
230 case ZBX_RTC_LOG_LEVEL_INCREASE:
231 case ZBX_RTC_LOG_LEVEL_DECREASE:
232 if ((ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID) == ZBX_RTC_GET_SCOPE(flags))
233 zbx_signal_process_by_pid(ZBX_RTC_GET_DATA(flags), flags);
234 else
235 zbx_signal_process_by_type(ZBX_RTC_GET_SCOPE(flags), ZBX_RTC_GET_DATA(flags), flags);
236 break;
237 }
238 #endif
239 }
240
241 /******************************************************************************
242 * *
243 * Function: pipe_signal_handler *
244 * *
245 * Purpose: handle pipe signal SIGPIPE *
246 * *
247 ******************************************************************************/
pipe_signal_handler(int sig,siginfo_t * siginfo,void * context)248 static void pipe_signal_handler(int sig, siginfo_t *siginfo, void *context)
249 {
250 SIG_CHECK_PARAMS(sig, siginfo, context);
251
252 zabbix_log(LOG_LEVEL_DEBUG, "Got signal [signal:%d(%s),sender_pid:%d]. Ignoring ...",
253 sig, get_signal_name(sig),
254 SIG_CHECKED_FIELD(siginfo, si_pid));
255 }
256
257 /******************************************************************************
258 * *
259 * Function: set_daemon_signal_handlers *
260 * *
261 * Purpose: set the signal handlers used by daemons *
262 * *
263 ******************************************************************************/
set_daemon_signal_handlers(void)264 static void set_daemon_signal_handlers(void)
265 {
266 struct sigaction phan;
267
268 sig_parent_pid = (int)getpid();
269
270 sigemptyset(&phan.sa_mask);
271 phan.sa_flags = SA_SIGINFO;
272
273 phan.sa_sigaction = user1_signal_handler;
274 sigaction(SIGUSR1, &phan, NULL);
275
276 phan.sa_sigaction = pipe_signal_handler;
277 sigaction(SIGPIPE, &phan, NULL);
278 }
279
280 /******************************************************************************
281 * *
282 * Function: daemon_start *
283 * *
284 * Purpose: init process as daemon *
285 * *
286 * Parameters: allow_root - allow root permission for application *
287 * user - user on the system to which to drop the *
288 * privileges *
289 * flags - daemon startup flags *
290 * *
291 * Author: Alexei Vladishev *
292 * *
293 * Comments: it doesn't allow running under 'root' if allow_root is zero *
294 * *
295 ******************************************************************************/
daemon_start(int allow_root,const char * user,unsigned int flags)296 int daemon_start(int allow_root, const char *user, unsigned int flags)
297 {
298 pid_t pid;
299 struct passwd *pwd;
300
301 if (0 == allow_root && 0 == getuid()) /* running as root? */
302 {
303 if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND))
304 {
305 zbx_error("cannot run as root!");
306 exit(EXIT_FAILURE);
307 }
308
309 if (NULL == user)
310 user = "zabbix";
311
312 pwd = getpwnam(user);
313
314 if (NULL == pwd)
315 {
316 zbx_error("user %s does not exist", user);
317 zbx_error("cannot run as root!");
318 exit(EXIT_FAILURE);
319 }
320
321 if (0 == pwd->pw_uid)
322 {
323 zbx_error("User=%s contradicts AllowRoot=0", user);
324 zbx_error("cannot run as root!");
325 exit(EXIT_FAILURE);
326 }
327
328 if (-1 == setgid(pwd->pw_gid))
329 {
330 zbx_error("cannot setgid to %s: %s", user, zbx_strerror(errno));
331 exit(EXIT_FAILURE);
332 }
333
334 #ifdef HAVE_FUNCTION_INITGROUPS
335 if (-1 == initgroups(user, pwd->pw_gid))
336 {
337 zbx_error("cannot initgroups to %s: %s", user, zbx_strerror(errno));
338 exit(EXIT_FAILURE);
339 }
340 #endif
341
342 if (-1 == setuid(pwd->pw_uid))
343 {
344 zbx_error("cannot setuid to %s: %s", user, zbx_strerror(errno));
345 exit(EXIT_FAILURE);
346 }
347
348 #ifdef HAVE_FUNCTION_SETEUID
349 if (-1 == setegid(pwd->pw_gid) || -1 == seteuid(pwd->pw_uid))
350 {
351 zbx_error("cannot setegid or seteuid to %s: %s", user, zbx_strerror(errno));
352 exit(EXIT_FAILURE);
353 }
354 #endif
355 }
356
357 umask(0002);
358
359 if (0 == (flags & ZBX_TASK_FLAG_FOREGROUND))
360 {
361 if (0 != (pid = zbx_fork()))
362 exit(EXIT_SUCCESS);
363
364 setsid();
365
366 signal(SIGHUP, SIG_IGN);
367
368 if (0 != (pid = zbx_fork()))
369 exit(EXIT_SUCCESS);
370
371 if (-1 == chdir("/")) /* this is to eliminate warning: ignoring return value of chdir */
372 assert(0);
373
374 zbx_redirect_stdio(LOG_TYPE_FILE == CONFIG_LOG_TYPE ? CONFIG_LOG_FILE : NULL);
375 }
376
377 if (FAIL == create_pid_file(CONFIG_PID_FILE))
378 exit(EXIT_FAILURE);
379
380 atexit(daemon_stop);
381
382 parent_pid = (int)getpid();
383
384 zbx_set_common_signal_handlers();
385 set_daemon_signal_handlers();
386
387 /* Set SIGCHLD now to avoid race conditions when a child process is created before */
388 /* sigaction() is called. To avoid problems when scripts exit in zbx_execute() and */
389 /* other cases, SIGCHLD is set to SIG_DFL in zbx_child_fork(). */
390 zbx_set_child_signal_handler();
391
392 return MAIN_ZABBIX_ENTRY(flags);
393 }
394
daemon_stop(void)395 void daemon_stop(void)
396 {
397 /* this function is registered using atexit() to be called when we terminate */
398 /* there should be nothing like logging or calls to exit() beyond this point */
399
400 if (parent_pid != (int)getpid())
401 return;
402
403 drop_pid_file(CONFIG_PID_FILE);
404 }
405
zbx_sigusr_send(int flags)406 int zbx_sigusr_send(int flags)
407 {
408 int ret = FAIL;
409 char error[256];
410 #ifdef HAVE_SIGQUEUE
411 pid_t pid;
412
413 if (SUCCEED == read_pid_file(CONFIG_PID_FILE, &pid, error, sizeof(error)))
414 {
415 union sigval s;
416
417 s.ZBX_SIVAL_INT = flags;
418
419 if (-1 != sigqueue(pid, SIGUSR1, s))
420 {
421 zbx_error("command sent successfully");
422 ret = SUCCEED;
423 }
424 else
425 {
426 zbx_snprintf(error, sizeof(error), "cannot send command to PID [%d]: %s",
427 (int)pid, zbx_strerror(errno));
428 }
429 }
430 #else
431 zbx_snprintf(error, sizeof(error), "operation is not supported on the given operating system");
432 #endif
433 if (SUCCEED != ret)
434 zbx_error("%s", error);
435
436 return ret;
437 }
438