git-svn: trunk@4034
Török Edvin authored on 2008/07/31 02:26:46... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Wed Jul 30 20:09:03 EEST 2008 (edwin) |
|
2 |
+------------------------------------- |
|
3 |
+ * clamd/others.c: avoid calling non-async-signal-safe functions between fork() |
|
4 |
+ and exec() (bb #889) |
|
5 |
+ * unit_tests: add unit-test for virusaction |
|
6 |
+ |
|
1 | 7 |
Wed Jul 30 17:02:40 CEST 2008 (tk) |
2 | 8 |
---------------------------------- |
3 | 9 |
* clamscan, clamav-milter: catch and ignore SIGXFSZ; display warning if |
... | ... |
@@ -90,61 +90,67 @@ void virusaction(const char *filename, const char *virname, const struct cfgstru |
90 | 90 |
} |
91 | 91 |
|
92 | 92 |
#else |
93 |
- |
|
94 | 93 |
void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt) |
95 | 94 |
{ |
96 | 95 |
pid_t pid; |
97 | 96 |
const struct cfgstruct *cpt; |
97 |
+ char *buffer, *pt, *cmd, *buffer_file, *buffer_vir; |
|
98 |
+ size_t j; |
|
99 |
+ char *env[4]; |
|
98 | 100 |
|
99 |
- if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled) |
|
100 |
- return; |
|
101 |
+ if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled) |
|
102 |
+ return; |
|
101 | 103 |
|
102 |
- /* NB: we need to fork here since this function modifies the environment. |
|
103 |
- (Modifications to the env. are not reentrant, but we need to be.) */ |
|
104 |
- pid = fork(); |
|
104 |
+ env[0] = getenv("PATH"); |
|
105 |
+ j = env[0] ? 1 : 0; |
|
106 |
+ /* Allocate env vars.. to be portable env vars should not be freed */ |
|
107 |
+ buffer_file = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2); |
|
108 |
+ if(buffer_file) { |
|
109 |
+ sprintf(buffer_file, "%s=%s", ENV_FILE, filename); |
|
110 |
+ env[j++] = buffer_file; |
|
111 |
+ } |
|
105 | 112 |
|
106 |
- if ( pid == 0 ) { |
|
107 |
- /* child... */ |
|
108 |
- char *buffer, *pt, *cmd; |
|
113 |
+ buffer_vir = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2); |
|
114 |
+ if(buffer_vir) { |
|
115 |
+ sprintf(buffer_vir, "%s=%s", ENV_VIRUS, virname); |
|
116 |
+ env[j++] = buffer_vir; |
|
117 |
+ } |
|
118 |
+ env[j++] = NULL; |
|
109 | 119 |
|
110 | 120 |
cmd = strdup(cpt->strarg); |
111 | 121 |
|
112 | 122 |
if(cmd && (pt = strstr(cmd, "%v"))) { |
113 |
- buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10); |
|
114 |
- if(buffer) { |
|
115 |
- *pt = 0; pt += 2; |
|
116 |
- strcpy(buffer, cmd); |
|
117 |
- strcat(buffer, virname); |
|
118 |
- strcat(buffer, pt); |
|
119 |
- free(cmd); |
|
120 |
- cmd = strdup(buffer); |
|
121 |
- free(buffer); |
|
122 |
- } |
|
123 |
- } |
|
124 |
- |
|
125 |
- /* Allocate env vars.. to be portable env vars should not be freed */ |
|
126 |
- buffer = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2); |
|
127 |
- if(buffer) { |
|
128 |
- sprintf(buffer, "%s=%s", ENV_FILE, filename); |
|
129 |
- putenv(buffer); |
|
123 |
+ buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10); |
|
124 |
+ if(buffer) { |
|
125 |
+ *pt = 0; pt += 2; |
|
126 |
+ strcpy(buffer, cmd); |
|
127 |
+ strcat(buffer, virname); |
|
128 |
+ strcat(buffer, pt); |
|
129 |
+ free(cmd); |
|
130 |
+ cmd = strdup(buffer); |
|
131 |
+ free(buffer); |
|
132 |
+ } |
|
130 | 133 |
} |
131 | 134 |
|
132 |
- buffer = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2); |
|
133 |
- if(buffer) { |
|
134 |
- sprintf(buffer, "%s=%s", ENV_VIRUS, virname); |
|
135 |
- putenv(buffer); |
|
135 |
+ if(!cmd) |
|
136 |
+ return; |
|
137 |
+ /* We can only call async-signal-safe functions after fork(). */ |
|
138 |
+ pid = fork(); |
|
139 |
+ |
|
140 |
+ if ( pid == 0 ) { |
|
141 |
+ /* child... */ |
|
142 |
+ /* WARNING: this is uninterruptable ! */ |
|
143 |
+ exit(execle("/bin/sh", "sh", "-c", cmd, NULL, env)); |
|
144 |
+ } else if (pid > 0) { |
|
145 |
+ /* parent */ |
|
146 |
+ waitpid(pid, NULL, 0); |
|
147 |
+ } else { |
|
148 |
+ /* error.. */ |
|
149 |
+ logg("!VirusAction: fork failed.\n"); |
|
136 | 150 |
} |
137 |
- /* WARNING: this is uninterruptable ! */ |
|
138 |
- if(cmd) |
|
139 |
- exit(system(cmd)); |
|
140 |
- |
|
141 |
- } else if (pid > 0) { |
|
142 |
- /* parent */ |
|
143 |
- waitpid(pid, NULL, 0); |
|
144 |
- } else { |
|
145 |
- /* error.. */ |
|
146 |
- logg("!VirusAction: fork failed.\n"); |
|
147 |
- } |
|
151 |
+ free(cmd); |
|
152 |
+ free(buffer_file); |
|
153 |
+ free(buffer_vir); |
|
148 | 154 |
} |
149 | 155 |
#endif /* C_WINDOWS */ |
150 | 156 |
|
... | ... |
@@ -1,7 +1,7 @@ |
1 | 1 |
#!/bin/sh |
2 | 2 |
die() { |
3 | 3 |
test /tmp/clamd-test.pid && kill `cat /tmp/clamd-test.pid` |
4 |
- rm -r test-db |
|
4 |
+ rm -rf test-db test-clamd-viraction.conf test-clamd.log |
|
5 | 5 |
exit $1 |
6 | 6 |
} |
7 | 7 |
|
... | ... |
@@ -26,4 +26,15 @@ if test "$NFILES" -ne "$NINFECTED"; then |
26 | 26 |
grep OK clamdscan.log >&2; |
27 | 27 |
die 4; |
28 | 28 |
fi |
29 |
+cp $srcdir/test-clamd.conf test-clamd-viraction.conf |
|
30 |
+echo "VirusEvent `pwd`/$srcdir/virusaction-test.sh `pwd` \"Virus found: %v\"" >>test-clamd-viraction.conf |
|
31 |
+rm -f test-clamd.log |
|
32 |
+test /tmp/clamd-test.pid && kill `cat /tmp/clamd-test.pid` |
|
33 |
+../clamd/.libs/lt-clamd -c test-clamd-viraction.conf || { echo "Failed to start clamd!" >&2; die 1;} |
|
34 |
+../clamdscan/clamdscan --quiet --config-file test-clamd-viraction.conf ../test/clam.exe |
|
35 |
+if ! grep "Virus found: ClamAV-Test-File.UNOFFICIAL" test-clamd.log >/dev/null 2>/dev/null; then |
|
36 |
+ echo "Virusaction test failed!" >&2; |
|
37 |
+ cat test-clamd.log |
|
38 |
+ die 2; |
|
39 |
+fi |
|
29 | 40 |
die 0; |
30 | 41 |
new file mode 100755 |
... | ... |
@@ -0,0 +1,10 @@ |
0 |
+#!/bin/sh |
|
1 |
+if test ! "x$CLAM_VIRUSEVENT_FILENAME" = "x$1/../test/clam.exe"; then |
|
2 |
+ echo "VirusEvent incorrect: $CLAM_VIRUSEVENT_FILENAME" >$1/test-clamd.log |
|
3 |
+ exit 1 |
|
4 |
+fi |
|
5 |
+if test ! "x$CLAM_VIRUSEVENT_VIRUSNAME" = "xClamAV-Test-File.UNOFFICIAL"; then |
|
6 |
+ echo "VirusName incorrect: $CLAM_VIRUSEVENT_VIRUSNAME" >$1/test-clamd.log |
|
7 |
+ exit 2 |
|
8 |
+fi |
|
9 |
+echo $2 >$1/test-clamd.log |