Browse code

remove the use of tmpfile()

git-svn: trunk@1561

Tomasz Kojm authored on 2005/05/21 09:39:13
Showing 5 changed files
... ...
@@ -1,3 +1,31 @@
1
+Sat May 21 02:17:08 CEST 2005 (tk)
2
+----------------------------------
3
+  * Remove the use of tmpfile(). Patch by Mark Pizzolato
4
+    <clamav-devel@subscriptions.pizzolato.net>, full list of changes:
5
+
6
+  * libclamav/others.c
7
+    - in cli_gentempname call cli_rndnum with 256 instead of 255 to get the
8
+      full range of possible byte values
9
+    - new functions: cli_gentempdir, cli_gentempdesc, and cli_gentempstream
10
+      which generate the appropriate type of object (and return its name)
11
+    - fix bug in memory error path of cli_gentemp (now cli_gentempname)
12
+      which printed the wrong (possibly null) value for the directory name
13
+
14
+  * libclamav/scanners.c
15
+    - use cli_gentempstream instead of tmpfile()
16
+    - fix file descriptor leak in error path in cli_scangzip()
17
+    - fix file descriptor leaks if cli_msexpand returns an error in cli_scanszdd
18
+
19
+  * clamd/scanner.c
20
+    - use cli_gentempstream instead of tmpfile() and remove the old tmpfile()
21
+      logic
22
+    - add port number to log messages for stream connections (helps
23
+      interpreting log data when multiple sessions are active)
24
+    - fix error path for a read timeout which logged messages indicating
25
+      that both a timeout and a poll error occurred.
26
+    - support configuration option LeaveTemporaryFiles for stream scanned
27
+      temporary files.
28
+
1 29
 Fri May 20 09:16:36 BST 2005 (njh)
2 30
 ----------------------------------
3 31
   * libclamav/pdf.c:	Ignore leading NL in FlateDecode messages
... ...
@@ -306,7 +306,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
306 306
 	struct sockaddr_in server;
307 307
 	struct hostent *he;
308 308
 	struct cfgstruct *cpt;
309
-	FILE *tmp = NULL;
309
+	char *tmpname;
310 310
 
311 311
 
312 312
     /* get min port */
... ...
@@ -386,12 +386,12 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
386 386
     switch(retval = poll_fd(sockfd, timeout)) {
387 387
 	case 0: /* timeout */
388 388
 	    mdprintf(odesc, "Accept timeout. ERROR\n");
389
-	    logg("!ScanStream: accept timeout.\n");
389
+	    logg("!ScanStream %d: accept timeout.\n", port);
390 390
 	    close(sockfd);
391 391
 	    return -1;
392 392
 	case -1:
393 393
 	    mdprintf(odesc, "Accept poll. ERROR\n");
394
-	    logg("!ScanStream: accept poll failed.\n");
394
+	    logg("!ScanStream %d: accept poll failed.\n", port);
395 395
 	    close(sockfd);
396 396
 	    return -1;
397 397
     }
... ...
@@ -399,21 +399,20 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
399 399
     if((acceptd = accept(sockfd, NULL, NULL)) == -1) {
400 400
 	close(sockfd);
401 401
 	mdprintf(odesc, "accept() ERROR\n");
402
-	logg("!ScanStream: accept() failed.\n");
402
+	logg("!ScanStream %d: accept() failed.\n", port);
403 403
 	return -1;
404 404
     }
405 405
 
406 406
     logg("*Accepted connection on port %d, fd %d\n", port, acceptd);
407 407
 
408
-    if((tmp = tmpfile()) == NULL) {
408
+    if ((tmpname = cli_gentempdesc(NULL, &tmpd)) == NULL) {
409 409
 	shutdown(sockfd, 2);
410 410
 	close(sockfd);
411 411
 	close(acceptd);
412 412
 	mdprintf(odesc, "tempfile() failed. ERROR\n");
413
-	logg("!ScanStream: Can't create temporary file.\n");
413
+	logg("!ScanStream %d: Can't create temporary file.\n", port);
414 414
 	return -1;
415 415
     }
416
-    tmpd = fileno(tmp);
417 416
 
418 417
     if((cpt = cfgopt(copt, "StreamMaxLength")))
419 418
 	maxsize = cpt->numarg;
... ...
@@ -434,9 +433,11 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
434 434
 	    close(sockfd);
435 435
 	    close(acceptd);
436 436
 	    mdprintf(odesc, "Temporary file -> write ERROR\n");
437
-	    logg("!ScanStream: Can't write to temporary file.\n");
438
-	    if(tmp)
439
-		fclose(tmp);
437
+	    logg("!ScanStream %d: Can't write to temporary file.\n", port);
438
+	    close(tmpd);
439
+	    if(!cfgopt(copt, "LeaveTemporaryFiles"))
440
+		unlink(tmpname);
441
+	    free(tmpname);
440 442
 	    return -1;
441 443
 	}
442 444
 
... ...
@@ -444,7 +445,7 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
444 444
 	    btread = (maxsize - size); /* only read up to max */
445 445
 
446 446
 	    if(btread <= 0) {
447
-		logg("^ScanStream: Size limit reached ( max: %d)\n", maxsize);
447
+		logg("^ScanStream %d: Size limit reached (max: %d)\n", port, maxsize);
448 448
 	    	break; /* Scan what we have */
449 449
 	    }
450 450
 	}
... ...
@@ -453,23 +454,27 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
453 453
     switch(retval) {
454 454
 	case 0: /* timeout */
455 455
 	    mdprintf(odesc, "read timeout ERROR\n");
456
-	    logg("!ScanStream: read timeout.\n");
456
+	    logg("!ScanStream %d: read timeout.\n", port);
457
+	    break;
457 458
 	case -1:
458 459
 	    mdprintf(odesc, "read poll ERROR\n");
459
-	    logg("!ScanStream: read poll failed.\n");
460
+	    logg("!ScanStream %d: read poll failed.\n", port);
461
+	    break;
460 462
     }
461 463
 
462 464
     lseek(tmpd, 0, SEEK_SET);
463 465
     ret = cl_scandesc(tmpd, &virname, scanned, root, limits, options);
464
-    if(tmp)
465
-	fclose(tmp);
466
+    close(tmpd);
467
+    if(!cfgopt(copt, "LeaveTemporaryFiles"))
468
+	unlink(tmpname);
469
+    free(tmpname);
466 470
 
467 471
     close(acceptd);
468 472
     close(sockfd);
469 473
 
470 474
     if(ret == CL_VIRUS) {
471 475
 	mdprintf(odesc, "stream: %s FOUND\n", virname);
472
-	logg("stream: %s FOUND\n", virname);
476
+	logg("stream %d: %s FOUND\n", port, virname);
473 477
 	virusaction("stream", virname, copt);
474 478
     } else if(ret != CL_CLEAN) {
475 479
 	mdprintf(odesc, "stream: %s ERROR\n", cl_strerror(ret));
... ...
@@ -370,7 +370,7 @@ void cl_settempdir(const char *dir, short leavetemps)
370 370
     cli_leavetemps_flag = leavetemps;
371 371
 }
372 372
 
373
-char *cli_gentemp(const char *dir)
373
+static char *cli_gentempname(const char *dir)
374 374
 {
375 375
 	char *name, *tmp;
376 376
         const char *mdir;
... ...
@@ -391,19 +391,15 @@ char *cli_gentemp(const char *dir)
391 391
 
392 392
     name = (char*) cli_calloc(strlen(mdir) + 1 + 16 + 1 + 7, sizeof(char));
393 393
     if(name == NULL) {
394
-	cli_dbgmsg("cli_gentemp('%s'): out of memory\n", dir);
394
+	cli_dbgmsg("cli_gentempname('%s'): out of memory\n", mdir);
395 395
 	return NULL;
396 396
     }
397 397
 
398
-#ifdef CL_THREAD_SAFE
399
-    pthread_mutex_lock(&cli_gentemp_mutex);
400
-#endif
401
-
402 398
     memcpy(salt, oldmd5buff, 16);
403 399
 
404
-    do {
400
+    do {	
405 401
 	for(i = 16; i < 48; i++)
406
-	    salt[i] = cli_rndnum(255);
402
+	    salt[i] = cli_rndnum(256);
407 403
 
408 404
 	tmp = cli_md5buff(( char* ) salt, 48);
409 405
 	sprintf(name, "%s/clamav-", mdir);
... ...
@@ -411,6 +407,19 @@ char *cli_gentemp(const char *dir)
411 411
 	free(tmp);
412 412
     } while(stat(name, &foo) != -1);
413 413
 
414
+    return(name);
415
+}
416
+
417
+char *cli_gentemp(const char *dir)
418
+{
419
+	char *name;
420
+
421
+#ifdef CL_THREAD_SAFE
422
+    pthread_mutex_lock(&cli_gentemp_mutex);
423
+#endif
424
+
425
+    name = cli_gentempname(dir);
426
+
414 427
 #ifdef CL_THREAD_SAFE
415 428
     pthread_mutex_unlock(&cli_gentemp_mutex);
416 429
 #endif
... ...
@@ -418,6 +427,76 @@ char *cli_gentemp(const char *dir)
418 418
     return(name);
419 419
 }
420 420
 
421
+
422
+char *cli_gentempdir(const char *dir)
423
+{
424
+	char *name;
425
+
426
+#ifdef CL_THREAD_SAFE
427
+    pthread_mutex_lock(&cli_gentemp_mutex);
428
+#endif
429
+
430
+    name = cli_gentempname(dir);
431
+
432
+#ifdef CL_THREAD_SAFE
433
+    pthread_mutex_unlock(&cli_gentemp_mutex);
434
+#endif
435
+
436
+    if(name && mkdir(name, 0700)) {
437
+	cli_dbgmsg("cli_gentempdir(): can't create temp directory: %s\n", name);
438
+        free(name);
439
+        name = NULL;
440
+    }
441
+
442
+    return(name);
443
+}
444
+
445
+char *cli_gentempdesc(const char *dir, int *fd)
446
+{
447
+	char *name;
448
+
449
+#ifdef CL_THREAD_SAFE
450
+    pthread_mutex_lock(&cli_gentemp_mutex);
451
+#endif
452
+
453
+    name = cli_gentempname(dir);
454
+
455
+#ifdef CL_THREAD_SAFE
456
+    pthread_mutex_unlock(&cli_gentemp_mutex);
457
+#endif
458
+
459
+    if(name && ((*fd = open(name, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0)) {
460
+	cli_dbgmsg("cli_gentempdesc(): can't create temp file: %s\n", name);
461
+        free(name);
462
+        name = NULL;
463
+    }
464
+
465
+    return(name);
466
+}
467
+
468
+char *cli_gentempstream(const char *dir, FILE **fs)
469
+{
470
+	char *name;
471
+
472
+#ifdef CL_THREAD_SAFE
473
+    pthread_mutex_lock(&cli_gentemp_mutex);
474
+#endif
475
+
476
+    name = cli_gentempname(dir);
477
+
478
+#ifdef CL_THREAD_SAFE
479
+    pthread_mutex_unlock(&cli_gentemp_mutex);
480
+#endif
481
+
482
+    if(name && ((*fs = fopen(name, "wb+")) == NULL)) {
483
+	cli_dbgmsg("cli_gentempstream(): can't create temp file: %s\n", name);
484
+        free(name);
485
+        name = NULL;
486
+    }
487
+
488
+    return(name);
489
+}
490
+
421 491
 int cli_rmdirs(const char *dirname)
422 492
 {
423 493
 	DIR *dd;
... ...
@@ -38,6 +38,9 @@ int cli_writen(int fd, void *buff, unsigned int count);
38 38
 int32_t cli_readint32(const char *buff);
39 39
 void cli_writeint32(char *offset, uint32_t value);
40 40
 char *cli_gentemp(const char *dir);
41
+char *cli_gentempdir(const char *dir);
42
+char *cli_gentempdesc(const char *dir, int *fd);
43
+char *cli_gentempstream(const char *dir, FILE **fs);
41 44
 unsigned int cli_rndnum(unsigned int max);
42 45
 int cli_filecopy(const char *src, const char *dest);
43 46
 
... ...
@@ -268,6 +268,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
268 268
 	ZZIP_DIRENT zdirent;
269 269
 	ZZIP_FILE *zfp;
270 270
 	FILE *tmp = NULL;
271
+	char *tmpname;
271 272
 	char *buff;
272 273
 	int fd, bytes, ret = CL_CLEAN;
273 274
 	unsigned long int size = 0;
... ...
@@ -428,7 +429,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
428 428
 	}
429 429
 
430 430
 	/* generate temporary file and get its descriptor */
431
-	if((tmp = tmpfile()) == NULL) {
431
+	if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
432 432
 	    cli_dbgmsg("Zip: Can't generate tmpfile().\n");
433 433
 	    zzip_file_close(zfp);
434 434
 	    ret = CL_ETMPFILE;
... ...
@@ -443,6 +444,9 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
443 443
 		zzip_file_close(zfp);
444 444
 		zzip_dir_close(zdir);
445 445
 		fclose(tmp);
446
+		if(!cli_leavetemps_flag)
447
+		    unlink(tmpname);
448
+		free(tmpname);
446 449
 		free(buff);
447 450
 		return CL_EIO;
448 451
 	    }
... ...
@@ -478,6 +482,9 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
478 478
 
479 479
 	if (tmp) {
480 480
 	    fclose(tmp);
481
+	    if(!cli_leavetemps_flag)
482
+		unlink(tmpname);
483
+	    free(tmpname);
481 484
 	    tmp = NULL;
482 485
 	}
483 486
     }
... ...
@@ -485,6 +492,9 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
485 485
     zzip_dir_close(zdir);
486 486
     if (tmp) {
487 487
 	fclose(tmp);
488
+	if(!cli_leavetemps_flag)
489
+	    unlink(tmpname);
490
+	free(tmpname);
488 491
 	tmp = NULL;
489 492
     }
490 493
 
... ...
@@ -498,6 +508,7 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
498 498
 	unsigned long int size = 0;
499 499
 	char *buff;
500 500
 	FILE *tmp = NULL;
501
+	char *tmpname;
501 502
 	gzFile gd;
502 503
 
503 504
 
... ...
@@ -508,7 +519,7 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
508 508
 	return CL_EGZIP;
509 509
     }
510 510
 
511
-    if((tmp = tmpfile()) == NULL) {
511
+    if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
512 512
 	cli_dbgmsg("GZip: Can't generate temporary file.\n");
513 513
 	gzclose(gd);
514 514
 	return CL_ETMPFILE;
... ...
@@ -518,6 +529,10 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
518 518
     if(!(buff = (char *) cli_malloc(FILEBUFF))) {
519 519
 	cli_dbgmsg("GZip: Unable to malloc %d bytes.\n", FILEBUFF);
520 520
 	gzclose(gd);
521
+	fclose(tmp);
522
+	if(!cli_leavetemps_flag)
523
+	    unlink(tmpname);
524
+	free(tmpname);	
521 525
 	return CL_EMEM;
522 526
     }
523 527
 
... ...
@@ -537,6 +552,9 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
537 537
 	if(cli_writen(fd, buff, bytes) != bytes) {
538 538
 	    cli_dbgmsg("GZip: Can't write to file.\n");
539 539
 	    fclose(tmp);
540
+	    if(!cli_leavetemps_flag)
541
+		unlink(tmpname);
542
+	    free(tmpname);	
540 543
 	    gzclose(gd);
541 544
 	    free(buff);
542 545
 	    return CL_EGZIP;
... ...
@@ -548,12 +566,18 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
548 548
 
549 549
     if(ret == CL_VIRUS) {
550 550
 	fclose(tmp);
551
+	if(!cli_leavetemps_flag)
552
+	    unlink(tmpname);
553
+	free(tmpname);	
551 554
 	return ret;
552 555
     }
553 556
 
554 557
     if(fsync(fd) == -1) {
555 558
 	cli_dbgmsg("GZip: Can't synchronise descriptor %d\n", fd);
556 559
 	fclose(tmp);
560
+	if(!cli_leavetemps_flag)
561
+	    unlink(tmpname);
562
+	free(tmpname);	
557 563
 	return CL_EFSYNC;
558 564
     }
559 565
 
... ...
@@ -561,9 +585,15 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
561 561
     if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS ) {
562 562
 	cli_dbgmsg("GZip: Infected with %s\n", *virname);
563 563
 	fclose(tmp);
564
+	if(!cli_leavetemps_flag)
565
+	    unlink(tmpname);
566
+	free(tmpname);	
564 567
 	return CL_VIRUS;
565 568
     }
566 569
     fclose(tmp);
570
+    if(!cli_leavetemps_flag)
571
+	unlink(tmpname);
572
+    free(tmpname);	
567 573
 
568 574
     return ret;
569 575
 }
... ...
@@ -584,6 +614,7 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
584 584
 	unsigned long int size = 0;
585 585
 	char *buff;
586 586
 	FILE *fs, *tmp = NULL;
587
+	char *tmpname;
587 588
 	BZFILE *bfd;
588 589
 
589 590
 
... ...
@@ -602,7 +633,7 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
602 602
 	return CL_EBZIP;
603 603
     }
604 604
 
605
-    if((tmp = tmpfile()) == NULL) {
605
+    if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
606 606
 	cli_dbgmsg("Bzip: Can't generate temporary file.\n");
607 607
 	BZ2_bzReadClose(&bzerror, bfd);
608 608
 	fclose(fs);
... ...
@@ -613,6 +644,9 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
613 613
     if(!(buff = (char *) malloc(FILEBUFF))) {
614 614
 	cli_dbgmsg("Bzip: Unable to malloc %d bytes.\n", FILEBUFF);
615 615
 	fclose(tmp);
616
+	if(!cli_leavetemps_flag)
617
+	    unlink(tmpname);
618
+	free(tmpname);	
616 619
 	fclose(fs);
617 620
 	BZ2_bzReadClose(&bzerror, bfd);
618 621
 	return CL_EMEM;
... ...
@@ -635,6 +669,9 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
635 635
 	    cli_dbgmsg("Bzip: Can't write to file.\n");
636 636
 	    BZ2_bzReadClose(&bzerror, bfd);
637 637
 	    fclose(tmp);
638
+	    if(!cli_leavetemps_flag)
639
+		unlink(tmpname);
640
+	    free(tmpname);	
638 641
 	    free(buff);
639 642
 	    fclose(fs);
640 643
 	    return CL_EGZIP;
... ...
@@ -646,6 +683,9 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
646 646
 
647 647
     if(ret == CL_VIRUS) {
648 648
 	fclose(tmp);
649
+	if(!cli_leavetemps_flag)
650
+	    unlink(tmpname);
651
+	free(tmpname);	
649 652
 	fclose(fs);
650 653
 	return ret;
651 654
     }
... ...
@@ -653,6 +693,9 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
653 653
     if(fsync(fd) == -1) {
654 654
 	cli_dbgmsg("Bzip: Synchronisation failed for descriptor %d\n", fd);
655 655
 	fclose(tmp);
656
+	if(!cli_leavetemps_flag)
657
+	    unlink(tmpname);
658
+	free(tmpname);	
656 659
 	fclose(fs);
657 660
 	return CL_EFSYNC;
658 661
     }
... ...
@@ -662,6 +705,9 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
662 662
 	cli_dbgmsg("Bzip: Infected with %s\n", *virname);
663 663
     }
664 664
     fclose(tmp);
665
+    if(!cli_leavetemps_flag)
666
+	unlink(tmpname);
667
+    free(tmpname);	
665 668
     fclose(fs);
666 669
 
667 670
     return ret;
... ...
@@ -672,6 +718,7 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
672 672
 {
673 673
 	int fd, ret = CL_CLEAN;
674 674
 	FILE *tmp = NULL, *in;
675
+	char *tmpname;
675 676
 
676 677
 
677 678
     cli_dbgmsg("in cli_scanmscomp()\n");
... ...
@@ -681,7 +728,7 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
681 681
 	return CL_EMSCOMP;
682 682
     }
683 683
 
684
-    if((tmp = tmpfile()) == NULL) {
684
+    if((tmpname = cli_gentempstream(NULL, &tmp)) == NULL) {
685 685
 	cli_dbgmsg("SZDD: Can't generate temporary file.\n");
686 686
 	fclose(in);
687 687
 	return CL_ETMPFILE;
... ...
@@ -689,6 +736,11 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
689 689
 
690 690
     if(cli_msexpand(in, tmp) == -1) {
691 691
 	cli_dbgmsg("SZDD: msexpand failed.\n");
692
+	fclose(in);
693
+	fclose(tmp);
694
+	if(!cli_leavetemps_flag)
695
+	    unlink(tmpname);
696
+	free(tmpname);	
692 697
 	return CL_EMSCOMP;
693 698
     }
694 699
 
... ...
@@ -696,6 +748,9 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
696 696
     if(fflush(tmp)) {
697 697
 	cli_dbgmsg("SZDD: fflush() failed.\n");
698 698
 	fclose(tmp);
699
+	if(!cli_leavetemps_flag)
700
+	    unlink(tmpname);
701
+	free(tmpname);	
699 702
 	return CL_EFSYNC;
700 703
     }
701 704
 
... ...
@@ -704,10 +759,16 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
704 704
     if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS) {
705 705
 	cli_dbgmsg("SZDD: Infected with %s\n", *virname);
706 706
 	fclose(tmp);
707
+	if(!cli_leavetemps_flag)
708
+	    unlink(tmpname);
709
+	free(tmpname);	
707 710
 	return CL_VIRUS;
708 711
     }
709 712
 
710 713
     fclose(tmp);
714
+    if(!cli_leavetemps_flag)
715
+	unlink(tmpname);
716
+    free(tmpname);	
711 717
     return ret;
712 718
 }
713 719