Browse code

clamd, clamscan: add support for CrossFilesystems/--cross-fs (bb#1607)

Tomasz Kojm authored on 2009/08/05 23:27:48
Showing 10 changed files
... ...
@@ -1,3 +1,7 @@
1
+Wed Aug  5 16:27:06 CEST 2009 (tk)
2
+----------------------------------
3
+ * clamd, clamscan: add support for CrossFilesystems/--cross-fs (bb#1607)
4
+
1 5
 Tue Aug  4 23:15:26 CEST 2009 (tk)
2 6
 ----------------------------------
3 7
  * configure, libclamav: fix compile issues on IRIX (bb#1532)
... ...
@@ -237,17 +237,29 @@ int scan_pathchk(const char *path, struct cli_ftw_cbdata *data)
237 237
 {
238 238
 	struct scan_cb_data *scandata = data->data;
239 239
 	const struct optstruct *opt;
240
+	struct stat statbuf;
240 241
 
241 242
     if((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
242 243
 	while(opt) {
243 244
 	    if(match_regex(path, opt->strarg) == 1) {
244 245
 		if(scandata->type != TYPE_MULTISCAN)
245 246
 		    conn_reply_single(scandata->conn, path, "Excluded");
246
-		    return 1;
247
+		return 1;
247 248
 	    }
248 249
 	    opt = (const struct optstruct *) opt->nextarg;
249 250
 	}
250 251
     }
252
+
253
+    if(!optget(scandata->opts, "CrossFilesystems")->enabled) {
254
+	if(stat(path, &statbuf) == 0) {
255
+	    if(statbuf.st_dev != scandata->dev) {
256
+		if(scandata->type != TYPE_MULTISCAN)
257
+		    conn_reply_single(scandata->conn, path, "Excluded (another filesystem)");
258
+		return 1;
259
+	    }
260
+	}
261
+    }
262
+
251 263
     return 0;
252 264
 }
253 265
 
... ...
@@ -25,6 +25,8 @@
25 25
 #define TYPE_CONTSCAN	1
26 26
 #define TYPE_MULTISCAN	2
27 27
 
28
+#include <sys/types.h>
29
+
28 30
 #include "libclamav/clamav.h"
29 31
 #include "shared/optparser.h"
30 32
 #include "thrmgr.h"
... ...
@@ -46,6 +48,7 @@ struct scan_cb_data {
46 46
     const struct optstruct *opts;
47 47
     threadpool_t *thr_pool;
48 48
     jobgroup_t *group;
49
+    dev_t dev;
49 50
 };
50 51
 
51 52
 int scanfd(const int fd, const client_conn_t *conn, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, int odesc, int stream);
... ...
@@ -192,6 +192,7 @@ int command(client_conn_t *conn, int *virus)
192 192
     struct scan_cb_data scandata;
193 193
     struct cli_ftw_cbdata data;
194 194
     unsigned ok, error, total;
195
+    struct stat sb;
195 196
     jobgroup_t *group = NULL;
196 197
 
197 198
     if (thrmgr_group_need_terminate(conn->group)) {
... ...
@@ -316,6 +317,11 @@ int command(client_conn_t *conn, int *virus)
316 316
 	flags |= CLI_FTW_FOLLOW_DIR_SYMLINK;
317 317
     if (optget(opts, "FollowFileSymlinks")->enabled)
318 318
 	flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
319
+
320
+    if(!optget(opts, "CrossFilesystems")->enabled)
321
+	if(stat(conn->filename, &sb) == 0)
322
+	    scandata.dev = sb.st_dev;
323
+
319 324
     ret = cli_ftw(conn->filename, flags,  maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk);
320 325
     if (ret == CL_EMEM)
321 326
 	if(optget(opts, "ExitOnOOM")->enabled)
... ...
@@ -238,6 +238,7 @@ void help(void)
238 238
     mprintf("                                         all supported db files from DIR\n");
239 239
     mprintf("    --log=FILE            -l FILE        Save scan report to FILE\n");
240 240
     mprintf("    --recursive[=yes/no(*)]  -r          Scan subdirectories recursively\n");
241
+    mprintf("    --cross-fs[=yes(*)/no]               Scan files and directories on other filesystems\n");
241 242
     mprintf("    --file-list=FILE      -f FILE        Scan files from FILE\n");
242 243
     mprintf("    --remove[=yes/no(*)]                 Remove infected files. Be careful!\n");
243 244
     mprintf("    --move=DIRECTORY                     Move infected files into DIRECTORY\n");
... ...
@@ -169,7 +169,7 @@ static int scanfile(const char *filename, struct cl_engine *engine, const struct
169 169
     return ret;
170 170
 }
171 171
 
172
-static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth)
172
+static int scandirs(const char *dirname, struct cl_engine *engine, const struct optstruct *opts, unsigned int options, unsigned int depth, dev_t dev)
173 173
 {
174 174
 	DIR *dd;
175 175
 	struct dirent *dent;
... ...
@@ -228,8 +228,16 @@ static int scandirs(const char *dirname, struct cl_engine *engine, const struct
228 228
 
229 229
 		    /* stat the file */
230 230
 		    if(lstat(fname, &statbuf) != -1) {
231
+			if(!optget(opts, "cross-fs")->enabled) {
232
+			    if(statbuf.st_dev != dev) {
233
+				if(!printinfected)
234
+				    logg("~%s: Excluded\n", fname);
235
+				free(fname);
236
+				continue;
237
+			    }
238
+			}
231 239
 			if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode) && recursion) {
232
-			    if(scandirs(fname, engine, opts, options, depth) == 1)
240
+			    if(scandirs(fname, engine, opts, options, depth, dev) == 1)
233 241
 				scanret++;
234 242
 			} else {
235 243
 			    if(S_ISREG(statbuf.st_mode))
... ...
@@ -593,8 +601,10 @@ int scanmanager(const struct optstruct *opts)
593 593
 	if(!getcwd(cwd, sizeof(cwd))) {
594 594
 	    logg("!Can't get absolute pathname of current working directory\n");
595 595
 	    ret = 57;
596
-	} else
597
-	    ret = scandirs(cwd, engine, opts, options, 1);
596
+	} else {
597
+	    stat(cwd, &sb);
598
+	    ret = scandirs(cwd, engine, opts, options, 1, sb.st_dev);
599
+	}
598 600
 
599 601
     } else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */
600 602
 	ret = scanstdin(engine, opts, options);
... ...
@@ -624,7 +634,8 @@ int scanmanager(const struct optstruct *opts)
624 624
 			break;
625 625
 
626 626
 		    case S_IFDIR:
627
-			ret = scandirs(file, engine, opts, options, 1);
627
+			stat(file, &sb);
628
+			ret = scandirs(file, engine, opts, options, 1, sb.st_dev);
628 629
 			break;
629 630
 
630 631
 		    default:
... ...
@@ -162,6 +162,11 @@ Follow directory symlinks.
162 162
 .br 
163 163
 Default: no
164 164
 .TP 
165
+\fBCrossFilesystems BOOL\fR
166
+Scan files and directories on other filesystems.
167
+.br 
168
+Default: yes
169
+.TP 
165 170
 \fBFollowFileSymlinks BOOL\fR
166 171
 Follow regular file symlinks.
167 172
 .br 
... ...
@@ -48,6 +48,9 @@ Scan files listed line by line in FILE.
48 48
 \fB\-r, \-\-recursive\fR
49 49
 Scan directories recursively. All the subdirectories in the given directory will be scanned.
50 50
 .TP 
51
+\fB\-\-cross\-fs=[yes(*)/no]\fR
52
+Scan files and directories on other filesystems.
53
+.TP 
51 54
 \fB\-\-bell\fR
52 55
 Sound bell on virus detection.
53 56
 .TP 
... ...
@@ -156,6 +156,10 @@ LocalSocket /tmp/clamd.socket
156 156
 # Default: no
157 157
 #FollowFileSymlinks yes
158 158
 
159
+# Scan files and directories on other filesystems.
160
+# Default: yes
161
+#CrossFilesystems yes
162
+
159 163
 # Perform a database check.
160 164
 # Default: 600 (10 min)
161 165
 #SelfCheck 600
... ...
@@ -211,6 +211,8 @@ const struct clam_option clam_options[] = {
211 211
 
212 212
     { "FollowFileSymlinks", NULL, 0, TYPE_BOOL, MATCH_BOOL, 0, NULL, 0, OPT_CLAMD, "Follow symlinks to regular files.", "no" },
213 213
 
214
+    { "CrossFilesystems", "cross-fs", 0, TYPE_BOOL, MATCH_BOOL, 1, NULL, 0, OPT_CLAMD | OPT_CLAMSCAN, "Scan files and directories on other filesystems.", "yes" },
215
+
214 216
     { "SelfCheck", NULL, 0, TYPE_NUMBER, MATCH_NUMBER, 600, NULL, 0, OPT_CLAMD, "This option specifies the time intervals (in seconds) in which clamd\nshould perform a database check.", "600" },
215 217
 
216 218
     { "VirusEvent", NULL, 0, TYPE_STRING, NULL, -1, NULL, 0, OPT_CLAMD, "Execute a command when a virus is found. In the command string %v will be\nreplaced with the virus name. Additionally, two environment variables will\nbe defined: $CLAM_VIRUSEVENT_FILENAME and $CLAM_VIRUSEVENT_VIRUSNAME.", "/usr/bin/mailx -s \"ClamAV VIRUS ALERT: %v\" alert < /dev/null" },