git-svn: trunk@2509
Nigel Horne authored on 2006/11/19 07:46:01... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Sat Nov 18 22:44:37 GMT 2006 (njh) |
|
2 |
+---------------------------------- |
|
3 |
+ * libclamav: Don't implement the sleep function |
|
4 |
+ Handle DoS attacks on the JS VM by adding a timeout guarding |
|
5 |
+ against infinite loops |
|
6 |
+ |
|
1 | 7 |
Sat Nov 18 21:46:10 CET 2006 (tk) |
2 | 8 |
--------------------------------- |
3 | 9 |
* libclamav/matcher-ac.c: multipart signatures: give higher priority to new |
... | ... |
@@ -28,7 +28,7 @@ |
28 | 28 |
* TODO: Add mailfollowurls type feature |
29 | 29 |
* TODO: Check for vulnerabilities, leaks etc. |
30 | 30 |
*/ |
31 |
-static char const rcsid[] = "$Id: jscript.c,v 1.5 2006/11/11 17:18:10 njh Exp $"; |
|
31 |
+static char const rcsid[] = "$Id: jscript.c,v 1.6 2006/11/18 22:42:40 njh Exp $"; |
|
32 | 32 |
|
33 | 33 |
#if HAVE_CONFIG_H |
34 | 34 |
#include "clamav-config.h" |
... | ... |
@@ -70,6 +70,16 @@ static char const rcsid[] = "$Id: jscript.c,v 1.5 2006/11/11 17:18:10 njh Exp $" |
70 | 70 |
# endif |
71 | 71 |
#endif |
72 | 72 |
|
73 |
+#ifdef CL_THREAD_SAFE |
|
74 |
+#define VM_TIMEOUT 5 /* In seconds: FIXME should be configurable */ |
|
75 |
+#endif |
|
76 |
+ |
|
77 |
+#if defined(VM_TIMEOUT) && (VM_TIMEOUT > 0) |
|
78 |
+#include <pthread.h> |
|
79 |
+#include <sys/time.h> |
|
80 |
+#include <signal.h> |
|
81 |
+#endif |
|
82 |
+ |
|
73 | 83 |
static int run_js(const char *filename, const char *dir); |
74 | 84 |
static const char *cli_pmemstr(const char *haystack, size_t hs, const char *needle, size_t ns); |
75 | 85 |
|
... | ... |
@@ -268,6 +278,111 @@ write_to_fout(void *context, unsigned char *buf, unsigned int len) |
268 | 268 |
return (int)fwrite(buf, (size_t)len, 1, fout); |
269 | 269 |
} |
270 | 270 |
|
271 |
+#if defined(VM_TIMEOUT) && (VM_TIMEOUT > 0) |
|
272 |
+ |
|
273 |
+struct args { |
|
274 |
+ const char *filename; |
|
275 |
+ const char *dir; |
|
276 |
+ pthread_cond_t *cond; |
|
277 |
+ int result; |
|
278 |
+}; |
|
279 |
+ |
|
280 |
+static void |
|
281 |
+sigrecv(int sig) |
|
282 |
+{ |
|
283 |
+ /* pthread_cond_broadcast(&cond); */ |
|
284 |
+ pthread_exit(NULL); /* FIXME: interp isn't destroyed - mem leak? */ |
|
285 |
+} |
|
286 |
+ |
|
287 |
+static void * |
|
288 |
+js_thread(void *a) |
|
289 |
+{ |
|
290 |
+ JSInterpPtr interp; |
|
291 |
+ char *outputfilename; |
|
292 |
+ struct args *args = (struct args *)a; |
|
293 |
+ const char *dir = args->dir; |
|
294 |
+ const char *filename = args->filename; |
|
295 |
+ |
|
296 |
+ cli_dbgmsg("run_js(%s)\n", filename); |
|
297 |
+ |
|
298 |
+ outputfilename = cli_gentemp(dir); |
|
299 |
+ if(outputfilename == NULL) { |
|
300 |
+ pthread_cond_broadcast(args->cond); |
|
301 |
+ args->result = CL_ETMPFILE; |
|
302 |
+ return NULL; |
|
303 |
+ } |
|
304 |
+ |
|
305 |
+ fout = fopen(outputfilename, "wb"); |
|
306 |
+ if(fout == NULL) { |
|
307 |
+ pthread_cond_broadcast(args->cond); |
|
308 |
+ cli_warnmsg("Can't create %s\n", outputfilename); |
|
309 |
+ free(outputfilename); |
|
310 |
+ args->result = CL_ETMPFILE; |
|
311 |
+ return NULL; |
|
312 |
+ } |
|
313 |
+ |
|
314 |
+ cli_dbgmsg("Redirecting JS VM stdout to %s\n", outputfilename); |
|
315 |
+ free(outputfilename); |
|
316 |
+ |
|
317 |
+ /* |
|
318 |
+ * Run NGS on the file |
|
319 |
+ */ |
|
320 |
+ interp = create_interp(write_to_fout); |
|
321 |
+ |
|
322 |
+ args->result = CL_EIO; /* TODO: CL_TIMEOUT */ |
|
323 |
+ |
|
324 |
+ if(!js_eval_file(interp, filename)) { |
|
325 |
+ cli_warnmsg("JS failed: %s\n", js_error_message(interp)); |
|
326 |
+ /*rc = CL_EIO;*/ |
|
327 |
+ } |
|
328 |
+ |
|
329 |
+ if(pthread_cond_broadcast(args->cond) < 0) |
|
330 |
+ perror("pthread_cond_broadcast"); |
|
331 |
+ |
|
332 |
+ js_destroy_interp(interp); |
|
333 |
+ |
|
334 |
+ fclose(fout); |
|
335 |
+ |
|
336 |
+ args->result = CL_SUCCESS; |
|
337 |
+ return NULL; |
|
338 |
+} |
|
339 |
+ |
|
340 |
+static int |
|
341 |
+run_js(const char *filename, const char *dir) |
|
342 |
+{ |
|
343 |
+ struct args args; |
|
344 |
+ pthread_t tid; |
|
345 |
+ struct timespec ts; |
|
346 |
+ struct timeval tp; |
|
347 |
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
|
348 |
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER; |
|
349 |
+ void (*oldkill)(int); |
|
350 |
+ |
|
351 |
+ args.filename = filename; |
|
352 |
+ args.dir = dir; |
|
353 |
+ args.cond = &cond; |
|
354 |
+ |
|
355 |
+ pthread_create(&tid, NULL, js_thread, &args); |
|
356 |
+ |
|
357 |
+ gettimeofday(&tp, NULL); |
|
358 |
+ |
|
359 |
+ ts.tv_sec = tp.tv_sec + VM_TIMEOUT; |
|
360 |
+ ts.tv_nsec = tp.tv_usec * 1000; |
|
361 |
+ |
|
362 |
+ oldkill = signal(SIGUSR1, sigrecv); |
|
363 |
+ pthread_mutex_lock(&mutex); |
|
364 |
+ if(pthread_cond_timedwait(&cond, &mutex, &ts) == ETIMEDOUT) { |
|
365 |
+ cli_warnmsg("Run away javascript stopped after %d seconds\n", |
|
366 |
+ VM_TIMEOUT); |
|
367 |
+ pthread_kill(tid, SIGUSR1); |
|
368 |
+ } |
|
369 |
+ pthread_mutex_unlock(&mutex); |
|
370 |
+ pthread_join(tid, NULL); |
|
371 |
+ signal(SIGUSR1, oldkill); |
|
372 |
+ |
|
373 |
+ return args.result; |
|
374 |
+} |
|
375 |
+#else |
|
271 | 376 |
static int |
272 | 377 |
run_js(const char *filename, const char *dir) |
273 | 378 |
{ |
... | ... |
@@ -306,6 +421,7 @@ run_js(const char *filename, const char *dir) |
306 | 306 |
|
307 | 307 |
return CL_SUCCESS; |
308 | 308 |
} |
309 |
+#endif |
|
309 | 310 |
|
310 | 311 |
/* Copied from pdf.c :-( */ |
311 | 312 |
/* |