git-svn: trunk@4800
Török Edvin authored on 2009/02/17 06:27:22... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Mon Feb 16 23:56:34 EET 2009 (edwin) |
|
2 |
+------------------------------------ |
|
3 |
+ * clamd/clamd.c, clamd/server-th.c, unit_tests/check_clamd.c, |
|
4 |
+ unit_tests/check_clamd.sh: fix typo. add another stress test. |
|
5 |
+ Don't leak file descriptors. Fix IDSESSION delimiter handling. |
|
6 |
+ |
|
1 | 7 |
Mon Feb 16 20:53:45 EET 2009 (edwin) |
2 | 8 |
------------------------------------ |
3 | 9 |
* clamd/thrmgr.c: fix valgrind warning about locking order |
... | ... |
@@ -289,7 +289,7 @@ int main(int argc, char **argv) |
289 | 289 |
min_port = optget(opts, "StreamMinPort")->numarg; |
290 | 290 |
max_port = optget(opts, "StreamMaxPort")->numarg; |
291 | 291 |
if (min_port < 1024 || min_port > max_port || max_port > 65535) { |
292 |
- logg("!Invalid StreaMinPort/StreamMaxPort: %d, %d\n", min_port, max_port); |
|
292 |
+ logg("!Invalid StreamMinPort/StreamMaxPort: %d, %d\n", min_port, max_port); |
|
293 | 293 |
ret = 1; |
294 | 294 |
break; |
295 | 295 |
} |
... | ... |
@@ -256,7 +256,7 @@ static const char *get_cmd(struct fd_buf *buf, size_t off, size_t *len, char *te |
256 | 256 |
} |
257 | 257 |
|
258 | 258 |
*term = '\n'; |
259 |
- switch (buf->buffer[0]) { |
|
259 |
+ switch (buf->buffer[off]) { |
|
260 | 260 |
/* commands terminated by delimiters */ |
261 | 261 |
case 'z': |
262 | 262 |
*term = '\0'; |
... | ... |
@@ -953,6 +953,10 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi |
953 | 953 |
} |
954 | 954 |
conn.id++; |
955 | 955 |
} |
956 |
+ if (conn.scanfd != -1 && conn.scanfd != buf->dumpfd) { |
|
957 |
+ logg("*Unclaimed file descriptor received, closing: %d\n", conn.scanfd); |
|
958 |
+ close(conn.scanfd); |
|
959 |
+ } |
|
956 | 960 |
buf->mode = conn.mode; |
957 | 961 |
buf->id = conn.id; |
958 | 962 |
buf->group = conn.group; |
... | ... |
@@ -95,6 +95,8 @@ static void commands_teardown(void) |
95 | 95 |
fail_unless_fmt(rc != -1, "Failed to unlink access denied testfile: %s\n", strerror(errno)); |
96 | 96 |
} |
97 | 97 |
|
98 |
+#define VERSION_REPLY "ClamAV "REPO_VERSION""VERSION_SUFFIX |
|
99 |
+ |
|
98 | 100 |
static struct basic_test { |
99 | 101 |
const char *command; |
100 | 102 |
const char *extra; |
... | ... |
@@ -102,7 +104,7 @@ static struct basic_test { |
102 | 102 |
} basic_tests[] = { |
103 | 103 |
{"PING", NULL, "PONG"}, |
104 | 104 |
{"RELOAD", NULL, "RELOADING"}, |
105 |
- {"VERSION", NULL, "ClamAV "REPO_VERSION""VERSION_SUFFIX}, |
|
105 |
+ {"VERSION", NULL, VERSION_REPLY}, |
|
106 | 106 |
{"SCAN "SCANFILE, NULL, FOUNDREPLY}, |
107 | 107 |
{"SCAN "CLEANFILE, NULL, CLEANREPLY}, |
108 | 108 |
{"CONTSCAN "SCANFILE, NULL, FOUNDREPLY}, |
... | ... |
@@ -130,7 +132,7 @@ static struct basic_test { |
130 | 130 |
{"FILDES", "X", "No file descriptor received. ERROR"}, /* FILDES w/o ancillary data */ |
131 | 131 |
}; |
132 | 132 |
|
133 |
-static void *recvfull(int sd, size_t *len) |
|
133 |
+static void *recvpartial(int sd, size_t *len, int partial) |
|
134 | 134 |
{ |
135 | 135 |
char *buf = NULL; |
136 | 136 |
size_t off = 0; |
... | ... |
@@ -147,12 +149,17 @@ static void *recvfull(int sd, size_t *len) |
147 | 147 |
rc = recv(sd, buf + off, BUFSIZ, 0); |
148 | 148 |
fail_unless_fmt(rc != -1, "recv() failed: %s\n", strerror(errno)); |
149 | 149 |
off += rc; |
150 |
- } while (rc); |
|
150 |
+ } while (rc && (!partial || !memchr(buf, '\0', off))); |
|
151 | 151 |
*len = off; |
152 | 152 |
buf[*len] = '\0'; |
153 | 153 |
return buf; |
154 | 154 |
} |
155 | 155 |
|
156 |
+static void *recvfull(int sd, size_t *len) |
|
157 |
+{ |
|
158 |
+ return recvpartial(sd, len, 0); |
|
159 |
+} |
|
160 |
+ |
|
156 | 161 |
static void test_command(const char *cmd, size_t len, const char *extra, const char *expect, size_t expect_len) |
157 | 162 |
{ |
158 | 163 |
void *recvdata; |
... | ... |
@@ -464,6 +471,45 @@ START_TEST (test_fildes_many) |
464 | 464 |
} |
465 | 465 |
END_TEST |
466 | 466 |
|
467 |
+START_TEST (test_fildes_unwanted) |
|
468 |
+{ |
|
469 |
+ char buf[BUFSIZ]; |
|
470 |
+ size_t i; |
|
471 |
+ int dummyfd; |
|
472 |
+ char *data, *p; |
|
473 |
+ size_t len; |
|
474 |
+ |
|
475 |
+ conn_setup(); |
|
476 |
+ dummyfd = open(SCANFILE, O_RDONLY); |
|
477 |
+ |
|
478 |
+ fail_unless_fmt(send(sockd, "zIDSESSION", sizeof("zIDSESSION"), 0) == sizeof("zIDSESSION"), |
|
479 |
+ "send() failed: %s\n", strerror(errno)); |
|
480 |
+ for (i=0;i < 1024; i++) { |
|
481 |
+ snprintf(buf, sizeof(buf), "%u", i+1); |
|
482 |
+ /* send a 'zVERSION\0' including the ancillary data. |
|
483 |
+ * The \0 is from the extra char needed when sending ancillary data */ |
|
484 |
+ fail_unless_fmt(sendmsg_fd(sockd, "zVERSION", sizeof("zVERSION")-1, dummyfd, 1) != -1, |
|
485 |
+ "sendmsg (%u) failed: %s\n", i, strerror(errno)); |
|
486 |
+/* fail_unless(send(sockd, "zVERSION", sizeof("zVERSION"), 0) == sizeof("zVERSION"), |
|
487 |
+ "send failed: %s\n",strerror(errno));*/ |
|
488 |
+ data = recvpartial(sockd, &len, 1); |
|
489 |
+ p = strchr(data, ':'); |
|
490 |
+ fail_unless_fmt(!!p, "wrong VERSION reply (%u): %s\n", i, data); |
|
491 |
+ *p++ = '\0'; |
|
492 |
+ fail_unless_fmt(*p == ' ', "wrong VERSION reply (%u): %s\n", i, p); |
|
493 |
+ *p++ = '\0'; |
|
494 |
+ |
|
495 |
+ fail_unless_fmt(!strcmp(p, VERSION_REPLY), "wrong VERSION reply: %s\n", data); |
|
496 |
+ fail_unless_fmt(!strcmp(data, buf), "wrong IDSESSION id: %s\n", data); |
|
497 |
+ |
|
498 |
+ free(data); |
|
499 |
+ } |
|
500 |
+ |
|
501 |
+ close(dummyfd); |
|
502 |
+ conn_teardown(); |
|
503 |
+} |
|
504 |
+END_TEST |
|
505 |
+ |
|
467 | 506 |
static Suite *test_clamd_suite(void) |
468 | 507 |
{ |
469 | 508 |
Suite *s = suite_create("clamd"); |
... | ... |
@@ -481,6 +527,7 @@ static Suite *test_clamd_suite(void) |
481 | 481 |
tc_stress = tcase_create("clamd stress test"); |
482 | 482 |
suite_add_tcase(s, tc_stress); |
483 | 483 |
tcase_add_test(tc_stress, test_fildes_many); |
484 |
+ tcase_add_test(tc_stress, test_fildes_unwanted); |
|
484 | 485 |
|
485 | 486 |
return s; |
486 | 487 |
} |
... | ... |
@@ -52,6 +52,10 @@ scan_failed() { |
52 | 52 |
start_clamd() |
53 | 53 |
{ |
54 | 54 |
rm -f clamd-test.log |
55 |
+ $LTEXEC $CLAMD_WRAPPER $TOP/clamd/clamd -c $1 --help >clamd-test.log || |
|
56 |
+ { error "Failed to start clamd --help!"; die 1; } |
|
57 |
+ grep "Clam AntiVirus Daemon" clamd-test.log >/dev/null || |
|
58 |
+ { error "Wrong --help reply from clamd!"; die 1; } |
|
55 | 59 |
$LTEXEC $CLAMD_WRAPPER $TOP/clamd/clamd -c $1 || |
56 | 60 |
{ error "Failed to start clamd!"; die 1; } |
57 | 61 |
} |
... | ... |
@@ -159,13 +163,15 @@ EOF |
159 | 159 |
rm -rf clamdtest$CLAMD_TEST_UNIQ1 clamdtest$CLAMD_TEST_UNIQ2 |
160 | 160 |
mkdir clamdtest$CLAMD_TEST_UNIQ1 clamdtest$CLAMD_TEST_UNIQ2 || |
161 | 161 |
{ echo "Unable to create temporary directories!"; exit 1; } |
162 |
- |
|
162 |
+ |
|
163 | 163 |
# Prepare configuration for clamd #1 and #2 |
164 | 164 |
(prepare_clamd $CLAMD_TEST_UNIQ1) |
165 | 165 |
(prepare_clamd $CLAMD_TEST_UNIQ2) |
166 | 166 |
# Add clamd #2 specific configuration |
167 | 167 |
echo "VirusEvent $abs_srcdir/virusaction-test.sh `pwd`/clamdtest$CLAMD_TEST_UNIQ2 \"Virus found: %v\"" >>clamdtest$CLAMD_TEST_UNIQ2/test-clamd.conf |
168 | 168 |
echo "HeuristicScanPrecedence yes" >>clamdtest$CLAMD_TEST_UNIQ2/test-clamd.conf |
169 |
+grep -v LogFile clamdtest$CLAMD_TEST_UNIQ2/test-clamd.conf >tmp__ |
|
170 |
+mv tmp__ clamdtest$CLAMD_TEST_UNIQ2/test-clamd.conf |
|
169 | 171 |
|
170 | 172 |
# Start clamd #1 tests |
171 | 173 |
(cd clamdtest$CLAMD_TEST_UNIQ1 |