~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/matcher-bm.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
2
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
3
3
 *
4
4
 *  Authors: Tomasz Kojm
5
5
 *
31
31
#include "matcher.h"
32
32
#include "matcher-bm.h"
33
33
#include "filetypes.h"
 
34
#include "filtering.h"
34
35
 
35
36
#include "mpool.h"
36
37
 
38
39
#define BM_BLOCK_SIZE   3
39
40
#define HASH(a,b,c) (211 * a + 37 * b + c)
40
41
 
41
 
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern)
 
42
int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern, const char *offset)
42
43
{
43
44
        uint16_t idx, i;
44
45
        const unsigned char *pt = pattern->pattern;
45
46
        struct cli_bm_patt *prev, *next = NULL;
 
47
        int ret;
46
48
 
47
49
 
48
50
    if(pattern->length < BM_MIN_LENGTH) {
50
52
        return CL_EMALFDB;
51
53
    }
52
54
 
 
55
    if((ret = cli_caloff(offset, NULL, NULL, root->type, pattern->offdata, &pattern->offset_min, &pattern->offset_max))) {
 
56
        cli_errmsg("cli_bm_addpatt: Can't calculate offset for signature %s\n", pattern->virname);
 
57
        return ret;
 
58
    }
 
59
    if(pattern->offdata[0] != CLI_OFF_ANY) {
 
60
        if(pattern->offdata[0] == CLI_OFF_ABSOLUTE)
 
61
            root->bm_absoff_num++;
 
62
        else
 
63
            root->bm_reloff_num++;
 
64
    }
 
65
 
 
66
    if(root->filter) {
 
67
        /* the bm_suffix load balancing below can shorten the sig,
 
68
         * we want to see the entire signature! */
 
69
        if (filter_add_static(root->filter, pattern->pattern, pattern->length, pattern->virname) == -1) {
 
70
            cli_warnmsg("cli_bm_addpatt: cannot use filter for trie\n");
 
71
            mpool_free(root->mempool, root->filter);
 
72
            root->filter = NULL;
 
73
        }
 
74
        /* TODO: should this affect maxpatlen? */
 
75
    }
 
76
 
53
77
#if BM_MIN_LENGTH == BM_BLOCK_SIZE
54
78
    /* try to load balance bm_suffix (at the cost of bm_shift) */
55
79
    for(i = 0; i < pattern->length - BM_BLOCK_SIZE + 1; i++) {
92
116
    pattern->pattern0 = pattern->pattern[0];
93
117
    root->bm_suffix[idx]->cnt++;
94
118
 
 
119
    if(root->bm_offmode) {
 
120
        root->bm_pattab = (struct cli_bm_patt **) mpool_realloc2(root->mempool, root->bm_pattab, (root->bm_patterns + 1) * sizeof(struct cli_bm_patt *));
 
121
        if(!root->bm_pattab) {
 
122
            cli_errmsg("cli_bm_addpatt: Can't allocate memory for root->bm_pattab\n");
 
123
            return CL_EMEM;
 
124
        }
 
125
        root->bm_pattab[root->bm_patterns] = pattern;
 
126
        if(pattern->offdata[0] != CLI_OFF_ABSOLUTE)
 
127
            pattern->offset_min = root->bm_patterns;
 
128
    }
 
129
 
95
130
    root->bm_patterns++;
96
131
    return CL_SUCCESS;
97
132
}
102
137
#ifdef USE_MPOOL
103
138
    assert (root->mempool && "mempool must be initialized");
104
139
#endif
 
140
 
105
141
    if(!(root->bm_shift = (uint8_t *) mpool_calloc(root->mempool, size, sizeof(uint8_t))))
106
142
        return CL_EMEM;
107
143
 
116
152
    return CL_SUCCESS;
117
153
}
118
154
 
 
155
int cli_bm_initoff(const struct cli_matcher *root, struct cli_bm_off *data, fmap_t *map)
 
156
{
 
157
        int ret;
 
158
        unsigned int i;
 
159
        struct cli_bm_patt *patt;
 
160
        struct cli_target_info info;
 
161
 
 
162
 
 
163
    if(!root->bm_patterns) {
 
164
        data->offtab = data->offset = NULL;
 
165
        data->cnt = data->pos = 0;
 
166
        return CL_SUCCESS;
 
167
    }
 
168
    memset(&info, 0, sizeof(info));
 
169
    info.fsize = map->len;
 
170
 
 
171
    data->cnt = data->pos = 0;
 
172
    data->offtab = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
 
173
    if(!data->offtab) {
 
174
        cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offtab\n");
 
175
        return CL_EMEM;
 
176
    }
 
177
    data->offset = (uint32_t *) cli_malloc(root->bm_patterns * sizeof(uint32_t));
 
178
    if(!data->offset) {
 
179
        cli_errmsg("cli_bm_initoff: Can't allocate memory for data->offset\n");
 
180
        free(data->offtab);
 
181
        return CL_EMEM;
 
182
    }
 
183
    for(i = 0; i < root->bm_patterns; i++) {
 
184
        patt = root->bm_pattab[i];
 
185
        if(patt->offdata[0] == CLI_OFF_ABSOLUTE) {
 
186
            data->offtab[data->cnt] = patt->offset_min + patt->prefix_length;
 
187
            if(data->offtab[data->cnt] >= map->len)
 
188
                continue;
 
189
            data->cnt++;
 
190
        } else if((ret = cli_caloff(NULL, &info, map, root->type, patt->offdata, &data->offset[patt->offset_min], NULL))) {
 
191
            cli_errmsg("cli_bm_initoff: Can't calculate relative offset in signature for %s\n", patt->virname);
 
192
            if(info.exeinfo.section)
 
193
                free(info.exeinfo.section);
 
194
            free(data->offtab);
 
195
            free(data->offset);
 
196
            return ret;
 
197
        } else if((data->offset[patt->offset_min] != CLI_OFF_NONE) && (data->offset[patt->offset_min] + patt->length <= info.fsize)) {
 
198
            if(!data->cnt || (data->offset[patt->offset_min] + patt->prefix_length != data->offtab[data->cnt - 1])) {
 
199
                data->offtab[data->cnt] = data->offset[patt->offset_min] + patt->prefix_length;
 
200
                if(data->offtab[data->cnt] >= map->len)
 
201
                    continue;
 
202
                data->cnt++;
 
203
            }
 
204
        }
 
205
    }
 
206
    if(info.exeinfo.section)
 
207
        free(info.exeinfo.section);
 
208
 
 
209
    cli_qsort(data->offtab, data->cnt, sizeof(uint32_t), NULL);
 
210
    return CL_SUCCESS;
 
211
}
 
212
 
 
213
void cli_bm_freeoff(struct cli_bm_off *data)
 
214
{
 
215
    free(data->offset);
 
216
    data->offset = NULL;
 
217
    free(data->offtab);
 
218
    data->offtab = NULL;
 
219
}
 
220
 
119
221
void cli_bm_free(struct cli_matcher *root)
120
222
{
121
223
        struct cli_bm_patt *patt, *prev;
125
227
    if(root->bm_shift)
126
228
        mpool_free(root->mempool, root->bm_shift);
127
229
 
 
230
    if(root->bm_pattab)
 
231
        mpool_free(root->mempool, root->bm_pattab);
 
232
 
128
233
    if(root->bm_suffix) {
129
234
        for(i = 0; i < size; i++) {
130
235
            patt = root->bm_suffix[i];
137
242
                    mpool_free(root->mempool, prev->pattern);
138
243
                if(prev->virname)
139
244
                    mpool_free(root->mempool, prev->virname);
140
 
                if(prev->offset)
141
 
                    mpool_free(root->mempool, prev->offset);
142
245
                mpool_free(root->mempool, prev);
143
246
            }
144
247
        }
146
249
    }
147
250
}
148
251
 
149
 
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, cli_file_t ftype, int fd)
 
252
int cli_bm_scanbuff(const unsigned char *buffer, uint32_t length, const char **virname, const struct cli_bm_patt **patt, const struct cli_matcher *root, uint32_t offset, fmap_t *map, struct cli_bm_off *offdata)
150
253
{
151
 
        uint32_t i, j, off;
 
254
        uint32_t i, j, off, off_min, off_max;
152
255
        uint8_t found, pchain, shift;
153
256
        uint16_t idx, idxchk;
154
257
        struct cli_bm_patt *p;
155
258
        const unsigned char *bp, *pt;
156
259
        unsigned char prefix;
157
 
        struct cli_target_info info;
158
 
 
 
260
        struct cli_target_info info;
 
261
        int ret;
159
262
 
160
263
    if(!root || !root->bm_shift)
161
264
        return CL_CLEAN;
164
267
        return CL_CLEAN;
165
268
 
166
269
    memset(&info, 0, sizeof(info));
167
 
 
168
 
    for(i = BM_MIN_LENGTH - BM_BLOCK_SIZE; i < length - BM_BLOCK_SIZE + 1; ) {
 
270
    i = BM_MIN_LENGTH - BM_BLOCK_SIZE;
 
271
    if(offdata) {
 
272
        if(!offdata->cnt)
 
273
            return CL_CLEAN;
 
274
        for(; offdata->pos && offdata->offtab[offdata->pos] > offset; offdata->pos--);
 
275
        if(offdata->offtab[offdata->pos] < offset)
 
276
            offdata->pos++;
 
277
        if(offdata->pos >= offdata->cnt)
 
278
            return CL_CLEAN;
 
279
        i += offdata->offtab[offdata->pos] - offset;
 
280
    }
 
281
    for(; i < length - BM_BLOCK_SIZE + 1; ) {
169
282
        idx = HASH(buffer[i], buffer[i + 1], buffer[i + 2]);
170
283
        shift = root->bm_shift[idx];
171
284
 
172
285
        if(shift == 0) {
173
286
            prefix = buffer[i - BM_MIN_LENGTH + BM_BLOCK_SIZE];
174
287
            p = root->bm_suffix[idx];
 
288
            if(p && p->cnt == 1 && p->pattern0 != prefix) {
 
289
                if(offdata) {
 
290
                    off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
 
291
                    for(; offdata->pos < offdata->cnt && off >= offdata->offtab[offdata->pos]; offdata->pos++);
 
292
                    if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
 
293
                        return CL_CLEAN;
 
294
                    i += offdata->offtab[offdata->pos] - off;
 
295
                } else {
 
296
                    i++;
 
297
                }
 
298
                continue;
 
299
            }
175
300
            pchain = 0;
176
301
            while(p) {
177
302
                if(p->pattern0 != prefix) {
189
314
                    continue;
190
315
                }
191
316
 
 
317
                if(offdata) {
 
318
                    if(p->offdata[0] == CLI_OFF_ABSOLUTE) {
 
319
                        if(p->offset_min != offset + off - p->prefix_length) {
 
320
                            p = p->next;
 
321
                            continue;
 
322
                        }
 
323
                    } else if((offdata->offset[p->offset_min] == CLI_OFF_NONE) || (offdata->offset[p->offset_min] != offset + off - p->prefix_length)) {
 
324
                        p = p->next;
 
325
                        continue;
 
326
                    }
 
327
                }
 
328
 
192
329
                idxchk = MIN(p->length, length - off) - 1;
193
330
                if(idxchk) {
194
331
                    if((bp[idxchk] != p->pattern[idxchk]) ||  (bp[idxchk / 2] != p->pattern[idxchk / 2])) {
213
350
                    }
214
351
                }
215
352
 
 
353
                if(found && (p->boundary & BM_BOUNDARY_EOL)) {
 
354
                    if(off != length) {
 
355
                        p = p->next;
 
356
                        continue;
 
357
                    }
 
358
                }
 
359
 
216
360
                if(found && p->length + p->prefix_length == j) {
217
 
 
218
 
                    if(p->offset) {
 
361
                    if(!offdata && (p->offset_min != CLI_OFF_ANY)) {
 
362
                        if(p->offdata[0] != CLI_OFF_ABSOLUTE) {
 
363
                            ret = cli_caloff(NULL, &info, map, root->type, p->offdata, &off_min, &off_max);
 
364
                            if(ret != CL_SUCCESS) {
 
365
                                cli_errmsg("cli_bm_scanbuff: Can't calculate relative offset in signature for %s\n", p->virname);
 
366
                                if(info.exeinfo.section)
 
367
                                    free(info.exeinfo.section);
 
368
                                return ret;
 
369
                            }
 
370
                        } else {
 
371
                            off_min = p->offset_min;
 
372
                            off_max = p->offset_max;
 
373
                        }
219
374
                        off = offset + i - p->prefix_length - BM_MIN_LENGTH + BM_BLOCK_SIZE;
220
 
                        if(!cli_validatesig(ftype, p->offset, off, &info, fd, p->virname)) {
 
375
                        if(off_min == CLI_OFF_NONE || off_max < off || off_min > off) {
221
376
                            p = p->next;
222
377
                            continue;
223
378
                        }
224
379
                    }
225
 
 
226
380
                    if(virname)
227
381
                        *virname = p->virname;
228
382
                    if(patt)
229
383
                        *patt = p;
230
384
                    if(info.exeinfo.section)
231
385
                        free(info.exeinfo.section);
232
 
 
233
386
                    return CL_VIRUS;
234
387
                }
235
 
 
236
388
                p = p->next;
237
389
            }
238
 
 
239
390
            shift = 1;
240
391
        }
241
392
 
242
 
        i += shift;
 
393
        if(offdata) {
 
394
            off = offset + i - BM_MIN_LENGTH + BM_BLOCK_SIZE;
 
395
            for(; offdata->pos < offdata->cnt && off >= offdata->offtab[offdata->pos]; offdata->pos++);
 
396
            if(offdata->pos == offdata->cnt || off >= offdata->offtab[offdata->pos])
 
397
                return CL_CLEAN;
 
398
            i += offdata->offtab[offdata->pos] - off;
 
399
        } else {
 
400
            i += shift;
 
401
        }
 
402
 
243
403
    }
244
404
 
245
405
    if(info.exeinfo.section)
246
406
        free(info.exeinfo.section);
247
 
 
248
407
    return CL_CLEAN;
249
408
}