1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <pthread.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <malloc.h>
13 #include <errno.h>
14 #include <sys/inotify.h>
15 #include <sys/epoll.h>
16 #include <time.h>
17 #include <signal.h>
18 #include "load_conf.h"
19 #include "event_queue.h"
20 #include "fsutils.h"
21 #include "strutils.h"
22 #include "channels.h"
23 #include "startupreason.h"
24 #include "probeutils.h"
25 #include "log_sys.h"
26 #include "android_events.h"
27 #include "crash_reclassify.h"
28 
29 #define POLLING_TIMER_SIG 0xCEAC
30 
31 static void channel_oneshot(struct channel_t *cnl);
32 static void channel_polling(struct channel_t *cnl);
33 static void channel_inotify(struct channel_t *cnl);
34 
35 /**
36  * @brief structure containing implementation of each channel.
37  *
38  * This structure describes all channels, all channel_* functions would
39  * called by main thread in order.
40  */
41 static struct channel_t channels[] = {
42 	{"oneshot", -1, channel_oneshot},
43 	{"polling", -1, channel_polling},
44 	{"inotify", -1, channel_inotify},
45 };
46 
47 #define for_each_channel(i, channel) \
48 	for (i = 0; \
49 	     (i < (int)ARRAY_SIZE(channels)) && (channel = &channels[i]); \
50 	     i++)
51 
52 /**
53  * Helper function to create a event and fill event_t structure.
54  *
55  * @param event_type Type of this event.
56  * @param channel Channel where the event comes from.
57  * @param private The corresponding configuration info to the event.
58  * @param watchfd For watch channel, so far, only used by inotify.
59  * @param path File which trigger this event.
60  * @param plen The length of path.
61  *
62  * @return a pointer to the filled event if successful,
63  *  or NULL on error.
64  */
create_event(enum event_type_t event_type,const char * channel,void * private,int watchfd,const char * path,size_t plen)65 static struct event_t *create_event(enum event_type_t event_type,
66 				const char *channel, void *private,
67 				int watchfd, const char *path, size_t plen)
68 {
69 	struct event_t *e;
70 	size_t path_len = 0;
71 
72 	if (path) {
73 		path_len = plen;
74 		if (path_len > PATH_MAX) {
75 			LOGE("invalid path, drop event.\n");
76 			return NULL;
77 		}
78 	}
79 
80 	e = malloc(sizeof(*e) + path_len + 1);
81 	if (e) {
82 		memset(e, 0, sizeof(*e) + path_len + 1);
83 		e->watchfd = watchfd;
84 		e->channel = channel;
85 		e->private = private;
86 		e->event_type = event_type;
87 		if (path_len > 0) {
88 			e->len = path_len;
89 			*(char *)(mempcpy(e->path, path, path_len)) = '\0';
90 		}
91 	} else {
92 		LOGE("malloc failed, error (%s)\n", strerror(errno));
93 	}
94 
95 	return e;
96 }
97 
98 /**
99  * Only check once when process startup
100  *
101  * @param cnl Structure of channel.
102  */
channel_oneshot(struct channel_t * cnl)103 static void channel_oneshot(struct channel_t *cnl)
104 {
105 	int id;
106 	struct crash_t *crash;
107 	struct info_t *info;
108 	struct event_t *e;
109 	char *cname = cnl->name;
110 
111 	LOGD("initializing channel %s ...\n", cname);
112 
113 	if (!is_boot_id_changed())
114 		return;
115 
116 	for_each_crash(id, crash, conf) {
117 		if (!crash || !is_root_crash(crash))
118 			continue;
119 
120 		if (strcmp(crash->channel, cname))
121 			continue;
122 
123 		if (!crash->trigger)
124 			continue;
125 
126 		if (!strcmp("file", crash->trigger->type) ||
127 				!strcmp("node", crash->trigger->type)) {
128 			if (!crash_match_filefmt(crash, crash->trigger->path))
129 				continue;
130 
131 			e = create_event(CRASH, cname, (void *)crash,
132 					 0, crash->trigger->path,
133 					 crash->trigger->path_len);
134 			if (e)
135 				event_enqueue(e);
136 		} else if (!strcmp("rebootreason", crash->trigger->type)) {
137 			char rreason[REBOOT_REASON_SIZE];
138 
139 			read_startupreason(rreason, sizeof(rreason));
140 			if (!strcmp(rreason, crash->content[0])) {
141 				e = create_event(CRASH, cname, (void *)crash,
142 						 0, crash->trigger->path,
143 						 crash->trigger->path_len);
144 				if (e)
145 					event_enqueue(e);
146 			}
147 		}
148 	}
149 
150 	e = create_event(REBOOT, cname, NULL, 0, NULL, 0);
151 	if (e)
152 		event_enqueue(e);
153 
154 	for_each_info(id, info, conf) {
155 		if (!info)
156 			continue;
157 
158 		if (strcmp(info->channel, cname))
159 			continue;
160 
161 		if (info->trigger &&
162 		    !strcmp("file", info->trigger->type) &&
163 		    file_exists(info->trigger->path)) {
164 			e = create_event(INFO, cname, (void *)info,
165 					 0, NULL, 0);
166 			if (e)
167 				event_enqueue(e);
168 		}
169 	}
170 }
171 
172 /* TODO: implement multiple polling jobs */
173 static struct polling_job_t {
174 	timer_t timerid;
175 	uint32_t timer_val;
176 
177 	enum event_type_t type;
178 	void (*fn)(union sigval v);
179 } vm_job;
180 
create_vm_event(const char * msg,size_t len,const struct vm_t * vm)181 static int create_vm_event(const char *msg, size_t len, const struct vm_t *vm)
182 {
183 	struct vm_event_t *vme = malloc(sizeof(*vme));
184 	struct event_t *e;
185 
186 	if (!vme)
187 		return VMEVT_DEFER;
188 
189 	vme->vm_msg = strndup(msg, len);
190 	if (!vme->vm_msg) {
191 		free(vme);
192 		return VMEVT_DEFER;
193 	}
194 
195 	vme->vm_msg_len = len;
196 	vme->vm = vm;
197 
198 	e = create_event(VM, "polling", (void *)vme, 0, NULL, 0);
199 	if (e) {
200 		event_enqueue(e);
201 		return VMEVT_HANDLED;
202 	}
203 
204 	free(vme->vm_msg);
205 	free(vme);
206 	return VMEVT_DEFER;
207 }
208 
209 /**
210  * Callback thread of a polling job.
211  */
polling_vm(union sigval v)212 static void polling_vm(union sigval v __attribute__((unused)))
213 {
214 	refresh_vm_history(get_sender_by_name("crashlog"), create_vm_event);
215 }
216 
217 /**
218  * Setup a timer with specific loop time. The callback fn will be performed
219  * after timer expire.
220  *
221  * @param pjob Polling_job filled by caller.
222  *
223  * @return 0 if successful, or -1 if not.
224  */
create_polling_job(struct polling_job_t * pjob)225 static int create_polling_job(struct polling_job_t *pjob)
226 {
227 	struct sigevent sig_evt;
228 	struct itimerspec timer_val;
229 
230 	memset(&sig_evt, 0, sizeof(struct sigevent));
231 	sig_evt.sigev_value.sival_int = POLLING_TIMER_SIG;
232 	sig_evt.sigev_notify = SIGEV_THREAD;
233 	sig_evt.sigev_notify_function = pjob->fn;
234 
235 	if (timer_create(CLOCK_REALTIME, &sig_evt, &pjob->timerid) == -1) {
236 		LOGE("timer_create failed.\n");
237 		return -1;
238 	}
239 
240 	memset(&timer_val, 0, sizeof(struct itimerspec));
241 	timer_val.it_value.tv_sec = pjob->timer_val;
242 	timer_val.it_interval.tv_sec = pjob->timer_val;
243 
244 	if (timer_settime(pjob->timerid, 0, &timer_val, NULL) == -1) {
245 		LOGE("timer_settime failed.\n");
246 		timer_delete(pjob->timerid);
247 		return -1;
248 	}
249 
250 	return 0;
251 }
252 
253 /**
254  * Setup polling jobs. These jobs running with fixed time interval.
255  *
256  * @param cnl Structure of channel.
257  */
channel_polling(struct channel_t * cnl)258 static void channel_polling(struct channel_t *cnl)
259 {
260 	int id;
261 	int jt;
262 	struct vm_t *vm;
263 	char *cname = cnl->name;
264 
265 	LOGD("initializing channel %s ...\n", cname);
266 
267 	/* one job for all vm polling*/
268 	for_each_vm(id, vm, conf) {
269 		if (!vm)
270 			continue;
271 
272 		if (strcmp(vm->channel, "polling"))
273 			continue;
274 
275 		if (cfg_atoi(vm->interval, vm->interval_len,
276 			     &jt) == -1) {
277 			LOGE("invalid interval (%s) in config file, exiting\n",
278 			     vm->interval);
279 			exit(EXIT_FAILURE);
280 		}
281 
282 		if (jt <= 0) {
283 			LOGE("interval (%s) must be greater than 0, exiting\n",
284 			     vm->interval);
285 			exit(EXIT_FAILURE);
286 		} else
287 			vm_job.timer_val = (uint32_t)jt;
288 
289 	}
290 
291 	LOGD("start polling job with %ds\n", vm_job.timer_val);
292 	vm_job.fn = polling_vm;
293 	vm_job.type = VM;
294 	if (create_polling_job(&vm_job) == -1) {
295 		LOGE("failed to create polling job\n, error (%s)\n",
296 		     strerror(errno));
297 		exit(EXIT_FAILURE);
298 	}
299 }
300 
301 /**
302  * Setup inotify, watch the changes of dir/file.
303  *
304  * @param cnl Structure of channel.
305  */
channel_inotify(struct channel_t * cnl)306 static void channel_inotify(struct channel_t *cnl)
307 {
308 	int inotify_fd;
309 	int id;
310 	struct crash_t *crash;
311 	struct sender_t *sender;
312 	struct uptime_t *uptime;
313 	struct trigger_t *trigger;
314 	char *cname = cnl->name;
315 
316 	LOGD("initializing channel %s ...\n", cname);
317 
318 	/* use this func to get "return 0" from read */
319 	inotify_fd = inotify_init1(IN_NONBLOCK);
320 	if (inotify_fd < 0) {
321 		LOGE("inotify init fail, %s\n", strerror(errno));
322 		return;
323 	}
324 
325 	for_each_crash(id, crash, conf) {
326 		if (!crash || !is_root_crash(crash))
327 			continue;
328 
329 		if (strcmp(crash->channel, cname))
330 			continue;
331 
332 		if (!crash->trigger)
333 			continue;
334 
335 		trigger = crash->trigger;
336 		if (!strcmp("dir", trigger->type)) {
337 			if (directory_exists(trigger->path)) {
338 				crash->wd = inotify_add_watch(inotify_fd,
339 							      trigger->path,
340 							      BASE_DIR_MASK);
341 				if (crash->wd < 0) {
342 					LOGE("add %s failed, error (%s)\n",
343 					     trigger->path, strerror(errno));
344 					exit(EXIT_FAILURE);
345 				}
346 				LOGI("add %s succuessed\n", trigger->path);
347 			} else {
348 				LOGW("path to watch (%s) isn't exsits\n",
349 				     trigger->path);
350 			}
351 		}
352 		/* TODO: else for other types to use channel inotify */
353 	}
354 	/* add uptime path for each sender */
355 	for_each_sender(id, sender, conf) {
356 		if (!sender)
357 			continue;
358 
359 		uptime = sender->uptime;
360 		uptime->wd = inotify_add_watch(inotify_fd, uptime->path,
361 					       UPTIME_MASK);
362 		if (uptime->wd < 0) {
363 			LOGE("add %s failed, error (%s)\n",
364 			     uptime->path, strerror(errno));
365 			exit(EXIT_FAILURE);
366 		}
367 		LOGI("add %s succuessed\n", uptime->path);
368 	}
369 
370 	cnl->fd = inotify_fd;
371 }
372 
373 /**
374  * Handle inotify events, read out all events and enqueue.
375  *
376  * @param channel Channel structure of inotify.
377  *
378  * @return 0 if successful, or -1 if not.
379  */
receive_inotify_events(struct channel_t * channel)380 static int receive_inotify_events(struct channel_t *channel)
381 {
382 	int len;
383 	int read_left;
384 	char buf[256];
385 	char *p;
386 	struct event_t *e;
387 	struct inotify_event *ievent;
388 	enum event_type_t event_type;
389 	void *private;
390 
391 	read_left = 0;
392 	while (1) {
393 		len = read(channel->fd, (char *)&buf[read_left],
394 			   (int)sizeof(buf) - read_left);
395 		if (len < 0) {
396 			if (errno == EAGAIN)
397 				break;
398 			LOGE("read fail with (%d, %p, %d), error: %s\n",
399 			     channel->fd, (char *)&buf[read_left],
400 			     (int)sizeof(buf) - read_left, strerror(errno));
401 			return -1;
402 		}
403 		if (len == 0)
404 			break;
405 
406 		for (p = buf; p < buf + read_left + len;) {
407 			if (p + sizeof(struct inotify_event) >
408 			    &buf[0] + len + read_left) {
409 				/* we dont recv the entire inotify_event yet */
410 				break;
411 			}
412 
413 			/* then we can get len */
414 			ievent = (struct inotify_event *)p;
415 			if (p + sizeof(struct inotify_event) + ievent->len >
416 						&buf[0] + len + read_left) {
417 				/* we dont recv the entire
418 				 * inotify_event + name
419 				 */
420 				break;
421 			}
422 			/* we have a entire event, send it... */
423 			event_type = get_conf_by_wd(ievent->wd, &private);
424 			if (event_type == UNKNOWN) {
425 				LOGE("get a unknown event\n");
426 			} else {
427 				e = create_event(event_type, channel->name,
428 						 private, channel->fd,
429 						 ievent->name, ievent->len);
430 				if (e)
431 					event_enqueue(e);
432 			}
433 			/* next event start */
434 			p += sizeof(struct inotify_event) + ievent->len;
435 		}
436 		/* move the bytes that have been read out to the head of buf,
437 		 * and let the rest of the buf do recv continually
438 		 */
439 		read_left = &buf[0] + len + read_left - p;
440 		memmove(buf, p, read_left);
441 	}
442 
443 	return 0;
444 }
445 
446 /**
447  * Enqueue a HEART_BEAT event to event_queue.
448  */
heart_beat(void)449 static void heart_beat(void)
450 {
451 	struct event_t *e = create_event(HEART_BEAT, NULL, NULL, 0, NULL, 0);
452 
453 	if (e)
454 		event_enqueue(e);
455 }
456 
457 /**
458  * Wait events asynchronously for all watch needed channels.
459  */
wait_events(void * unused)460 static void *wait_events(void *unused __attribute__((unused)))
461 {
462 	int epfd;
463 	int id;
464 	int ret;
465 	struct channel_t *channel;
466 	struct epoll_event ev, *events;
467 
468 	epfd = epoll_create(MAXEVENTS + 1);
469 	if (epfd < 0) {
470 		LOGE("epoll_create failed, exiting\n");
471 		exit(EXIT_FAILURE);
472 	}
473 
474 	ev.events = EPOLLIN | EPOLLET;
475 	for_each_channel(id, channel) {
476 		if (channel->fd <= 0)
477 			continue;
478 
479 		ev.data.fd = channel->fd;
480 		ret = epoll_ctl(epfd, EPOLL_CTL_ADD, channel->fd, &ev);
481 		if (ret < 0) {
482 			LOGE("epoll_ctl failed, exiting\n");
483 			exit(EXIT_FAILURE);
484 		} else
485 			LOGD("add (%d) to epoll for (%s)\n", channel->fd,
486 			     channel->name);
487 	}
488 
489 	events = calloc(MAXEVENTS, sizeof(ev));
490 	if (events == NULL) {
491 		LOGE("calloc failed, error (%s)\n", strerror(errno));
492 		exit(EXIT_FAILURE);
493 	}
494 
495 	while (1) {
496 		int i;
497 		int n;
498 
499 		n = epoll_wait(epfd, events, MAXEVENTS, HEART_RATE);
500 		heart_beat();
501 		for (i = 0; i < n; i++) {
502 			for_each_channel(id, channel)
503 				if (channel->fd == events[i].data.fd) {
504 					if (events[i].events & EPOLLERR ||
505 					    !(events[i].events & EPOLLIN)) {
506 						LOGE("error ev, channel:%s\n",
507 						     channel->name);
508 						continue;
509 					}
510 					/* Until now, we only have
511 					 * inotify channel to wait
512 					 */
513 					receive_inotify_events(channel);
514 				}
515 		}
516 	}
517 }
518 
519 /**
520  * Create a detached thread.
521  * Once these thread exit, their resources would be released immediately.
522  *
523  * @param[out] pid Pid of new thread.
524  * @param fn The entry of new thread.
525  * @param arg The arg of fn.
526  *
527  * @return 0 if successful, or errno if not.
528  */
create_detached_thread(pthread_t * pid,void * (* fn)(void *),void * arg)529 int create_detached_thread(pthread_t *pid, void *(*fn)(void *), void *arg)
530 {
531 	int ret;
532 	pthread_attr_t attr;
533 
534 	ret = pthread_attr_init(&attr);
535 	if (ret) {
536 		LOGE("pthread attr init failed\n, error (%s)\n",
537 		     strerror(ret));
538 		return ret;
539 	}
540 
541 	ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
542 	if (ret) {
543 		LOGE("pthread attr setdetachstate failed\n, error (%s)\n",
544 		     strerror(ret));
545 		goto fail;
546 	}
547 
548 	ret = pthread_create(pid, &attr, fn, arg);
549 	if (ret) {
550 		LOGE("pthread create failed\n, error (%s)\n",
551 		     strerror(ret));
552 	}
553 fail:
554 	pthread_attr_destroy(&attr);
555 
556 	return ret;
557 }
558 
559 /**
560  * Initailize all channels, performing channel_* in channels one by one.
561  *
562  * @return 0 if successful, or errno if not.
563  */
init_channels(void)564 int init_channels(void)
565 {
566 	pthread_t pid;
567 	int id;
568 	int ret;
569 	struct channel_t *channel;
570 
571 	for_each_channel(id, channel) {
572 		channel->channel_fn(channel);
573 	}
574 
575 	ret = create_detached_thread(&pid, &wait_events, NULL);
576 	if (ret) {
577 		LOGE("create wait_events fail, ret (%s)\n", strerror(ret));
578 		return ret;
579 	}
580 
581 	return 0;
582 }
583