1
From d2564db5d3f50adc67474ffb22b0ee7027a82828 Mon Sep 17 00:00:00 2001
2
From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
3
Date: Mon, 11 Aug 2014 23:22:05 +0200
4
Subject: Add upstream systemd support for clamav-daemon and clamav-freshclam.
8
clamd/Makefile.am | 4 ++
9
clamd/clamav-daemon.service.in | 17 ++++++
10
clamd/clamav-daemon.socket | 12 ++++
11
clamd/clamd.c | 102 +++++++++++++++++++++++++++-------
12
clamd/localserver.c | 34 ++++++++++++
13
clamd/server-th.c | 55 +++++++++++-------
14
clamd/tcpserver.c | 50 +++++++++++++++++
16
freshclam/Makefile.am | 4 ++
17
freshclam/clamav-freshclam.service.in | 12 ++++
18
freshclam/freshclam.c | 39 +++++++++++--
19
m4/reorganization/libs/systemd.m4 | 18 ++++++
21
shared/optparser.c | 2 +-
22
15 files changed, 318 insertions(+), 44 deletions(-)
23
create mode 100644 clamd/clamav-daemon.service.in
24
create mode 100644 clamd/clamav-daemon.socket
25
create mode 100644 freshclam/clamav-freshclam.service.in
26
create mode 100644 m4/reorganization/libs/systemd.m4
28
diff --git a/Makefile.am b/Makefile.am
29
index 2eecd94b668b..017d6327ff58 100644
32
@@ -33,7 +33,7 @@ pkgconfig_DATA = libclamav.pc
33
# don't complain that configuration files and databases are not removed, this is intended
34
distuninstallcheck_listfiles = find . -type f ! -name clamd.conf ! -name freshclam.conf ! -name daily.cvd ! -name main.cvd -print
35
DISTCLEANFILES = target.h
36
-DISTCHECK_CONFIGURE_FLAGS=--enable-milter --disable-clamav --enable-all-jit-targets --enable-llvm=yes
37
+DISTCHECK_CONFIGURE_FLAGS=--enable-milter --disable-clamav --enable-all-jit-targets --enable-llvm=yes --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
39
($(MAKE); cd unit_tests; $(MAKE) lcov)
41
diff --git a/clamd/Makefile.am b/clamd/Makefile.am
42
index 61bbd69d1133..edc133138e58 100644
43
--- a/clamd/Makefile.am
44
+++ b/clamd/Makefile.am
45
@@ -50,6 +50,10 @@ clamd_SOURCES = \
47
AM_CFLAGS=@WERR_CFLAGS@
49
+if INSTALL_SYSTEMD_UNITS
50
+systemdsystemunit_DATA = clamav-daemon.socket clamav-daemon.service
55
LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMD_LIBS@ @THREAD_LIBS@
56
diff --git a/clamd/clamav-daemon.service.in b/clamd/clamav-daemon.service.in
58
index 000000000000..0a5d456a2b36
60
+++ b/clamd/clamav-daemon.service.in
63
+Description=Clam AntiVirus userspace daemon
64
+Documentation=man:clamd(8) man:clamd.conf(5) http://www.clamav.net/lang/en/doc/
65
+Requires=clamav-daemon.socket
66
+# Check for database existence
67
+ConditionPathExistsGlob=@DBDIR@/main.{c[vl]d,inc}
68
+ConditionPathExistsGlob=@DBDIR@/daily.{c[vl]d,inc}
71
+ExecStart=@prefix@/sbin/clamd --foreground=true
72
+# Reload the database
73
+ExecReload=/bin/kill -USR2 $MAINPID
74
+StandardOutput=syslog
77
+WantedBy=multi-user.target
78
+Also=clamav-daemon.socket
79
diff --git a/clamd/clamav-daemon.socket b/clamd/clamav-daemon.socket
81
index 000000000000..43a34cd36aad
83
+++ b/clamd/clamav-daemon.socket
86
+Description=Socket for Clam AntiVirus userspace daemon
87
+Documentation=man:clamd(8) man:clamd.conf(5) http://www.clamav.net/lang/en/doc/
90
+ListenStream=/run/clamav/clamd.ctl
91
+#ListenStream=127.0.0.1:1024
92
+ExecStartPost=/bin/chown -R clamav:clamav /run/clamav/
93
+ExecStopPost=/bin/rm /run/clamav/clamd.ctl
96
+WantedBy=sockets.target
97
diff --git a/clamd/clamd.c b/clamd/clamd.c
98
index 96204291f433..ec15eacc8c25 100644
104
short debug_mode = 0, logok = 0;
105
-short foreground = 0;
106
+short foreground = -1;
109
char *get_hostid(void *cbdata);
110
@@ -160,6 +160,31 @@ int main(int argc, char **argv)
114
+ /* check foreground option from command line to override config file */
116
+ for(j = 0; j < argc; j += 1)
118
+ if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
127
+ if(optget(opts, "Foreground")->enabled)
137
+ int num_fd = sd_listen_fds(0);
139
/* parse the config file */
140
cfgfile = optget(opts, "config-file")->strarg;
141
pt = strdup(cfgfile);
142
@@ -295,7 +320,9 @@ int main(int argc, char **argv)
143
if(optget(opts, "LocalSocket")->enabled)
146
- if(!tcpsock && !localsock) {
147
+ logg("#Received %d file descriptor(s) from systemd.\n", num_fd);
149
+ if(!tcpsock && !localsock && num_fd == 0) {
150
logg("!Please define server type (local and/or TCP).\n");
153
@@ -577,7 +604,9 @@ int main(int argc, char **argv)
158
+ if(tcpsock || num_fd > 0) {
161
opt = optget(opts, "TCPAddr");
164
@@ -604,7 +633,7 @@ int main(int argc, char **argv)
169
+ if(localsock && num_fd == 0) {
171
mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */
173
@@ -666,8 +695,43 @@ int main(int argc, char **argv)
177
+ /* check for local sockets passed by systemd */
181
+ t = realloc(lsockets, sizeof(int) * (nlsockets + 1));
188
+ lsockets[nlsockets] = localserver(opts);
189
+ if (lsockets[nlsockets] == -1)
194
+ else if (lsockets[nlsockets] > 0)
200
/* fork into background */
201
- if(!optget(opts, "Foreground")->enabled) {
202
+ if (foreground == -1)
204
+ if (optget(opts, "Foreground")->enabled)
213
+ if(foreground == 0)
216
/* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */
217
for(ret=0;(unsigned int)ret<nlsockets;ret++) {
218
@@ -701,8 +765,6 @@ int main(int argc, char **argv)
220
logg("^Can't change current working directory to root\n");
227
@@ -716,22 +778,24 @@ int main(int argc, char **argv)
231
- logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");
233
- for (i = 0; i < nlsockets; i++) {
234
- closesocket(lsockets[i]);
238
+ logg("*Closing the main socket%s.\n", (nlsockets > 1) ? "s" : "");
240
+ for (i = 0; i < nlsockets; i++) {
241
+ closesocket(lsockets[i]);
244
- if(nlsockets && localsock) {
245
- opt = optget(opts, "LocalSocket");
246
+ if(nlsockets && localsock) {
247
+ opt = optget(opts, "LocalSocket");
249
- if(unlink(opt->strarg) == -1)
250
- logg("!Can't unlink the socket file %s\n", opt->strarg);
252
- logg("Socket file removed.\n");
254
+ if(unlink(opt->strarg) == -1)
255
+ logg("!Can't unlink the socket file %s\n", opt->strarg);
257
+ logg("Socket file removed.\n");
264
diff --git a/clamd/localserver.c b/clamd/localserver.c
265
index db07415212ad..d963efd244f5 100644
266
--- a/clamd/localserver.c
267
+++ b/clamd/localserver.c
270
#include "shared/optparser.h"
271
#include "shared/output.h"
272
+#include "shared/misc.h"
276
@@ -60,6 +61,39 @@ int localserver(const struct optstruct *opts)
280
+ int num_fd = sd_listen_fds(0);
283
+ logg("!LOCAL: Received more than two file descriptors from systemd.\n");
286
+ else if (num_fd > 0)
288
+ /* use socket passed by systemd */
290
+ for(i = 0; i < num_fd; i += 1)
292
+ sockfd = SD_LISTEN_FDS_START + i;
293
+ if (sd_is_socket(sockfd, AF_UNIX, SOCK_STREAM, 1) == 1)
295
+ /* correct socket */
306
+ logg("#LOCAL: No local AF_UNIX SOCK_STREAM socket received from systemd.\n");
309
+ logg("#LOCAL: Received AF_UNIX SOCK_STREAM socket from systemd.\n");
312
+ /* create socket */
313
memset((char *) &server, 0, sizeof(server));
314
server.sun_family = AF_UNIX;
315
strncpy(server.sun_path, optget(opts, "LocalSocket")->strarg, sizeof(server.sun_path));
316
diff --git a/clamd/server-th.c b/clamd/server-th.c
317
index d97cd6fb34e1..5c12811b662b 100644
318
--- a/clamd/server-th.c
319
+++ b/clamd/server-th.c
322
#include "shared/output.h"
323
#include "shared/optparser.h"
324
+#include "shared/misc.h"
328
@@ -445,13 +446,19 @@ static void *acceptloop_th(void *arg)
330
pthread_mutex_unlock(fds->buf_mutex);
332
- for (i=0;i < fds->nfds; i++) {
333
- if (fds->buf[i].fd == -1)
335
- logg("$Shutdown: closed fd %d\n", fds->buf[i].fd);
336
- shutdown(fds->buf[i].fd, 2);
337
- closesocket(fds->buf[i].fd);
338
+ if (sd_listen_fds(0) == 0)
340
+ /* only close the sockets, when not using systemd socket activation */
341
+ for (i=0;i < fds->nfds; i++)
343
+ if (fds->buf[i].fd == -1)
345
+ logg("$Shutdown: closed fd %d\n", fds->buf[i].fd);
346
+ shutdown(fds->buf[i].fd, 2);
347
+ closesocket(fds->buf[i].fd);
352
pthread_mutex_destroy(fds->buf_mutex);
353
pthread_mutex_lock(&exit_mutex);
354
@@ -1344,16 +1351,22 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
356
pthread_mutex_unlock(&exit_mutex);
357
pthread_mutex_lock(fds->buf_mutex);
358
- for (i=0;i < fds->nfds; i++) {
359
- if (fds->buf[i].fd == -1)
361
- thrmgr_group_terminate(fds->buf[i].group);
362
- if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR)) {
363
- logg("$Shutdown closed fd %d\n", fds->buf[i].fd);
364
- shutdown(fds->buf[i].fd, 2);
365
- closesocket(fds->buf[i].fd);
366
- fds->buf[i].fd = -1;
368
+ if (sd_listen_fds(0) == 0)
370
+ /* only close the sockets, when not using systemd socket activation */
371
+ for (i=0;i < fds->nfds; i++)
373
+ if (fds->buf[i].fd == -1)
375
+ thrmgr_group_terminate(fds->buf[i].group);
376
+ if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR))
378
+ logg("$Shutdown closed fd %d\n", fds->buf[i].fd);
379
+ shutdown(fds->buf[i].fd, 2);
380
+ closesocket(fds->buf[i].fd);
381
+ fds->buf[i].fd = -1;
385
pthread_mutex_unlock(fds->buf_mutex);
387
@@ -1462,9 +1475,13 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
390
cl_statfree(&dbstat);
391
- logg("*Shutting down the main socket%s.\n", (nsockets > 1) ? "s" : "");
392
- for (i = 0; i < nsockets; i++)
393
- shutdown(socketds[i], 2);
394
+ if (sd_listen_fds(0) == 0)
396
+ /* only close the sockets, when not using systemd socket activation */
397
+ logg("*Shutting down the main socket%s.\n", (nsockets > 1) ? "s" : "");
398
+ for (i = 0; i < nsockets; i++)
399
+ shutdown(socketds[i], 2);
402
if((opt = optget(opts, "PidFile"))->enabled) {
403
if(unlink(opt->strarg) == -1)
404
diff --git a/clamd/tcpserver.c b/clamd/tcpserver.c
405
index c3027a85c1f4..81387b3c8512 100644
406
--- a/clamd/tcpserver.c
407
+++ b/clamd/tcpserver.c
408
@@ -60,6 +60,56 @@ int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struc
412
+ int num_fd = sd_listen_fds(0);
415
+ logg("!TCP: Received more than two file descriptors from systemd.\n");
418
+ else if (num_fd > 0)
420
+ /* use socket passed by systemd */
422
+ for(i = 0; i < num_fd; i += 1)
424
+ sockfd = SD_LISTEN_FDS_START + i;
425
+ if (sd_is_socket(sockfd, AF_INET, SOCK_STREAM, 1) == 1)
427
+ /* correct socket */
428
+ logg("#TCP: Received AF_INET SOCK_STREAM socket from systemd.\n");
431
+ else if (sd_is_socket(sockfd, AF_INET6, SOCK_STREAM, 1) == 1)
433
+ /* correct socket */
434
+ logg("#TCP: Received AF_INET6 SOCK_STREAM socket from systemd.\n");
445
+ logg("#TCP: No tcp AF_INET/AF_INET6 SOCK_STREAM socket received from systemd.\n");
449
+ t = realloc(sockets, sizeof(int) * (*nlsockets + 1));
455
+ sockets[*nlsockets] = sockfd;
457
+ *lsockets = sockets;
461
+ /* create socket */
462
snprintf(port, sizeof(port), "%lld", optget(opts, "TCPSocket")->numarg);
464
memset(&hints, 0x00, sizeof(struct addrinfo));
465
diff --git a/configure.ac b/configure.ac
466
index 41043753fc92..02caad29410a 100644
469
@@ -86,6 +86,7 @@ AM_MAINTAINER_MODE
470
m4_include([m4/reorganization/libs/libz.m4])
471
m4_include([m4/reorganization/libs/bzip.m4])
472
m4_include([m4/reorganization/libs/unrar.m4])
473
+m4_include([m4/reorganization/libs/systemd.m4])
474
m4_include([m4/reorganization/code_checks/ipv6.m4])
475
m4_include([m4/reorganization/code_checks/dns.m4])
476
m4_include([m4/reorganization/code_checks/fanotify.m4])
477
@@ -137,9 +138,11 @@ clamscan/Makefile
481
+clamd/clamav-daemon.service
484
clamav-milter/Makefile
485
+freshclam/clamav-freshclam.service
489
diff --git a/freshclam/Makefile.am b/freshclam/Makefile.am
490
index 58fc17471c35..051bf3380e98 100644
491
--- a/freshclam/Makefile.am
492
+++ b/freshclam/Makefile.am
493
@@ -49,6 +49,10 @@ freshclam_SOURCES = \
497
+if INSTALL_SYSTEMD_UNITS
498
+systemdsystemunit_DATA = clamav-freshclam.service
501
AM_CFLAGS=@WERR_CFLAGS@
502
DEFS = @DEFS@ -DCL_NOTHREADS
503
AM_CPPFLAGS = @SSL_CPPFLAGS@ -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @FRESHCLAM_CPPFLAGS@ @JSON_CPPFLAGS@
504
diff --git a/freshclam/clamav-freshclam.service.in b/freshclam/clamav-freshclam.service.in
506
index 000000000000..f717cd642106
508
+++ b/freshclam/clamav-freshclam.service.in
511
+Description=ClamAV virus database updater
512
+Documentation=man:freshclam(1) man:freshclam.conf(5) http://www.clamav.net/lang/en/doc/
513
+# If user wants it run from cron, don't start the daemon.
514
+ConditionPathExists=!/etc/cron.d/clamav-freshclam
517
+ExecStart=@prefix@/bin/freshclam -d --foreground=true
518
+StandardOutput=syslog
521
+WantedBy=multi-user.target
522
diff --git a/freshclam/freshclam.c b/freshclam/freshclam.c
523
index 166586bf6447..f170613877c4 100644
524
--- a/freshclam/freshclam.c
525
+++ b/freshclam/freshclam.c
527
static short terminate = 0;
528
extern int active_children;
530
-static short foreground = 1;
531
+static short foreground = -1;
532
char updtmpdir[512], dbdir[512];
533
int sigchld_wait = 1;
534
const char *pidfile = NULL;
535
@@ -117,7 +117,7 @@ sighandler (int sig)
538
logg ("Update process terminated\n");
544
@@ -322,6 +322,26 @@ main (int argc, char **argv)
548
+ /* check foreground option from command line to override config file */
550
+ for(j = 0; j < argc; j += 1)
552
+ if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0))
560
+ if(optget(opts, "Foreground")->enabled) {
568
/* parse the config file */
569
cfgfile = optget (opts, "config-file")->strarg;
570
pt = strdup (cfgfile);
571
@@ -638,7 +658,19 @@ main (int argc, char **argv)
572
bigsleep = 24 * 3600 / checks;
575
- if (!optget (opts, "Foreground")->enabled)
576
+ /* fork into background */
577
+ if (foreground == -1)
579
+ if (optget(opts, "Foreground")->enabled)
588
+ if(foreground == 0)
590
if (daemonize () == -1)
592
@@ -646,7 +678,6 @@ main (int argc, char **argv)
594
return FCE_FAILEDUPDATE;
597
mprintf_disabled = 1;
600
diff --git a/m4/reorganization/libs/systemd.m4 b/m4/reorganization/libs/systemd.m4
602
index 000000000000..cac5d4272fda
604
+++ b/m4/reorganization/libs/systemd.m4
606
+dnl Check for systemd-daemon
607
+PKG_CHECK_MODULES(SYSTEMD, [libsystemd-daemon], [AC_DEFINE([HAVE_SYSTEMD],,[systemd-daemon is supported])], [AC_MSG_RESULT([systemd-daemon is not supported])])
608
+CLAMD_LIBS="$CLAMD_LIBS $SYSTEMD_LIBS"
609
+CFLAGS="$CFLAGS $SYSTEMD_CFLAGS"
611
+dnl Check for systemd system unit installation directory (see man 7 daemon)
612
+AC_ARG_WITH([systemdsystemunitdir], AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),, [with_systemdsystemunitdir=auto])
613
+AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
614
+ def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
615
+ AS_IF([test "x$def_systemdsystemunitdir" = "x"],
616
+ [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"], [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
617
+ with_systemdsystemunitdir=no],
618
+ [with_systemdsystemunitdir=$def_systemdsystemunitdir])])
619
+AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
620
+ [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
621
+AM_CONDITIONAL(INSTALL_SYSTEMD_UNITS, [test "x$with_systemdsystemunitdir" != "xno"])
622
+AC_MSG_RESULT([checking for systemd system unit installation directory... $with_systemdsystemunitdir])
624
diff --git a/shared/misc.h b/shared/misc.h
625
index 7f3a9f962d0d..3e093936caa1 100644
633
+# include <systemd/sd-daemon.h>
635
+# define sd_listen_fds(u) 0
636
+# define SD_LISTEN_FDS_START 3
637
+# define sd_is_socket(f, a, s, l) 1
643
diff --git a/shared/optparser.c b/shared/optparser.c
644
index 63c88550d5b8..b61ec832a32f 100644
645
--- a/shared/optparser.c
646
+++ b/shared/optparser.c
647
@@ -272,7 +272,7 @@ const struct clam_option __clam_options[] = {
649
{ "AllowAllMatchScan", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD, "Permit use of the ALLMATCHSCAN command.", "yes" },
651
- { "Foreground", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Don't fork into background.", "no" },
652
+ { "Foreground", "foreground", 'F', CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM | OPT_MILTER, "Don't fork into background.", "no" },
654
{ "Debug", NULL, 0, CLOPT_TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD | OPT_FRESHCLAM, "Enable debug messages in libclamav.", "no" },