clsync
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 
33 struct bsm_event {
34  u_int16_t type;
35  char path [PATH_MAX];
36  char path_to[PATH_MAX];
37  int w_id;
38 };
39 
40 struct mondata {
41  FILE *pipe;
42  int config_fd;
43  size_t event_count;
45  size_t event_alloc;
46  struct bsm_event *event;
47 };
48 typedef struct mondata mondata_t;
49 
50 enum event_bits {
51  UEM_DIR = 0x01,
52  UEM_CREATED = 0x02,
53  UEM_DELETED = 0x04,
54 };
55 
59 };
60 
62  struct {
65  } f;
66  struct {
69  } t;
70 };
71 
73 pthread_mutex_t bsm_mutex_prefetcher = PTHREAD_MUTEX_INITIALIZER;
74 pthread_cond_t bsm_cond_gotevent = PTHREAD_COND_INITIALIZER;
75 pthread_cond_t bsm_cond_queueend = PTHREAD_COND_INITIALIZER;
76 
78 
79 int ( *bsm_wait ) ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
80 int ( *bsm_handle ) ( struct ctx *ctx_p, struct indexes *indexes_p );
81 
82 extern int bsm_prefetcher ( struct ctx *ctx_p );
83 extern int bsm_wait_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
84 extern int bsm_wait_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p );
85 extern int bsm_handle_prefetched ( struct ctx *ctx_p, struct indexes *indexes_p );
86 extern int bsm_handle_noprefetch ( struct ctx *ctx_p, struct indexes *indexes_p );
87 
88 static 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 
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 
375 int 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 
387 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 )
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 }
556 };
558 int 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 ) {
636  case BSM_HANDLE_CALLWAIT:
637  debug ( 15, "BSM_HANDLE_CALLWAIT" );
638  left_count = bsm_wait ( ctx_p, indexes_p, &tv );
639  break;
640 
641  case BSM_HANDLE_ITERATE:
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 ) {
652  case BSM_HANDLE_ITERATE:
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 
684 void 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 
692 static int bsm_prefetcher_running = 2;
693 int 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 
712  if ( mondata->event_count >= mondata->event_alloc ) {
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 }
731 int 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 }
795 int 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 }
804 int 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 }
836 int 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 }
841 int 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 
bsm_event::w_id
int w_id
Definition: mon_bsm.c:37
bsm_wait
int(* bsm_wait)(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition: mon_bsm.c:79
bsm_init
int bsm_init(ctx_t *ctx_p)
Definition: mon_bsm.c:303
bsm_wait_noprefetch
int bsm_wait_noprefetch(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition: mon_bsm.c:804
sync_prequeue_unload
int sync_prequeue_unload(ctx_t *ctx_p, indexes_t *indexes_p)
Definition: sync.c:2564
register_blockthread
#define register_blockthread(thread)
Definition: ctx.h:31
auditd_restart
int auditd_restart()
Definition: mon_bsm.c:165
ctx
Definition: ctx.h:315
EXITONSYNCSKIP
@ EXITONSYNCSKIP
Definition: ctx.h:129
AUDIT_CONTROL_HEADER
#define AUDIT_CONTROL_HEADER
Definition: configuration.h:138
close
close(fd_w)
ALLOC_PORTION
#define ALLOC_PORTION
Definition: configuration.h:117
bsm_event::path_to
char path_to[PATH_MAX]
Definition: mon_bsm.c:36
recognize_event_return::t
struct recognize_event_return::@3 t
sync.h
EOT_DOESNTEXIST
@ EOT_DOESNTEXIST
Definition: clsync.h:31
AUDIT_CONTROL_CONTENT
#define AUDIT_CONTROL_CONTENT
Definition: configuration.h:139
eventobjtype_t
enum eventobjtype eventobjtype_t
Definition: clsync.h:37
ctx::fsmondata
void * fsmondata
Definition: ctx.h:419
BSM_HANDLE_ITERATE
@ BSM_HANDLE_ITERATE
Definition: mon_bsm.c:555
bsm_event::path
char path[PATH_MAX]
Definition: mon_bsm.c:35
recognize_event_return
Definition: mon_bsm.c:61
sync_prequeue_loadmark
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
BSM_INIT_ERROR
#define BSM_INIT_ERROR
Definition: mon_bsm.c:297
EOT_UNKNOWN
@ EOT_UNKNOWN
Definition: clsync.h:30
indexes
Definition: indexes.h:34
bsm_fetch
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
bsm_prefetcher_sig_int
void bsm_prefetcher_sig_int(int signal)
Definition: mon_bsm.c:684
bsm_event::type
u_int16_t type
Definition: mon_bsm.c:34
event
Definition: mon_gio.c:41
NE_BSM_PREFETCH
@ NE_BSM_PREFETCH
Definition: common.h:110
recognize_event_return::f
struct recognize_event_return::@2 f
ctx::flags
int flags[(1<< 10)]
Definition: ctx.h:338
UEM_CREATED
@ UEM_CREATED
Definition: mon_bsm.c:52
SIGUSR_BLOPINT
@ SIGUSR_BLOPINT
Definition: ctx.h:202
mondata::event_alloc
size_t event_alloc
Definition: mon_bsm.c:45
select_rfd
int select_rfd(int fd, struct timeval *timeout_p)
Definition: mon_bsm.c:375
AUDIT_CONTROL_INITSCRIPT
#define AUDIT_CONTROL_INITSCRIPT
Definition: configuration.h:137
CSC_MON_STAT
@ CSC_MON_STAT
Definition: ctx.h:310
bsm_prefetcher
int bsm_prefetcher(struct ctx *ctx_p)
Definition: mon_bsm.c:693
bsm_handle_type
bsm_handle_type
Definition: mon_bsm.c:56
INFINITETIME
#define INFINITETIME
UEM_DELETED
@ UEM_DELETED
Definition: mon_bsm.c:53
recognize_event_return::objtype_new
eventobjtype_t objtype_new
Definition: mon_bsm.c:64
bsm_event
Definition: mon_bsm.c:33
CANCEL_SYSCALLS
@ CANCEL_SYSCALLS
Definition: ctx.h:128
AUDIT_CONTROL_PATH
#define AUDIT_CONTROL_PATH
Definition: configuration.h:136
bsm_queue_len
int bsm_queue_len
Definition: mon_bsm.c:77
bsm_mutex_prefetcher
pthread_mutex_t bsm_mutex_prefetcher
Definition: mon_bsm.c:73
error
#define error(...)
Definition: error.h:36
indexes.h
mondata::event
struct bsm_event * event
Definition: mon_bsm.c:46
bsm_cond_gotevent
pthread_cond_t bsm_cond_gotevent
Definition: mon_bsm.c:74
critical_or_warning
#define critical_or_warning(cond,...)
Definition: error.h:57
error.h
recognize_event
static void recognize_event(struct recognize_event_return *r, uint32_t event)
Definition: mon_bsm.c:88
UEM_DIR
@ UEM_DIR
Definition: mon_bsm.c:51
MONITOR
@ MONITOR
Definition: ctx.h:104
bsm_handle
int(* bsm_handle)(struct ctx *ctx_p, struct indexes *indexes_p)
Definition: mon_bsm.c:80
bsm_handle_allevents
int bsm_handle_allevents(struct ctx *ctx_p, struct indexes *indexes_p, bsm_handletype_t how)
Definition: mon_bsm.c:558
mondata::event_count_wasinqueue
size_t event_count_wasinqueue
Definition: mon_bsm.c:44
NE_BSM
@ NE_BSM
Definition: common.h:109
bsm_handle_noprefetch
int bsm_handle_noprefetch(struct ctx *ctx_p, struct indexes *indexes_p)
Definition: mon_bsm.c:836
malloc.h
event_bits
event_bits
Definition: mon_bsm.c:50
debug
#define debug(debug_level,...)
Definition: error.h:50
bsm_config_revert
int bsm_config_revert(mondata_t *mondata)
Definition: mon_bsm.c:270
bsm_handletype_t
enum bsm_handletype bsm_handletype_t
Definition: mon_bsm.c:557
XTOSTR
#define XTOSTR(a)
Definition: macros.h:45
critical
#define critical(...)
Definition: error.h:32
AUDITPIPE_PATH
#define AUDITPIPE_PATH
Definition: configuration.h:135
warning
#define warning(...)
Definition: error.h:40
prefetcher_thread
pthread_t prefetcher_thread
Definition: mon_bsm.c:72
recognize_event_return::objtype_old
eventobjtype_t objtype_old
Definition: mon_bsm.c:63
common.h
bsm_config_setup
int bsm_config_setup(mondata_t *mondata)
Definition: mon_bsm.c:229
bsm_add_watch_dir
int bsm_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath)
Definition: mon_bsm.c:841
BSM_HANDLE_CALLWAIT
@ BSM_HANDLE_CALLWAIT
Definition: mon_bsm.c:554
mondata::pipe
FILE * pipe
Definition: mon_bsm.c:41
BSM_HANDLER_ITERATE
@ BSM_HANDLER_ITERATE
Definition: mon_bsm.c:58
mondata
Definition: mon_bsm.c:40
bsm_config_backup
int bsm_config_backup(mondata_t *mondata)
Definition: mon_bsm.c:199
mondata::config_fd
int config_fd
Definition: mon_bsm.c:42
BSM_HANDLER_CALLWAIT
@ BSM_HANDLER_CALLWAIT
Definition: mon_bsm.c:57
mon_bsm.h
mondata::event_count
size_t event_count
Definition: mon_bsm.c:43
bsm_handletype
bsm_handletype
Definition: mon_bsm.c:553
indexes::fpath2ei_ht
GHashTable * fpath2ei_ht
Definition: indexes.h:37
bsm_deinit
int bsm_deinit(ctx_t *ctx_p)
Definition: mon_bsm.c:854
critical_on
#define critical_on(cond)
Definition: error.h:33
bsm_wait_prefetched
int bsm_wait_prefetched(struct ctx *ctx_p, struct indexes *indexes_p, struct timeval *timeout_p)
Definition: mon_bsm.c:731
BSM_QUEUE_LENGTH_MAX
#define BSM_QUEUE_LENGTH_MAX
Definition: configuration.h:244
exitcode
volatile int exitcode
Definition: sync.c:547
EOT_FILE
@ EOT_FILE
Definition: clsync.h:32
EOT_DIR
@ EOT_DIR
Definition: clsync.h:33
bsm_handle_prefetched
int bsm_handle_prefetched(struct ctx *ctx_p, struct indexes *indexes_p)
Definition: mon_bsm.c:795
bsm_prefetcher_running
static int bsm_prefetcher_running
Definition: mon_bsm.c:692
bsm_cond_queueend
pthread_cond_t bsm_cond_queueend
Definition: mon_bsm.c:75
ctx_p
ctx_t * ctx_p
Definition: mon_kqueue.c:85