~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/bytecode_api.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
/*
 
2
 *  ClamAV bytecode internal API
 
3
 *
 
4
 *  Copyright (C) 2009-2010 Sourcefire, Inc.
 
5
 *
 
6
 *  Authors: Török Edvin
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License version 2 as
 
10
 *  published by the Free Software Foundation.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, write to the Free Software
 
19
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
20
 *  MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "clamav-config.h"
 
25
#endif
 
26
 
 
27
#ifdef HAVE_UNISTD_H
 
28
#include <unistd.h>
 
29
#endif
 
30
#include <stdlib.h>
 
31
#include <fcntl.h>
 
32
#include <errno.h>
 
33
#include <string.h>
 
34
#include "cltypes.h"
 
35
#include "clambc.h"
 
36
#include "bytecode.h"
 
37
#include "bytecode_priv.h"
 
38
#include "type_desc.h"
 
39
#include "bytecode_api.h"
 
40
#include "bytecode_api_impl.h"
 
41
#include "others.h"
 
42
#include "pe.h"
 
43
#include "disasm.h"
 
44
 
 
45
uint32_t cli_bcapi_test1(struct cli_bc_ctx *ctx, uint32_t a, uint32_t b)
 
46
{
 
47
    return (a==0xf00dbeef && b==0xbeeff00d) ? 0x12345678 : 0x55;
 
48
}
 
49
 
 
50
uint32_t cli_bcapi_test2(struct cli_bc_ctx *ctx, uint32_t a)
 
51
{
 
52
    return a == 0xf00d ? 0xd00f : 0x5555;
 
53
}
 
54
 
 
55
int32_t cli_bcapi_read(struct cli_bc_ctx* ctx, uint8_t *data, int32_t size)
 
56
{
 
57
    int n;
 
58
    if (!ctx->fmap)
 
59
        return -1;
 
60
    if (size < 0) {
 
61
        cli_errmsg("bytecode: negative read size: %d\n", size);
 
62
        return -1;
 
63
    }
 
64
    n = fmap_readn(ctx->fmap, data, ctx->off, size);
 
65
    if (n <= 0)
 
66
        return n;
 
67
    ctx->off += n;
 
68
    return n;
 
69
}
 
70
 
 
71
int32_t cli_bcapi_seek(struct cli_bc_ctx* ctx, int32_t pos, uint32_t whence)
 
72
{
 
73
    off_t off;
 
74
    if (!ctx->fmap)
 
75
        return -1;
 
76
    switch (whence) {
 
77
        case 0:
 
78
            off = pos;
 
79
            break;
 
80
        case 1:
 
81
            off = ctx->off + pos;
 
82
            break;
 
83
        case 2:
 
84
            off = ctx->file_size + pos;
 
85
            break;
 
86
    }
 
87
    if (off < 0 || off > ctx->file_size)
 
88
        return -1;
 
89
    ctx->off = off;
 
90
    return off;
 
91
}
 
92
 
 
93
uint32_t cli_bcapi_debug_print_str(struct cli_bc_ctx *ctx, const uint8_t *str, uint32_t len)
 
94
{
 
95
    cli_dbgmsg("bytecode debug: %s\n", str);
 
96
    return 0;
 
97
}
 
98
 
 
99
uint32_t cli_bcapi_debug_print_uint(struct cli_bc_ctx *ctx, uint32_t a)
 
100
{
 
101
    cli_dbgmsg("bytecode debug: %u\n", a);
 
102
    return 0;
 
103
}
 
104
 
 
105
/*TODO: compiler should make sure that only constants are passed here, and not
 
106
 * pointers to arbitrary locations that may not be valid when bytecode finishes
 
107
 * executing */
 
108
uint32_t cli_bcapi_setvirusname(struct cli_bc_ctx* ctx, const uint8_t *name, uint32_t len)
 
109
{
 
110
    ctx->virname = name;
 
111
    return 0;
 
112
}
 
113
 
 
114
uint32_t cli_bcapi_disasm_x86(struct cli_bc_ctx *ctx, struct DISASM_RESULT *res, uint32_t len)
 
115
{
 
116
    int n;
 
117
    const char *buf;
 
118
    const char* next;
 
119
    if (!res || !ctx->fmap || ctx->off >= ctx->fmap->len)
 
120
        return -1;
 
121
    /* 32 should be longest instr we support decoding.
 
122
     * When we'll support mmx/sse instructions this should be updated! */
 
123
    n = MIN(32, ctx->fmap->len - ctx->off);
 
124
    buf = fmap_need_off_once(ctx->fmap, ctx->off, n);
 
125
    next = cli_disasm_one(buf, n, res, 0);
 
126
    if (!next)
 
127
        return -1;
 
128
    return ctx->off + next - buf;
 
129
}
 
130
 
 
131
/* TODO: field in ctx, id of last bytecode that called magicscandesc, reset
 
132
 * after hooks/other bytecodes are run. TODO: need a more generic solution
 
133
 * to avoid uselessly recursing on bytecode-unpacked files, but also a way to
 
134
 * override the limit if we need it in a special situation */
 
135
int32_t cli_bcapi_write(struct cli_bc_ctx *ctx, uint8_t*data, int32_t len)
 
136
{
 
137
    int32_t res;
 
138
    cli_ctx *cctx = (cli_ctx*)ctx->ctx;
 
139
    if (len < 0) {
 
140
        cli_warnmsg("Bytecode API: called with negative length!\n");
 
141
        return -1;
 
142
    }
 
143
    if (ctx->outfd == -1) {
 
144
        ctx->tempfile = cli_gentemp(cctx ? cctx->engine->tmpdir : NULL);
 
145
        if (!ctx->tempfile) {
 
146
            cli_dbgmsg("Bytecode API: Unable to allocate memory for tempfile\n");
 
147
            return -1;
 
148
        }
 
149
        ctx->outfd = open(ctx->tempfile, O_RDWR|O_CREAT|O_EXCL|O_TRUNC|O_BINARY, 0600);
 
150
        if (ctx->outfd == -1) {
 
151
            cli_warnmsg("Bytecode API: Can't create file %s\n", ctx->tempfile);
 
152
            free(ctx->tempfile);
 
153
            return -1;
 
154
        }
 
155
    }
 
156
    if (cli_checklimits("bytecode api", cctx, ctx->written + len, 0, 0))
 
157
        return -1;
 
158
    res = cli_writen(ctx->outfd, data, len);
 
159
    if (res > 0) ctx->written += res;
 
160
    if (res == -1)
 
161
            cli_dbgmsg("Bytecode API: write failed: %d\n", errno);
 
162
    return res;
 
163
}
 
164
 
 
165
void cli_bytecode_context_set_trace(struct cli_bc_ctx* ctx, unsigned level,
 
166
                                    bc_dbg_callback_trace trace,
 
167
                                    bc_dbg_callback_trace_op trace_op,
 
168
                                    bc_dbg_callback_trace_val trace_val,
 
169
                                    bc_dbg_callback_trace_ptr trace_ptr)
 
170
{
 
171
    ctx->trace = trace;
 
172
    ctx->trace_op = trace_op;
 
173
    ctx->trace_val = trace_val;
 
174
    ctx->trace_ptr = trace_ptr;
 
175
    ctx->trace_level = level;
 
176
}
 
177
 
 
178
uint32_t cli_bcapi_trace_scope(struct cli_bc_ctx *ctx, const uint8_t *scope, uint32_t scopeid)
 
179
{
 
180
    if (LIKELY(!ctx->trace_level))
 
181
        return 0;
 
182
    if (ctx->scope != (const char*)scope) {
 
183
        ctx->scope = (const char*)scope ? (const char*)scope : "?";
 
184
        ctx->scopeid = scopeid;
 
185
        ctx->trace_level |= 0x80;/* temporarely increase level to print params */
 
186
    } else if ((ctx->trace_level >= trace_scope) && ctx->scopeid != scopeid) {
 
187
        ctx->scopeid = scopeid;
 
188
        ctx->trace_level |= 0x40;/* temporarely increase level to print location */
 
189
    }
 
190
    return 0;
 
191
}
 
192
 
 
193
uint32_t cli_bcapi_trace_directory(struct cli_bc_ctx *ctx, const uint8_t* dir, uint32_t dummy)
 
194
{
 
195
    if (LIKELY(!ctx->trace_level))
 
196
        return 0;
 
197
    ctx->directory = (const char*)dir ? (const char*)dir : "";
 
198
    return 0;
 
199
}
 
200
 
 
201
uint32_t cli_bcapi_trace_source(struct cli_bc_ctx *ctx, const uint8_t *file, uint32_t line)
 
202
{
 
203
    if (LIKELY(ctx->trace_level < trace_line))
 
204
        return 0;
 
205
    if (ctx->file != (const char*)file || ctx->line != line) {
 
206
        ctx->col = 0;
 
207
        ctx->file =(const char*)file ? (const char*)file : "??";
 
208
        ctx->line = line;
 
209
    }
 
210
    return 0;
 
211
}
 
212
 
 
213
uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const uint8_t *op, uint32_t col)
 
214
{
 
215
    if (LIKELY(ctx->trace_level < trace_col))
 
216
        return 0;
 
217
    if (ctx->trace_level&0xc0) {
 
218
        ctx->col = col;
 
219
        /* func/scope changed and they needed param/location event */
 
220
        ctx->trace(ctx, (ctx->trace_level&0x80) ? trace_func : trace_scope);
 
221
        ctx->trace_level &= ~0xc0;
 
222
    }
 
223
    if (LIKELY(ctx->trace_level < trace_col))
 
224
        return 0;
 
225
    if (ctx->col != col) {
 
226
        ctx->col = col;
 
227
        ctx->trace(ctx, trace_col);
 
228
    } else {
 
229
        ctx->trace(ctx, trace_line);
 
230
    }
 
231
    if (LIKELY(ctx->trace_level < trace_op))
 
232
        return 0;
 
233
    if (ctx->trace_op && op)
 
234
        ctx->trace_op(ctx, (const char*)op);
 
235
    return 0;
 
236
}
 
237
 
 
238
uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const uint8_t* name, uint32_t value)
 
239
{
 
240
    if (LIKELY(ctx->trace_level < trace_val))
 
241
        return 0;
 
242
    if (ctx->trace_level&0x80) {
 
243
        if ((ctx->trace_level&0x7f) < trace_param)
 
244
            return 0;
 
245
        ctx->trace(ctx, trace_param);
 
246
    }
 
247
    if (ctx->trace_val && name)
 
248
        ctx->trace_val(ctx, name, value);
 
249
    return 0;
 
250
}
 
251
 
 
252
uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const uint8_t* ptr, uint32_t dummy)
 
253
{
 
254
    if (LIKELY(ctx->trace_level < trace_val))
 
255
        return 0;
 
256
    if (ctx->trace_level&0x80) {
 
257
        if ((ctx->trace_level&0x7f) < trace_param)
 
258
            return 0;
 
259
        ctx->trace(ctx, trace_param);
 
260
    }
 
261
    if (ctx->trace_ptr)
 
262
        ctx->trace_ptr(ctx, ptr);
 
263
    return 0;
 
264
}
 
265
 
 
266
uint32_t cli_bcapi_pe_rawaddr(struct cli_bc_ctx *ctx, uint32_t rva)
 
267
{
 
268
  uint32_t ret;
 
269
  int err = 0;
 
270
  const struct cli_pe_hook_data *pe = ctx->hooks.pedata;
 
271
  ret = cli_rawaddr(rva, ctx->sections, pe->nsections, &err,
 
272
                    ctx->file_size, pe->hdr_size);
 
273
  if (err)
 
274
    return PE_INVALID_RVA;
 
275
  return ret;
 
276
}
 
277
 
 
278
static inline const char* cli_memmem(const char *haystack, unsigned hlen,
 
279
                                     const unsigned char *needle, unsigned nlen)
 
280
{
 
281
    const char *p;
 
282
    unsigned char c;
 
283
    if (!needle || !haystack)
 
284
        return NULL;
 
285
    c = *needle++;
 
286
    if (nlen == 1)
 
287
        return memchr(haystack, c, hlen);
 
288
 
 
289
    while (hlen >= nlen) {
 
290
        p = haystack;
 
291
        haystack = memchr(haystack, c, hlen - nlen + 1);
 
292
        if (!haystack)
 
293
            return NULL;
 
294
        p = haystack + 1;
 
295
        if (!memcmp(p, needle, nlen-1))
 
296
            return haystack;
 
297
        hlen -= p - haystack;
 
298
        haystack = p;
 
299
    }
 
300
    return NULL;
 
301
}
 
302
 
 
303
int32_t cli_bcapi_file_find(struct cli_bc_ctx *ctx, const uint8_t* data, uint32_t len)
 
304
{
 
305
    char buf[4096];
 
306
    fmap_t *map = ctx->fmap;
 
307
    uint32_t off = ctx->off, newoff;
 
308
    int n;
 
309
 
 
310
    if (!map || len > sizeof(buf)/4 || len <= 0)
 
311
        return -1;
 
312
    for (;;) {
 
313
        const char *p;
 
314
        n = fmap_readn(map, buf, off, sizeof(buf));
 
315
        if ((unsigned)n < len)
 
316
            return -1;
 
317
        p = cli_memmem(buf, n, data, len);
 
318
        if (p)
 
319
            return off + p - buf;
 
320
        off += n-len;
 
321
    }
 
322
    return -1;
 
323
}
 
324
 
 
325
int32_t cli_bcapi_file_byteat(struct cli_bc_ctx *ctx, uint32_t off)
 
326
{
 
327
    unsigned char c;
 
328
    if (!ctx->fmap)
 
329
        return -1;
 
330
    if (fmap_readn(ctx->fmap, &c, off, 1) != 1)
 
331
        return -1;
 
332
    return c;
 
333
}
 
334
 
 
335
uint8_t* cli_bcapi_malloc(struct cli_bc_ctx *ctx, uint32_t size)
 
336
{
 
337
#if USE_MPOOL
 
338
    if (!ctx->mpool) {
 
339
        ctx->mpool = mpool_create();
 
340
        if (!ctx->mpool) {
 
341
            cli_dbgmsg("bytecode: mpool_create failed!\n");
 
342
            return NULL;
 
343
        }
 
344
    }
 
345
    return mpool_malloc(ctx->mpool, size);
 
346
#else
 
347
    /* TODO: implement using a list of pointers we allocated! */
 
348
    cli_errmsg("cli_bcapi_malloc not implemented for systems without mmap yet!\n");
 
349
    return cli_malloc(size);
 
350
#endif
 
351
}
 
352
 
 
353
int32_t cli_bcapi_get_pe_section(struct cli_bc_ctx *ctx, struct cli_exe_section* section, uint32_t num)
 
354
{
 
355
    if (num < ctx->hooks.pedata->nsections) {
 
356
        memcpy(section, &ctx->sections[num], sizeof(*section));
 
357
        return 0;
 
358
    }
 
359
    return -1;
 
360
}