Browse code

clamonacc: Fix scan on file creation race condition

Clamonacc was missing scanning files when the system was under load,
due to scanning on file creation, which would occasionally scan before
the file had been written. This pr modifies clamonacc to scan when the file
is closed.

Andy Ragusa (aragusa) authored on 2021/03/20 10:21:02
Showing 2 changed files
... ...
@@ -76,9 +76,10 @@ static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t ti
76 76
 {
77 77
     uint32_t buf[BUFSIZ / sizeof(uint32_t)];
78 78
     uint64_t len;
79
-    uint64_t todo  = maxstream;
80 79
     int ret        = 1;
81 80
     int close_flag = 0;
81
+    STATBUF statbuf;
82
+    uint64_t bytesRead = 0;
82 83
 
83 84
     if (-1 == fd) {
84 85
         if (NULL == filename) {
... ...
@@ -94,30 +95,51 @@ static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t ti
94 94
         }
95 95
     }
96 96
 
97
+    if (FSTAT(fd, &statbuf)){
98
+        logg("!onas_send_stream: Invalid args, bad file descriptor.\n");
99
+        ret = -1;
100
+        goto strm_out;
101
+    }
102
+
103
+    if (S_ISDIR(statbuf.st_mode)){
104
+        ret = 0;
105
+        goto strm_out;
106
+    }
107
+
108
+    if ((uint64_t) statbuf.st_size > maxstream){
109
+        ret = 0;
110
+        goto strm_out;
111
+    }
112
+
97 113
     if (onas_sendln(curl, "zINSTREAM", 10, timeout)) {
98 114
         ret = -1;
99 115
         goto strm_out;
100 116
     }
101 117
 
102
-    while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) {
103
-        if ((uint64_t)len > todo) len = todo;
104
-        buf[0] = htonl(len);
105
-        if (onas_sendln(curl, (const char *)buf, len + sizeof(uint32_t), timeout)) {
118
+    len = statbuf.st_size;
119
+    buf[0] = htonl(len);
120
+    if (onas_sendln(curl, (const char *) buf, sizeof(uint32_t), timeout)){
121
+        ret = -1;
122
+        goto strm_out;
123
+    }
124
+
125
+    while (bytesRead < len){
126
+        ssize_t ret = read(fd, buf, sizeof(buf));
127
+        if (ret < 0){
128
+            logg("!Failed to read from %s.\n", filename ? filename : "FD");
106 129
             ret = -1;
107 130
             goto strm_out;
108
-        }
109
-        todo -= len;
110
-        if (!todo) {
111
-            len = 0;
131
+        } else if (0 == ret){
112 132
             break;
113 133
         }
114
-    }
134
+        bytesRead += ret;
115 135
 
116
-    if (len) {
117
-        logg("!Failed to read from %s.\n", filename ? filename : "FD");
118
-        ret = -1;
119
-        goto strm_out;
136
+        if (onas_sendln(curl, (const char *) buf, ret, timeout)) {
137
+            ret = -1;
138
+            goto strm_out;
139
+        }
120 140
     }
141
+
121 142
     *buf = 0;
122 143
     onas_sendln(curl, (const char *)buf, 4, timeout);
123 144
 
... ...
@@ -72,6 +72,7 @@ static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd,
72 72
 
73 73
 static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
74 74
 static void onas_ddd_handle_in_create(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask);
75
+static void onas_ddd_handle_in_close_write(struct onas_context *ctx, const char *child_path);
75 76
 static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd);
76 77
 static void onas_ddd_handle_in_delete(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd);
77 78
 static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options);
... ...
@@ -363,7 +364,7 @@ void *onas_ddd_th(void *arg)
363 363
     const struct optstruct *pt;
364 364
     const struct optstruct *pt_tmpdir;
365 365
     const char *clamd_tmpdir;
366
-    uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
366
+    uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE | IN_CLOSE_WRITE;
367 367
     fd_set rfds;
368 368
     char buf[4096];
369 369
     ssize_t bread;
... ...
@@ -659,6 +660,9 @@ void *onas_ddd_th(void *arg)
659 659
                 } else if (event->mask & IN_CREATE) {
660 660
                     onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask);
661 661
 
662
+                } else if (event->mask & IN_CLOSE_WRITE) {
663
+                    onas_ddd_handle_in_close_write(ctx, child_path);
664
+
662 665
                 } else if (event->mask & IN_MOVED_TO) {
663 666
                     onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask);
664 667
                 }
... ...
@@ -708,26 +712,29 @@ static void onas_ddd_handle_in_create(struct onas_context *ctx,
708 708
                                       const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask)
709 709
 {
710 710
 
711
+    if (!(event->mask & IN_ISDIR)){
712
+        return;
713
+    }
714
+
715
+    if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) {
716
+        logg("*ClamInotif: CREATE - adding %s to %s with wd:%d\n", child_path, path, wd);
717
+        onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR);
718
+    }
719
+
720
+    onas_ht_add_hierarchy(ddd_ht, child_path);
721
+    onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask);
722
+
723
+    return;
724
+}
725
+
726
+static void onas_ddd_handle_in_close_write(struct onas_context *ctx, const char *child_path)
727
+{
711 728
     struct stat s;
712 729
 
713 730
     if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) {
714 731
         if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) {
715 732
             onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE);
716
-
717
-        } else if (event->mask & IN_ISDIR) {
718
-            logg("*ClamInotif: CREATE - adding %s to %s with wd:%d\n", child_path, path, wd);
719
-            onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR);
720
-
721
-            onas_ht_add_hierarchy(ddd_ht, child_path);
722
-            onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask);
723 733
         }
724
-    } else {
725
-        if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
726
-        if (!(event->mask & IN_ISDIR)) return;
727
-
728
-        logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd);
729
-        onas_ht_add_hierarchy(ddd_ht, child_path);
730
-        onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask);
731 734
     }
732 735
 
733 736
     return;