configure,meson: support Control-Flow Integrity
This patch adds a flag to enable/disable control flow integrity checks on indirect function calls. This feature only allows indirect function calls at runtime to functions with compatible signatures. This feature is only provided by LLVM/Clang, and depends on link-time optimization which is currently supported only with LLVM/Clang >= 6.0 We also add an option to enable a debugging version of cfi, with verbose output in case of a CFI violation. CFI on indirect function calls does not support calls to functions in shared libraries (since they were not known at compile time), and such calls are forbidden. QEMU relies on dlopen/dlsym when using modules, so we make modules incompatible with CFI. All the checks are performed in meson.build. configure is only used to forward the flags to meson Signed-off-by: Daniele Buono <dbuono@linux.vnet.ibm.com> Message-Id: <20201204230615.2392-5-dbuono@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
24496fe851
commit
9e62ba48ea
22
configure
vendored
22
configure
vendored
@ -411,6 +411,8 @@ coroutine=""
|
||||
coroutine_pool="$default_feature"
|
||||
debug_stack_usage="no"
|
||||
crypto_afalg="no"
|
||||
cfi="false"
|
||||
cfi_debug="false"
|
||||
seccomp="$default_feature"
|
||||
glusterfs="$default_feature"
|
||||
glusterfs_xlator_opt="no"
|
||||
@ -1195,6 +1197,16 @@ for opt do
|
||||
;;
|
||||
--disable-safe-stack) safe_stack="no"
|
||||
;;
|
||||
--enable-cfi)
|
||||
cfi="true";
|
||||
lto="true";
|
||||
;;
|
||||
--disable-cfi) cfi="false"
|
||||
;;
|
||||
--enable-cfi-debug) cfi_debug="true"
|
||||
;;
|
||||
--disable-cfi-debug) cfi_debug="false"
|
||||
;;
|
||||
--disable-curses) curses="disabled"
|
||||
;;
|
||||
--enable-curses) curses="enabled"
|
||||
@ -1788,7 +1800,13 @@ disabled with --disable-FEATURE, default is enabled if available
|
||||
sparse sparse checker
|
||||
safe-stack SafeStack Stack Smash Protection. Depends on
|
||||
clang/llvm >= 3.7 and requires coroutine backend ucontext.
|
||||
|
||||
cfi Enable Control-Flow Integrity for indirect function calls.
|
||||
In case of a cfi violation, QEMU is terminated with SIGILL
|
||||
Depends on lto and is incompatible with modules
|
||||
Automatically enables Link-Time Optimization (lto)
|
||||
cfi-debug In case of a cfi violation, a message containing the line that
|
||||
triggered the error is written to stderr. After the error,
|
||||
QEMU is still terminated with SIGILL
|
||||
gnutls GNUTLS cryptography support
|
||||
nettle nettle cryptography support
|
||||
gcrypt libgcrypt cryptography support
|
||||
@ -6971,7 +6989,7 @@ NINJA=$ninja $meson setup \
|
||||
-Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \
|
||||
${staticpic:+-Db_staticpic=$staticpic} \
|
||||
-Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \
|
||||
-Db_lto=$lto \
|
||||
-Db_lto=$lto -Dcfi=$cfi -Dcfi_debug=$cfi_debug \
|
||||
-Dmalloc=$malloc -Dmalloc_trim=$malloc_trim -Dsparse=$sparse \
|
||||
-Dkvm=$kvm -Dhax=$hax -Dwhpx=$whpx -Dhvf=$hvf \
|
||||
-Dxen=$xen -Dxen_pci_passthrough=$xen_pci_passthrough -Dtcg=$tcg \
|
||||
|
44
meson.build
44
meson.build
@ -773,6 +773,7 @@ elif get_option('vhost_user_blk_server').disabled() or not have_system
|
||||
have_vhost_user_blk_server = false
|
||||
endif
|
||||
|
||||
|
||||
if get_option('fuse').disabled() and get_option('fuse_lseek').enabled()
|
||||
error('Cannot enable fuse-lseek while fuse is disabled')
|
||||
endif
|
||||
@ -795,6 +796,46 @@ if not get_option('fuse_lseek').disabled()
|
||||
endif
|
||||
endif
|
||||
|
||||
if get_option('cfi')
|
||||
cfi_flags=[]
|
||||
# Check for dependency on LTO
|
||||
if not get_option('b_lto')
|
||||
error('Selected Control-Flow Integrity but LTO is disabled')
|
||||
endif
|
||||
if config_host.has_key('CONFIG_MODULES')
|
||||
error('Selected Control-Flow Integrity is not compatible with modules')
|
||||
endif
|
||||
# Check for cfi flags. CFI requires LTO so we can't use
|
||||
# get_supported_arguments, but need a more complex "compiles" which allows
|
||||
# custom arguments
|
||||
if cc.compiles('int main () { return 0; }', name: '-fsanitize=cfi-icall',
|
||||
args: ['-flto', '-fsanitize=cfi-icall'] )
|
||||
cfi_flags += '-fsanitize=cfi-icall'
|
||||
else
|
||||
error('-fsanitize=cfi-icall is not supported by the compiler')
|
||||
endif
|
||||
if cc.compiles('int main () { return 0; }',
|
||||
name: '-fsanitize-cfi-icall-generalize-pointers',
|
||||
args: ['-flto', '-fsanitize=cfi-icall',
|
||||
'-fsanitize-cfi-icall-generalize-pointers'] )
|
||||
cfi_flags += '-fsanitize-cfi-icall-generalize-pointers'
|
||||
else
|
||||
error('-fsanitize-cfi-icall-generalize-pointers is not supported by the compiler')
|
||||
endif
|
||||
if get_option('cfi_debug')
|
||||
if cc.compiles('int main () { return 0; }',
|
||||
name: '-fno-sanitize-trap=cfi-icall',
|
||||
args: ['-flto', '-fsanitize=cfi-icall',
|
||||
'-fno-sanitize-trap=cfi-icall'] )
|
||||
cfi_flags += '-fno-sanitize-trap=cfi-icall'
|
||||
else
|
||||
error('-fno-sanitize-trap=cfi-icall is not supported by the compiler')
|
||||
endif
|
||||
endif
|
||||
add_project_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
|
||||
add_project_link_arguments(cfi_flags, native: false, language: ['c', 'cpp', 'objc'])
|
||||
endif
|
||||
|
||||
#################
|
||||
# config-host.h #
|
||||
#################
|
||||
@ -831,6 +872,7 @@ config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
|
||||
config_host_data.set('CONFIG_STATX', has_statx)
|
||||
config_host_data.set('CONFIG_FUSE', fuse.found())
|
||||
config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found())
|
||||
config_host_data.set('CONFIG_CFI', get_option('cfi'))
|
||||
config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
|
||||
config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
|
||||
config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
|
||||
@ -2195,6 +2237,8 @@ if targetos == 'windows'
|
||||
summary_info += {'QGA MSI support': config_host.has_key('CONFIG_QGA_MSI')}
|
||||
endif
|
||||
summary_info += {'seccomp support': config_host.has_key('CONFIG_SECCOMP')}
|
||||
summary_info += {'CFI support': get_option('cfi')}
|
||||
summary_info += {'CFI debug support': get_option('cfi_debug')}
|
||||
summary_info += {'coroutine backend': config_host['CONFIG_COROUTINE_BACKEND']}
|
||||
summary_info += {'coroutine pool': config_host['CONFIG_COROUTINE_POOL'] == '1'}
|
||||
summary_info += {'debug stack usage': config_host.has_key('CONFIG_DEBUG_STACK_USAGE')}
|
||||
|
@ -35,6 +35,10 @@ option('xen_pci_passthrough', type: 'feature', value: 'auto',
|
||||
description: 'Xen PCI passthrough support')
|
||||
option('tcg', type: 'feature', value: 'auto',
|
||||
description: 'TCG support')
|
||||
option('cfi', type: 'boolean', value: 'false',
|
||||
description: 'Control-Flow Integrity (CFI)')
|
||||
option('cfi_debug', type: 'boolean', value: 'false',
|
||||
description: 'Verbose errors in case of CFI violation')
|
||||
|
||||
option('cocoa', type : 'feature', value : 'auto',
|
||||
description: 'Cocoa user interface (macOS only)')
|
||||
|
Loading…
Reference in New Issue
Block a user