Browse code

introduce cli_ctime() that uses ctime_r() when available, and falls back to locking with a mutex around ctime(). (ensures we are using the same mutex always). use cli_ctime() instead of the thread-unsafe ctime(). This fixes stability problems.

git-svn: trunk@3578

Török Edvin authored on 2008/02/04 04:23:20
Showing 9 changed files
... ...
@@ -1,3 +1,11 @@
1
+Sun Feb  3 21:04:54 EET 2008 (edwin)
2
+---------------------------------
3
+  * libclamav/others.[ch]: introduce cli_ctime() that uses ctime_r() when
4
+		available, and falls back to locking with a mutex around
5
+		ctime(). (ensures we are using the same mutex always).
6
+  * clamd, shared: use cli_ctime() instead of the thread-unsafe ctime().
7
+		This fixes stability problems.
8
+
1 9
 Sun Feb  3 19:13:43 CET 2008 (tk)
2 10
 ---------------------------------
3 11
   * libclamav/filetypes.h: set MAGIC_BUFFER_SIZE to 512
... ...
@@ -216,6 +216,7 @@ int main(int argc, char **argv)
216 216
 	cl_debug();
217 217
 
218 218
     if((cpt = cfgopt(copt, "LogFile"))->enabled) {
219
+	char timestr[32];
219 220
 	logg_file = cpt->strarg;
220 221
 	if(strlen(logg_file) < 2 || (logg_file[0] != '/' && logg_file[0] != '\\' && logg_file[1] != ':')) {
221 222
 	    fprintf(stderr, "ERROR: LogFile requires full path.\n");
... ...
@@ -224,7 +225,7 @@ int main(int argc, char **argv)
224 224
 	    return 1;
225 225
 	}
226 226
 	time(&currtime);
227
-	if(logg("#+++ Started at %s", ctime(&currtime))) {
227
+	if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) {
228 228
 	    fprintf(stderr, "ERROR: Problem with internal logger. Please check the permissions on the %s file.\n", logg_file);
229 229
 	    logg_close();
230 230
 	    freecfg(copt);
... ...
@@ -50,6 +50,7 @@
50 50
 #include "clamuko.h"
51 51
 #include "others.h"
52 52
 #include "shared.h"
53
+#include "libclamav/others.h"
53 54
 
54 55
 #ifndef	C_WINDOWS
55 56
 #define	closesocket(s)	close(s)
... ...
@@ -260,6 +261,7 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
260 260
 	int max_threads, i, ret = 0;
261 261
 	unsigned int options = 0;
262 262
 	threadpool_t *thr_pool;
263
+	char timestr[32];
263 264
 #ifndef	C_WINDOWS
264 265
 	struct sigaction sigact;
265 266
 #endif
... ...
@@ -664,7 +666,7 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
664 664
     }
665 665
 
666 666
     time(&current_time);
667
-    logg("--- Stopped at %s", ctime(&current_time));
667
+    logg("--- Stopped at %s", cli_ctime(&current_time, timestr, sizeof(timestr)));
668 668
 
669 669
     return ret;
670 670
 }
... ...
@@ -43,6 +43,7 @@
43 43
 
44 44
 #include "libclamav/clamav.h"
45 45
 #include "libclamav/str.h"
46
+#include "libclamav/others.h"
46 47
 
47 48
 #include "shared/cfgparser.h"
48 49
 #include "shared/output.h"
... ...
@@ -53,8 +54,6 @@
53 53
 #include "server.h"
54 54
 #include "session.h"
55 55
 
56
-static pthread_mutex_t ctime_mutex = PTHREAD_MUTEX_INITIALIZER;
57
-
58 56
 int command(int desc, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, const struct cfgstruct *copt, int timeout)
59 57
 {
60 58
 	char buff[1025];
... ...
@@ -117,11 +116,10 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
117 117
 	    sprintf(path, "%s/daily.cld", dbdir);
118 118
 
119 119
 	if(!access(path, R_OK) && (daily = cl_cvdhead(path))) {
120
+		char timestr[32];
120 121
 		time_t t = (time_t) daily->stime;
121 122
 
122
-	    pthread_mutex_lock(&ctime_mutex);
123
-	    mdprintf(desc, "ClamAV "VERSION"/%d/%s", daily->version, ctime(&t));
124
-	    pthread_mutex_unlock(&ctime_mutex);
123
+	    mdprintf(desc, "ClamAV "VERSION"/%d/%s", daily->version, cli_ctime(&t, timestr, sizeof(timestr)));
125 124
 	    cl_cvdfree(daily);
126 125
 	} else {
127 126
 	    mdprintf(desc, "ClamAV "VERSION"\n");
... ...
@@ -62,6 +62,7 @@ CLAMAV_PRIVATE {
62 62
     cli_memstr;
63 63
     cli_strdup;
64 64
     cli_realloc;
65
+    cli_ctime;
65 66
     tableCreate;
66 67
     tableDestroy;
67 68
     tableRemove;
... ...
@@ -59,6 +59,11 @@
59 59
 #ifdef CL_THREAD_SAFE
60 60
 #  include <pthread.h>
61 61
 static pthread_mutex_t cli_gentemp_mutex = PTHREAD_MUTEX_INITIALIZER;
62
+
63
+# ifndef HAVE_CTIME_R
64
+static pthread_mutex_t cli_ctime_mutex = PTHREAD_MUTEX_INITIALIZER;
65
+# endif
66
+
62 67
 #endif
63 68
 
64 69
 #if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
... ...
@@ -853,3 +858,32 @@ int cli_bitset_test(bitset_t *bs, unsigned long bit_offset)
853 853
 	}
854 854
 	return (bs->bitset[char_offset] & ((unsigned char)1 << bit_offset));
855 855
 }
856
+
857
+const char* cli_ctime(const time_t *timep, char *buf, const size_t bufsize)
858
+{
859
+	if(bufsize < 26) {
860
+		/* standard says we must have at least 26 bytes buffer */
861
+		cli_warnmsg("buffer too small for ctime\n");
862
+		return NULL;
863
+	}
864
+#ifdef HAVE_CTIME_R	
865
+# ifdef HAVE_CTIME_R_2
866
+	char* y = ctime_r(timep, buf);
867
+	return y;
868
+# else
869
+	return ctime_r(timep, buf, bufsize);
870
+# endif
871
+#else /* no ctime_r */
872
+
873
+# ifdef CL_THREAD_SAFE
874
+	pthread_mutex_lock(&cli_ctime_mutex);
875
+# endif
876
+	strncpy(buf, ctime(timep), bufsize-1);
877
+	buf[bufsize-1] = '\0';
878
+# ifdef CL_THREAD_SAFE
879
+	pthread_mutex_unlock(&cli_ctime_mutex);
880
+# endif
881
+	return buf;
882
+#endif
883
+}
884
+
... ...
@@ -230,5 +230,6 @@ bitset_t *cli_bitset_init(void);
230 230
 void cli_bitset_free(bitset_t *bs);
231 231
 int cli_bitset_set(bitset_t *bs, unsigned long bit_offset);
232 232
 int cli_bitset_test(bitset_t *bs, unsigned long bit_offset);
233
+const char* cli_ctime(const time_t *timep, char *buf, const size_t bufsize);
233 234
 
234 235
 #endif
... ...
@@ -334,6 +334,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
334 334
 	uint32_t valign, falign, hdr_size, j;
335 335
 	struct cli_exe_section *exe_sections;
336 336
 	struct cli_matcher *md5_sect;
337
+	char timestr[32];
337 338
 
338 339
 
339 340
     if(!ctx) {
... ...
@@ -506,7 +507,7 @@ int cli_scanpe(int desc, cli_ctx *ctx)
506 506
     cli_dbgmsg("NumberOfSections: %d\n", nsections);
507 507
 
508 508
     timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
509
-    cli_dbgmsg("TimeDateStamp: %s", ctime(&timestamp));
509
+    cli_dbgmsg("TimeDateStamp: %s", cli_ctime(&timestamp, timestr, sizeof(timestr)));
510 510
 
511 511
     cli_dbgmsg("SizeOfOptionalHeader: %x\n", EC16(file_hdr.SizeOfOptionalHeader));
512 512
 
... ...
@@ -50,6 +50,7 @@
50 50
 #endif
51 51
 
52 52
 #include "output.h"
53
+#include "libclamav/others.h"
53 54
 
54 55
 #ifdef CL_NOTHREADS
55 56
 #undef CL_THREAD_SAFE
... ...
@@ -132,7 +133,7 @@ int logg(const char *str, ...)
132 132
 #ifdef F_WRLCK
133 133
 	struct flock fl;
134 134
 #endif
135
-	char *pt, *timestr, vbuff[1025];
135
+	char vbuff[1025];
136 136
 	time_t currtime;
137 137
 	struct stat sb;
138 138
 	mode_t old_umask;
... ...
@@ -189,12 +190,12 @@ int logg(const char *str, ...)
189 189
                is not set or we get a bunch of timestamps in the log without
190 190
                newlines... */
191 191
 	    if(logg_time && ((*vbuff != '*') || logg_verbose)) {
192
+	        char timestr[32];
192 193
 		time(&currtime);
193
-		pt = ctime(&currtime);
194
-		timestr = calloc(strlen(pt), 1);
195
-		strncpy(timestr, pt, strlen(pt) - 1);
194
+		cli_ctime(&currtime, timestr, sizeof(timestr));
195
+		/* cut trailing \n */
196
+		timestr[strlen(timestr)-1] = '\0';
196 197
 		fprintf(logg_fd, "%s -> ", timestr);
197
-		free(timestr);
198 198
 	    }
199 199
 
200 200
 	    if(*vbuff == '!') {