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

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


git-svn: trunk@4034
remotes/push_mirror/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) Wed Jul 30 17:02:40 CEST 2008 (tk)
---------------------------------- ----------------------------------
* clamscan, clamav-milter: catch and ignore SIGXFSZ; display warning if * 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 #else
void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt) void virusaction(const char *filename, const char *virname, const struct cfgstruct *copt)
{ {
pid_t pid; pid_t pid;
const struct cfgstruct *cpt; const struct cfgstruct *cpt;
char *buffer, *pt, *cmd, *buffer_file, *buffer_vir;
size_t j;
char *env[4];
if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled) if(!(cpt = cfgopt(copt, "VirusEvent"))->enabled)
return; return;
/* NB: we need to fork here since this function modifies the environment. env[0] = getenv("PATH");
(Modifications to the env. are not reentrant, but we need to be.) */ j = env[0] ? 1 : 0;
pid = fork(); /* 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 ) { buffer_vir = (char *) malloc(strlen(ENV_VIRUS) + strlen(virname) + 2);
/* child... */ if(buffer_vir) {
char *buffer, *pt, *cmd; sprintf(buffer_vir, "%s=%s", ENV_VIRUS, virname);
env[j++] = buffer_vir;
}
env[j++] = NULL;
cmd = strdup(cpt->strarg); cmd = strdup(cpt->strarg);
if(cmd && (pt = strstr(cmd, "%v"))) { if(cmd && (pt = strstr(cmd, "%v"))) {
buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10); buffer = (char *) malloc(strlen(cmd) + strlen(virname) + 10);
if(buffer) { if(buffer) {
*pt = 0; pt += 2; *pt = 0; pt += 2;
strcpy(buffer, cmd); strcpy(buffer, cmd);
strcat(buffer, virname); strcat(buffer, virname);
strcat(buffer, pt); strcat(buffer, pt);
free(cmd); free(cmd);
cmd = strdup(buffer); cmd = strdup(buffer);
free(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(ENV_VIRUS) + strlen(virname) + 2); if(!cmd)
if(buffer) { return;
sprintf(buffer, "%s=%s", ENV_VIRUS, virname); /* We can only call async-signal-safe functions after fork(). */
putenv(buffer); 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 ! */ free(cmd);
if(cmd) free(buffer_file);
exit(system(cmd)); free(buffer_vir);
} else if (pid > 0) {
/* parent */
waitpid(pid, NULL, 0);
} else {
/* error.. */
logg("!VirusAction: fork failed.\n");
}
} }
#endif /* C_WINDOWS */ #endif /* C_WINDOWS */

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
die() { die() {
test /tmp/clamd-test.pid && kill `cat /tmp/clamd-test.pid` 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 exit $1
} }
@ -26,4 +26,15 @@ if test "$NFILES" -ne "$NINFECTED"; then
grep OK clamdscan.log >&2; grep OK clamdscan.log >&2;
die 4; die 4;
fi 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; 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