#!/bin/bash # # Copyright (c) 2018 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 #--------------------------------------------------------------------- # Description: This script is the *ONLY* place where "qemu*" build options # should be defined. # # Note to maintainers: # # XXX: Every option group *MUST* be documented explaining why it has # been specified. #--------------------------------------------------------------------- script_name=${0##*/} arch="${3:-$(uname -m)}" # Array of configure options. # # Each element is comprised of two parts in the form: # # tags:option # # Where, # # - 'tags' is a comma-separated list of values which denote why # the option is being specified. # # - 'option' is the hypervisor configuration option. typeset -a qemu_options typeset -A recognised_tags # Prefix were kata will be installed prefix=${PREFIX:-/usr} recognised_tags=( [arch]="architecture-specific" [functionality]="required functionality" [minimal]="specified to avoid building unnecessary elements" [misc]="miscellaneous" [security]="specified for security reasons" [size]="minimise binary size" [speed]="maximise startup speed" ) # Display message to stderr and exit indicating script failed. die() { local msg="$*" echo >&2 "$script_name: ERROR: $msg" exit 1 } # Display usage to stdout. usage() { cat < Options: -d : Dump all options along with the tags explaining why each option is specified. -h : Display this help. -m : Display options one per line (includes continuation characters). -s : Generate options to build static Example: $ $script_name qemu-lite EOT } show_tags_header() { local keys local key local value cat <= 4.1" | bc)" == "1" ]; then qemu_options+=(size:--disable-libssh) else qemu_options+=(size:--disable-libssh2) fi # Disable unused compression support qemu_options+=(size:--disable-bzip2) qemu_options+=(size:--disable-lzo) qemu_options+=(size:--disable-snappy) # Disable unused security options qemu_options+=(security:--disable-seccomp) qemu_options+=(security:--disable-tpm) # Disable userspace network access ("-net user") qemu_options+=(size:--disable-slirp) # Disable USB qemu_options+=(size:--disable-libusb) qemu_options+=(size:--disable-usb-redir) # Disable TCG support case "$arch" in aarch64) echo $hypervisor | grep -q nemu && qemu_options+=(size:--disable-tcg) ;; x86_64) qemu_options+=(size:--disable-tcg) ;; ppc64le) ;; s390x) qemu_options+=(size:--disable-tcg) ;; esac # SECURITY: Don't build a static binary (lowers security) # needed if qemu version is less than 2.7 if [ "${qemu_version_major}" -eq 2 ] && [ "${qemu_version_minor}" -lt 7 ]; then qemu_options+=(security:--disable-static) fi if [ "${static}" == "true" ]; then qemu_options+=(misc:--static) fi # Disable debug and "-uuid ..." is always passed to the qemu binary so not required. case "$arch" in aarch64) qemu_options+=(size:--disable-uuid) ;; x86_64) qemu_options+=(size:--disable-uuid) qemu_options+=(size:--disable-debug-tcg) qemu_options+=(size:--disable-tcg-interpreter) ;; ppc64le) qemu_options+=(size:--disable-debug-tcg) qemu_options+=(size:--disable-tcg-interpreter) ;; s390x) qemu_options+=(size:--disable-uuid) qemu_options+=(size:--disable-debug-tcg) qemu_options+=(size:--disable-tcg-interpreter) ;; esac qemu_options+=(size:--disable-qom-cast-debug) qemu_options+=(size:--disable-tcmalloc) # Disallow network downloads qemu_options+=(security:--disable-curl) # Disable Remote Direct Memory Access (Live Migration) # https://wiki.qemu.org/index.php/Features/RDMALiveMigration qemu_options+=(size:--disable-rdma) # Don't build the qemu-io, qemu-nbd and qemu-image tools qemu_options+=(size:--disable-tools) # Disable XEN driver case "$arch" in aarch64) ;; x86_64) qemu_options+=(size:--disable-xen) ;; ppc64le) qemu_options+=(size:--disable-xen) ;; s390x) qemu_options+=(size:--disable-xen) ;; esac # FIXME: why is this disabled? # (for reference, it's explicitly enabled in Ubuntu 17.10 and # implicitly enabled in Fedora 27). qemu_options+=(size:--disable-linux-aio) if [[ "${qemu_version_major}" -ge 4 || ( "${qemu_version_major}" -eq 3 && "${qemu_version_minor}" -ge 1 ) ]]; then # Disable libpmem, vNVDIMM backend (aka rootfs image) shouldn't be modifed # by the guest qemu_options+=(security:--disable-libpmem) # Disable graphics qemu_options+=(size:--disable-virglrenderer) # Disable block replication qemu_options+=(size:--disable-replication) # Disable USB smart card reader qemu_options+=(size:--disable-smartcard) # Disable guest agent qemu_options+=(size:--disable-guest-agent) qemu_options+=(size:--disable-guest-agent-msi) # unused image formats qemu_options+=(size:--disable-vvfat) qemu_options+=(size:--disable-vdi) qemu_options+=(size:--disable-qed) qemu_options+=(size:--disable-qcow1) qemu_options+=(size:--disable-bochs) qemu_options+=(size:--disable-cloop) qemu_options+=(size:--disable-dmg) qemu_options+=(size:--disable-parallels) qemu_options+=(size:--disable-vxhs) fi #--------------------------------------------------------------------- # Enabled options # Enable kernel Virtual Machine support. # This is the default, but be explicit to avoid any future surprises qemu_options+=(speed:--enable-kvm) # Required for fast network access qemu_options+=(speed:--enable-vhost-net) # Always strip binaries # needed if qemu version is less than 2.7 if [ "${qemu_version_major}" -eq 2 ] && [ "${qemu_version_minor}" -lt 7 ]; then qemu_options+=(size:--enable-strip) fi # Support Ceph RADOS Block Device (RBD) [ -z "${static}" ] && qemu_options+=(functionality:--enable-rbd) # In "passthrough" security mode # (-fsdev "...,security_model=passthrough,..."), qemu uses a helper # application called virtfs-proxy-helper(1) to make certain 9p # operations safer. qemu_options+=(functionality:--enable-virtfs) qemu_options+=(functionality:--enable-attr) qemu_options+=(functionality:--enable-cap-ng) if [[ "${qemu_version_major}" -ge 4 || ( "${qemu_version_major}" -eq 3 && "${qemu_version_minor}" -ge 1 ) ]]; then # AVX2 is enabled by default by x86_64, make sure it's enabled only # for that architecture if [ "$arch" == x86_64 ]; then qemu_options+=(speed:--enable-avx2) else qemu_options+=(speed:--disable-avx2) fi # Enable libc malloc_trim() for memory optimization. qemu_options+=(speed:--enable-malloc-trim) fi #--------------------------------------------------------------------- # Other options # 64-bit only if [ "${arch}" = "ppc64le" ]; then qemu_options+=(arch:"--target-list=ppc64-softmmu") else qemu_options+=(arch:"--target-list=${arch}-softmmu") fi _qemu_cflags="" # compile with high level of optimisation _qemu_cflags+=" -O3" # Improve code quality by assuming identical semantics for interposed # synmbols. # Only enable if gcc is 5.3 or newer if [ "${gcc_version_major}" -ge 5 ] && [ "${gcc_version_minor}" -ge 3 ]; then _qemu_cflags+=" -fno-semantic-interposition" fi # Performance optimisation _qemu_cflags+=" -falign-functions=32" # SECURITY: make the compiler check for common security issues # (such as argument and buffer overflows checks). _qemu_cflags+=" -D_FORTIFY_SOURCE=2" # SECURITY: Create binary as a Position Independant Executable, # and take advantage of ASLR, making ROP attacks much harder to perform. # (https://wiki.debian.org/Hardening) case "$arch" in aarch64) _qemu_cflags+=" -fPIC" ;; x86_64) _qemu_cflags+=" -fPIE" ;; ppc64le) _qemu_cflags+=" -fPIE" ;; s390x) _qemu_cflags+=" -fPIE" ;; esac # Set compile options qemu_options+=(functionality,security,speed,size:"--extra-cflags=\"${_qemu_cflags}\"") unset _qemu_cflags _qemu_ldflags="" # SECURITY: Link binary as a Position Independant Executable, # and take advantage of ASLR, making ROP attacks much harder to perform. # (https://wiki.debian.org/Hardening) case "$arch" in aarch64) ;; x86_64) [ -z "${static}" ] && _qemu_ldflags+=" -pie" ;; ppc64le) [ -z "${static}" ] && _qemu_ldflags+=" -pie" ;; s390x) [ -z "${static}" ] && _qemu_ldflags+=" -pie" ;; esac # SECURITY: Disallow executing code on the stack. _qemu_ldflags+=" -z noexecstack" # SECURITY: Make the linker set some program sections to read-only # before the program is run to stop certain attacks. _qemu_ldflags+=" -z relro" # SECURITY: Make the linker resolve all symbols immediately on program # load. _qemu_ldflags+=" -z now" qemu_options+=(security:"--extra-ldflags=\"${_qemu_ldflags}\"") unset _qemu_ldflags # Where to install qemu helper binaries qemu_options+=(misc:--prefix=${prefix}) # Where to install qemu libraries qemu_options+=(arch:--libdir=${prefix}/lib/${hypervisor}) # Where to install qemu helper binaries qemu_options+=(misc:--libexecdir=${prefix}/libexec/${hypervisor}) # Where to install data files qemu_options+=(misc:--datadir=${prefix}/share/${hypervisor}) } # Entry point main() { action="" while getopts "dhms" opt; do case "$opt" in d) action="dump" ;; h) usage exit 0 ;; m) action="multi" ;; s) static="true" ;; esac done shift $((OPTIND - 1)) [ -z "$1" ] && die "need hypervisor name" hypervisor="$1" local qemu_version_file="VERSION" [ -f ${qemu_version_file} ] || die "QEMU version file '$qemu_version_file' not found" local qemu_version_major=$(cut -d. -f1 "${qemu_version_file}") local qemu_version_minor=$(cut -d. -f2 "${qemu_version_file}") [ -n "${qemu_version_major}" ] || die "cannot determine qemu major version from file $qemu_version_file" [ -n "${qemu_version_minor}" ] || die "cannot determine qemu minor version from file $qemu_version_file" local gcc_version_major=$(gcc -dumpversion | cut -f1 -d.) local gcc_version_minor=$(gcc -dumpversion | cut -f2 -d.) [ -n "${gcc_version_major}" ] || die "cannot determine gcc major version, please ensure it is installed" [ -n "${gcc_version_minor}" ] || die "cannot determine gcc minor version, please ensure it is installed" # Generate qemu options generate_qemu_options show_array "$action" "${qemu_options[@]}" exit 0 } main $@