Browse code

clamd: initial support for on-access scanner using fanotify (bb#2236)

only works in notification mode (no access blocking) right now

Tomasz Kojm authored on 2011/11/17 00:00:13
Showing 13 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Nov 16 15:57:24 CET 2011 (tk)
2
+---------------------------------
3
+ * clamd: initial support for on-access scanner using fanotify (bb#2236)
4
+
1 5
 Mon Nov 14 21:22:26 CET 2011 (acab)
2 6
 -----------------------------------
3 7
  * libclamav: add preliminary support for iso9660 image files
... ...
@@ -18,9 +18,6 @@
18 18
 /* name of the clamav user */
19 19
 #undef CLAMAVUSER
20 20
 
21
-/* enable clamuko */
22
-#undef CLAMUKO
23
-
24 21
 /* enable debugging */
25 22
 #undef CL_DEBUG
26 23
 
... ...
@@ -87,6 +84,9 @@
87 87
 /* "default FD_SETSIZE value" */
88 88
 #undef DEFAULT_FD_SETSIZE
89 89
 
90
+/* use fanotify */
91
+#undef FANOTIFY
92
+
90 93
 /* whether _XOPEN_SOURCE needs to be defined for fd passing to work */
91 94
 #undef FDPASS_NEED_XOPEN
92 95
 
... ...
@@ -44,7 +44,9 @@ clamd_SOURCES = \
44 44
     scanner.h \
45 45
     others.c \
46 46
     others.h \
47
-    shared.h
47
+    shared.h \
48
+    fan.c \
49
+    fan-syscalllib.h
48 50
 
49 51
 AM_CFLAGS=@WERR_CFLAGS@
50 52
 
... ...
@@ -83,14 +83,14 @@ am__clamd_SOURCES_DIST = $(top_srcdir)/shared/output.c \
83 83
 	$(top_srcdir)/shared/misc.h clamd.c tcpserver.c tcpserver.h \
84 84
 	localserver.c localserver.h session.c session.h thrmgr.c \
85 85
 	thrmgr.h server-th.c server.h scanner.c scanner.h others.c \
86
-	others.h shared.h
86
+	others.h shared.h fan.c fan-syscalllib.h
87 87
 @BUILD_CLAMD_TRUE@am_clamd_OBJECTS = output.$(OBJEXT) \
88 88
 @BUILD_CLAMD_TRUE@	optparser.$(OBJEXT) getopt.$(OBJEXT) \
89 89
 @BUILD_CLAMD_TRUE@	misc.$(OBJEXT) clamd.$(OBJEXT) \
90 90
 @BUILD_CLAMD_TRUE@	tcpserver.$(OBJEXT) localserver.$(OBJEXT) \
91 91
 @BUILD_CLAMD_TRUE@	session.$(OBJEXT) thrmgr.$(OBJEXT) \
92 92
 @BUILD_CLAMD_TRUE@	server-th.$(OBJEXT) scanner.$(OBJEXT) \
93
-@BUILD_CLAMD_TRUE@	others.$(OBJEXT)
93
+@BUILD_CLAMD_TRUE@	others.$(OBJEXT) fan.$(OBJEXT)
94 94
 clamd_OBJECTS = $(am_clamd_OBJECTS)
95 95
 clamd_LDADD = $(LDADD)
96 96
 AM_V_lt = $(am__v_lt_$(V))
... ...
@@ -316,7 +316,9 @@ top_srcdir = @top_srcdir@
316 316
 @BUILD_CLAMD_TRUE@    scanner.h \
317 317
 @BUILD_CLAMD_TRUE@    others.c \
318 318
 @BUILD_CLAMD_TRUE@    others.h \
319
-@BUILD_CLAMD_TRUE@    shared.h
319
+@BUILD_CLAMD_TRUE@    shared.h \
320
+@BUILD_CLAMD_TRUE@    fan.c \
321
+@BUILD_CLAMD_TRUE@    fan-syscalllib.h
320 322
 
321 323
 @BUILD_CLAMD_TRUE@AM_CFLAGS = @WERR_CFLAGS@
322 324
 AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav
... ...
@@ -429,6 +431,7 @@ distclean-compile:
429 429
 	-rm -f *.tab.c
430 430
 
431 431
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamd.Po@am__quote@
432
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fan.Po@am__quote@
432 433
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
433 434
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localserver.Po@am__quote@
434 435
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
435 436
new file mode 100644
... ...
@@ -0,0 +1,28 @@
0
+#ifndef __FANOTIFY_SYSCALL_LIB
1
+#define __FANOTIFY_SYSCALL_LIB
2
+
3
+#include <unistd.h>
4
+#include <linux/types.h>
5
+
6
+#if defined(__x86_64__)
7
+# define __NR_fanotify_init	300
8
+# define __NR_fanotify_mark	301
9
+#elif defined(__i386__)
10
+# define __NR_fanotify_init	338
11
+# define __NR_fanotify_mark	339
12
+#else
13
+# error "System call numbers not defined for this architecture"
14
+#endif
15
+
16
+static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags)
17
+{
18
+	return syscall(__NR_fanotify_init, flags, event_f_flags);
19
+}
20
+
21
+static inline int fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,
22
+				int dfd, const char *pathname)
23
+{
24
+	return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask,
25
+		       dfd, pathname);
26
+}
27
+#endif
0 28
new file mode 100644
... ...
@@ -0,0 +1,225 @@
0
+/*
1
+ *  Copyright (C) 2011 Sourcefire, Inc.
2
+ *
3
+ *  Authors: Tomasz Kojm
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#if HAVE_CONFIG_H
21
+#include "clamav-config.h"
22
+#endif
23
+
24
+#ifdef FANOTIFY
25
+
26
+#include <stdio.h>
27
+#include <unistd.h>
28
+#include <sys/types.h>
29
+#include <sys/stat.h>
30
+#include <fcntl.h>
31
+#include <signal.h>
32
+#include <pthread.h>
33
+#include <string.h>
34
+#include <errno.h>
35
+
36
+#include <linux/fanotify.h>
37
+#include "fan-syscalllib.h"
38
+#include "fan.h"
39
+
40
+#include "libclamav/clamav.h"
41
+#include "libclamav/scanners.h"
42
+
43
+#include "shared/optparser.h"
44
+#include "shared/output.h"
45
+
46
+#include "server.h"
47
+#include "others.h"
48
+#include "scanner.h"
49
+
50
+static void fan_exit(int sig)
51
+{
52
+
53
+    logg("*ScanOnAccess: fan_exit(), signal %d\n", sig);
54
+    pthread_exit(NULL);
55
+    logg("ScanOnAccess: stopped\n");
56
+}
57
+
58
+static int fan_scanfile(int fan_fd, const char *fname, struct fanotify_event_metadata *fmd, int scan, int extinfo, struct thrarg *tharg)
59
+{
60
+	struct fanotify_response res;
61
+	struct cb_context context;
62
+	const char *virname;
63
+	int ret = 0;
64
+
65
+    res.fd = fmd->fd;
66
+    res.response = FAN_ALLOW;
67
+    context.filename = fname;
68
+    context.virsize = 0;
69
+    if(scan && cl_scandesc_callback(fmd->fd, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) {
70
+	if(context.virsize)
71
+	    detstats_add(virname, fname, context.virsize, context.virhash);
72
+	if(extinfo && context.virsize)
73
+	    logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, virname, context.virhash, context.virsize);
74
+	else
75
+	    logg("ScanOnAccess: %s: %s FOUND\n", fname, virname);
76
+	virusaction(fname, virname, tharg->opts);
77
+	res.response = FAN_DENY;
78
+    }
79
+
80
+    if(fmd->mask & FAN_ALL_PERM_EVENTS) {
81
+	ret = write(fan_fd, &res, sizeof(res));
82
+	if(ret == -1)
83
+	    logg("!ScanOnAccess: Internal error (can't write to fanotify)\n");
84
+    }
85
+
86
+    return ret;
87
+}
88
+
89
+void *fan_th(void *arg)
90
+{
91
+	struct thrarg *tharg = (struct thrarg *) arg;
92
+	sigset_t sigset;
93
+        struct sigaction act;
94
+	const struct optstruct *pt;
95
+	short int scan;
96
+	int sizelimit = 0, extinfo;
97
+	struct stat sb;
98
+        uint64_t fan_mask = FAN_ACCESS | FAN_EVENT_ON_CHILD;
99
+	int fan_fd;
100
+        fd_set rfds;
101
+	char buf[4096];
102
+	ssize_t bread;
103
+	struct fanotify_event_metadata *fmd;
104
+	char fname[1024];
105
+	int ret, len;
106
+	char err[128];
107
+
108
+    /* ignore all signals except SIGUSR1 */
109
+    sigfillset(&sigset);
110
+    sigdelset(&sigset, SIGUSR1);
111
+    /* The behavior of a process is undefined after it ignores a 
112
+     * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
113
+    sigdelset(&sigset, SIGFPE);
114
+    sigdelset(&sigset, SIGILL);
115
+    sigdelset(&sigset, SIGSEGV);
116
+#ifdef SIGBUS    
117
+    sigdelset(&sigset, SIGBUS);
118
+#endif
119
+    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
120
+    memset(&act, 0, sizeof(struct sigaction));
121
+    act.sa_handler = fan_exit;
122
+    sigfillset(&(act.sa_mask));
123
+    sigaction(SIGUSR1, &act, NULL);
124
+    sigaction(SIGSEGV, &act, NULL);
125
+
126
+    fan_fd = fanotify_init(0, O_RDONLY);
127
+    if(fan_fd < 0) {
128
+	logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err)));
129
+	if(errno == EPERM)
130
+	    logg("ScanOnAccess: clamd must be started by root\n");
131
+	return NULL;
132
+    }
133
+
134
+    if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) {
135
+	while(pt) {
136
+	    if(fanotify_mark(fan_fd, FAN_MARK_ADD, fan_mask, fan_fd, pt->strarg) != 0) {
137
+		logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg);
138
+		return NULL;
139
+	    } else
140
+		logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg);
141
+	    pt = (struct optstruct *) pt->nextarg;
142
+	}
143
+    } else {
144
+	logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n");
145
+	return NULL;
146
+    }
147
+
148
+    if((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) {
149
+	while(pt) {
150
+            if(fanotify_mark(fan_fd, FAN_MARK_REMOVE, fan_mask, fan_fd, pt->strarg) != 0) {
151
+		logg("!ScanOnAccess: Can't exclude path %s\n", pt->strarg);
152
+		return NULL;
153
+	    } else
154
+		logg("ScanOnAccess: Excluded path %s\n", pt->strarg);
155
+	    pt = (struct optstruct *) pt->nextarg;
156
+	}
157
+    }
158
+
159
+    sizelimit = optget(tharg->opts, "OnAccessMaxFileSize")->numarg;
160
+    if(sizelimit)
161
+	logg("ScanOnAccess: Max file size limited to %d bytes\n", sizelimit);
162
+    else
163
+	logg("ScanOnAccess: File size limit disabled\n");
164
+
165
+    extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled;
166
+
167
+    FD_ZERO(&rfds);
168
+    FD_SET(fan_fd, &rfds);
169
+    do {
170
+        ret = select(fan_fd + 1, &rfds, NULL, NULL, NULL);
171
+    } while(ret == -1 && errno == EINTR);
172
+
173
+    while((bread = read(fan_fd, buf, sizeof(buf))) > 0) {
174
+	fmd = (struct fanotify_event_metadata *) buf;
175
+	while(FAN_EVENT_OK(fmd, bread)) {
176
+	    scan = 1;
177
+	    if(fmd->fd >= 0) {
178
+		sprintf(fname, "/proc/self/fd/%d", fmd->fd);
179
+		len = readlink(fname, fname, sizeof(fname) - 1);
180
+		if(len == -1) {
181
+		    close(fmd->fd);
182
+		    logg("!ScanOnAccess: Internal error (readlink() failed)\n");
183
+		    return NULL;
184
+		}
185
+		fname[len] = 0;
186
+
187
+		if(fan_checkowner(fmd->pid, tharg->opts)) {
188
+		    scan = 0;
189
+		    logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname);
190
+		}
191
+
192
+		if(sizelimit) {
193
+		    fstat(fmd->fd, &sb);
194
+		    if(sb.st_size > sizelimit) {
195
+			scan = 0;
196
+			/* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */
197
+		    }
198
+		}
199
+
200
+		if(fan_scanfile(fan_fd, fname, fmd, scan, extinfo, tharg) == -1) {
201
+		    close(fmd->fd);
202
+		    return NULL;
203
+		}
204
+
205
+		if(close(fmd->fd) == -1) {
206
+		    printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd);
207
+		    close(fmd->fd);
208
+		    return NULL;
209
+		}
210
+	    }
211
+	    fmd = FAN_EVENT_NEXT(fmd, bread);
212
+	}
213
+	do {
214
+	    ret = select(fan_fd + 1, &rfds, NULL, NULL, NULL);
215
+	} while(ret == -1 && errno == EINTR);
216
+    }
217
+
218
+    if(bread < 0)
219
+	logg("!ScanOnAccess: Internal error (failed to read data)\n");
220
+
221
+    return NULL;
222
+}
223
+
224
+#endif
0 225
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+/*
1
+ *  Copyright (C) 2011 Sourcefire, Inc.
2
+ *
3
+ *  Authors: Tomasz Kojm
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License version 2 as
7
+ *  published by the Free Software Foundation.
8
+ *
9
+ *  This program is distributed in the hope that it will be useful,
10
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+ *  GNU General Public License for more details.
13
+ *
14
+ *  You should have received a copy of the GNU General Public License
15
+ *  along with this program; if not, write to the Free Software
16
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17
+ *  MA 02110-1301, USA.
18
+ */
19
+
20
+#ifndef __FAN_H
21
+#define __FAN_H
22
+
23
+void *fan_th(void *arg);
24
+
25
+#endif
... ...
@@ -723,14 +723,14 @@ void detstats_print(int desc, char term)
723 723
     pthread_mutex_unlock(&detstats_lock);
724 724
 }
725 725
 
726
-#if 0 /* CLAMUKO */
727
-int clamuko_checkowner(int pid, const struct optstruct *opts)
726
+#ifdef FANOTIFY
727
+int fan_checkowner(int pid, const struct optstruct *opts)
728 728
 {
729 729
 	char path[32];
730 730
 	struct stat sb;
731 731
 	const struct optstruct *opt;
732 732
 
733
-    if(!(opt = optget(opts, "ClamukoExcludeUID"))->enabled)
733
+    if(!(opt = optget(opts, "OnAccessExcludeUID"))->enabled)
734 734
 	return 0;
735 735
 
736 736
     snprintf(path, sizeof(path), "/proc/%u", pid);
... ...
@@ -86,8 +86,8 @@ void detstats_clear(void);
86 86
 void detstats_add(const char *virname, const char *fname, unsigned int fsize, const char *md5);
87 87
 void detstats_print(int desc, char term);
88 88
 
89
-#if 0 /* CLAMUKO */
90
-int clamuko_checkowner(int pid, const struct optstruct *opts);
89
+#ifdef FANOTIFY
90
+int fan_checkowner(int pid, const struct optstruct *opts);
91 91
 #endif
92 92
 
93 93
 #endif
... ...
@@ -49,6 +49,7 @@
49 49
 #include "shared/output.h"
50 50
 #include "shared/optparser.h"
51 51
 
52
+#include "fan.h"
52 53
 #include "server.h"
53 54
 #include "thrmgr.h"
54 55
 #include "session.h"
... ...
@@ -60,8 +61,6 @@
60 60
 
61 61
 #define BUFFSIZE 1024
62 62
 
63
-#undef CLAMUKO /* FIXME */
64
-
65 63
 int progexit = 0;
66 64
 pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
67 65
 int reload = 0;
... ...
@@ -710,9 +709,9 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
710 710
 	unsigned int selfchk;
711 711
 	threadpool_t *thr_pool;
712 712
 
713
-#ifdef CLAMUKO
714
-	pthread_t clamuko_pid;
715
-	pthread_attr_t clamuko_attr;
713
+#ifdef FANOTIFY
714
+	pthread_t fan_pid;
715
+	pthread_attr_t fan_attr;
716 716
 	struct thrarg *tharg = NULL; /* shut up gcc */
717 717
 #endif
718 718
 
... ...
@@ -1005,24 +1004,24 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
1005 1005
     logg("*MaxQueue set to: %d\n", max_queue);
1006 1006
     acceptdata.max_queue = max_queue;
1007 1007
 
1008
-    if(optget(opts, "ClamukoScanOnAccess")->enabled)
1009
-#ifdef CLAMUKO
1008
+    if(optget(opts, "ScanOnAccess")->enabled)
1009
+#ifdef FANOTIFY
1010 1010
     {
1011 1011
         do {
1012
-	    if(pthread_attr_init(&clamuko_attr)) break;
1013
-	    pthread_attr_setdetachstate(&clamuko_attr, PTHREAD_CREATE_JOINABLE);
1012
+	    if(pthread_attr_init(&fan_attr)) break;
1013
+	    pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE);
1014 1014
 	    if(!(tharg = (struct thrarg *) malloc(sizeof(struct thrarg)))) break;
1015 1015
 	    tharg->opts = opts;
1016 1016
 	    tharg->engine = engine;
1017 1017
 	    tharg->options = options;
1018
-	    if(!pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg)) break;
1018
+	    if(!pthread_create(&fan_pid, &fan_attr, fan_th, tharg)) break;
1019 1019
 	    free(tharg);
1020 1020
 	    tharg=NULL;
1021 1021
 	} while(0);
1022
-	if (!tharg) logg("!Unable to start Clamuko\n");
1022
+	if (!tharg) logg("!Unable to start on-access scan\n");
1023 1023
     }
1024 1024
 #else
1025
-	logg("Clamuko is not available.\n");
1025
+	logg("!On-access scan is not available\n");
1026 1026
 #endif
1027 1027
 
1028 1028
 #ifndef	_WIN32
... ...
@@ -1285,11 +1284,11 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
1285 1285
 	pthread_mutex_lock(&reload_mutex);
1286 1286
 	if(reload) {
1287 1287
 	    pthread_mutex_unlock(&reload_mutex);
1288
-#ifdef CLAMUKO
1289
-	    if(optget(opts, "ClamukoScanOnAccess")->enabled && tharg) {
1290
-		logg("Stopping and restarting Clamuko.\n");
1291
-		pthread_kill(clamuko_pid, SIGUSR1);
1292
-		pthread_join(clamuko_pid, NULL);
1288
+#ifdef FANOTIFY
1289
+	    if(optget(opts, "ScanOnAccess")->enabled && tharg) {
1290
+		logg("Restarting on-access scan\n");
1291
+		pthread_kill(fan_pid, SIGUSR1);
1292
+		pthread_join(fan_pid, NULL);
1293 1293
 	    }
1294 1294
 #endif
1295 1295
 	    engine = reload_db(engine, dboptions, opts, FALSE, &ret);
... ...
@@ -1304,10 +1303,10 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
1304 1304
 	    reload = 0;
1305 1305
 	    time(&reloaded_time);
1306 1306
 	    pthread_mutex_unlock(&reload_mutex);
1307
-#ifdef CLAMUKO
1308
-	    if(optget(opts, "ClamukoScanOnAccess")->enabled && tharg) {
1307
+#ifdef FANOTIFY
1308
+	    if(optget(opts, "ScanOnAccess")->enabled && tharg) {
1309 1309
 		tharg->engine = engine;
1310
-		pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg);
1310
+		pthread_create(&fan_pid, &fan_attr, fan_th, tharg);
1311 1311
 	    }
1312 1312
 #endif
1313 1313
 	    time(&start_time);
... ...
@@ -1331,11 +1330,11 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsi
1331 1331
      */
1332 1332
     logg("*Waiting for all threads to finish\n");
1333 1333
     thrmgr_destroy(thr_pool);
1334
-#ifdef CLAMUKO
1335
-    if(optget(opts, "ClamukoScanOnAccess")->enabled) {
1336
-	logg("Stopping Clamuko.\n");
1337
-	pthread_kill(clamuko_pid, SIGUSR1);
1338
-	pthread_join(clamuko_pid, NULL);
1334
+#ifdef FANOTIFY
1335
+    if(optget(opts, "ScanOnAccess")->enabled) {
1336
+	logg("Stopping on-access scan\n");
1337
+	pthread_kill(fan_pid, SIGUSR1);
1338
+	pthread_join(fan_pid, NULL);
1339 1339
     }
1340 1340
 #endif
1341 1341
     if(engine) {
... ...
@@ -836,7 +836,7 @@ enable_unrar
836 836
 enable_getaddrinfo
837 837
 enable_ipv6
838 838
 enable_dns
839
-enable_clamuko
839
+enable_fanotify
840 840
 enable_milter
841 841
 with_system_tommath
842 842
 with_iconv
... ...
@@ -1518,7 +1518,7 @@ Optional Features:
1518 1518
   --disable-ipv6          disable IPv6 support
1519 1519
   --disable-dns           disable support for database verification through
1520 1520
                           DNS
1521
-  --disable-clamuko	  disable clamuko support (Linux, DragonFly and FreeBSD only)
1521
+  --disable-fanotify	  disable fanotify support (Linux only)
1522 1522
   --enable-milter	  build clamav-milter
1523 1523
   --disable-pthreads      disable POSIX threads support
1524 1524
   --disable-cr		  don't link with C reentrant library (BSD)
... ...
@@ -17107,11 +17107,11 @@ fi
17107 17107
 
17108 17108
 
17109 17109
 
17110
-# Check whether --enable-clamuko was given.
17111
-if test "${enable_clamuko+set}" = set; then :
17112
-  enableval=$enable_clamuko; want_clamuko=$enableval
17110
+# Check whether --enable-fanotify was given.
17111
+if test "${enable_fanotify+set}" = set; then :
17112
+  enableval=$enable_fanotify; want_fanotify=$enableval
17113 17113
 else
17114
-  want_clamuko="yes"
17114
+  want_fanotify="yes"
17115 17115
 fi
17116 17116
 
17117 17117
 
... ...
@@ -17622,9 +17622,14 @@ $as_echo "#define C_LINUX 1" >>confdefs.h
17622 17622
     if test "$have_pthreads" = "yes"; then
17623 17623
 	THREAD_LIBS="-lpthread"
17624 17624
 	TH_SAFE="-thread-safe"
17625
-	if test "$want_clamuko" = "yes"; then
17625
+	if test "$want_fanotify" = "yes"; then
17626
+	    ac_fn_c_check_header_mongrel "$LINENO" "linux/fanotify.h" "ac_cv_header_linux_fanotify_h" "$ac_includes_default"
17627
+if test "x$ac_cv_header_linux_fanotify_h" = xyes; then :
17628
+
17629
+$as_echo "#define FANOTIFY 1" >>confdefs.h
17630
+
17631
+fi
17626 17632
 
17627
-$as_echo "#define CLAMUKO 1" >>confdefs.h
17628 17633
 
17629 17634
 	fi
17630 17635
     fi
... ...
@@ -17636,11 +17641,6 @@ $as_echo "#define C_KFREEBSD_GNU 1" >>confdefs.h
17636 17636
     if test "$have_pthreads" = "yes"; then
17637 17637
        THREAD_LIBS="-lpthread"
17638 17638
        TH_SAFE="-thread-safe"
17639
-       if test "$want_clamuko" = "yes"; then
17640
-
17641
-$as_echo "#define CLAMUKO 1" >>confdefs.h
17642
-
17643
-       fi
17644 17639
     fi
17645 17640
     ;;
17646 17641
 solaris*)
... ...
@@ -17660,11 +17660,6 @@ freebsd[45]*)
17660 17660
     if test "$have_pthreads" = "yes"; then
17661 17661
 	THREAD_LIBS="-pthread -lc_r"
17662 17662
 	TH_SAFE="-thread-safe"
17663
-	if test "$want_clamuko" = "yes"; then
17664
-
17665
-$as_echo "#define CLAMUKO 1" >>confdefs.h
17666
-
17667
-	fi
17668 17663
     fi
17669 17664
 
17670 17665
 $as_echo "#define C_BSD 1" >>confdefs.h
... ...
@@ -17674,11 +17669,6 @@ freebsd*)
17674 17674
     if test "$have_pthreads" = "yes"; then
17675 17675
 	THREAD_LIBS="-lthr"
17676 17676
 	TH_SAFE="-thread-safe"
17677
-	if test "$want_clamuko" = "yes"; then
17678
-
17679
-$as_echo "#define CLAMUKO 1" >>confdefs.h
17680
-
17681
-	fi
17682 17677
     fi
17683 17678
 
17684 17679
 $as_echo "#define C_BSD 1" >>confdefs.h
... ...
@@ -17688,11 +17678,6 @@ dragonfly*)
17688 17688
     if test "$have_pthreads" = "yes"; then
17689 17689
 	THREAD_LIBS="-pthread"
17690 17690
 	TH_SAFE="-thread-safe"
17691
-	if test "$want_clamuko" = "yes"; then
17692
-
17693
-$as_echo "#define CLAMUKO 1" >>confdefs.h
17694
-
17695
-	fi
17696 17691
     fi
17697 17692
 
17698 17693
 $as_echo "#define C_BSD 1" >>confdefs.h
... ...
@@ -26143,15 +26128,15 @@ fi
26143 26143
 
26144 26144
 
26145 26145
 
26146
-   $as_echo_n "              clamuko     : "
26147
-   if test "x$want_clamuko" = "xno"; then :
26148
-  $as_echo "$want_clamuko (disabled)"
26149
-elif test "x$want_clamuko" = "xyes"; then :
26150
-  $as_echo "$want_clamuko"
26151
-elif test "x$want_clamuko" = "x"; then :
26152
-  $as_echo "$want_clamuko"
26146
+   $as_echo_n "              fanotify    : "
26147
+   if test "x$want_fanotify" = "xno"; then :
26148
+  $as_echo "$want_fanotify (disabled)"
26149
+elif test "x$want_fanotify" = "xyes"; then :
26150
+  $as_echo "$want_fanotify"
26151
+elif test "x$want_fanotify" = "x"; then :
26152
+  $as_echo "$want_fanotify"
26153 26153
 else
26154
-  $as_echo "$want_clamuko ($want_clamuko)"
26154
+  $as_echo "$want_fanotify ($want_fanotify)"
26155 26155
 fi
26156 26156
 
26157 26157
 if test "x$ac_cv_have_control_in_msghdr" = "xyes"; then
... ...
@@ -730,9 +730,9 @@ fi
730 730
 
731 731
 AC_C_DNS
732 732
 
733
-AC_ARG_ENABLE([clamuko],
734
-[  --disable-clamuko	  disable clamuko support (Linux, DragonFly and FreeBSD only)],
735
-want_clamuko=$enableval, want_clamuko="yes")
733
+AC_ARG_ENABLE([fanotify],
734
+[  --disable-fanotify	  disable fanotify support (Linux only)],
735
+want_fanotify=$enableval, want_fanotify="yes")
736 736
 
737 737
 dnl AC_FUNC_SETPGRP does not work when cross compiling
738 738
 dnl Instead, assume we will have a prototype for setpgrp if cross compiling.
... ...
@@ -952,8 +952,8 @@ linux*)
952 952
     if test "$have_pthreads" = "yes"; then
953 953
 	THREAD_LIBS="-lpthread"
954 954
 	TH_SAFE="-thread-safe"
955
-	if test "$want_clamuko" = "yes"; then
956
-	    AC_DEFINE([CLAMUKO],1,[enable clamuko])
955
+	if test "$want_fanotify" = "yes"; then
956
+	    AC_CHECK_HEADER([linux/fanotify.h],AC_DEFINE([FANOTIFY],1,[use fanotify]),)
957 957
 	fi
958 958
     fi
959 959
     ;;
... ...
@@ -962,9 +962,6 @@ kfreebsd*-gnu)
962 962
     if test "$have_pthreads" = "yes"; then
963 963
        THREAD_LIBS="-lpthread"
964 964
        TH_SAFE="-thread-safe"
965
-       if test "$want_clamuko" = "yes"; then
966
-           AC_DEFINE([CLAMUKO],1,[enable clamuko])
967
-       fi
968 965
     fi
969 966
     ;;
970 967
 solaris*)
... ...
@@ -982,9 +979,6 @@ freebsd[[45]]*)
982 982
     if test "$have_pthreads" = "yes"; then
983 983
 	THREAD_LIBS="-pthread -lc_r"
984 984
 	TH_SAFE="-thread-safe"
985
-	if test "$want_clamuko" = "yes"; then
986
-	    AC_DEFINE([CLAMUKO],1,[enable clamuko])
987
-	fi
988 985
     fi
989 986
     AC_DEFINE([C_BSD],1,[os is freebsd 4 or 5])
990 987
     ;;
... ...
@@ -992,9 +986,6 @@ freebsd*)
992 992
     if test "$have_pthreads" = "yes"; then
993 993
 	THREAD_LIBS="-lthr"
994 994
 	TH_SAFE="-thread-safe"
995
-	if test "$want_clamuko" = "yes"; then
996
-	    AC_DEFINE([CLAMUKO],1,[enable clamuko])
997
-	fi
998 995
     fi
999 996
     AC_DEFINE([C_BSD],1,[os is freebsd 6])
1000 997
     ;;
... ...
@@ -1002,9 +993,6 @@ dragonfly*)
1002 1002
     if test "$have_pthreads" = "yes"; then
1003 1003
 	THREAD_LIBS="-pthread"
1004 1004
 	TH_SAFE="-thread-safe"
1005
-	if test "$want_clamuko" = "yes"; then
1006
-	    AC_DEFINE([CLAMUKO],1,[enable clamuko])
1007
-	fi
1008 1005
     fi
1009 1006
     AC_DEFINE([C_BSD],1,[os is dragonfly])
1010 1007
     ;;
... ...
@@ -1676,7 +1664,7 @@ else
1676 1676
     check_libs="$CHECK_LIBS"
1677 1677
 fi
1678 1678
 CL_MSG_STATUS([check       ],[$check_libs],[$enable_check_ut])
1679
-CL_MSG_STATUS([clamuko     ],[$want_clamuko],[$want_clamuko])
1679
+CL_MSG_STATUS([fanotify    ],[$want_fanotify],[$want_fanotify])
1680 1680
 if test "x$ac_cv_have_control_in_msghdr" = "xyes"; then
1681 1681
     CL_MSG_STATUS([fdpassing   ],[$have_fdpass],[$want_fdpassing])
1682 1682
 else
... ...
@@ -329,23 +329,15 @@ const struct clam_option __clam_options[] = {
329 329
 
330 330
     { "MaxFiles", "max-files", 0, TYPE_NUMBER, MATCH_NUMBER, CLI_DEFAULT_MAXFILES, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Number of files to be scanned within an archive, a document, or any other\ncontainer file.\nThe value of 0 disables the limit.\nWARNING: disabling this limit or setting it too high may result in severe\ndamage to the system.", "10000" },
331 331
 
332
-    { "ClamukoScanOnAccess", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables Clamuko. Dazuko needs to be already configured and\nrunning.", "no" },
332
+    { "ScanOnAccess", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "This option enables on-access scanning (Linux only)", "no" },
333 333
 
334
-    { "ClamukoScannerCount", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD, "The number of scanner threads that will be started (DazukoFS only).\nHaving multiple scanner threads allows Clamuko to serve multiple\nprocesses simultaneously. This is particularly beneficial on SMP machines.", "3" },
334
+    { "OnAccessIncludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory (including all files and directories\ninside it), which should be scanned on access. This option can\nbe used multiple times.", "/home\n/students" },
335 335
 
336
-    { "ClamukoScanOnOpen", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Scan files when they get opened by the system.", "yes" },
336
+    { "OnAccessExcludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times.", "/home/bofh\n/root" },
337 337
 
338
-    { "ClamukoScanOnClose", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Scan files when they get closed by the system.", "yes" },
338
+    { "OnAccessExcludeUID", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can whitelist specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line).", "0" },
339 339
 
340
-    { "ClamukoScanOnExec", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD, "Scan files when they get executed by the system.", "yes" },
341
-
342
-    { "ClamukoIncludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option specifies a directory (together will all files and directories\ninside this directory) which should be scanned on-access. This option can\nbe used multiple times.", "/home\n/students" },
343
-
344
-    { "ClamukoExcludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "This option allows excluding directories from on-access scanning. It can\nbe used multiple times.", "/home/bofh\n/root" },
345
-
346
-    { "ClamukoExcludeUID", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD, "With this option you can whitelist specific UIDs. Processes with these UIDs\nwill be able to access all files.\nThis option can be used multiple times (one per line).", "0" },
347
-
348
-    { "ClamukoMaxFileSize", NULL, 0, TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD, "Files larger than this value will not be scanned.", "5M" },
340
+    { "OnAccessMaxFileSize", NULL, 0, TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD, "Files larger than this value will not be scanned in on access.", "5M" },
349 341
 
350 342
     /* FIXME: mark these as private and don't output into clamd.conf/man */
351 343
     { "DevACOnly", "dev-ac-only", 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, FLAG_HIDDEN, OPT_CLAMD | OPT_CLAMSCAN, "", "" },
... ...
@@ -430,6 +422,15 @@ const struct clam_option __clam_options[] = {
430 430
     { "ArchiveBlockMax", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
431 431
     { "ArchiveLimitMemoryUsage", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
432 432
     { "MailFollowURLs", "mail-follow-urls", 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN | OPT_DEPRECATED, "", "" },
433
+    { "ClamukoScanOnAccess", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
434
+    { "ClamukoScannerCount", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 3, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
435
+    { "ClamukoScanOnOpen", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
436
+    { "ClamukoScanOnClose", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
437
+    { "ClamukoScanOnExec", NULL, 0, TYPE_BOOL, MATCH_BOOL, -1, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
438
+    { "ClamukoIncludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
439
+    { "ClamukoExcludePath", NULL, 0, TYPE_STRING, NULL, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
440
+    { "ClamukoExcludeUID", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, -1, NULL, FLAG_MULTIPLE, OPT_CLAMD | OPT_DEPRECATED, "", "" },
441
+    { "ClamukoMaxFileSize", NULL, 0, TYPE_SIZE, MATCH_SIZE, 5242880, NULL, 0, OPT_CLAMD | OPT_DEPRECATED, "", "" },
433 442
 
434 443
     /* Milter specific options */
435 444