~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/regex_list.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:
65
65
static int add_static_pattern(struct regex_matcher *matcher, char* pattern);
66
66
/* ---------- */
67
67
 
68
 
/* ----- shift-or filtering -------------- */
69
 
 
70
 
#define BITMAP_CONTAINS(bmap, val) ((bmap)[(val) >> 5] & (1 << ((val) & 0x1f)))
71
 
#define BITMAP_INSERT(bmap, val) ((bmap)[(val) >> 5] |= (1 << ((val) & 0x1f)))
72
 
 
73
 
static void SO_init(struct filter *m)
74
 
{
75
 
        memset(m->B, ~0, sizeof(m->B));
76
 
        memset(m->end, ~0, sizeof(m->end));
77
 
        memset(m->end_fast, ~0, sizeof(m->end_fast));
78
 
}
79
 
 
80
 
/* because we use uint32_t */
81
 
#define MAXSOPATLEN 32
82
 
 
83
 
/* merge another pattern into the filter
84
 
 * add('abc'); add('bcd'); will match [ab][bc][cd] */
85
 
static int SO_preprocess_add(struct filter *m, const unsigned char *pattern, size_t len)
86
 
{
87
 
        uint16_t q;
88
 
        uint8_t j;
89
 
 
90
 
        /* cut length, and make it modulo 2 */
91
 
        if(len > MAXSOPATLEN) {
92
 
                len = MAXSOPATLEN;
93
 
        } else {
94
 
                /* we use 2-grams, must be multiple of 2 */
95
 
                len = len & ~1;
96
 
        }
97
 
        if(!len)
98
 
                return 0;
99
 
 
100
 
        /* Shift-Or like preprocessing */
101
 
        for(j=0;j < len-1;j++) {
102
 
                /* use overlapping 2-grams. We need them overlapping because matching can start at any position */
103
 
                q = cli_readint16( &pattern[j] );
104
 
                m->B[q] &= ~(1 << j);
105
 
        }
106
 
        /* we use variable length patterns, use last character to mark pattern end,
107
 
         * can lead to false positives.*/
108
 
        /* mark that at state j, the q-gram q can end the pattern */
109
 
        if(j) {
110
 
                j--;
111
 
                m->end[q] &= ~(1 << j);
112
 
                m->end_fast[pattern[j+1]] &= ~(1<<j);
113
 
        }
114
 
        return 0;
115
 
}
116
 
 
117
 
/* this is like a FSM, with multiple active states at the same time.
118
 
 * each bit in "state" means an active state, when a char is encountered
119
 
 * we determine what states can remain active.
120
 
 * The FSM transition rules are expressed as bit-masks */
121
 
long SO_search(const struct filter *m, const unsigned char *data, unsigned long len)
122
 
{
123
 
        size_t j;
124
 
        uint32_t state = ~0;
125
 
        const uint32_t *B = m->B;
126
 
        const uint32_t *End = m->end;
127
 
        const uint32_t *EndFast = m->end_fast;
128
 
 
129
 
        /* cut length, and make it modulo 2 */
130
 
        if(len > MAXSOPATLEN) {
131
 
                len = MAXSOPATLEN;
132
 
        } else {
133
 
                /* we use 2-grams, must be multiple of 2 */
134
 
                len = len & ~1;
135
 
        }
136
 
        if(!len) return -1;
137
 
        /* Shift-Or like search algorithm */
138
 
        for(j=0;j < len-1; j++) {
139
 
                const uint16_t q0 = cli_readint16( &data[j] );
140
 
                uint32_t match_end;
141
 
                state = (state << 1) | B[q0];
142
 
                /* state marks with a 0 bit all active states
143
 
                 * End[q0] marks with a 0 bit all states where the q-gram 'q' can end a pattern
144
 
                 * if we got two 0's at matching positions, it means we encountered a pattern's end */
145
 
                match_end = state | EndFast[data[j+1]];
146
 
                if((match_end != 0xffffffff) && (state | End[q0]) !=  0xffffffff) {
147
 
                        /* note: we rely on short-circuit eval here, we only evaluate and fetch End[q0], if
148
 
                         * end_fast has matched. This reduces cache pressure on End[], and allows us to keep the working
149
 
                         * set inside L2 */
150
 
 
151
 
                        /* if state is reachable, and this character can finish a pattern, assume match */
152
 
                        /* to reduce false positives check if qgram can finish the pattern */
153
 
                        /* return position of probable match */
154
 
                        /* find first 0 starting from MSB, the position of that bit as counted from LSB, is the length of the
155
 
                         * longest pattern that could match */
156
 
                        return j >= MAXSOPATLEN  ? j - MAXSOPATLEN : 0;
157
 
                }
158
 
        }
159
 
        /* no match */
160
 
        return -1;
161
 
}
162
 
 
163
 
/* ----------------------------------------------------------- */
164
 
 
165
 
 
166
68
#define MATCH_SUCCESS 0
167
69
#define MATCH_FAILED  -1
168
70
 
289
191
                buffer[buffer_len]=0;
290
192
                cli_dbgmsg("Looking up in regex_list: %s\n", buffer);
291
193
 
292
 
                if((rc = cli_ac_initdata(&mdata, 0, 0, CLI_DEFAULT_AC_TRACKLEN)))
 
194
                if((rc = cli_ac_initdata(&mdata, 0, 0, 0, CLI_DEFAULT_AC_TRACKLEN)))
293
195
                        return rc;
294
196
 
295
197
                bufrev = cli_strdup(buffer);
296
198
                if(!bufrev)
297
199
                        return CL_EMEM;
298
200
                reverse_string(bufrev);
299
 
                rc = SO_search(&matcher->filter, (const unsigned char*)bufrev, buffer_len) != -1;
 
201
                rc = filter_search(&matcher->filter, (const unsigned char*)bufrev, buffer_len) != -1;
300
202
                if(rc == -1) {
301
203
                        free(buffer);
302
204
                        free(bufrev);
305
207
                         * negatives */
306
208
                        return 0;
307
209
                }
308
 
                rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)&regex, &res, &matcher->suffixes,&mdata,0,0,-1,NULL,AC_SCAN_VIR,NULL);
 
210
                rc = cli_ac_scanbuff((const unsigned char*)bufrev,buffer_len, NULL, (void*)&regex, &res, &matcher->suffixes,&mdata,0,0,NULL,AC_SCAN_VIR,NULL);
309
211
                free(bufrev);
310
212
                cli_ac_freedata(&mdata);
311
213
 
349
251
 
350
252
/* Initialization & loading */
351
253
/* Initializes @matcher, allocating necesarry substructures */
352
 
int init_regex_list(struct regex_matcher* matcher)
 
254
int init_regex_list(struct regex_matcher* matcher, uint8_t dconf_prefiltering)
353
255
{
354
256
#ifdef USE_MPOOL
355
257
        mpool_t *mp = matcher->mempool;
368
270
        matcher->suffixes.mempool = mp;
369
271
        assert(mp && "mempool must be initialized");
370
272
#endif
371
 
        if((rc = cli_ac_init(&matcher->suffixes, 2, 32))) {
 
273
        if((rc = cli_ac_init(&matcher->suffixes, 2, 32, dconf_prefiltering))) {
372
274
                return rc;
373
275
        }
374
276
#ifdef USE_MPOOL
381
283
        if((rc = cli_bm_init(&matcher->hostkey_prefix))) {
382
284
                return rc;
383
285
        }
384
 
        SO_init(&matcher->filter);
 
286
        filter_init(&matcher->filter);
385
287
        return CL_SUCCESS;
386
288
}
387
289
 
455
357
 
456
358
        if (fl != 'W' && pat->length == 32 &&
457
359
            cli_hashset_contains(&matcher->sha256_pfx_set, cli_readint32(pat->pattern)) &&
458
 
            cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,0,-1) == CL_VIRUS) {
 
360
            cli_bm_scanbuff(pat->pattern, 32, &vname, NULL, &matcher->sha256_hashes,0,NULL,NULL) == CL_VIRUS) {
459
361
            if (*vname == 'W') {
460
362
                /* hash is whitelisted in local.gdb */
461
363
                cli_dbgmsg("Skipping hash %s\n", pattern);
471
373
        }
472
374
        *pat->virname = fl;
473
375
        cli_hashset_addkey(&matcher->sha256_pfx_set, cli_readint32(pat->pattern));
474
 
        if((rc = cli_bm_addpatt(bm, pat))) {
 
376
        if((rc = cli_bm_addpatt(bm, pat, "*"))) {
475
377
                cli_errmsg("add_hash: failed to add BM pattern\n");
476
378
                free(pat->pattern);
477
379
                free(pat->virname);
483
385
 
484
386
 
485
387
/* Load patterns/regexes from file */
486
 
int load_regex_matcher(struct regex_matcher* matcher,FILE* fd,unsigned int *signo,unsigned int options,int is_whitelist,struct cli_dbio *dbio)
 
388
int load_regex_matcher(struct regex_matcher* matcher,FILE* fd,unsigned int *signo,unsigned int options,int is_whitelist,struct cli_dbio *dbio, uint8_t dconf_prefiltering)
487
389
{
488
390
        int rc,line=0,entry=0;
489
391
        char buffer[FILEBUFF];
499
401
 
500
402
        cli_dbgmsg("Loading regex_list\n");
501
403
        if(!matcher->list_inited) {
502
 
                rc = init_regex_list(matcher);
 
404
                rc = init_regex_list(matcher, dconf_prefiltering);
503
405
                if (!matcher->list_inited) {
504
406
                        cli_errmsg("Regex list failed to initialize!\n");
505
407
                        fatal_error(matcher);
675
577
        new->partno = 0;
676
578
        new->mindist = 0;
677
579
        new->maxdist = 0;
678
 
        new->offset = 0;
 
580
        new->offset_min = CLI_OFF_ANY;
679
581
        new->length = len;
680
582
 
681
583
        new->ch[0] = new->ch[1] |= CLI_MATCH_IGNORE;
697
599
                mpool_free(matcher->mempool, new);
698
600
                return ret;
699
601
        }
700
 
        SO_preprocess_add(&matcher->filter, (const unsigned char*)suffix, len);
 
602
        filter_add_static(&matcher->filter, (const unsigned char*)suffix, len, "regex");
701
603
        return CL_SUCCESS;
702
604
}
703
605