clsync
Loading...
Searching...
No Matches
mon_bsm.c
Go to the documentation of this file.
1/*
2 clsync - file tree sync utility based on inotify/kqueue
3
4 Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "common.h"
21#include "malloc.h"
22#include "error.h"
23#include "indexes.h"
24#include "sync.h"
25#include "mon_bsm.h"
26
27#include <bsm/libbsm.h>
28#include <bsm/audit_kevents.h>
29#include <glib.h>
30#include <sys/ioctl.h>
31#include <security/audit/audit_ioctl.h>
32
33struct bsm_event {
34 u_int16_t type;
35 char path [PATH_MAX];
36 char path_to[PATH_MAX];
37 int w_id;
38};
39
40struct mondata {
41 FILE *pipe;
47};
48typedef struct mondata mondata_t;
49
51 UEM_DIR = 0x01,
54};
55
60
71
73pthread_mutex_t bsm_mutex_prefetcher = PTHREAD_MUTEX_INITIALIZER;
74pthread_cond_t bsm_cond_gotevent = PTHREAD_COND_INITIALIZER;
75pthread_cond_t bsm_cond_queueend = PTHREAD_COND_INITIALIZER;
76
78
79int ( *bsm_wait ) ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
80int ( *bsm_handle ) ( struct ctx *ctx_p, struct indexes *indexes_p );
81
82extern int bsm_prefetcher ( struct ctx *ctx_p );
83extern int bsm_wait_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
84extern int bsm_wait_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
85extern int bsm_handle_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p );
86extern int bsm_handle_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p );
87
88static inline void recognize_event ( struct recognize_event_return *r, uint32_t event )
89{
90 int is_created, is_deleted, is_moved;
91 eventobjtype_t type;
92 type = EOT_FILE;
93 is_moved = 0;
94 is_created = 0;
95 is_deleted = 0;
96
97 switch ( event ) {
98 case AUE_MKDIR:
99 case AUE_MKDIRAT:
100 type = EOT_DIR;
101
102 case AUE_OPEN_RC:
103 case AUE_OPEN_RTC:
104 case AUE_OPEN_WC:
105 case AUE_OPEN_WTC:
106 case AUE_OPEN_RWC:
107 case AUE_OPEN_RWTC:
108 case AUE_LINK:
109 case AUE_LINKAT:
110 case AUE_MKFIFO:
111 case AUE_MKFIFOAT:
112 case AUE_MKNOD:
113 case AUE_MKNODAT:
114 case AUE_SYMLINK:
115 case AUE_SYMLINKAT:
116 is_created = 1;
117 break;
118
119 case AUE_RMDIR:
120#if AUE_RMDIRAT
121 case AUE_RMDIRAT:
122#endif
123 type = EOT_DIR;
124
125 case AUE_UNLINK:
126 case AUE_UNLINKAT:
127 is_deleted = 1;
128 break;
129
130 case AUE_RENAME:
131 case AUE_RENAMEAT:
132 type = EOT_DIR;
133 is_moved = 1;
134 break;
135
136 case AUE_CLOSE:
137 case AUE_CLOSEFROM:
138 break;
139
140 default:
141 warning ( "Unknown event: 0x%x", event );
142 break;
143 }
144
145 r->f.objtype_old = type;
146
147 if ( is_moved ) {
150 r->t.objtype_new = type;
151 return;
152 }
153
154 r->f.objtype_new = type;
155
156 if ( is_created )
158
159 if ( is_deleted )
161
162 return;
163}
164
166{
167 debug ( 1, "Running \""AUDIT_CONTROL_INITSCRIPT" onerestart\"" );
168 pid_t pid = fork();
169
170 switch ( pid ) {
171 case -1:
172 error ( "Cannot fork()." );
173 return -1;
174
175 case 0:
176 debug ( 5, "fork: execl(\""AUDIT_CONTROL_INITSCRIPT"\", \""AUDIT_CONTROL_INITSCRIPT"\", \"onerestart\", NULL);", pid );
177 execl ( AUDIT_CONTROL_INITSCRIPT, AUDIT_CONTROL_INITSCRIPT, "onerestart", NULL );
178 error ( "fork: Cannot execute \""AUDIT_CONTROL_INITSCRIPT" onerestart\"" );
179 return -1;
180 }
181
182 debug ( 6, "Waiting for %u", pid );
183 int status;
184
185 if ( waitpid ( pid, &status, 0 ) != pid ) {
186 error ( "Cannot waitid()." );
187 return -1;
188 }
189
190 int exitcode = WEXITSTATUS ( status );
191
192 if ( exitcode )
193 error ( "Got error while running \""AUDIT_CONTROL_INITSCRIPT" onerestart\"" );
194
195 debug ( 4, "exitcode == %u", exitcode );
196 return exitcode;
197}
198
200{
201 char buf[sizeof ( AUDIT_CONTROL_HEADER )];
202 int fd = open ( AUDIT_CONTROL_PATH, O_RDONLY );
203
204 if ( fd == -1 ) {
205 debug ( 4, "Cannot open "AUDIT_CONTROL_PATH". No need for backup." );
206 return 1;
207 }
208
209 int r = read ( fd, buf, sizeof ( AUDIT_CONTROL_HEADER ) - 1 );
210 close ( fd );
211
212 if ( r == sizeof ( AUDIT_CONTROL_HEADER ) - 1 )
213 if ( !memcmp ( buf, AUDIT_CONTROL_HEADER, sizeof ( AUDIT_CONTROL_HEADER ) - 1 ) ) {
214 debug ( 4, "File "AUDIT_CONTROL_PATH" is already clsync-compatible." );
215 return 0;
216 }
217
218 if ( !access ( AUDIT_CONTROL_PATH"-clsync_backup", R_OK ) ) {
219 error ( "File \""AUDIT_CONTROL_PATH"-clsync_backup\" already exists. Cannot backup \""AUDIT_CONTROL_PATH"\"." );
220 return -1;
221 }
222
223 debug ( 3, "mv: "AUDIT_CONTROL_PATH" -> "AUDIT_CONTROL_PATH"-clsync_backup" );
224 rename ( AUDIT_CONTROL_PATH, AUDIT_CONTROL_PATH"-clsync_backup" );
225 close ( fd );
226 return 1;
227}
228
230{
231 debug ( 3, "" );
232
233 switch ( bsm_config_backup ( mondata ) ) {
234 case 0:
235 debug ( 4, "bsm_config_backup(): no reconfig required" );
236 return 0;
237
238 case -1:
239 debug ( 4, "bsm_config_backup(): error" );
240 return -1;
241 }
242
243 debug ( 3, "Writting a new audit_control file to \""AUDIT_CONTROL_PATH"\"" );
244 mondata->config_fd = open ( AUDIT_CONTROL_PATH, O_RDONLY );
245 flock ( mondata->config_fd, LOCK_SH );
246 int fd_w = open ( AUDIT_CONTROL_PATH, O_WRONLY | O_CREAT );
247
248 if ( fd_w == -1 ) {
249 error ( "Cannot open file \""AUDIT_CONTROL_PATH"\" for writing" );
250 return -1;
251 }
252
253 int w;
254
256 error ( "Cannot write to \""AUDIT_CONTROL_HEADER AUDIT_CONTROL_CONTENT"\" (%u != %u)", w, sizeof ( AUDIT_CONTROL_HEADER AUDIT_CONTROL_CONTENT ) - 1 );
257 return -1;
258 }
259
260 close ( fd_w );
261
262 if ( auditd_restart() ) {
263 error ( "Cannot restart auditd to apply a new "AUDIT_CONTROL_PATH );
264 return -1;
265 }
266
267 return 0;
268}
269
270int bsm_config_revert ( mondata_t *mondata )
271{
272 int rc = 0;
273 int fd = mondata->config_fd;
274 flock ( fd, LOCK_UN );
275
276 if ( flock ( fd, LOCK_NB | LOCK_EX ) )
277 return 0;
278
279 debug ( 1, "I'm the last BSM clsync instance." );
280
281 if ( !access ( AUDIT_CONTROL_PATH"-clsync_backup", R_OK ) ) {
282 debug ( 1, "Reverting the audit config file (\""AUDIT_CONTROL_PATH"-clsync_backup\" -> \""AUDIT_CONTROL_PATH"\")." );
283 rc = rename ( AUDIT_CONTROL_PATH"-clsync_backup", AUDIT_CONTROL_PATH );
284 }
285
286 flock ( fd, LOCK_UN );
287
288 if ( rc ) {
289 error ( "Got error while rename(\""AUDIT_CONTROL_PATH"-clsync_backup\", \""AUDIT_CONTROL_PATH"\")" );
290 return -1;
291 }
292
293 return 0;
294}
295
296
297#define BSM_INIT_ERROR {\
298 free(ctx_p->fsmondata);\
299 ctx_p->fsmondata = NULL;\
300 return -1;\
301 }
302
304{
305 debug ( 9, "" );
306 ctx_p->fsmondata = xcalloc ( sizeof ( mondata_t ), 1 );
308
309 if ( bsm_config_setup ( mondata ) == -1 )
311
312 debug ( 5, "Openning \""AUDITPIPE_PATH"\"" );
313 FILE *pipe = fopen ( AUDITPIPE_PATH, "r" );
314
315 if ( pipe == NULL ) {
316 error ( "Cannot open \""AUDITPIPE_PATH"\" for reading." );
318 }
319
320 {
321 // Setting auditpipe queue length to be maximal
322 int fd;
323 u_int len;
324 fd = fileno ( pipe );
325
326 if ( ioctl ( fd, AUDITPIPE_GET_QLIMIT_MAX, &len ) < 0 ) {
327 error ( "Cannot read QLIMIT_MAX from auditpipe" );
329 }
330
331 if ( ioctl ( fd, AUDITPIPE_SET_QLIMIT, &len ) < 0 ) {
332 error ( "Cannot set QLIMIT through auditpipe" );
334 }
335
336 if ( ioctl ( fd, AUDITPIPE_GET_QLIMIT, &len ) < 0 ) {
337 error ( "Cannot read QLIMIT from auditpipe" );
339 }
340
341 bsm_queue_len = len;
342 debug ( 5, "auditpipe QLIMIT -> %i", ( int ) len );
343 }
344
345 if ( setvbuf ( pipe, NULL, _IONBF, 0 ) ) {
346 error ( "Cannot set unbuffered mode for auditpipe" );
348 }
349
350 mondata->pipe = pipe;
351
352 switch ( ctx_p->flags[MONITOR] ) {
353 case NE_BSM:
356 mondata->event = xcalloc ( sizeof ( *mondata->event ), 1 );
357 break;
358
359 case NE_BSM_PREFETCH:
360 pthread_mutex_init ( &bsm_mutex_prefetcher, NULL );
361 pthread_cond_init ( &bsm_cond_gotevent, NULL );
362 pthread_cond_init ( &bsm_cond_queueend, NULL );
365 critical_on ( pthread_create ( &prefetcher_thread, NULL, ( void * ( * ) ( void * ) ) bsm_prefetcher, ctx_p ) );
366 break;
367
368 default:
369 critical ( "Invalid ctx_p->flags[MONITOR]: %u", ctx_p->flags[MONITOR] );
370 }
371
372 return 0;
373}
374
375int select_rfd ( int fd, struct timeval *timeout_p )
376{
377 int rc;
378 debug ( 9, "%i, {%li, %li}", fd, timeout_p == NULL ? -1 : timeout_p->tv_sec, timeout_p == NULL ? 0 : timeout_p->tv_usec );
379 fd_set rfds;
380 FD_ZERO ( &rfds );
381 FD_SET ( fd, &rfds );
382 rc = select ( fd + 1, &rfds, NULL, NULL, timeout_p );
383 debug ( 9, "rc -> %i", rc );
384 return rc;
385}
386
387int bsm_fetch ( ctx_t *ctx_p, indexes_t *indexes_p, struct bsm_event *event_p, int pipe_fd, struct timeval *timeout_p, struct timeval *timeout_abs_p )
388{
389 size_t au_len;
390 size_t au_parsed;
391 u_char *au_buf;
392 tokenstr_t tok;
393 int recalc_timeout;
394 static int dont_wait = 0;
395 struct timeval tv_abs;
396 struct timeval timeout_zero = {0};
398 recalc_timeout = 0;
399
400 if ( timeout_p != NULL )
401 if ( timeout_p->tv_sec != 0 || timeout_p->tv_usec != 0 )
402 recalc_timeout = 1;
403
404 while ( 42 ) {
405 int path_count;
406
407 // Checking if there already a recond in mondata
408 if ( *event_p->path ) {
409 debug ( 2, "we have an event. return 1." );
410 return 1;
411 }
412
413 // Getting a record
414 {
415 int rc;
416 rc = 0;
417
418 if ( dont_wait ) {
419 debug ( 4, "select() without waiting" );
420 rc = select_rfd ( pipe_fd, &timeout_zero );
421
422 if ( rc == 0 ) {
423 dont_wait = 0;
425
426 switch ( ctx_p->flags[MONITOR] ) {
427 case NE_BSM_PREFETCH:
428 pthread_cond_broadcast ( &bsm_cond_queueend );
429 break;
430
431 default:
432 break;
433 }
434 } else if ( rc > 0 ) {
436
438 critical_or_warning ( ctx_p->flags[EXITONSYNCSKIP], "The was too many events in BSM queue (reached kernel BSM queue limit: %u).", bsm_queue_len );
439 }
440 }
441
442 if ( rc == 0 ) {
443 if ( recalc_timeout == 2 ) {
444 debug ( 5, "old timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec );
445 gettimeofday ( &tv_abs, NULL );
446
447 if ( timercmp ( timeout_abs_p, &tv_abs, < ) )
448 timersub ( timeout_abs_p, &tv_abs, timeout_p );
449 else
450 memset ( timeout_p, 0, sizeof ( *timeout_p ) );
451
452 debug ( 5, "new timeout_p->: tv_sec == %lu; tv_usec == %lu", timeout_p->tv_sec, timeout_p->tv_usec );
453 }
454
455 debug ( 3, "select() with timeout %li.%06li secs (recalc_timeout == %u).",
456 timeout_p == NULL ? -1 : timeout_p->tv_sec,
457 timeout_p == NULL ? 0 : timeout_p->tv_usec,
458 recalc_timeout );
459 rc = select_rfd ( pipe_fd, timeout_p );
460
461 if ( rc > 0 )
463
464 if ( recalc_timeout == 1 )
465 recalc_timeout++;
466 }
467
468 critical_on ( ( rc == -1 ) && ( errno != EINTR ) );
469
470 if ( rc == 0 || rc == -1 ) {
471 debug ( 3, "rc == %i; errno == %i; return 0", rc, errno );
472 return 0;
473 }
474
475 dont_wait = 1;
476 au_len = au_read_rec ( mondata->pipe, &au_buf );
477 critical_on ( au_len == -1 );
478 }
479 // Parsing the record
480 au_parsed = 0;
481 path_count = 0;
482 debug ( 3, "parsing the event (au_parsed == %u; au_len == %u)", au_parsed, au_len );
483
484 while ( au_parsed < au_len ) {
485 critical_on ( au_fetch_tok ( &tok, &au_buf[au_parsed], au_len - au_parsed ) == -1 );
486 au_parsed += tok.len;
487 debug ( 4, "au_fetch_tok(): au_parsed -> %u", tok.len );
488
489 switch ( tok.id ) {
490 case AUT_HEADER32:
491 case AUT_HEADER32_EX:
492 case AUT_HEADER64:
493 case AUT_HEADER64_EX: {
494 event_p->type = tok.tt.hdr32.e_type;
495 path_count = 0;
496 break;
497 }
498
499 case AUT_PATH: {
500 char *ptr;
501 int dir_wd, dir_iswatched;
502 ptr = memrchr ( tok.tt.path.path, '/', tok.tt.path.len );
503#ifdef PARANOID
504
505 if ( ptr == NULL )
506 critical ( "relative path received from au_fetch_tok(): \"%s\" (len: %u)", tok.tt.path.path, tok.tt.path.len );
507
508#endif
509 debug ( 6, "Event on \"%s\".", tok.tt.path.path );
510 *ptr = 0;
511 dir_wd = indexes_fpath2wd ( indexes_p, tok.tt.path.path );
512 dir_iswatched = ( dir_wd != -1 );
513 debug ( 7, "Directory is \"%s\". dir_wd == %i; dir_iswatched == %u", tok.tt.path.path, dir_wd, dir_iswatched );
514 *ptr = '/';
515
516 if ( dir_iswatched ) {
517 debug ( 5, "Event on \"%s\" is watched. Pushing. path_count == %u", tok.tt.path.path, path_count );
518
519 switch ( path_count ) {
520 case 0:
521 memcpy ( event_p->path, tok.tt.path.path, tok.tt.path.len + 1 );
522 break;
523
524 case 1:
525 memcpy ( event_p->path_to, tok.tt.path.path, tok.tt.path.len + 1 );
526 break;
527#ifdef PARANOID
528
529 default:
530 warning ( "To many paths on BSM event: \"%s\" (already count: %u)", tok.tt.path.path, path_count );
531 break;
532#endif
533 }
534 }
535
536 path_count++;
537 break;
538 }
539
540 default:
541 continue;
542 }
543 }
544
545 // Cleanup
546 debug ( 4, "clean up" );
547 free ( au_buf );
548 }
549
550 critical ( "This code shouldn't be reached" );
551 return -1;
552}
558int bsm_handle_allevents ( struct ctx *ctx_p, struct indexes *indexes_p, bsm_handletype_t how )
559{
560 debug ( 4, "" );
561 static struct timeval tv = {0};
563 int count, event_num;
564 char *path_rel = NULL;
565 size_t path_rel_len = 0;
566 int left_count;
567 event_num = 0;
568 count = 0;
569#ifdef PARANOID
570 g_hash_table_remove_all ( indexes_p->fpath2ei_ht );
571#endif
572
573 do {
574 struct recognize_event_return r = {{0}};
575 char *path_stat;
576 struct stat st, *st_p;
577 mode_t st_mode;
578 size_t st_size;
579 struct bsm_event *event_p = &mondata->event[event_num];
580#ifdef PARANOID
581
582 if ( !*event_p->path && !*event_p->path_to ) {
583 warning ( "no events are parsed (event_p == %p; mondata->event_count == %i).", event_p, mondata->event_count );
584 continue;
585 }
586
587#endif
588 recognize_event ( &r, event_p->type );
589
590 if ( r.t.objtype_new != EOT_UNKNOWN )
591 path_stat = event_p->path_to;
592 else
593 path_stat = event_p->path;
594
595 if ( ( r.t.objtype_new == EOT_DOESNTEXIST ) || ( ctx_p->flags[CANCEL_SYSCALLS]&CSC_MON_STAT ) || lstat ( path_stat, &st ) ) {
596 debug ( 2, "Cannot lstat(\"%s\", st). Seems, that the object had been deleted (%i) or option \"--cancel-syscalls=mon_stat\" (%i) is set.", path_stat, r.t.objtype_new == EOT_DOESNTEXIST, ctx_p->flags[CANCEL_SYSCALLS]&CSC_MON_STAT );
597
598 if ( r.f.objtype_old == EOT_DIR || r.f.objtype_new == EOT_DIR )
599 st_mode = S_IFDIR;
600 else
601 st_mode = S_IFREG;
602
603 st_size = 0;
604 st_p = NULL;
605 } else {
606 st_mode = st.st_mode;
607 st_size = st.st_size;
608 st_p = &st;
609 }
610
611 if ( *event_p->path ) {
612 if ( sync_prequeue_loadmark ( 1, ctx_p, indexes_p, event_p->path, NULL, st_p, r.f.objtype_old, r.f.objtype_new, event_p->type, event_p->w_id, st_mode, st_size, &path_rel, &path_rel_len, NULL ) ) {
613 error ( "Got error while load_mark-ing into pre-queue \"%s\"", event_p->path );
614 count = -1;
615 *event_p->path = 0;
616 break;
617 }
618
619 *event_p->path = 0;
620 count++;
621 }
622
623 if ( ( r.t.objtype_new != EOT_UNKNOWN ) && *event_p->path_to ) {
624 if ( sync_prequeue_loadmark ( 1, ctx_p, indexes_p, event_p->path_to, NULL, st_p, r.t.objtype_old, r.t.objtype_new, event_p->type, event_p->w_id, st_mode, st_size, &path_rel, &path_rel_len, NULL ) ) {
625 error ( "Got error while load_mark-ing into pre-queue \"%s\"", event_p->path_to );
626 count = -1;
627 *event_p->path_to = 0;
628 break;
629 }
630
631 *event_p->path_to = 0;
632 count++;
633 }
634
635 switch ( how ) {
637 debug ( 15, "BSM_HANDLE_CALLWAIT" );
638 left_count = bsm_wait ( ctx_p, indexes_p, &tv );
639 break;
640
642 debug ( 15, "BSM_HANDLE_ITERATE" );
643 event_num++;
644 left_count = mondata->event_count - event_num;
645 break;
646 }
647
648 debug ( 10, "left_count: %i; event_num: %i; mondata->event_count: %i", left_count, event_num, mondata->event_count );
649 } while ( left_count > 0 );
650
651 switch ( how ) {
653 if ( event_num < mondata->event_count ) {
654 memmove (
655 mondata->event,
656 &mondata->event[event_num],
657 sizeof ( *mondata->event ) * ( mondata->event_count - event_num )
658 );
659 }
660
661 mondata->event_count -= event_num;
662 break;
663
664 default:
665 break;
666 }
667
668 free ( path_rel );
669#ifdef VERYPARANOID
670 path_rel = NULL;
671 path_rel_len = 0;
672#endif
673 // Globally queueing captured events:
674 // Moving events from local queue to global ones
675 sync_prequeue_unload ( ctx_p, indexes_p );
676 debug ( 4, "Result processed count: %i (left, mondata->event_count == %i)", count, mondata->event_count );
677
678 if ( count == -1 )
679 return -1;
680
681 return count;
682}
683
684void bsm_prefetcher_sig_int ( int signal )
685{
686 debug ( 2, "signal -> %i. Sending pthread_cond_broadcast() to bsm_cond_gotevent and bsm_cond_queueend.", signal );
687 pthread_cond_broadcast ( &bsm_cond_gotevent );
688 pthread_cond_broadcast ( &bsm_cond_queueend );
689 return;
690}
691
693int bsm_prefetcher ( struct ctx *ctx_p )
694{
696 indexes_t *indexes_p = ctx_p->indexes_p;
697 struct bsm_event event, *event_p;
700 int pipe_fd = fileno ( mondata->pipe );
701 mondata->event = xcalloc ( sizeof ( *mondata->event ), ALLOC_PORTION );
703
704 while ( bsm_prefetcher_running ) {
705 if ( bsm_fetch ( ctx_p, indexes_p, &event, pipe_fd, NULL, NULL ) > 0 ) {
706 // Pushing the event
707 debug ( 5, "We have an event. Pushing." );
708#ifdef PARANOID
710#endif
711
713 debug ( 2, "Increasing queue length: %u -> %u (limit is "XTOSTR ( BSM_QUEUE_LENGTH_MAX ) ")", mondata->event_alloc, mondata->event_alloc + ALLOC_PORTION );
715 mondata->event = xrealloc ( mondata->event, mondata->event_alloc * sizeof ( *mondata->event ) );
716 memset ( &mondata->event[mondata->event_count], 0, sizeof ( *mondata->event ) * ( mondata->event_alloc - mondata->event_count ) );
717 }
718
719 pthread_mutex_lock ( &bsm_mutex_prefetcher );
720 event_p = &mondata->event[mondata->event_count++];
721 memcpy ( event_p, &event, sizeof ( *event_p ) );
722 debug ( 2, "event_count -> %u (event_p == %p; event_p->path == \"%s\")", mondata->event_count, event_p, event_p->path );
723 pthread_cond_broadcast ( &bsm_cond_gotevent );
724 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
725 memset ( &event, 0, sizeof ( event ) );
726 }
727 }
728
729 return 0;
730}
731int bsm_wait_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p )
732{
733 debug ( 3, "(ctx_p, indexes_p, %p {%u, %u})", timeout_p, timeout_p == NULL ? -1 : timeout_p->tv_sec, timeout_p == NULL ? 0 : timeout_p->tv_usec );
734#ifdef PARANOID
735 critical_on ( timeout_p == NULL );
736#endif
738 struct timespec ts_abs;
739 struct timeval tv_abs, timeout_abs;
740#define INFINITETIME (3600 * 24 * 365 * 10) /* ~10 years */
741
742 if ( timeout_p->tv_sec > INFINITETIME )
743 timeout_p->tv_sec = INFINITETIME;
744
745#undef INFINITETIME
746 gettimeofday ( &tv_abs, NULL );
747 timeradd ( &tv_abs, timeout_p, &timeout_abs );
748 ts_abs.tv_sec = timeout_abs.tv_sec;
749 ts_abs.tv_nsec = timeout_abs.tv_usec * 1000;
750 pthread_mutex_lock ( &bsm_mutex_prefetcher );
751
752 if ( mondata->event_count ) {
753 debug ( 2, "Already have an event. mondata->event_count == %i", mondata->event_count );
754 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
755 return mondata->event_count;
756 }
757
758 if ( timeout_p->tv_sec == 0 && timeout_p->tv_sec == 0 ) {
759 debug ( 2, "Zero timeout. Waiting for the current queue to be processed." )
760 pthread_cond_wait ( &bsm_cond_queueend, &bsm_mutex_prefetcher );
761 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
762 debug ( 3, "return mondata->event_count == %i", mondata->event_count );
763 return mondata->event_count;
764 }
765
766//l_pthread_cond_timedwait_restart:
767 debug ( 10, "pthread_cond_timedwait(&bsm_cond_gotevent, &bsm_mutex_prefetcher, {%i, %i})", ts_abs.tv_sec, ts_abs.tv_nsec );
768
769 if ( ( errno = pthread_cond_timedwait ( &bsm_cond_gotevent, &bsm_mutex_prefetcher, &ts_abs ) ) ) {
770 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
771
772 switch ( errno ) {
773 case ETIMEDOUT:
774#ifdef PARANOID
776#endif
777 debug ( 2, "Timed out -> no events (mondata->event_count == %i)", mondata->event_count );
778 return 0;
779
780 /* case EINTR:
781 debug(3, "pthread_cond_timedwait() -> EINTR. Restarting.");
782 goto l_pthread_cond_timedwait_restart;*/
783 default:
784 critical ( "Got unhandled error on pthread_cond_timedwait()" );
785 }
786 }
787
788 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
789 /*#ifdef PARANOID
790 critical_on (!mondata->event_count);
791 #endif*/
792 debug ( 2, "%s. mondata->event_count == %i", mondata->event_count ? "Got an event" : "Got signal SIGUSR_BLOPINT", mondata->event_count );
793 return mondata->event_count;
794}
795int bsm_handle_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p )
796{
797 int count;
798 debug ( 8, "" );
799 pthread_mutex_lock ( &bsm_mutex_prefetcher );
800 count = bsm_handle_allevents ( ctx_p, indexes_p, BSM_HANDLE_ITERATE );
801 pthread_mutex_unlock ( &bsm_mutex_prefetcher );
802 return count;
803}
804int bsm_wait_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p )
805{
806 debug ( 3, "(ctx_p, indexes_p, %p {%u, %u})", timeout_p, timeout_p == NULL ? -1 : timeout_p->tv_sec, timeout_p == NULL ? 0 : timeout_p->tv_usec );
808 struct timeval timeout_abs, tv_abs;
809 struct bsm_event *event_p = mondata->event;
810
811 if ( timeout_p->tv_sec != 0 || timeout_p->tv_usec != 0 ) {
812 gettimeofday ( &tv_abs, NULL );
813 timeradd ( &tv_abs, timeout_p, &timeout_abs );
814 }
815
816 int pipe_fd = fileno ( mondata->pipe );
817
818 if ( *event_p->path ) {
819 debug ( 2, "We already have an event. Return 1." );
820 return 1;
821 }
822
823 if ( bsm_fetch ( ctx_p, indexes_p, mondata->event, pipe_fd, timeout_p, &timeout_abs ) == 0 ) {
824 debug ( 2, "No events. Return 0" );
825 return 0;
826 }
827
828 if ( *event_p->path ) {
829 debug ( 2, "We have an event. Return 1." );
830 return 1;
831 }
832
833 critical ( "This code shouldn't be reached" );
834 return -1;
835}
836int bsm_handle_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p )
837{
838 debug ( 3, "" );
839 return bsm_handle_allevents ( ctx_p, indexes_p, BSM_HANDLE_CALLWAIT );
840}
841int bsm_add_watch_dir ( struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath )
842{
843 static int id = 1;
844
845 if ( id == -1 )
846 id = ( int ) ( ( unsigned int ) ~0 >> 2 );
847
848 // TODO: optimize this line out:
849 while ( indexes_wd2fpath ( indexes_p, id ) != NULL )
850 id++;
851
852 return id++;
853}
855{
856 void *ret;
857 int rc = 0;
860 pthread_kill ( prefetcher_thread, SIGUSR_BLOPINT );
861 pthread_cond_destroy ( &bsm_cond_gotevent );
862 pthread_mutex_destroy ( &bsm_mutex_prefetcher );
863 pthread_join ( prefetcher_thread, &ret );
864 rc |= fclose ( mondata->pipe );
865 rc |= bsm_config_revert ( mondata );
866 free ( ctx_p->fsmondata );
867 ctx_p->fsmondata = NULL;
868 rc |= auditd_restart();
869 return rc;
870}
871
enum eventobjtype eventobjtype_t
Definition clsync.h:37
@ EOT_DIR
Definition clsync.h:33
@ EOT_DOESNTEXIST
Definition clsync.h:31
@ EOT_FILE
Definition clsync.h:32
@ EOT_UNKNOWN
Definition clsync.h:30
@ NE_BSM_PREFETCH
Definition common.h:110
@ NE_BSM
Definition common.h:109
#define BSM_QUEUE_LENGTH_MAX
#define AUDIT_CONTROL_HEADER
#define AUDIT_CONTROL_INITSCRIPT
#define AUDIT_CONTROL_PATH
#define AUDIT_CONTROL_CONTENT
#define AUDITPIPE_PATH
#define ALLOC_PORTION
@ CANCEL_SYSCALLS
Definition ctx.h:128
@ EXITONSYNCSKIP
Definition ctx.h:129
@ MONITOR
Definition ctx.h:104
@ CSC_MON_STAT
Definition ctx.h:310
@ SIGUSR_BLOPINT
Definition ctx.h:202
#define register_blockthread(thread)
Definition ctx.h:31
#define critical(...)
Definition error.h:32
#define error(...)
Definition error.h:36
#define debug(debug_level,...)
Definition error.h:50
#define warning(...)
Definition error.h:40
#define critical_on(cond)
Definition error.h:33
#define critical_or_warning(cond,...)
Definition error.h:57
#define XTOSTR(a)
Definition macros.h:45
int bsm_fetch(ctx_t *ctx_p, indexes_t *indexes_p, struct bsm_event *event_p, int pipe_fd, struct timeval *timeout_p, struct timeval *timeout_abs_p)
Definition mon_bsm.c:387
int bsm_wait_prefetched(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition mon_bsm.c:731
int(* bsm_handle)(struct ctx *ctx_p, struct indexes *indexes_p)
Definition mon_bsm.c:80
int bsm_wait_noprefetch(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition mon_bsm.c:804
event_bits
Definition mon_bsm.c:50
@ UEM_CREATED
Definition mon_bsm.c:52
@ UEM_DELETED
Definition mon_bsm.c:53
@ UEM_DIR
Definition mon_bsm.c:51
int auditd_restart()
Definition mon_bsm.c:165
int select_rfd(int fd, struct timeval *timeout_p)
Definition mon_bsm.c:375
int bsm_handle_prefetched(struct ctx *ctx_p, struct indexes *indexes_p)
Definition mon_bsm.c:795
pthread_cond_t bsm_cond_queueend
Definition mon_bsm.c:75
#define BSM_INIT_ERROR
Definition mon_bsm.c:297
int bsm_deinit(ctx_t *ctx_p)
Definition mon_bsm.c:854
int bsm_queue_len
Definition mon_bsm.c:77
int bsm_handle_noprefetch(struct ctx *ctx_p, struct indexes *indexes_p)
Definition mon_bsm.c:836
#define INFINITETIME
int(* bsm_wait)(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition mon_bsm.c:79
int bsm_config_setup(mondata_t *mondata)
Definition mon_bsm.c:229
int bsm_handle_allevents(struct ctx *ctx_p, struct indexes *indexes_p, bsm_handletype_t how)
Definition mon_bsm.c:558
static int bsm_prefetcher_running
Definition mon_bsm.c:692
void bsm_prefetcher_sig_int(int signal)
Definition mon_bsm.c:684
pthread_mutex_t bsm_mutex_prefetcher
Definition mon_bsm.c:73
enum bsm_handletype bsm_handletype_t
Definition mon_bsm.c:557
int bsm_prefetcher(struct ctx *ctx_p)
Definition mon_bsm.c:693
pthread_t prefetcher_thread
Definition mon_bsm.c:72
int bsm_init(ctx_t *ctx_p)
Definition mon_bsm.c:303
static void recognize_event(struct recognize_event_return *r, uint32_t event)
Definition mon_bsm.c:88
bsm_handletype
Definition mon_bsm.c:553
@ BSM_HANDLE_CALLWAIT
Definition mon_bsm.c:554
@ BSM_HANDLE_ITERATE
Definition mon_bsm.c:555
bsm_handle_type
Definition mon_bsm.c:56
@ BSM_HANDLER_ITERATE
Definition mon_bsm.c:58
@ BSM_HANDLER_CALLWAIT
Definition mon_bsm.c:57
int bsm_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath)
Definition mon_bsm.c:841
pthread_cond_t bsm_cond_gotevent
Definition mon_bsm.c:74
int bsm_config_backup(mondata_t *mondata)
Definition mon_bsm.c:199
ctx_t * ctx_p
Definition mon_kqueue.c:85
u_int16_t type
Definition mon_bsm.c:34
int w_id
Definition mon_bsm.c:37
char path_to[PATH_MAX]
Definition mon_bsm.c:36
char path[PATH_MAX]
Definition mon_bsm.c:35
Definition ctx.h:315
void * fsmondata
Definition ctx.h:419
int flags[(1<< 10)]
Definition ctx.h:338
GHashTable * fpath2ei_ht
Definition indexes.h:37
struct bsm_event * event
Definition mon_bsm.c:46
FILE * pipe
Definition mon_bsm.c:41
size_t event_count_wasinqueue
Definition mon_bsm.c:44
size_t event_count
Definition mon_bsm.c:43
size_t event_alloc
Definition mon_bsm.c:45
int config_fd
Definition mon_bsm.c:42
struct recognize_event_return::@3 t
eventobjtype_t objtype_old
Definition mon_bsm.c:63
eventobjtype_t objtype_new
Definition mon_bsm.c:64
struct recognize_event_return::@2 f
int sync_prequeue_unload(ctx_t *ctx_p, indexes_t *indexes_p)
Definition sync.c:2564
int sync_prequeue_loadmark(int monitored, ctx_t *ctx_p, indexes_t *indexes_p, const char *path_full, const char *path_rel, stat64_t *lst_p, eventobjtype_t objtype_old, eventobjtype_t objtype_new, uint32_t event_mask, int event_wd, mode_t st_mode, off_t st_size, char **path_buf_p, size_t *path_buf_len_p, eventinfo_t *evinfo)
Definition sync.c:2143
volatile int exitcode
Definition sync.c:547