c85060ff |
/*
* Detect environment for bytecode.
* |
e1cbc270 |
* Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc. |
c85060ff |
*
* Authors: Török Edvin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif |
b2e7c931 |
|
60d8d2c3 |
#include "clamav.h" |
c85060ff |
#include "target.h"
#include "bytecode_detect.h"
#include "others.h"
#include <string.h>
#include <stdio.h> |
cdb69c09 |
#include <errno.h> |
c85060ff |
#ifdef HAVE_UNAME_SYSCALL
#include <sys/utsname.h>
#endif
|
288057e9 |
#define CHECK_ARCH(a) \
if (!strcmp(TARGET_ARCH_TYPE, #a)) env->arch = arch_##a |
c85060ff |
extern int have_clamjit;
static void cli_print_environment(struct cli_environment *env)
{
uint32_t id_a = env->platform_id_a;
uint32_t id_b = env->platform_id_b;
uint32_t id_c = env->platform_id_c;
/* the bytecode instruction that exactly identifies this platform */
/* the space separated groups can be a concrete value, or 0xff for ANY */
cli_dbgmsg("environment detected:\n");
cli_dbgmsg("check_platform(0x%08x, 0x%08x, 0x%08x)\n", |
288057e9 |
id_a, id_b, id_c); |
c85060ff |
cli_dbgmsg("check_platform(0x%02x %01x %01x %02x %02x," |
288057e9 |
"0x%01x %01x %02x %02x %02x,"
"0x%02x %02x %02x %02x)\n",
env->os_category, env->arch, env->compiler,
env->functionality_level,
env->dconf_level, |
c85060ff |
env->big_endian,
env->sizeof_ptr, |
288057e9 |
(env->cpp_version >> 16) & 0xff,
(env->cpp_version >> 8) & 0xff,
env->cpp_version & 0xff,
env->os_features,
(env->c_version >> 16) & 0xff,
(env->c_version >> 8) & 0xff,
env->c_version & 0xff); |
c85060ff |
cli_dbgmsg("check_platform( OS CPU COM FL DCONF,BE PTR CXX VV.VV.VV, FLG CC VV.VV.VV)\n");
cli_dbgmsg("Engine version: %s\n", env->engine_version);
cli_dbgmsg("Host triple: %s\n", env->triple);
cli_dbgmsg("Host CPU: %s\n", env->cpu);
cli_dbgmsg("OS: %s\n", env->sysname);
cli_dbgmsg("OS release: %s\n", env->release);
cli_dbgmsg("OS version: %s\n", env->version);
cli_dbgmsg("OS hardware: %s\n", env->machine);
cli_dbgmsg("OS LLVM category: %d\n", env->os);
cli_dbgmsg("Has JIT compiled: %d\n", env->has_jit_compiled);
cli_dbgmsg("------------------------------------------------------\n");
}
#ifdef __linux__
static int detect_PaX(void)
{
char line[128];
int pax = 0;
FILE *f = fopen("/proc/self/status", "r");
if (!f) |
288057e9 |
return 0; |
c85060ff |
while (fgets(line, sizeof(line), f)) { |
288057e9 |
if (!memcmp(line, "PaX:", 4)) {
pax = 1;
if (!strchr(line, 'm'))
pax = 2;
break;
} |
c85060ff |
}
fclose(f); |
e2a499a0 |
return pax; |
c85060ff |
}
static int detect_SELinux(void)
{
char line[128];
int selinux = 0;
int enforce = 0; |
288057e9 |
FILE *f = fopen("/proc/filesystems", "r"); |
cdb69c09 |
if (!f) { |
288057e9 |
f = fopen("/selinux/enforce", "r"); |
cdb69c09 |
if (!f && errno == EACCES) |
288057e9 |
return 2;
if (f) {
if (fscanf(f, "%d", &enforce) == 1)
selinux = 2;
fclose(f);
}
return selinux; |
cdb69c09 |
} |
c85060ff |
while (fgets(line, sizeof(line), f)) { |
288057e9 |
if (strstr(line, "selinuxfs\n")) {
selinux = 1;
break;
} |
c85060ff |
}
fclose(f);
if (!selinux) |
288057e9 |
return 0; |
c85060ff |
f = fopen("/selinux/enforce", "r"); |
bebd86a6 |
if (f) { |
288057e9 |
if (fscanf(f, "%d", &enforce) == 1) {
if (enforce == 1)
selinux = 2;
if (enforce == -1)
selinux = 0;
}
fclose(f); |
c85060ff |
}
return selinux;
}
static void detect_os_features(uint8_t *os_features)
{
int features = 0;
switch (detect_PaX()) { |
288057e9 |
case 2:
features |= 1 << feature_pax_mprotect;
/* fall through */
case 1:
features |= 1 << feature_pax;
break;
default:
break; |
c85060ff |
}
switch (detect_SELinux()) { |
288057e9 |
case 2:
features |= 1 << feature_selinux_enforcing;
/* fall through */
case 1:
features |= 1 << feature_selinux;
break;
default:
break; |
c85060ff |
}
*os_features = features;
}
#else
static void detect_os_features(uint8_t *os_features)
{
*os_features = 0;
}
#endif
/* OS features :
* Linux: PaX << 2| SELinux << 1| mmap-RWX
* Other: mmap-RWX */
void cli_detect_environment(struct cli_environment *env)
{
memset(env, 0, sizeof(*env));
#if WORDS_BIGENDIAN == 0
env->big_endian = 0;
#else |
288057e9 |
env->big_endian = 1; |
c85060ff |
#endif |
288057e9 |
env->sizeof_ptr = sizeof(void *); |
c85060ff |
/* -- Detect arch -- */
CHECK_ARCH(i386);
else CHECK_ARCH(x86_64); |
288057e9 |
else if (!strcmp(TARGET_ARCH_TYPE, "amd64")) env->arch = arch_x86_64;
else if (!strcmp(TARGET_ARCH_TYPE, "ppc")) env->arch = arch_ppc32; /* llvm will fix ppc64 */ |
c85060ff |
else CHECK_ARCH(arm);
else CHECK_ARCH(sparc);
else CHECK_ARCH(sparc64);
else CHECK_ARCH(mips);
else CHECK_ARCH(mips64);
else CHECK_ARCH(alpha);
else CHECK_ARCH(hppa1);
else CHECK_ARCH(hppa2);
else CHECK_ARCH(m68k);
else env->arch = arch_unknown;
/* -- Detect OS -- */
#ifdef C_AIX
env->os_category = os_aix;
#elif defined(C_BEOS)
env->os_category = os_beos;
/* DARWIN must come before BSD since it defines both */
#elif defined(C_DARWIN)
env->os_category = os_darwin;
#elif defined(C_BSD)
env->os_category = os_bsd;
#elif defined(C_GNU_HURD)
env->os_category = os_gnu_hurd;
#elif defined(C_HPUX)
env->os_category = os_hpux;
#elif defined(C_INTERIX)
env->os_category = os_interix;
#elif defined(C_IRIX)
env->os_category = os_irix;
#elif defined(C_KFREEBSD_GNU)
env->os_category = os_kfreebsd_gnu;
#elif defined(C_LINUX)
env->os_category = os_linux;
#elif defined(C_OS2)
env->os_category = os_os2;
#elif defined(C_OSF)
env->os_category = os_osf;
#elif defined(C_QNX6)
env->os_category = os_qnx6;
#elif defined(C_SOLARIS)
env->os_category = os_solaris;
#elif defined(_WIN64)
env->os_category = os_win64;
#elif defined(_WIN32)
env->os_category = os_win32;
#else
env->os_category = os_generic;
#endif
env->os = llvm_os_UnknownOS;
/* -- Detect compiler -- */
/* check GNUC last, because some other compilers might define it */
#ifdef __INTEL_COMPILER |
288057e9 |
env->compiler = compiler_intel; |
c85060ff |
env->c_version = __INTEL_COMPILER;
#elif defined(_MSC_VER) |
288057e9 |
env->compiler = compiler_msc; |
c85060ff |
env->c_version = _MSC_VER;
#elif defined(__SUNPRO_C) |
288057e9 |
env->compiler = compiler_sun;
env->c_version = __SUNPRO_C; |
c85060ff |
#elif defined(__GNUC__)
#ifdef __clang__ |
288057e9 |
env->compiler = compiler_clang; |
c85060ff |
#elif defined(__llvm__)
env->compiler = compiler_llvm;
#else
env->compiler = compiler_gnuc;
#endif
env->c_version = |
288057e9 |
MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); |
c85060ff |
#else |
288057e9 |
env->compiler = compiler_other;
env->c_version = 0; |
c85060ff |
#endif
env->cpp_version = 0;
env->has_jit_compiled = have_clamjit;
/* engine */
env->functionality_level = cl_retflevel(); |
288057e9 |
env->dconf_level = CL_FLEVEL_DCONF; |
c85060ff |
INIT_STRFIELD(env->engine_version, cl_retver());
#ifdef HAVE_UNAME_SYSCALL
{ |
288057e9 |
struct utsname name;
if (uname(&name) == 0) {
INIT_STRFIELD(env->sysname, name.sysname);
INIT_STRFIELD(env->release, name.release);
INIT_STRFIELD(env->version, name.version);
INIT_STRFIELD(env->machine, name.machine);
} |
c85060ff |
}
#endif
#ifdef _WIN32
{ |
288057e9 |
OSVERSIONINFOEX info;
info.dwOSVersionInfoSize = sizeof(info);
if (GetVersionEx((OSVERSIONINFO *)&info) != 0 && info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
if (info.wProductType == VER_NT_WORKSTATION)
INIT_STRFIELD(env->sysname, "Microsoft Windows");
else
INIT_STRFIELD(env->sysname, "Microsoft Windows Server");
snprintf((char *)env->release, sizeof(env->release), "%d.%d SP%d.%d",
info.dwMajorVersion, info.dwMinorVersion,
info.wServicePackMajor, info.wServicePackMinor);
snprintf((char *)env->version, sizeof(env->version), "Build %d",
info.dwBuildNumber);
} |
c85060ff |
} |
288057e9 |
|
c85060ff |
#endif
if (!env->sysname[0]) { |
288057e9 |
INIT_STRFIELD(env->sysname, TARGET_OS_TYPE); |
c85060ff |
}
detect_os_features(&env->os_features);
cli_detect_env_jit(env);
env->platform_id_a = (env->os_category << 24) | (env->arch << 20) | |
288057e9 |
(env->compiler << 16) | (env->functionality_level << 8) |
(env->dconf_level); |
c85060ff |
env->platform_id_b = (env->big_endian << 28) | (env->sizeof_ptr << 24) | |
288057e9 |
env->cpp_version; |
c85060ff |
env->platform_id_c = (env->os_features << 24) | env->c_version;
cli_print_environment(env);
} |