| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  JIT detection for ClamAV bytecode. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-03-19 15:12:26 -07:00
										 |  |  |  *  Copyright (C) 2013-2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | 
					
						
							| 
									
										
										
										
											2019-01-25 10:15:50 -05:00
										 |  |  |  *  Copyright (C) 2010-2013 Sourcefire, Inc. | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "llvm/ADT/Triple.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-23 04:28:38 -07:00
										 |  |  | #include "llvm/Config/llvm-config.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | #include "llvm/Support/raw_ostream.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-28 16:14:58 -04:00
										 |  |  | #if LLVM_VERSION < 29
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | #include "llvm/System/DataTypes.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-28 16:14:58 -04:00
										 |  |  | #include "llvm/System/Host.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | #include "llvm/System/Memory.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-28 16:14:58 -04:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #include "llvm/Support/DataTypes.h"
 | 
					
						
							|  |  |  | #include "llvm/Support/Host.h"
 | 
					
						
							|  |  |  | #include "llvm/Support/Memory.h"
 | 
					
						
							| 
									
										
										
										
											2011-05-06 15:18:32 +03:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | extern "C" { | 
					
						
							|  |  |  | #include "bytecode_detect.h"
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace llvm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void warn_assumptions(const char *msg, int a, int b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-08-05 12:08:13 +02:00
										 |  |  |     errs() << "LibClamAV Warning: libclamav and llvm make inconsistent " | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	<< "assumptions about " << msg << ": " << | 
					
						
							|  |  |  | 	a << " and " << b << "." | 
					
						
							| 
									
										
										
										
											2018-03-27 13:06:46 -04:00
										 |  |  | 	<< "Please report to https://bugzilla.clamav.net\n"; | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CASE_OS(theos, compat) case Triple::theos:\
 | 
					
						
							|  |  |  |     env->os = llvm_os_##theos;\ | 
					
						
							|  |  |  |     if (env->os_category != compat)\ | 
					
						
							|  |  |  |         warn_assumptions("Operating System", env->os_category, Triple::theos);\ | 
					
						
							|  |  |  |     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void cli_detect_env_jit(struct cli_environment *env) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #if LLVM_VERSION < 31
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |     std::string host_triple = sys::getHostTriple(); | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     std::string host_triple = sys::getDefaultTargetTriple(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |     INIT_STRFIELD(env->triple, host_triple.c_str()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::string cpu = sys::getHostCPUName(); | 
					
						
							|  |  |  |     INIT_STRFIELD(env->cpu, cpu.c_str()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #if LLVM_VERSION < 33
 | 
					
						
							| 
									
										
										
										
											2010-07-29 22:17:30 +03:00
										 |  |  |     if (env->big_endian != (int)sys::isBigEndianHost()) { | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	warn_assumptions("host endianness", env->big_endian, sys::isBigEndianHost()); | 
					
						
							|  |  |  | 	env->big_endian = sys::isBigEndianHost(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     if (env->big_endian != (int)sys::IsBigEndianHost) { | 
					
						
							|  |  |  | 	warn_assumptions("host endianness", env->big_endian, sys::IsBigEndianHost); | 
					
						
							|  |  |  | 	env->big_endian = sys::IsBigEndianHost; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef __GNUC__
 | 
					
						
							|  |  |  |     env->cpp_version = MAKE_VERSION(0, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); | 
					
						
							|  |  |  | #elif defined (__INTEL_COMPILER)
 | 
					
						
							|  |  |  |     env->cpp_version = __INTEL_COMPILER; | 
					
						
							|  |  |  | #elif defined (_MSC_VER)
 | 
					
						
							|  |  |  |     env->cpp_version = _MSC_VER; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Triple triple(host_triple); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // CPU architecture
 | 
					
						
							|  |  |  |     enum Triple::ArchType arch = triple.getArch(); | 
					
						
							|  |  |  |     enum arch_list earch; | 
					
						
							|  |  |  |     bool conflicts = false; | 
					
						
							|  |  |  |     switch (arch) { | 
					
						
							|  |  |  | 	case Triple::arm: | 
					
						
							|  |  |  | 	    earch = arch_arm; | 
					
						
							|  |  |  | 	    if (env->arch != earch) conflicts = true; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	case Triple::ppc: | 
					
						
							|  |  |  | 	    earch = arch_ppc32; | 
					
						
							| 
									
										
										
										
											2010-08-09 19:47:32 +03:00
										 |  |  | 	    if (env->arch != earch && | 
					
						
							|  |  |  | 		env->arch != arch_ppc64) conflicts = true; | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	    break; | 
					
						
							|  |  |  | 	case Triple::ppc64: | 
					
						
							|  |  |  | 	    earch = arch_ppc64; | 
					
						
							|  |  |  | 	    // ppc64 is fixed up by llvm
 | 
					
						
							|  |  |  | 	    if (env->arch != arch_ppc32 && | 
					
						
							|  |  |  | 		env->arch != arch_ppc64) conflicts = true; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	case Triple::x86: | 
					
						
							|  |  |  | 	    earch = arch_i386; | 
					
						
							| 
									
										
										
										
											2010-08-09 19:47:32 +03:00
										 |  |  | 	    if (env->arch != earch) { | 
					
						
							|  |  |  | 		/* bb #2153 */ | 
					
						
							| 
									
										
										
										
											2010-08-31 10:36:52 +03:00
										 |  |  | 		if (env->arch != arch_x86_64) | 
					
						
							| 
									
										
										
										
											2010-08-09 19:47:32 +03:00
										 |  |  | 		    conflicts = true; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	    break; | 
					
						
							|  |  |  | 	case Triple::x86_64: | 
					
						
							|  |  |  | 	    earch = arch_x86_64; | 
					
						
							| 
									
										
										
										
											2010-08-09 19:47:32 +03:00
										 |  |  | 	    if (env->arch != earch) { | 
					
						
							| 
									
										
										
										
											2010-08-18 11:01:33 +03:00
										 |  |  | 		/* bb #2153, bb #2214 */ | 
					
						
							|  |  |  | 		/* configure can't detect -m32, so it thinks we are x86_64, when
 | 
					
						
							|  |  |  | 		 * in fact we are i386 only. | 
					
						
							|  |  |  | 		 * LLVM correctly detects which one it is using preprocessor | 
					
						
							|  |  |  | 		 * macros, so don't warn here, startup.cbc will just have to | 
					
						
							|  |  |  | 		 * rely on the LLVM provided info, and not the configure | 
					
						
							|  |  |  | 		 * provided one! */ | 
					
						
							|  |  |  | 		if (env->arch != arch_i386) | 
					
						
							| 
									
										
										
										
											2010-08-09 19:47:32 +03:00
										 |  |  | 		    conflicts = true; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	    break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 	    earch = arch_unknown; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-10-18 11:26:01 +03:00
										 |  |  | #ifndef AC_APPLE_UNIVERSAL_BUILD
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |     if (conflicts) | 
					
						
							|  |  |  | 	warn_assumptions("CPU architecture", env->arch, earch); | 
					
						
							| 
									
										
										
										
											2010-10-18 11:26:01 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |     if (earch != arch_unknown) | 
					
						
							|  |  |  | 	env->arch = earch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // OS
 | 
					
						
							|  |  |  |     Triple::OSType os = triple.getOS(); | 
					
						
							|  |  |  |     switch (os) { | 
					
						
							|  |  |  | 	case Triple::UnknownOS: | 
					
						
							|  |  |  | 	    env->os = llvm_os_UnknownOS; | 
					
						
							|  |  |  | 	    break; | 
					
						
							| 
									
										
										
										
											2015-10-28 17:11:23 -04:00
										 |  |  | #if LLVM_VERSION < 36
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(AuroraUX, os_solaris); | 
					
						
							|  |  |  | 	CASE_OS(Cygwin, os_win32); | 
					
						
							| 
									
										
										
										
											2015-10-28 17:11:23 -04:00
										 |  |  | 	CASE_OS(MinGW32, os_win32); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(Darwin, os_darwin); | 
					
						
							|  |  |  | 	CASE_OS(DragonFly, os_bsd); | 
					
						
							|  |  |  | 	CASE_OS(FreeBSD, os_bsd); | 
					
						
							|  |  |  | 	CASE_OS(Linux, os_linux); | 
					
						
							|  |  |  | 	CASE_OS(Lv2, os_unknown); | 
					
						
							| 
									
										
										
										
											2014-05-28 16:14:58 -04:00
										 |  |  | #if LLVM_VERSION < 29
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(MinGW64, os_win64); | 
					
						
							| 
									
										
										
										
											2011-05-06 15:18:32 +03:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(NetBSD,  os_bsd); | 
					
						
							|  |  |  | 	CASE_OS(OpenBSD, os_bsd); | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #if LLVM_VERSION < 31
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(Psp, os_unknown); | 
					
						
							| 
									
										
										
										
											2014-05-22 14:33:44 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(Solaris, os_solaris); | 
					
						
							| 
									
										
										
										
											2010-08-12 22:34:40 +03:00
										 |  |  | 	case Triple::Win32: | 
					
						
							|  |  |  | 	     env->os = llvm_os_Win32; | 
					
						
							|  |  |  | 	     if (env->os_category != os_win32 && | 
					
						
							|  |  |  | 		 env->os_category != os_win64) | 
					
						
							|  |  |  | 		 warn_assumptions("Operating System", env->os_category, Triple::Win32); | 
					
						
							|  |  |  | 	     break; | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  | 	CASE_OS(Haiku, os_unknown); | 
					
						
							| 
									
										
										
										
											2012-06-22 16:58:21 -04:00
										 |  |  | 	CASE_OS(Minix, os_unknown); | 
					
						
							| 
									
										
										
										
											2010-07-29 13:02:13 +03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // mmap RWX
 | 
					
						
							|  |  |  |     std::string ErrMsg; | 
					
						
							|  |  |  |     sys::MemoryBlock B = sys::Memory::AllocateRWX(4096, NULL, &ErrMsg); | 
					
						
							|  |  |  |     if (B.base() == 0) { | 
					
						
							|  |  |  | 	errs() << "LibClamAV Warning: RWX mapping denied: " << ErrMsg << "\n"; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | 	env->os_features |= 1 << feature_map_rwx; | 
					
						
							|  |  |  | 	sys::Memory::ReleaseRWX(B); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |