Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-reques…
Browse files Browse the repository at this point in the history
…t' into staging

Pull request

# gpg: Signature made Wed 24 Jun 2020 11:01:57 BST
# gpg:                using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <[email protected]>" [full]
# gpg:                 aka "Stefan Hajnoczi <[email protected]>" [full]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35  775A 9CA4 ABB3 81AB 73C8

* remotes/stefanha/tags/block-pull-request:
  block/nvme: support nested aio_poll()
  block/nvme: keep BDRVNVMeState pointer in NVMeQueuePair
  block/nvme: clarify that free_req_queue is protected by q->lock
  block/nvme: switch to a NVMeRequest freelist
  block/nvme: don't access CQE after moving cq.head
  block/nvme: drop tautologous assertion
  block/nvme: poll queues without q->lock
  check-block: enable iotests with SafeStack
  configure: add flags to support SafeStack
  coroutine: add check for SafeStack in sigaltstack
  coroutine: support SafeStack in ucontext backend
  minikconf: explicitly set encoding to UTF-8

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jun 26, 2020
2 parents 10f7ffa + 7838c67 commit 87fb952
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 65 deletions.
218 changes: 158 additions & 60 deletions block/nvme.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion block/trace-events
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ nvme_kick(void *s, int queue) "s %p queue %d"
nvme_dma_flush_queue_wait(void *s) "s %p"
nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x"
nvme_process_completion(void *s, int index, int inflight) "s %p queue %d inflight %d"
nvme_process_completion_queue_busy(void *s, int index) "s %p queue %d"
nvme_process_completion_queue_plugged(void *s, int index) "s %p queue %d"
nvme_complete_command(void *s, int index, int cid) "s %p queue %d cid %d"
nvme_submit_command(void *s, int index, int cid) "s %p queue %d cid %d"
nvme_submit_command_raw(int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7) "%02x %02x %02x %02x %02x %02x %02x %02x"
Expand Down
73 changes: 73 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ audio_win_int=""
libs_qga=""
debug_info="yes"
stack_protector=""
safe_stack=""
use_containers="yes"
gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")

Expand Down Expand Up @@ -1287,6 +1288,10 @@ for opt do
;;
--disable-stack-protector) stack_protector="no"
;;
--enable-safe-stack) safe_stack="yes"
;;
--disable-safe-stack) safe_stack="no"
;;
--disable-curses) curses="no"
;;
--enable-curses) curses="yes"
Expand Down Expand Up @@ -1829,6 +1834,8 @@ disabled with --disable-FEATURE, default is enabled if available:
debug-tcg TCG debugging (default is disabled)
debug-info debugging information
sparse sparse checker
safe-stack SafeStack Stack Smash Protection. Depends on
clang/llvm >= 3.7 and requires coroutine backend ucontext.
gnutls GNUTLS cryptography support
nettle nettle cryptography support
Expand Down Expand Up @@ -5573,6 +5580,67 @@ if test "$debug_stack_usage" = "yes"; then
fi
fi

##################################################
# SafeStack


if test "$safe_stack" = "yes"; then
cat > $TMPC << EOF
int main(int argc, char *argv[])
{
#if ! __has_feature(safe_stack)
#error SafeStack Disabled
#endif
return 0;
}
EOF
flag="-fsanitize=safe-stack"
# Check that safe-stack is supported and enabled.
if compile_prog "-Werror $flag" "$flag"; then
# Flag needed both at compilation and at linking
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
QEMU_LDFLAGS="$QEMU_LDFLAGS $flag"
else
error_exit "SafeStack not supported by your compiler"
fi
if test "$coroutine" != "ucontext"; then
error_exit "SafeStack is only supported by the coroutine backend ucontext"
fi
else
cat > $TMPC << EOF
int main(int argc, char *argv[])
{
#if defined(__has_feature)
#if __has_feature(safe_stack)
#error SafeStack Enabled
#endif
#endif
return 0;
}
EOF
if test "$safe_stack" = "no"; then
# Make sure that safe-stack is disabled
if ! compile_prog "-Werror" ""; then
# SafeStack was already enabled, try to explicitly remove the feature
flag="-fno-sanitize=safe-stack"
if ! compile_prog "-Werror $flag" "$flag"; then
error_exit "Configure cannot disable SafeStack"
fi
QEMU_CFLAGS="$QEMU_CFLAGS $flag"
QEMU_LDFLAGS="$QEMU_LDFLAGS $flag"
fi
else # "$safe_stack" = ""
# Set safe_stack to yes or no based on pre-existing flags
if compile_prog "-Werror" ""; then
safe_stack="no"
else
safe_stack="yes"
if test "$coroutine" != "ucontext"; then
error_exit "SafeStack is only supported by the coroutine backend ucontext"
fi
fi
fi
fi

##########################################
# check if we have open_by_handle_at
Expand Down Expand Up @@ -6765,6 +6833,7 @@ echo "sparse enabled $sparse"
echo "strip binaries $strip_opt"
echo "profiler $profiler"
echo "static build $static"
echo "safe stack $safe_stack"
if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa"
fi
Expand Down Expand Up @@ -8370,6 +8439,10 @@ if test "$ccache_cpp2" = "yes"; then
echo "export CCACHE_CPP2=y" >> $config_host_mak
fi

if test "$safe_stack" = "yes"; then
echo "CONFIG_SAFESTACK=y" >> $config_host_mak
fi

# If we're using a separate build tree, set it up now.
# DIRS are directories which we simply mkdir in the build tree;
# LINKS are things to symlink back into the source tree
Expand Down
5 changes: 5 additions & 0 deletions include/qemu/coroutine_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
#include "qemu/queue.h"
#include "qemu/coroutine.h"

#ifdef CONFIG_SAFESTACK
/* Pointer to the unsafe stack, defined by the compiler */
extern __thread void *__safestack_unsafe_stack_ptr;
#endif

#define COROUTINE_STACK_SIZE (1 << 20)

typedef enum {
Expand Down
6 changes: 3 additions & 3 deletions scripts/minikconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ def do_include(self, include):
if incl_abs_fname in self.data.previously_included:
return
try:
fp = open(incl_abs_fname, 'r')
fp = open(incl_abs_fname, 'rt', encoding='utf-8')
except IOError as e:
raise KconfigParserError(self,
'%s: %s' % (e.strerror, include))
Expand Down Expand Up @@ -696,7 +696,7 @@ def scan_token(self):
parser.do_assignment(name, value == 'y')
external_vars.add(name[7:])
else:
fp = open(arg, 'r')
fp = open(arg, 'rt', encoding='utf-8')
parser.parse_file(fp)
fp.close()

Expand All @@ -705,7 +705,7 @@ def scan_token(self):
if key not in external_vars and config[key]:
print ('CONFIG_%s=y' % key)

deps = open(argv[2], 'w')
deps = open(argv[2], 'wt', encoding='utf-8')
for fname in data.previously_included:
print ('%s: %s' % (argv[1], fname), file=deps)
deps.close()
12 changes: 11 additions & 1 deletion tests/check-block.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; then
exit 0
fi

if grep -q "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null ; then
# Disable tests with any sanitizer except for SafeStack
CFLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null )
SANITIZE_FLAGS=""
#Remove all occurrencies of -fsanitize=safe-stack
for i in ${CFLAGS}; do
if [ "${i}" != "-fsanitize=safe-stack" ]; then
SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}"
fi
done
if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then
# Have a sanitize flag that is not allowed, stop
echo "Sanitizers are enabled ==> Not running the qemu-iotests."
exit 0
fi
Expand Down
4 changes: 4 additions & 0 deletions util/coroutine-sigaltstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#include "qemu-common.h"
#include "qemu/coroutine_int.h"

#ifdef CONFIG_SAFESTACK
#error "SafeStack is not compatible with code run in alternate signal stacks"
#endif

typedef struct {
Coroutine base;
void *stack;
Expand Down
28 changes: 28 additions & 0 deletions util/coroutine-ucontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ typedef struct {
Coroutine base;
void *stack;
size_t stack_size;
#ifdef CONFIG_SAFESTACK
/* Need an unsafe stack for each coroutine */
void *unsafe_stack;
size_t unsafe_stack_size;
#endif
sigjmp_buf env;

void *tsan_co_fiber;
Expand Down Expand Up @@ -179,6 +184,10 @@ Coroutine *qemu_coroutine_new(void)
co = g_malloc0(sizeof(*co));
co->stack_size = COROUTINE_STACK_SIZE;
co->stack = qemu_alloc_stack(&co->stack_size);
#ifdef CONFIG_SAFESTACK
co->unsafe_stack_size = COROUTINE_STACK_SIZE;
co->unsafe_stack = qemu_alloc_stack(&co->unsafe_stack_size);
#endif
co->base.entry_arg = &old_env; /* stash away our jmp_buf */

uc.uc_link = &old_uc;
Expand All @@ -203,6 +212,22 @@ Coroutine *qemu_coroutine_new(void)
COROUTINE_YIELD,
&fake_stack_save,
co->stack, co->stack_size, co->tsan_co_fiber);

#ifdef CONFIG_SAFESTACK
/*
* Before we swap the context, set the new unsafe stack
* The unsafe stack grows just like the normal stack, so start from
* the last usable location of the memory area.
* NOTE: we don't have to re-set the usp afterwards because we are
* coming back to this context through a siglongjmp.
* The compiler already wrapped the corresponding sigsetjmp call with
* code that saves the usp on the (safe) stack before the call, and
* restores it right after (which is where we return with siglongjmp).
*/
void *usp = co->unsafe_stack + co->unsafe_stack_size;
__safestack_unsafe_stack_ptr = usp;
#endif

swapcontext(&old_uc, &uc);
}

Expand Down Expand Up @@ -235,6 +260,9 @@ void qemu_coroutine_delete(Coroutine *co_)
#endif

qemu_free_stack(co->stack, co->stack_size);
#ifdef CONFIG_SAFESTACK
qemu_free_stack(co->unsafe_stack, co->unsafe_stack_size);
#endif
g_free(co);
}

Expand Down

0 comments on commit 87fb952

Please sign in to comment.