~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/bytecode_detect.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Detect environment for bytecode.
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
 
#if HAVE_CONFIG_H
24
 
#include "clamav-config.h"
25
 
#endif
26
 
#include "target.h"
27
 
#include "cltypes.h"
28
 
 
29
 
#include "bytecode_detect.h"
30
 
#include "others.h"
31
 
#include <string.h>
32
 
#include <stdio.h>
33
 
#include <errno.h>
34
 
 
35
 
#ifdef HAVE_UNAME_SYSCALL
36
 
#include <sys/utsname.h>
37
 
#endif
38
 
 
39
 
#define CHECK_ARCH(a) if (!strcmp(TARGET_ARCH_TYPE, #a)) env->arch = arch_##a
40
 
 
41
 
extern int have_clamjit;
42
 
 
43
 
static void cli_print_environment(struct cli_environment *env)
44
 
{
45
 
    uint32_t id_a = env->platform_id_a;
46
 
    uint32_t id_b = env->platform_id_b;
47
 
    uint32_t id_c = env->platform_id_c;
48
 
    /* the bytecode instruction that exactly identifies this platform */
49
 
    /* the space separated groups can be a concrete value, or 0xff for ANY */
50
 
    cli_dbgmsg("environment detected:\n");
51
 
    cli_dbgmsg("check_platform(0x%08x, 0x%08x, 0x%08x)\n",
52
 
               id_a, id_b, id_c);
53
 
    cli_dbgmsg("check_platform(0x%02x  %01x  %01x  %02x  %02x,"
54
 
               "0x%01x  %01x       %02x %02x %02x,"
55
 
               "0x%02x    %02x %02x %02x)\n",
56
 
               env->os_category, env->arch, env->compiler,
57
 
               env->functionality_level,
58
 
               env->dconf_level,
59
 
               env->big_endian,
60
 
               env->sizeof_ptr,
61
 
               (env->cpp_version >> 16)&0xff,
62
 
               (env->cpp_version >> 8)&0xff,
63
 
               env->cpp_version&0xff,
64
 
               env->os_features,
65
 
               (env->c_version >> 16)&0xff,
66
 
               (env->c_version >> 8)&0xff,
67
 
               env->c_version&0xff);
68
 
    cli_dbgmsg("check_platform( OS CPU COM FL DCONF,BE PTR CXX VV.VV.VV, FLG CC VV.VV.VV)\n");
69
 
    cli_dbgmsg("Engine version: %s\n", env->engine_version);
70
 
    cli_dbgmsg("Host triple: %s\n", env->triple);
71
 
    cli_dbgmsg("Host CPU: %s\n", env->cpu);
72
 
    cli_dbgmsg("OS: %s\n", env->sysname);
73
 
    cli_dbgmsg("OS release: %s\n", env->release);
74
 
    cli_dbgmsg("OS version: %s\n", env->version);
75
 
    cli_dbgmsg("OS hardware: %s\n", env->machine);
76
 
    cli_dbgmsg("OS LLVM category: %d\n", env->os);
77
 
    cli_dbgmsg("Has JIT compiled: %d\n", env->has_jit_compiled);
78
 
    cli_dbgmsg("------------------------------------------------------\n");
79
 
}
80
 
 
81
 
#ifdef __linux__
82
 
 
83
 
static int detect_PaX(void)
84
 
{
85
 
    char line[128];
86
 
    int pax = 0;
87
 
    FILE *f = fopen("/proc/self/status", "r");
88
 
    if (!f)
89
 
        return 0;
90
 
    while (fgets(line, sizeof(line), f)) {
91
 
        if (!memcmp(line, "PaX:", 4)) {
92
 
            pax = 1;
93
 
            if (!strchr(line,'m'))
94
 
                pax = 2;
95
 
            break;
96
 
        }
97
 
    }
98
 
    fclose(f);
99
 
    return pax;
100
 
}
101
 
 
102
 
static int detect_SELinux(void)
103
 
{
104
 
    char line[128];
105
 
    int selinux = 0;
106
 
    int enforce = 0;
107
 
    FILE *f = fopen("/proc/filesystems", "r");
108
 
    if (!f) {
109
 
        f = fopen("/selinux/enforce", "r");
110
 
        if (!f && errno == EACCES)
111
 
                return 2;
112
 
        if (f) {
113
 
            if (fscanf(f, "%d", &enforce) == 1)
114
 
                selinux = 2;
115
 
            fclose(f);
116
 
        }
117
 
        return selinux;
118
 
    }
119
 
    while (fgets(line, sizeof(line), f)) {
120
 
        if (strstr(line, "selinuxfs\n")) {
121
 
            selinux = 1;
122
 
            break;
123
 
        }
124
 
    }
125
 
    fclose(f);
126
 
    if (!selinux)
127
 
        return 0;
128
 
 
129
 
    f = fopen("/selinux/enforce", "r");
130
 
    if (f && fscanf(f, "%d", &enforce) == 1) {
131
 
        if (enforce == 1)
132
 
            selinux = 2;
133
 
        if (enforce == -1)
134
 
            selinux = 0;
135
 
        fclose(f);
136
 
    }
137
 
    return selinux;
138
 
}
139
 
 
140
 
static void detect_os_features(uint8_t *os_features)
141
 
{
142
 
    int features = 0;
143
 
    switch (detect_PaX()) {
144
 
        case 2:
145
 
            features |= 1 << feature_pax_mprotect;
146
 
            /* fall through */
147
 
        case 1:
148
 
            features |= 1 << feature_pax;
149
 
            break;
150
 
        default:
151
 
            break;
152
 
    }
153
 
    switch (detect_SELinux()) {
154
 
        case 2:
155
 
            features |= 1 << feature_selinux_enforcing;
156
 
            /* fall through */
157
 
        case 1:
158
 
            features |= 1 << feature_selinux;
159
 
            break;
160
 
        default:
161
 
            break;
162
 
    }
163
 
 
164
 
    *os_features = features;
165
 
}
166
 
#else
167
 
static void detect_os_features(uint8_t *os_features)
168
 
{
169
 
    *os_features = 0;
170
 
}
171
 
#endif
172
 
 
173
 
/* OS features : 
174
 
 * Linux: PaX << 2| SELinux << 1| mmap-RWX
175
 
 * Other:                         mmap-RWX */
176
 
 
177
 
void cli_detect_environment(struct cli_environment *env)
178
 
{
179
 
    memset(env, 0, sizeof(*env));
180
 
#if WORDS_BIGENDIAN == 0
181
 
    env->big_endian = 0;
182
 
#else
183
 
    env->big_endian = 1;
184
 
#endif
185
 
    env->sizeof_ptr = sizeof(void*);
186
 
 
187
 
    /* -- Detect arch -- */
188
 
    CHECK_ARCH(i386);
189
 
    else CHECK_ARCH(x86_64);
190
 
    else if (!strcmp(TARGET_ARCH_TYPE,"amd64")) env->arch = arch_x86_64;
191
 
    else if (!strcmp(TARGET_ARCH_TYPE,"ppc")) env->arch = arch_ppc32;/* llvm will fix ppc64 */
192
 
    else CHECK_ARCH(arm);
193
 
    else CHECK_ARCH(sparc);
194
 
    else CHECK_ARCH(sparc64);
195
 
    else CHECK_ARCH(mips);
196
 
    else CHECK_ARCH(mips64);
197
 
    else CHECK_ARCH(alpha);
198
 
    else CHECK_ARCH(hppa1);
199
 
    else CHECK_ARCH(hppa2);
200
 
    else CHECK_ARCH(m68k);
201
 
    else env->arch = arch_unknown;
202
 
 
203
 
    /* -- Detect OS -- */
204
 
#ifdef C_AIX
205
 
    env->os_category = os_aix;
206
 
#elif defined(C_BEOS)
207
 
    env->os_category = os_beos;
208
 
    /* DARWIN must come before BSD since it defines both */
209
 
#elif defined(C_DARWIN)
210
 
    env->os_category = os_darwin;
211
 
#elif defined(C_BSD)
212
 
    env->os_category = os_bsd;
213
 
#elif defined(C_GNU_HURD)
214
 
    env->os_category = os_gnu_hurd;
215
 
#elif defined(C_HPUX)
216
 
    env->os_category = os_hpux;
217
 
#elif defined(C_INTERIX)
218
 
    env->os_category = os_interix;
219
 
#elif defined(C_IRIX)
220
 
    env->os_category = os_irix;
221
 
#elif defined(C_KFREEBSD_GNU)
222
 
    env->os_category = os_kfreebsd_gnu;
223
 
#elif defined(C_LINUX)
224
 
    env->os_category = os_linux;
225
 
#elif defined(C_OS2)
226
 
    env->os_category = os_os2;
227
 
#elif defined(C_OSF)
228
 
    env->os_category = os_osf;
229
 
#elif defined(C_QNX6)
230
 
    env->os_category = os_qnx6;
231
 
#elif defined(C_SOLARIS)
232
 
    env->os_category = os_solaris;
233
 
#elif defined(_WIN64)
234
 
    env->os_category = os_win64;
235
 
#elif defined(_WIN32)
236
 
    env->os_category = os_win32;
237
 
#else
238
 
    env->os_category = os_generic;
239
 
#endif
240
 
 
241
 
    env->os = llvm_os_UnknownOS;
242
 
    /* -- Detect compiler -- */
243
 
 
244
 
    /* check GNUC last, because some other compilers might define it */
245
 
#ifdef __INTEL_COMPILER
246
 
    env->compiler = compiler_intel;
247
 
    env->c_version = __INTEL_COMPILER;
248
 
#elif defined(_MSC_VER)
249
 
    env->compiler = compiler_msc;
250
 
    env->c_version = _MSC_VER;
251
 
#elif defined(__SUNPRO_C)
252
 
    env->compiler = compiler_sun;
253
 
    env->c_version = __SUNPRO_C;
254
 
#elif defined(__GNUC__)
255
 
 
256
 
#ifdef __clang__
257
 
    env->compiler = compiler_clang;
258
 
#elif defined(__llvm__)
259
 
    env->compiler = compiler_llvm;
260
 
#else
261
 
    env->compiler = compiler_gnuc;
262
 
#endif
263
 
    env->c_version =
264
 
        MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
265
 
 
266
 
#else
267
 
    env->compiler = compiler_other;
268
 
    env->c_version = 0;
269
 
#endif
270
 
    env->cpp_version = 0;
271
 
 
272
 
    env->has_jit_compiled = have_clamjit;
273
 
 
274
 
    /* engine */
275
 
    env->functionality_level = cl_retflevel();
276
 
    env->dconf_level = CL_FLEVEL_DCONF;
277
 
 
278
 
    INIT_STRFIELD(env->engine_version, cl_retver());
279
 
#ifdef HAVE_UNAME_SYSCALL
280
 
    {
281
 
        struct utsname name;
282
 
        if (uname(&name) == 0) {
283
 
            INIT_STRFIELD(env->sysname, name.sysname);
284
 
            INIT_STRFIELD(env->release, name.release);
285
 
            INIT_STRFIELD(env->version, name.version);
286
 
            INIT_STRFIELD(env->machine, name.machine);
287
 
        }
288
 
    }
289
 
#endif
290
 
#ifdef _WIN32
291
 
    {
292
 
        OSVERSIONINFOEX info;
293
 
        info.dwOSVersionInfoSize = sizeof(info);
294
 
        if (GetVersionEx((OSVERSIONINFO *)&info) != 0 && info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
295
 
            if (info.wProductType == VER_NT_WORKSTATION)
296
 
                INIT_STRFIELD(env->sysname, "Microsoft Windows");
297
 
            else
298
 
                INIT_STRFIELD(env->sysname, "Microsoft Windows Server");
299
 
            snprintf((char*)env->release, sizeof(env->release), "%d.%d SP%d.%d",
300
 
                     info.dwMajorVersion, info.dwMinorVersion,
301
 
                     info.wServicePackMajor, info.wServicePackMinor);
302
 
            snprintf((char*)env->version, sizeof(env->version),"Build %d",
303
 
                     info.dwBuildNumber);
304
 
        }
305
 
    }
306
 
    
307
 
#endif
308
 
    if (!env->sysname[0]) {
309
 
        INIT_STRFIELD(env->sysname, TARGET_OS_TYPE);
310
 
    }
311
 
 
312
 
    detect_os_features(&env->os_features);
313
 
 
314
 
    cli_detect_env_jit(env);
315
 
 
316
 
    env->platform_id_a = (env->os_category << 24) | (env->arch << 20) |
317
 
        (env->compiler << 16) | (env->functionality_level << 8) |
318
 
        (env->dconf_level);
319
 
    env->platform_id_b = (env->big_endian << 28) | (env->sizeof_ptr << 24) |
320
 
      env->cpp_version;
321
 
    env->platform_id_c = (env->os_features << 24) | env->c_version;
322
 
    cli_print_environment(env);
323
 
}