... | ... |
@@ -63,22 +63,24 @@ static void onas_fan_exit(int sig) |
63 | 63 |
{ |
64 | 64 |
logg("*ClamFanotif: onas_fan_exit(), signal %d\n", sig); |
65 | 65 |
|
66 |
- if(onas_fan_fd) { |
|
67 |
- close(onas_fan_fd); |
|
68 |
- } |
|
69 |
- onas_fan_fd = 0; |
|
70 |
- |
|
71 |
- if (ddd_pid > 0) { |
|
72 |
- pthread_kill(ddd_pid, SIGUSR1); |
|
73 |
- pthread_join(ddd_pid, NULL); |
|
74 |
- } |
|
75 |
- ddd_pid = 0; |
|
76 |
- |
|
77 |
- if (scque_pid > 0) { |
|
78 |
- pthread_kill(scque_pid, SIGUSR2); |
|
66 |
+ if(onas_fan_fd) { |
|
67 |
+ close(onas_fan_fd); |
|
68 |
+ } |
|
69 |
+ onas_fan_fd = 0; |
|
70 |
+ |
|
71 |
+ logg("*ClamFanotif: attempting to stop event consumer thread ...\n"); |
|
72 |
+ if (scque_pid > 0) { |
|
73 |
+ pthread_cancel(scque_pid); |
|
79 | 74 |
pthread_join(scque_pid, NULL); |
80 |
- } |
|
81 |
- scque_pid = 0; |
|
75 |
+ } |
|
76 |
+ scque_pid = 0; |
|
77 |
+ |
|
78 |
+ logg("*ClamFanotif: attempting to stop ddd thread ... \n"); |
|
79 |
+ if (ddd_pid > 0) { |
|
80 |
+ pthread_cancel(ddd_pid); |
|
81 |
+ pthread_join(ddd_pid, NULL); |
|
82 |
+ } |
|
83 |
+ ddd_pid = 0; |
|
82 | 84 |
|
83 | 85 |
logg("ClamFanotif: stopped\n"); |
84 | 86 |
pthread_exit(NULL); |
... | ... |
@@ -168,7 +170,7 @@ cl_error_t onas_setup_fanotif(struct onas_context **ctx) { |
168 | 168 |
|
169 | 169 |
int onas_fan_eloop(struct onas_context **ctx) { |
170 | 170 |
int ret = 0; |
171 |
- int err_cnt = 0; |
|
171 |
+ int err_cnt = 0; |
|
172 | 172 |
sigset_t sigset; |
173 | 173 |
struct sigaction act; |
174 | 174 |
short int scan; |
... | ... |
@@ -184,12 +186,14 @@ int onas_fan_eloop(struct onas_context **ctx) { |
184 | 184 |
/* ignore all signals except SIGUSR1 */ |
185 | 185 |
sigfillset(&sigset); |
186 | 186 |
sigdelset(&sigset, SIGUSR1); |
187 |
+ sigdelset(&sigset, SIGUSR2); |
|
187 | 188 |
/* The behavior of a process is undefined after it ignores a |
188 | 189 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
189 | 190 |
sigdelset(&sigset, SIGFPE); |
190 | 191 |
sigdelset(&sigset, SIGILL); |
191 | 192 |
sigdelset(&sigset, SIGSEGV); |
192 | 193 |
sigdelset(&sigset, SIGINT); |
194 |
+ sigdelset(&sigset, SIGTERM); |
|
193 | 195 |
#ifdef SIGBUS |
194 | 196 |
sigdelset(&sigset, SIGBUS); |
195 | 197 |
#endif |
... | ... |
@@ -197,28 +201,31 @@ int onas_fan_eloop(struct onas_context **ctx) { |
197 | 197 |
memset(&act, 0, sizeof(struct sigaction)); |
198 | 198 |
act.sa_handler = onas_fan_exit; |
199 | 199 |
sigfillset(&(act.sa_mask)); |
200 |
- sigaction(SIGUSR1, &act, NULL); |
|
200 |
+ sigaction(SIGUSR2, &act, NULL); |
|
201 |
+ sigaction(SIGTERM, &act, NULL); |
|
201 | 202 |
sigaction(SIGSEGV, &act, NULL); |
202 | 203 |
sigaction(SIGINT, &act, NULL); |
203 | 204 |
|
204 |
- FD_ZERO(&rfds); |
|
205 |
+ FD_ZERO(&rfds); |
|
205 | 206 |
FD_SET((*ctx)->fan_fd, &rfds); |
206 |
- do { |
|
207 |
+ |
|
208 |
+ logg("*ClamFanotif: starting fanotify event loop with process id (%d) ... \n", getpid()); |
|
209 |
+ do { |
|
207 | 210 |
ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
208 | 211 |
} while((ret == -1 && errno == EINTR)); |
209 | 212 |
|
210 |
- time_t start = time(NULL) - 30; |
|
213 |
+ time_t start = time(NULL) - 30; |
|
211 | 214 |
while(((bread = read((*ctx)->fan_fd, buf, sizeof(buf))) > 0) || (errno == EOVERFLOW || errno == EMFILE || errno == EACCES)) { |
212 | 215 |
switch(errno) { |
213 | 216 |
case EOVERFLOW: |
214 |
- if (time(NULL) - start >= 30) { |
|
217 |
+ if (time(NULL) - start >= 30) { |
|
215 | 218 |
logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
216 | 219 |
logg("*ClamFanotif: file too large for fanotify ... recovering and continuing scans...\n"); |
217 |
- start = time(NULL); |
|
218 |
- } |
|
220 |
+ start = time(NULL); |
|
221 |
+ } |
|
219 | 222 |
|
220 |
- errno = 0; |
|
221 |
- continue; |
|
223 |
+ errno = 0; |
|
224 |
+ continue; |
|
222 | 225 |
case EACCES: |
223 | 226 |
logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
224 | 227 |
logg("*ClamFanotif: check your SELinux audit logs and consider adding an exception \ |
... | ... |
@@ -228,113 +235,113 @@ int onas_fan_eloop(struct onas_context **ctx) { |
228 | 228 |
continue; |
229 | 229 |
case EMFILE: |
230 | 230 |
logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
231 |
- logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n"); |
|
232 |
- sleep(3); |
|
231 |
+ logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n"); |
|
232 |
+ sleep(3); |
|
233 | 233 |
|
234 | 234 |
errno = 0; |
235 |
- continue; |
|
235 |
+ continue; |
|
236 | 236 |
default: |
237 |
- break; |
|
238 |
- } |
|
239 |
- |
|
240 |
- fmd = (struct fanotify_event_metadata *)buf; |
|
241 |
- while (FAN_EVENT_OK(fmd, bread)) { |
|
242 |
- scan = 1; |
|
243 |
- if (fmd->fd >= 0) { |
|
244 |
- sprintf(fname, "/proc/self/fd/%d", fmd->fd); |
|
245 |
- errno = 0; |
|
246 |
- len = readlink(fname, fname, sizeof(fname) - 1); |
|
247 |
- if (len == -1) { |
|
248 |
- close(fmd->fd); |
|
237 |
+ break; |
|
238 |
+ } |
|
239 |
+ |
|
240 |
+ fmd = (struct fanotify_event_metadata *)buf; |
|
241 |
+ while (FAN_EVENT_OK(fmd, bread)) { |
|
242 |
+ scan = 1; |
|
243 |
+ if (fmd->fd >= 0) { |
|
244 |
+ sprintf(fname, "/proc/self/fd/%d", fmd->fd); |
|
245 |
+ errno = 0; |
|
246 |
+ len = readlink(fname, fname, sizeof(fname) - 1); |
|
247 |
+ if (len == -1) { |
|
248 |
+ close(fmd->fd); |
|
249 | 249 |
logg("!ClamFanotif: internal error (readlink() failed), %d, %s\n", fmd->fd, strerror(errno)); |
250 |
- if (errno == EBADF) { |
|
251 |
- logg("ClamWorker: fd already closed ... recovering ...\n"); |
|
252 |
- continue; |
|
253 |
- } else { |
|
254 |
- return 2; |
|
255 |
- } |
|
250 |
+ if (errno == EBADF) { |
|
251 |
+ logg("ClamWorker: fd already closed ... recovering ...\n"); |
|
252 |
+ continue; |
|
253 |
+ } else { |
|
254 |
+ return 2; |
|
255 |
+ } |
|
256 | 256 |
} |
257 | 257 |
fname[len] = '\0'; |
258 | 258 |
|
259 | 259 |
if((check = onas_fan_checkowner(fmd->pid, (*ctx)->clamdopts))) { |
260 |
- scan = 0; |
|
261 |
- if (check != CHK_SELF) { |
|
262 |
- logg("*ClamFanotif: %s skipped (excluded UID)\n", fname); |
|
263 |
- } |
|
264 |
- } |
|
260 |
+ scan = 0; |
|
261 |
+ if (check != CHK_SELF) { |
|
262 |
+ logg("*ClamFanotif: %s skipped (excluded UID)\n", fname); |
|
263 |
+ } |
|
264 |
+ } |
|
265 | 265 |
|
266 |
- if (scan) { |
|
266 |
+ if (scan) { |
|
267 | 267 |
struct onas_scan_event *event_data; |
268 | 268 |
|
269 | 269 |
event_data = cli_calloc(1, sizeof(struct onas_scan_event)); |
270 |
- if (NULL == event_data) { |
|
271 |
- logg("!ClamFanotif: could not allocate memory for event data struct\n"); |
|
272 |
- return 2; |
|
273 |
- } |
|
270 |
+ if (NULL == event_data) { |
|
271 |
+ logg("!ClamFanotif: could not allocate memory for event data struct\n"); |
|
272 |
+ return 2; |
|
273 |
+ } |
|
274 | 274 |
|
275 |
- /* general mapping */ |
|
276 |
- onas_map_context_info_to_event_data(*ctx, &event_data); |
|
275 |
+ /* general mapping */ |
|
276 |
+ onas_map_context_info_to_event_data(*ctx, &event_data); |
|
277 | 277 |
scan ? event_data->bool_opts |= ONAS_SCTH_B_SCAN : scan; |
278 | 278 |
|
279 |
- /* fanotify specific stuffs */ |
|
279 |
+ /* fanotify specific stuffs */ |
|
280 | 280 |
event_data->bool_opts |= ONAS_SCTH_B_FANOTIFY; |
281 |
- event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata)); |
|
282 |
- if (NULL == event_data->fmd) { |
|
283 |
- logg("!ClamFanotif: could not allocate memory for event data struct fmd\n"); |
|
284 |
- return 2; |
|
285 |
- } |
|
281 |
+ event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata)); |
|
282 |
+ if (NULL == event_data->fmd) { |
|
283 |
+ logg("!ClamFanotif: could not allocate memory for event data struct fmd\n"); |
|
284 |
+ return 2; |
|
285 |
+ } |
|
286 | 286 |
memcpy(event_data->fmd, fmd, sizeof(struct fanotify_event_metadata)); |
287 |
- event_data->pathname = cli_strdup(fname); |
|
287 |
+ event_data->pathname = cli_strdup(fname); |
|
288 | 288 |
|
289 | 289 |
|
290 | 290 |
logg("*ClamFanotif: attempting to feed consumer queue\n"); |
291 | 291 |
/* feed consumer queue */ |
292 | 292 |
if (CL_SUCCESS != onas_queue_event(event_data)) { |
293 |
- close(fmd->fd); |
|
293 |
+ close(fmd->fd); |
|
294 | 294 |
logg("!ClamFanotif: error occurred while feeding consumer queue ... \n"); |
295 |
- if ((*ctx)->retry_on_error) { |
|
296 |
- err_cnt++; |
|
297 |
- if (err_cnt < (*ctx)->retry_attempts) { |
|
298 |
- logg("ClamFanotif: ... recovering ...\n"); |
|
299 |
- continue; |
|
300 |
- } |
|
301 |
- } |
|
295 |
+ if ((*ctx)->retry_on_error) { |
|
296 |
+ err_cnt++; |
|
297 |
+ if (err_cnt < (*ctx)->retry_attempts) { |
|
298 |
+ logg("ClamFanotif: ... recovering ...\n"); |
|
299 |
+ continue; |
|
300 |
+ } |
|
301 |
+ } |
|
302 | 302 |
return 2; |
303 | 303 |
} |
304 |
- } else { |
|
305 |
- if (fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
306 |
- struct fanotify_response res; |
|
304 |
+ } else { |
|
305 |
+ if (fmd->mask & FAN_ALL_PERM_EVENTS) { |
|
306 |
+ struct fanotify_response res; |
|
307 | 307 |
|
308 |
- res.fd = fmd->fd; |
|
309 |
- res.response = FAN_ALLOW; |
|
308 |
+ res.fd = fmd->fd; |
|
309 |
+ res.response = FAN_ALLOW; |
|
310 | 310 |
|
311 |
- if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) { |
|
312 |
- logg("!ClamFanotif: error occurred while excluding event\n"); |
|
313 |
- return 2; |
|
314 |
- } |
|
311 |
+ if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) { |
|
312 |
+ logg("!ClamFanotif: error occurred while excluding event\n"); |
|
313 |
+ return 2; |
|
314 |
+ } |
|
315 | 315 |
} |
316 | 316 |
|
317 |
- if (-1 == close(fmd->fd)) { |
|
317 |
+ if (-1 == close(fmd->fd)) { |
|
318 | 318 |
logg("!ClamFanotif: error occurred while closing metadata fd, %d\n", fmd->fd); |
319 |
- if (errno == EBADF) { |
|
320 |
- logg("ClamFanotif: fd already closed ... recovering ...\n"); |
|
321 |
- } else { |
|
322 |
- return 2; |
|
323 |
- } |
|
324 |
- } |
|
325 |
- } |
|
326 |
- } |
|
327 |
- fmd = FAN_EVENT_NEXT(fmd, bread); |
|
328 |
- } |
|
329 |
- do { |
|
330 |
- ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
319 |
+ if (errno == EBADF) { |
|
320 |
+ logg("ClamFanotif: fd already closed ... recovering ...\n"); |
|
321 |
+ } else { |
|
322 |
+ return 2; |
|
323 |
+ } |
|
324 |
+ } |
|
325 |
+ } |
|
326 |
+ } |
|
327 |
+ fmd = FAN_EVENT_NEXT(fmd, bread); |
|
328 |
+ } |
|
329 |
+ do { |
|
330 |
+ ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); |
|
331 | 331 |
} while((ret == -1 && errno == EINTR)); |
332 |
-} |
|
332 |
+ } |
|
333 | 333 |
|
334 |
- if(bread < 0) { |
|
334 |
+ if(bread < 0) { |
|
335 | 335 |
logg("!ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); |
336 |
- return 2; |
|
337 |
- } |
|
336 |
+ return 2; |
|
337 |
+ } |
|
338 | 338 |
|
339 | 339 |
|
340 | 340 |
return ret; |
... | ... |
@@ -74,8 +74,7 @@ static void onas_ddd_handle_in_create(struct onas_context *ctx, const char *path |
74 | 74 |
static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); |
75 | 75 |
static void onas_ddd_handle_in_delete(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); |
76 | 76 |
static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options); |
77 |
- |
|
78 |
-static void onas_ddd_exit(int sig); |
|
77 |
+static void onas_ddd_exit(void *arg); |
|
79 | 78 |
|
80 | 79 |
/* TODO: Unglobalize these. */ |
81 | 80 |
static struct onas_ht *ddd_ht; |
... | ... |
@@ -327,57 +326,52 @@ cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx) { |
327 | 327 |
|
328 | 328 |
void *onas_ddd_th(void *arg) { |
329 | 329 |
struct onas_context *ctx = (struct onas_context *) arg; |
330 |
- sigset_t sigset; |
|
331 |
- struct sigaction act; |
|
332 |
- const struct optstruct *pt; |
|
333 |
- uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; |
|
334 |
- fd_set rfds; |
|
335 |
- char buf[4096]; |
|
336 |
- ssize_t bread; |
|
337 |
- const struct inotify_event *event; |
|
330 |
+ sigset_t sigset; |
|
331 |
+ struct sigaction act; |
|
332 |
+ const struct optstruct *pt; |
|
333 |
+ uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; |
|
334 |
+ fd_set rfds; |
|
335 |
+ char buf[4096]; |
|
336 |
+ ssize_t bread; |
|
337 |
+ const struct inotify_event *event; |
|
338 | 338 |
int ret, len, idx; |
339 | 339 |
|
340 | 340 |
char** include_list = NULL; |
341 | 341 |
char** exclude_list = NULL; |
342 | 342 |
int num_exdirs, num_indirs; |
343 |
- cl_error_t err; |
|
343 |
+ cl_error_t err; |
|
344 | 344 |
|
345 |
- /* ignore all signals except SIGUSR1 */ |
|
346 |
- sigfillset(&sigset); |
|
347 |
- sigdelset(&sigset, SIGUSR1); |
|
348 |
- /* The behavior of a process is undefined after it ignores a |
|
345 |
+ /* ignore all signals */ |
|
346 |
+ sigfillset(&sigset); |
|
347 |
+ sigdelset(&sigset, SIGUSR1); |
|
348 |
+ sigdelset(&sigset, SIGUSR2); |
|
349 |
+ /* The behavior of a process is undefined after it ignores a |
|
349 | 350 |
* SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ |
350 |
- sigdelset(&sigset, SIGFPE); |
|
351 |
- sigdelset(&sigset, SIGILL); |
|
352 |
- sigdelset(&sigset, SIGSEGV); |
|
351 |
+ sigdelset(&sigset, SIGFPE); |
|
352 |
+ sigdelset(&sigset, SIGILL); |
|
353 |
+ sigdelset(&sigset, SIGTERM); |
|
353 | 354 |
sigdelset(&sigset, SIGINT); |
354 | 355 |
#ifdef SIGBUS |
355 |
- sigdelset(&sigset, SIGBUS); |
|
356 |
+ sigdelset(&sigset, SIGBUS); |
|
356 | 357 |
#endif |
357 |
- pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
|
358 |
- memset(&act, 0, sizeof(struct sigaction)); |
|
359 |
- act.sa_handler = onas_ddd_exit; |
|
360 |
- sigfillset(&(act.sa_mask)); |
|
361 |
- sigaction(SIGUSR1, &act, NULL); |
|
362 |
- sigaction(SIGSEGV, &act, NULL); |
|
363 | 358 |
|
364 |
- logg("*ClamInotif: starting inotify event thread\n"); |
|
359 |
+ logg("*ClamInotif: starting inotify event loop ...\n"); |
|
365 | 360 |
|
366 |
- onas_in_fd = inotify_init1(IN_NONBLOCK); |
|
367 |
- if (onas_in_fd == -1) { |
|
361 |
+ onas_in_fd = inotify_init1(IN_NONBLOCK); |
|
362 |
+ if (onas_in_fd == -1) { |
|
368 | 363 |
logg("!ClamInotif: could not init inotify\n"); |
369 |
- return NULL; |
|
370 |
- } |
|
364 |
+ return NULL; |
|
365 |
+ } |
|
371 | 366 |
|
372 |
- ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); |
|
373 |
- if (ret) { |
|
367 |
+ ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); |
|
368 |
+ if (ret) { |
|
374 | 369 |
logg("!ClamInotif: failed to initialize DDD system\n"); |
375 |
- return NULL; |
|
376 |
- } |
|
370 |
+ return NULL; |
|
371 |
+ } |
|
377 | 372 |
|
378 | 373 |
|
379 | 374 |
logg("*ClamInotif: dynamically determining directory hierarchy...\n"); |
380 |
- /* Add provided paths recursively. */ |
|
375 |
+ /* Add provided paths recursively. */ |
|
381 | 376 |
|
382 | 377 |
if (!optget(ctx->opts, "watch-list")->enabled && !optget(ctx->clamdopts, "OnAccessIncludePath")->enabled) { |
383 | 378 |
logg("!ClamInotif: Please specify at least one path with OnAccessIncludePath\n"); |
... | ... |
@@ -386,24 +380,24 @@ void *onas_ddd_th(void *arg) { |
386 | 386 |
|
387 | 387 |
if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
388 | 388 |
|
389 |
- while (pt) { |
|
390 |
- if (!strcmp(pt->strarg, "/")) { |
|
389 |
+ while (pt) { |
|
390 |
+ if (!strcmp(pt->strarg, "/")) { |
|
391 | 391 |
logg("!ClamInotif: not including path '%s' while DDD is enabled\n", pt->strarg); |
392 | 392 |
logg("!ClamInotif: please use the OnAccessMountPath option to watch '%s'\n", pt->strarg); |
393 |
- pt = (struct optstruct *)pt->nextarg; |
|
394 |
- continue; |
|
395 |
- } |
|
396 |
- if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { |
|
397 |
- if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { |
|
393 |
+ pt = (struct optstruct *)pt->nextarg; |
|
394 |
+ continue; |
|
395 |
+ } |
|
396 |
+ if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { |
|
397 |
+ if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { |
|
398 | 398 |
logg("!ClamInotif: can't include '%s'\n", pt->strarg); |
399 |
- return NULL; |
|
399 |
+ return NULL; |
|
400 | 400 |
} else { |
401 | 401 |
logg("ClamInotif: watching '%s' (and all sub-directories)\n", pt->strarg); |
402 |
- } |
|
402 |
+ } |
|
403 | 403 |
} |
404 | 404 |
|
405 |
- pt = (struct optstruct *)pt->nextarg; |
|
406 |
- } |
|
405 |
+ pt = (struct optstruct *)pt->nextarg; |
|
406 |
+ } |
|
407 | 407 |
} |
408 | 408 |
|
409 | 409 |
if((pt = optget(ctx->opts, "watch-list"))->enabled) { |
... | ... |
@@ -413,8 +407,8 @@ void *onas_ddd_th(void *arg) { |
413 | 413 |
|
414 | 414 |
include_list = onas_get_opt_list(pt->strarg, &num_indirs, &err); |
415 | 415 |
if (NULL == include_list) { |
416 |
- return NULL; |
|
417 |
- } |
|
416 |
+ return NULL; |
|
417 |
+ } |
|
418 | 418 |
|
419 | 419 |
idx = 0; |
420 | 420 |
while (NULL != include_list[idx]) { |
... | ... |
@@ -432,21 +426,21 @@ void *onas_ddd_th(void *arg) { |
432 | 432 |
} |
433 | 433 |
} |
434 | 434 |
|
435 |
- /* Remove provided paths recursively. */ |
|
435 |
+ /* Remove provided paths recursively. */ |
|
436 | 436 |
if((pt = optget(ctx->clamdopts, "OnAccessExcludePath"))->enabled) { |
437 |
- while (pt) { |
|
438 |
- size_t ptlen = strlen(pt->strarg); |
|
439 |
- if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
440 |
- if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { |
|
437 |
+ while (pt) { |
|
438 |
+ size_t ptlen = strlen(pt->strarg); |
|
439 |
+ if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
440 |
+ if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { |
|
441 | 441 |
logg("!ClamInotif: can't exclude '%s'\n", pt->strarg); |
442 |
- return NULL; |
|
443 |
- } else |
|
442 |
+ return NULL; |
|
443 |
+ } else |
|
444 | 444 |
logg("ClamInotif: excluding '%s' (and all sub-directories)\n", pt->strarg); |
445 |
- } |
|
445 |
+ } |
|
446 | 446 |
|
447 |
- pt = (struct optstruct *)pt->nextarg; |
|
448 |
- } |
|
449 |
- } |
|
447 |
+ pt = (struct optstruct *)pt->nextarg; |
|
448 |
+ } |
|
449 |
+ } |
|
450 | 450 |
|
451 | 451 |
if((pt = optget(ctx->opts, "exclude-list"))->enabled) { |
452 | 452 |
|
... | ... |
@@ -473,35 +467,35 @@ void *onas_ddd_th(void *arg) { |
473 | 473 |
} |
474 | 474 |
} |
475 | 475 |
|
476 |
- /* Watch provided paths recursively */ |
|
476 |
+ /* Watch provided paths recursively */ |
|
477 | 477 |
if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { |
478 |
- while (pt) { |
|
478 |
+ while (pt) { |
|
479 | 479 |
errno = 0; |
480 |
- size_t ptlen = strlen(pt->strarg); |
|
481 |
- if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
480 |
+ size_t ptlen = strlen(pt->strarg); |
|
481 |
+ if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { |
|
482 | 482 |
if(err = onas_ddd_watch(pt->strarg, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { |
483 | 483 |
|
484 | 484 |
if (0 == errno) { |
485 | 485 |
logg("!ClamInotif: could not watch path '%s', %d\n ", pt->strarg, err); |
486 | 486 |
} else { |
487 | 487 |
logg("!ClamInotif: could not watch path '%s', %s\n", pt->strarg, strerror(errno)); |
488 |
- if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
488 |
+ if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { |
|
489 | 489 |
logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); |
490 | 490 |
|
491 |
- kill(getpid(), SIGTERM); |
|
492 |
- } |
|
491 |
+ kill(getpid(), SIGTERM); |
|
492 |
+ } |
|
493 | 493 |
if (errno == ENOSPC) { |
494 | 494 |
|
495 | 495 |
logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); |
496 | 496 |
logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); |
497 | 497 |
|
498 | 498 |
kill(getpid(), SIGTERM); |
499 |
- } |
|
500 |
- } |
|
501 |
- } |
|
502 |
- pt = (struct optstruct *)pt->nextarg; |
|
503 |
- } |
|
504 |
- } |
|
499 |
+ } |
|
500 |
+ } |
|
501 |
+ } |
|
502 |
+ pt = (struct optstruct *)pt->nextarg; |
|
503 |
+ } |
|
504 |
+ } |
|
505 | 505 |
} |
506 | 506 |
|
507 | 507 |
if(NULL != include_list) { |
... | ... |
@@ -536,82 +530,85 @@ void *onas_ddd_th(void *arg) { |
536 | 536 |
|
537 | 537 |
if(optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { |
538 | 538 |
logg("ClamInotif: extra scanning on inotify events enabled\n"); |
539 |
-} |
|
540 |
- |
|
541 |
- FD_ZERO(&rfds); |
|
542 |
- FD_SET(onas_in_fd, &rfds); |
|
543 |
- |
|
544 |
- while (1) { |
|
545 |
- do { |
|
546 |
- ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); |
|
547 |
- } while (ret == -1 && errno == EINTR); |
|
539 |
+ } |
|
548 | 540 |
|
549 |
- while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { |
|
541 |
+ FD_ZERO(&rfds); |
|
542 |
+ FD_SET(onas_in_fd, &rfds); |
|
550 | 543 |
|
551 |
- /* Handle events. */ |
|
552 |
- int wd; |
|
553 |
- char *p = buf; |
|
554 |
- const char *path = NULL; |
|
555 |
- const char *child = NULL; |
|
556 |
- for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { |
|
544 |
+ pthread_cleanup_push(onas_ddd_exit, NULL); |
|
557 | 545 |
|
558 |
- event = (const struct inotify_event *)p; |
|
559 |
- wd = event->wd; |
|
560 |
- path = wdlt[wd]; |
|
561 |
- child = event->name; |
|
546 |
+ while (1) { |
|
547 |
+ do { |
|
548 |
+ ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); |
|
549 |
+ } while (ret == -1 && errno == EINTR); |
|
550 |
+ |
|
551 |
+ while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { |
|
552 |
+ pthread_testcancel(); |
|
553 |
+ /* Handle events. */ |
|
554 |
+ int wd; |
|
555 |
+ char *p = buf; |
|
556 |
+ const char *path = NULL; |
|
557 |
+ const char *child = NULL; |
|
558 |
+ for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { |
|
559 |
+ |
|
560 |
+ event = (const struct inotify_event *)p; |
|
561 |
+ wd = event->wd; |
|
562 |
+ path = wdlt[wd]; |
|
563 |
+ child = event->name; |
|
562 | 564 |
|
563 | 565 |
if (path == NULL) { |
564 | 566 |
logg("*ClamInotif: watch descriptor not found in lookup table ... skipping\n"); |
565 | 567 |
continue; |
566 | 568 |
} |
567 | 569 |
|
568 |
- len = strlen(path); |
|
569 |
- size_t size = strlen(child) + len + 2; |
|
570 |
- char *child_path = (char *)cli_malloc(size); |
|
570 |
+ len = strlen(path); |
|
571 |
+ size_t size = strlen(child) + len + 2; |
|
572 |
+ char *child_path = (char *)cli_malloc(size); |
|
571 | 573 |
if (child_path == NULL) { |
572 | 574 |
logg("*ClamInotif: could not allocate space for child path ... aborting\n"); |
573 |
- return NULL; |
|
575 |
+ return NULL; |
|
574 | 576 |
} |
575 | 577 |
|
576 | 578 |
if (path[len-1] == '/') { |
577 |
- snprintf(child_path, --size, "%s%s", path, child); |
|
579 |
+ snprintf(child_path, --size, "%s%s", path, child); |
|
578 | 580 |
} else { |
579 |
- snprintf(child_path, size, "%s/%s", path, child); |
|
581 |
+ snprintf(child_path, size, "%s/%s", path, child); |
|
580 | 582 |
} |
581 | 583 |
|
582 |
- if (event->mask & IN_DELETE) { |
|
584 |
+ if (event->mask & IN_DELETE) { |
|
583 | 585 |
onas_ddd_handle_in_delete(ctx, path, child_path, event, wd); |
584 | 586 |
|
585 |
- } else if (event->mask & IN_MOVED_FROM) { |
|
587 |
+ } else if (event->mask & IN_MOVED_FROM) { |
|
586 | 588 |
onas_ddd_handle_in_moved_from(ctx, path, child_path, event, wd); |
587 | 589 |
|
588 |
- } else if (event->mask & IN_CREATE) { |
|
590 |
+ } else if (event->mask & IN_CREATE) { |
|
589 | 591 |
onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask); |
590 | 592 |
|
591 |
- } else if (event->mask & IN_MOVED_TO) { |
|
593 |
+ } else if (event->mask & IN_MOVED_TO) { |
|
592 | 594 |
onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask); |
593 |
- } |
|
594 |
- } |
|
595 |
- } |
|
596 |
- } |
|
595 |
+ } |
|
596 |
+ } |
|
597 |
+ } |
|
598 |
+ } |
|
597 | 599 |
|
598 |
- logg("*ClamInotif: exiting inotify event thread\n"); |
|
599 |
- return NULL; |
|
600 |
+ logg("*ClamInotif: exiting inotify event thread\n"); |
|
601 |
+ pthread_cleanup_pop(1); |
|
602 |
+ return NULL; |
|
600 | 603 |
} |
601 | 604 |
|
602 | 605 |
|
603 | 606 |
static void onas_ddd_handle_in_delete(struct onas_context *ctx, |
604 | 607 |
const char *path, const char *child_path, const struct inotify_event *event, int wd) { |
605 | 608 |
|
606 |
- struct stat s; |
|
607 |
- if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
608 |
- if (!(event->mask & IN_ISDIR)) return; |
|
609 |
+ struct stat s; |
|
610 |
+ if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; |
|
611 |
+ if (!(event->mask & IN_ISDIR)) return; |
|
609 | 612 |
|
610 | 613 |
logg("*ClamInotif: DELETE - removing %s from %s with wd:%d\n", child_path, path, wd); |
611 | 614 |
onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); |
612 |
- onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
615 |
+ onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); |
|
613 | 616 |
|
614 |
- return; |
|
617 |
+ return; |
|
615 | 618 |
} |
616 | 619 |
|
617 | 620 |
static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, |
... | ... |
@@ -716,25 +713,25 @@ static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char |
716 | 716 |
return; |
717 | 717 |
} |
718 | 718 |
|
719 |
-static void onas_ddd_exit(int sig) { |
|
720 |
- logg("*ClamInotif: onas_ddd_exit(), signal %d\n", sig); |
|
719 |
+static void onas_ddd_exit(void *arg) { |
|
720 |
+ logg("*ClamInotif: onas_ddd_exit()\n"); |
|
721 | 721 |
|
722 |
- if (onas_in_fd) { |
|
723 |
- close(onas_in_fd); |
|
724 |
- } |
|
725 |
- onas_in_fd = 0; |
|
722 |
+ if (onas_in_fd) { |
|
723 |
+ close(onas_in_fd); |
|
724 |
+ } |
|
725 |
+ onas_in_fd = 0; |
|
726 | 726 |
|
727 | 727 |
if (ddd_ht) { |
728 |
- onas_free_ht(ddd_ht); |
|
729 |
- } |
|
730 |
- ddd_ht = NULL; |
|
728 |
+ onas_free_ht(ddd_ht); |
|
729 |
+ } |
|
730 |
+ ddd_ht = NULL; |
|
731 | 731 |
|
732 |
- if (wdlt) { |
|
733 |
- free(wdlt); |
|
734 |
- } |
|
735 |
- wdlt = NULL; |
|
732 |
+ if (wdlt) { |
|
733 |
+ free(wdlt); |
|
734 |
+ } |
|
735 |
+ wdlt = NULL; |
|
736 | 736 |
|
737 | 737 |
logg("ClamInotif: stopped\n"); |
738 |
- pthread_exit(NULL); |
|
739 | 738 |
} |
739 |
+ |
|
740 | 740 |
#endif |
... | ... |
@@ -44,7 +44,7 @@ |
44 | 44 |
#include "./onaccess_scth.h" |
45 | 45 |
#include "./onaccess_scque.h" |
46 | 46 |
|
47 |
-static void onas_scanque_exit(int sig); |
|
47 |
+static void onas_scanque_exit(void * arg); |
|
48 | 48 |
static int onas_consume_event(threadpool thpool); |
49 | 49 |
static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node); |
50 | 50 |
static void onas_destroy_event_queue_node(struct onas_event_queue_node *node); |
... | ... |
@@ -121,6 +121,10 @@ static void onas_destroy_event_queue_node(struct onas_event_queue_node *node) { |
121 | 121 |
|
122 | 122 |
static void onas_destroy_event_queue() { |
123 | 123 |
|
124 |
+ if (NULL == g_onas_event_queue_head) { |
|
125 |
+ return; |
|
126 |
+ } |
|
127 |
+ |
|
124 | 128 |
struct onas_event_queue_node *curr = g_onas_event_queue_head; |
125 | 129 |
struct onas_event_queue_node *next = curr->next; |
126 | 130 |
|
... | ... |
@@ -147,7 +151,7 @@ void *onas_scanque_th(void *arg) { |
147 | 147 |
|
148 | 148 |
cl_error_t err; |
149 | 149 |
|
150 |
- /* ignore all signals except SIGUSR1 */ |
|
150 |
+ /* ignore all signals except SIGUSR2 */ |
|
151 | 151 |
sigfillset(&sigset); |
152 | 152 |
sigdelset(&sigset, SIGUSR2); |
153 | 153 |
/* The behavior of a process is undefined after it ignores a |
... | ... |
@@ -155,16 +159,11 @@ void *onas_scanque_th(void *arg) { |
155 | 155 |
sigdelset(&sigset, SIGFPE); |
156 | 156 |
sigdelset(&sigset, SIGILL); |
157 | 157 |
sigdelset(&sigset, SIGSEGV); |
158 |
+ sigdelset(&sigset, SIGTERM); |
|
158 | 159 |
sigdelset(&sigset, SIGINT); |
159 | 160 |
#ifdef SIGBUS |
160 | 161 |
sigdelset(&sigset, SIGBUS); |
161 | 162 |
#endif |
162 |
- pthread_sigmask(SIG_SETMASK, &sigset, NULL); |
|
163 |
- memset(&act, 0, sizeof(struct sigaction)); |
|
164 |
- act.sa_handler = onas_scanque_exit; |
|
165 |
- sigfillset(&(act.sa_mask)); |
|
166 |
- sigaction(SIGUSR2, &act, NULL); |
|
167 |
- sigaction(SIGSEGV, &act, NULL); |
|
168 | 163 |
|
169 | 164 |
logg("*ClamQueue: initializing event queue consumer ... (%d) threads in thread pool\n", ctx->maxthreads); |
170 | 165 |
onas_init_event_queue(); |
... | ... |
@@ -172,20 +171,21 @@ void *onas_scanque_th(void *arg) { |
172 | 172 |
g_thpool = thpool; |
173 | 173 |
|
174 | 174 |
/* loop w/ onas_consume_event until we die */ |
175 |
+ pthread_cleanup_push(onas_scanque_exit, NULL); |
|
175 | 176 |
logg("*ClamQueue: waiting to consume events ...\n"); |
176 | 177 |
do { |
177 |
- pthread_mutex_lock(&onas_scque_loop); |
|
178 |
- pthread_cond_wait(&onas_scque_empty_cond, &onas_scque_loop); |
|
179 |
- /* run 'till we're empty */ |
|
178 |
+ pthread_mutex_lock(&onas_scque_loop); |
|
179 |
+ pthread_cond_wait(&onas_scque_empty_cond, &onas_scque_loop); |
|
180 |
+ /* run 'till we're empty */ |
|
180 | 181 |
do { |
181 |
- ret = onas_consume_event(thpool); |
|
182 |
- } while (1 != ret); |
|
183 |
- pthread_mutex_unlock(&onas_scque_loop); |
|
184 |
- |
|
185 |
- |
|
182 |
+ pthread_testcancel(); |
|
183 |
+ ret = onas_consume_event(thpool); |
|
184 |
+ } while (1 != ret); |
|
185 |
+ pthread_mutex_unlock(&onas_scque_loop); |
|
186 | 186 |
|
187 | 187 |
} while(1); |
188 | 188 |
|
189 |
+ pthread_cleanup_pop(1); |
|
189 | 190 |
} |
190 | 191 |
|
191 | 192 |
static int onas_queue_is_b_empty() { |
... | ... |
@@ -282,17 +282,19 @@ cl_error_t onas_scanque_start(struct onas_context **ctx) { |
282 | 282 |
return CL_SUCCESS; |
283 | 283 |
} |
284 | 284 |
|
285 |
-static void onas_scanque_exit(int sig) { |
|
285 |
+static void onas_scanque_exit(void *arg) { |
|
286 | 286 |
|
287 |
- logg("*ClamScanque: onas_scanque_exit(), signal %d\n", sig); |
|
287 |
+ logg("*ClamScanque: onas_scanque_exit()\n"); |
|
288 | 288 |
|
289 |
+ pthread_mutex_lock(&onas_queue_lock); |
|
289 | 290 |
onas_destroy_event_queue(); |
291 |
+ |
|
290 | 292 |
if (g_thpool) { |
291 | 293 |
thpool_destroy(g_thpool); |
292 | 294 |
} |
293 | 295 |
g_thpool = NULL; |
296 |
+ pthread_mutex_unlock(&onas_queue_lock); |
|
294 | 297 |
|
295 | 298 |
logg("ClamScanque: stopped\n"); |
296 |
- pthread_exit(NULL); |
|
297 | 299 |
} |
298 | 300 |
|