... | ... |
@@ -33,6 +33,10 @@ |
33 | 33 |
#endif |
34 | 34 |
#include <time.h> |
35 | 35 |
#include <signal.h> |
36 |
+#if defined(FANOTIFY) |
|
37 |
+#include <sys/fanotify.h> |
|
38 |
+#include <fcntl.h> |
|
39 |
+#endif |
|
36 | 40 |
|
37 | 41 |
#include "../libclamav/clamav.h" |
38 | 42 |
#include "../libclamav/others.h" |
... | ... |
@@ -220,6 +224,9 @@ int onas_start_eloop(struct onas_context **ctx) { |
220 | 220 |
|
221 | 221 |
static int startup_checks(struct onas_context *ctx) { |
222 | 222 |
|
223 |
+#if defined(FANOTIFY) |
|
224 |
+ char faerr[128]; |
|
225 |
+#endif |
|
223 | 226 |
int ret = 0; |
224 | 227 |
cl_error_t err = CL_SUCCESS; |
225 | 228 |
|
... | ... |
@@ -235,6 +242,17 @@ static int startup_checks(struct onas_context *ctx) { |
235 | 235 |
goto done; |
236 | 236 |
} |
237 | 237 |
|
238 |
+#if defined(FANOTIFY) |
|
239 |
+ ctx->fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); |
|
240 |
+ if (ctx->fan_fd < 0) { |
|
241 |
+ logg("!Clamonacc: fanotify_init failed: %s\n", cli_strerror(errno, faerr, sizeof(faerr))); |
|
242 |
+ if (errno == EPERM) |
|
243 |
+ logg("!Clamonacc: clamonacc must have elevated permissions ... exiting ...\n"); |
|
244 |
+ ret = 2; |
|
245 |
+ goto done; |
|
246 |
+ } |
|
247 |
+#endif |
|
248 |
+ |
|
238 | 249 |
if (curl_global_init(CURL_GLOBAL_NOTHING)) { |
239 | 250 |
ret = 2; |
240 | 251 |
goto done; |
... | ... |
@@ -284,7 +302,6 @@ void help(void) |
284 | 284 |
|
285 | 285 |
void* onas_cleanup(struct onas_context *ctx) { |
286 | 286 |
onas_context_cleanup(ctx); |
287 |
- cl_cleanup_crypto(); |
|
288 | 287 |
logg_close(); |
289 | 288 |
} |
290 | 289 |
|
... | ... |
@@ -62,6 +62,9 @@ static int onas_fan_fd; |
62 | 62 |
static void onas_fan_exit(int sig) |
63 | 63 |
{ |
64 | 64 |
logg("*ClamFanotif: onas_fan_exit(), signal %d\n", sig); |
65 |
+ if (sig == 11) { |
|
66 |
+ logg("!Clamonacc: clamonacc has experienced a fatal error, if you continue to see this error, please run clamonacc with --debug and report the issue and crash report to the developpers\n"); |
|
67 |
+ } |
|
65 | 68 |
|
66 | 69 |
if(onas_fan_fd) { |
67 | 70 |
close(onas_fan_fd); |
... | ... |
@@ -88,80 +91,72 @@ static void onas_fan_exit(int sig) |
88 | 88 |
|
89 | 89 |
cl_error_t onas_setup_fanotif(struct onas_context **ctx) { |
90 | 90 |
|
91 |
- const struct optstruct *pt; |
|
92 |
- short int scan; |
|
93 |
- unsigned int sizelimit = 0, extinfo; |
|
91 |
+ const struct optstruct *pt; |
|
92 |
+ short int scan; |
|
93 |
+ unsigned int sizelimit = 0, extinfo; |
|
94 | 94 |
uint64_t fan_mask = FAN_EVENT_ON_CHILD; |
95 |
- char err[128]; |
|
96 |
- |
|
97 |
- pthread_attr_t ddd_attr; |
|
98 |
- struct ddd_thrarg *ddd_tharg = NULL; |
|
99 | 95 |
|
100 |
- ddd_pid = 0; |
|
101 |
- |
|
102 |
- /* Initialize fanotify */ |
|
103 |
- onas_fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); |
|
104 |
- if (onas_fan_fd < 0) { |
|
105 |
- logg("!ClamFanotif: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err))); |
|
106 |
- if (errno == EPERM) |
|
107 |
- logg("!ClamFanotif: clamonacc must have elevated permissions ... exiting ...\n"); |
|
108 |
- return CL_EOPEN; |
|
109 |
- } |
|
96 |
+ pthread_attr_t ddd_attr; |
|
97 |
+ struct ddd_thrarg *ddd_tharg = NULL; |
|
110 | 98 |
|
99 |
+ ddd_pid = 0; |
|
111 | 100 |
|
112 | 101 |
if (!ctx || !*ctx) { |
113 | 102 |
logg("!ClamFanotif: unable to start clamonacc. (bad context)\n"); |
114 | 103 |
return CL_EARG; |
115 |
- } |
|
104 |
+ } |
|
116 | 105 |
|
117 |
- (*ctx)->fan_fd = onas_fan_fd; |
|
106 |
+ onas_fan_fd = (*ctx)->fan_fd; |
|
118 | 107 |
(*ctx)->fan_mask = fan_mask; |
119 | 108 |
|
120 | 109 |
if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && !optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
121 | 110 |
logg("*ClamFanotif: kernel-level blocking feature enabled ... preventing malicious files access attempts\n"); |
122 | 111 |
(*ctx)->fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM; |
123 |
- } else { |
|
112 |
+ } else { |
|
124 | 113 |
logg("*ClamFanotif: kernel-level blocking feature disabled ...\n"); |
125 | 114 |
if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { |
126 | 115 |
logg("*ClamFanotif: feature not available when watching mounts ... \n"); |
127 | 116 |
} |
128 | 117 |
(*ctx)->fan_mask |= FAN_ACCESS | FAN_OPEN; |
129 |
- } |
|
118 |
+ } |
|
130 | 119 |
|
131 | 120 |
if ((pt = optget((*ctx)->clamdopts, "OnAccessMountPath"))->enabled) { |
132 |
- while (pt) { |
|
121 |
+ while (pt) { |
|
133 | 122 |
if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
134 | 123 |
logg("!ClamFanotif: can't include mountpoint '%s'\n", pt->strarg); |
135 | 124 |
return CL_EARG; |
136 |
- } else |
|
125 |
+ } else { |
|
137 | 126 |
logg("*ClamFanotif: recursively watching the mount point '%s'\n", pt->strarg); |
138 |
- pt = (struct optstruct *)pt->nextarg; |
|
139 |
- } |
|
127 |
+ } |
|
128 |
+ pt = (struct optstruct *)pt->nextarg; |
|
129 |
+ } |
|
140 | 130 |
|
141 | 131 |
} else if (!optget((*ctx)->clamdopts, "OnAccessDisableDDD")->enabled) { |
142 | 132 |
(*ctx)->ddd_enabled = 1; |
143 |
- } else { |
|
133 |
+ } else { |
|
144 | 134 |
if((pt = optget((*ctx)->clamdopts, "OnAccessIncludePath"))->enabled) { |
145 |
- while (pt) { |
|
135 |
+ while (pt) { |
|
146 | 136 |
if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { |
147 | 137 |
logg("!ClamFanotif: can't include path '%s'\n", pt->strarg); |
148 | 138 |
return CL_EARG; |
149 |
- } else |
|
139 |
+ } else { |
|
150 | 140 |
logg("*ClamFanotif: watching directory '%s' (non-recursively)\n", pt->strarg); |
151 |
- pt = (struct optstruct *)pt->nextarg; |
|
152 |
- } |
|
153 |
- } else { |
|
141 |
+ } |
|
142 |
+ pt = (struct optstruct *)pt->nextarg; |
|
143 |
+ } |
|
144 |
+ } else { |
|
154 | 145 |
logg("!ClamFanotif: please specify at least one path with OnAccessIncludePath\n"); |
155 | 146 |
return CL_EARG; |
156 |
- } |
|
157 |
- } |
|
147 |
+ } |
|
148 |
+ } |
|
158 | 149 |
|
159 |
- /* Load other options. */ |
|
150 |
+ /* Load other options. */ |
|
160 | 151 |
(*ctx)->sizelimit = optget((*ctx)->clamdopts, "OnAccessMaxFileSize")->numarg; |
161 |
- if((*ctx)->sizelimit) |
|
152 |
+ if((*ctx)->sizelimit) { |
|
162 | 153 |
logg("*ClamFanotif: max file size limited to %lu bytes\n", (*ctx)->sizelimit); |
163 |
- else |
|
154 |
+ } else { |
|
164 | 155 |
logg("*ClamFanotif: file size limit disabled\n"); |
156 |
+ } |
|
165 | 157 |
|
166 | 158 |
extinfo = optget((*ctx)->clamdopts, "ExtendedDetectionInfo")->enabled; |
167 | 159 |
|
... | ... |
@@ -38,9 +38,12 @@ |
38 | 38 |
#include "../../clamd/scanner.h" |
39 | 39 |
#include "../clamonacc.h" |
40 | 40 |
#include "../client/onaccess_client.h" |
41 |
+#include "../scan/onaccess_scque.h" |
|
41 | 42 |
|
42 | 43 |
#if defined(FANOTIFY) |
43 | 44 |
|
45 |
+extern pthread_cond_t onas_scque_empty_cond; |
|
46 |
+ |
|
44 | 47 |
int onas_fan_checkowner(int pid, const struct optstruct *opts) |
45 | 48 |
{ |
46 | 49 |
struct passwd *pwd; |
... | ... |
@@ -49,6 +52,7 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
49 | 49 |
const struct optstruct *opt = NULL; |
50 | 50 |
const struct optstruct *opt_root = NULL; |
51 | 51 |
const struct optstruct *opt_uname = NULL; |
52 |
+ int retry = 0; |
|
52 | 53 |
|
53 | 54 |
/* always ignore ourselves */ |
54 | 55 |
if (pid == (int)getpid()) { |
... | ... |
@@ -79,9 +83,45 @@ int onas_fan_checkowner(int pid, const struct optstruct *opts) |
79 | 79 |
if (opt_uname->enabled) { |
80 | 80 |
while (opt_uname) |
81 | 81 |
{ |
82 |
+ errno = 0; |
|
82 | 83 |
pwd = getpwuid(sb.st_uid); |
83 |
- if (!strncmp(opt_uname->strarg, pwd->pw_name, strlen(opt_uname->strarg))) |
|
84 |
- return CHK_FOUND; |
|
84 |
+ if (NULL == pwd) { |
|
85 |
+ if (errno) { |
|
86 |
+ logg("*ClamMisc: internal error (failed to exclude event) ... %s\n", strerror(errno)); |
|
87 |
+ switch (errno) { |
|
88 |
+ case EIO: |
|
89 |
+ logg("*ClamMisc: system i/o failed while retrieving username information (excluding for safety)\n"); |
|
90 |
+ return CHK_FOUND; |
|
91 |
+ break; |
|
92 |
+ case EINTR: |
|
93 |
+ logg("*ClamMisc: caught signal while retrieving username information from system (excluding for safety)\n"); |
|
94 |
+ return CHK_FOUND; |
|
95 |
+ break; |
|
96 |
+ case EMFILE: |
|
97 |
+ case ENFILE: |
|
98 |
+ if (0 == retry) { |
|
99 |
+ logg("*ClamMisc: waiting for consumer thread to catch up then retrying ...\n"); |
|
100 |
+ sleep(3); |
|
101 |
+ retry = 1; |
|
102 |
+ continue; |
|
103 |
+ } else { |
|
104 |
+ logg("*ClamMisc: fds have been exhausted ... attempting to force the consumer thread to catch up ... (excluding for safety)\n"); |
|
105 |
+ pthread_cond_signal(&onas_scque_empty_cond); |
|
106 |
+ sleep(3); |
|
107 |
+ return CHK_FOUND; |
|
108 |
+ } |
|
109 |
+ case ERANGE: |
|
110 |
+ default: |
|
111 |
+ logg("*ClamMisc: unknown error occurred (excluding for safety)\n"); |
|
112 |
+ return CHK_FOUND; |
|
113 |
+ break; |
|
114 |
+ } |
|
115 |
+ } |
|
116 |
+ } else { |
|
117 |
+ if (!strncmp(opt_uname->strarg, pwd->pw_name, strlen(opt_uname->strarg))) { |
|
118 |
+ return CHK_FOUND; |
|
119 |
+ } |
|
120 |
+ } |
|
85 | 121 |
opt_uname = opt_uname->nextarg; |
86 | 122 |
} |
87 | 123 |
} |
... | ... |
@@ -52,7 +52,7 @@ static void onas_destroy_event_queue_node(struct onas_event_queue_node *node); |
52 | 52 |
static pthread_mutex_t onas_queue_lock = PTHREAD_MUTEX_INITIALIZER; |
53 | 53 |
|
54 | 54 |
static pthread_mutex_t onas_scque_loop = PTHREAD_MUTEX_INITIALIZER; |
55 |
-static pthread_cond_t onas_scque_empty_cond = PTHREAD_COND_INITIALIZER; |
|
55 |
+pthread_cond_t onas_scque_empty_cond = PTHREAD_COND_INITIALIZER; |
|
56 | 56 |
extern pthread_t scque_pid; |
57 | 57 |
|
58 | 58 |
static threadpool g_thpool; |