diff options
-rwxr-xr-x | configure | 22 | ||||
-rw-r--r-- | meson.build | 44 | ||||
-rw-r--r-- | meson_options.txt | 4 |
3 files changed, 68 insertions, 2 deletions
@@ -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 \ diff --git a/meson.build b/meson.build index d05d880114..94ef023ad1 100644 --- a/meson.build +++ b/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')} diff --git a/meson_options.txt b/meson_options.txt index f8f053b5c8..242e0769fb 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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)') |