avoid calling non-async-signal-safe functions between fork()

and exec() (bb #889)
unit_tests: add unit-test for virusaction


git-svn: trunk@4034
0.95
Török Edvin 17 years ago
parent 9a03413e9b
commit 751f84706b
  1. 6
      ChangeLog
  2. 88
      clamd/others.c
  3. 13
      unit_tests/check_clamd.sh
  4. 10
      unit_tests/virusaction-test.sh

@ -1,3 +1,9 @@
Wed Jul 30 20:09:03 EEST 2008 (edwin)
-------------------------------------
* clamd/others.c: avoid calling non-async-signal-safe functions between fork()
and exec() (bb #889)
* unit_tests: add unit-test for virusaction
Wed Jul 30 17:02:40 CEST 2008 (tk)
----------------------------------
* 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
}
#else
void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt)
{
pid_t pid;
const struct cfgstruct *cpt;
char *buffer, *pt, *cmd, *buffer_file, *buffer_vir;
size_t j;
char *env[4];
if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
return;
if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
return;
/* NB: we need to fork here since this function modifies the environment.
(Modifications to the env. are not reentrant, but we need to be.) */
pid = fork();
env[0] = getenv("PATH");
j = env[0] ? 1 : 0;
/* Allocate env vars.. to be portable env vars should not be freed */
buffer_file = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
if(buffer_file) {
sprintf(buffer_file, "%s=%s", ENV_FILE, filename);
env[j++] = buffer_file;
}
if ( pid == 0 ) {
/* child... */
char *buffer, *pt, *cmd;
buffer_vir = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
if(buffer_vir) {
sprintf(buffer_vir, "%s=%s", ENV_VIRUS, virname);
env[j++] = buffer_vir;
}
env[j++] = NULL;
cmd = strdup(cpt->strarg);
if(cmd && (pt = strstr(cmd, "%v"))) {
buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
if(buffer) {
*pt = 0; pt += 2;
strcpy(buffer, cmd);
strcat(buffer, virname);
strcat(buffer, pt);
free(cmd);
cmd = strdup(buffer);
free(buffer);
}
}
/* Allocate env vars.. to be portable env vars should not be freed */
buffer = (char *) malloc(strlen(ENV_FILE) + strlen(filename) + 2);
if(buffer) {
sprintf(buffer, "%s=%s", ENV_FILE, filename);
putenv(buffer);
buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
if(buffer) {
*pt = 0; pt += 2;
strcpy(buffer, cmd);
strcat(buffer, virname);
strcat(buffer, pt);
free(cmd);
cmd = strdup(buffer);
free(buffer);
}
}
buffer = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
if(buffer) {
sprintf(buffer, "%s=%s", ENV_VIRUS, virname);
putenv(buffer);
if(!cmd)
return;
/* We can only call async-signal-safe functions after fork(). */
pid = fork();
if ( pid == 0 ) {
/* child... */
/* WARNING: this is uninterruptable ! */
exit(execle("/bin/sh", "sh", "-c", cmd, NULL, env));
} else if (pid > 0) {
/* parent */
waitpid(pid, NULL, 0);
} else {
/* error.. */
logg("!VirusAction: fork failed.\n");
}
/* WARNING: this is uninterruptable ! */
if(cmd)
exit(system(cmd));
} else if (pid > 0) {
/* parent */
waitpid(pid, NULL, 0);
} else {
/* error.. */
logg("!VirusAction: fork failed.\n");
}
free(cmd);
free(buffer_file);
free(buffer_vir);
}
#endif /* C_WINDOWS */

@ -1,7 +1,7 @@
#!/bin/sh
die() {
test /tmp/clamd-test.pid && kill `cat /tmp/clamd-test.pid`
rm -r test-db
rm -rf test-db test-clamd-viraction.conf test-clamd.log
exit $1
}
@ -26,4 +26,15 @@ if test "$NFILES" -ne "$NINFECTED"; then
grep OK clamdscan.log >&2;
die 4;
fi
cp $srcdir/test-clamd.conf test-clamd-viraction.conf
echo "VirusEvent `pwd`/$srcdir/virusaction-test.sh `pwd` \"Virus found: %v\"" >>test-clamd-viraction.conf
rm -f test-clamd.log
test /tmp/clamd-test.pid && kill `cat /tmp/clamd-test.pid`
../clamd/.libs/lt-clamd -c test-clamd-viraction.conf || { echo "Failed to start clamd!" >&2; die 1;}
../clamdscan/clamdscan --quiet --config-file test-clamd-viraction.conf ../test/clam.exe
if ! grep "Virus found: ClamAV-Test-File.UNOFFICIAL" test-clamd.log >/dev/null 2>/dev/null; then
echo "Virusaction test failed!" >&2;
cat test-clamd.log
die 2;
fi
die 0;

@ -0,0 +1,10 @@
#!/bin/sh
if test ! "x$CLAM_VIRUSEVENT_FILENAME" = "x$1/../test/clam.exe"; then
echo "VirusEvent incorrect: $CLAM_VIRUSEVENT_FILENAME" >$1/test-clamd.log
exit 1
fi
if test ! "x$CLAM_VIRUSEVENT_VIRUSNAME" = "xClamAV-Test-File.UNOFFICIAL"; then
echo "VirusName incorrect: $CLAM_VIRUSEVENT_VIRUSNAME" >$1/test-clamd.log
exit 2
fi
echo $2 >$1/test-clamd.log
Loading…
Cancel
Save