Re: [PATCH] coroutine: resize pool periodically instead of limiting size

2021-09-08 Thread Daniele Buono

Stefan, the patch looks great.
Thank you for debugging the performance issue that was happening with
SafeStack.

On 9/2/2021 4:10 AM, Stefan Hajnoczi wrote:

On Wed, Sep 01, 2021 at 05:09:23PM +0100, Stefan Hajnoczi wrote:

It was reported that enabling SafeStack reduces IOPS significantly
(>25%) with the following fio benchmark on virtio-blk using a NVMe host
block device:

   # fio --rw=randrw --bs=4k --iodepth=64 --runtime=1m --direct=1 \
--filename=/dev/vdb --name=job1 --ioengine=libaio --thread \
--group_reporting --numjobs=16 --time_based \
 --output=/tmp/fio_result

Serge Guelton and I found that SafeStack is not really at fault, it just
increases the cost of coroutine creation. This fio workload exhausts the
coroutine pool and coroutine creation becomes a bottleneck. Previous
work by Honghao Wang also pointed to excessive coroutine creation.

Creating new coroutines is expensive due to allocating new stacks with
mmap(2) and mprotect(2). Currently there are thread-local and global
pools that recycle old Coroutine objects and their stacks but the
hardcoded size limit of 64 for thread-local pools and 128 for the global
pool is insufficient for the fio benchmark shown above.

This patch changes the coroutine pool algorithm to a simple thread-local
pool without a size limit. Threads periodically shrink the pool down to
a size sufficient for the maximum observed number of coroutines.

This is a very simple algorithm. Fancier things could be done like
keeping a minimum number of coroutines around to avoid latency when a
new coroutine is created after a long period of inactivity. Another
thought is to stop the timer when the pool size is zero for power saving
on threads that aren't using coroutines. However, I'd rather not add
bells and whistles unless they are really necessary.


I agree we should aim at something that is as simple as possible.

However keeping a minumum number of coroutines could be useful to avoid
performance regressions from the previous version.

I wouldn't say restore the global pool - that's way too much trouble -
but keeping the old "pool size" configuration parameter as the miniumum
pool size could be a good idea to maintain the previous performance in
cases where the dynamic pool shrinks too much.



The global pool is removed by this patch. It can help to hide the fact
that local pools are easily exhausted, but it's doesn't fix the root
cause. I don't think there is a need for a global pool because QEMU's
threads are long-lived, so let's keep things simple.

Performance of the above fio benchmark is as follows:

   Before   After
IOPS 60k 97k

Memory usage varies over time as needed by the workload:

 VSZ (KB) RSS (KB)
Before fio  4705248  843128
During fio  5747668 (+ ~100 MB)  849280
After fio   4694996 (- ~100 MB)  845184

This confirms that coroutines are indeed being freed when no longer
needed.

Thanks to Serge Guelton for working on identifying the bottleneck with
me!

Reported-by: Tingting Mao 
Cc: Serge Guelton 
Cc: Honghao Wang 
Cc: Paolo Bonzini 
Cc: Daniele Buono 
Signed-off-by: Stefan Hajnoczi 
---
  include/qemu/coroutine-pool-timer.h | 36 +
  include/qemu/coroutine.h|  7 
  iothread.c  |  6 +++
  util/coroutine-pool-timer.c | 35 
  util/main-loop.c|  5 +++
  util/qemu-coroutine.c   | 62 ++---
  util/meson.build|  1 +
  7 files changed, 119 insertions(+), 33 deletions(-)
  create mode 100644 include/qemu/coroutine-pool-timer.h
  create mode 100644 util/coroutine-pool-timer.c


Adding Andrew and Jenifer in case they have thoughts on improving QEMU's
coroutine pool algorithm.



diff --git a/include/qemu/coroutine-pool-timer.h 
b/include/qemu/coroutine-pool-timer.h
new file mode 100644
index 00..c0b520ce99
--- /dev/null
+++ b/include/qemu/coroutine-pool-timer.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU coroutine pool timer
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#ifndef COROUTINE_POOL_TIMER_H
+#define COROUTINE_POOL_TIMER_H
+
+#include "qemu/osdep.h"
+#include "block/aio.h"
+
+/**
+ * A timer that periodically resizes this thread's coroutine pool, freeing
+ * memory if there are too many unused coroutines.
+ *
+ * Threads that make heavy use of coroutines should use this. Failure to resize
+ * the coroutine pool can lead to large amounts of memory sitting idle and
+ * never being used after the first time.
+ */
+typedef struct {
+QEMUTimer *timer;
+} CoroutinePoolTimer;
+
+/* Call this before the thread runs the AioContext */
+void coroutine_pool_timer_init(CoroutinePoolTimer *pt, AioContext *ctx);
+
+/* Cal

Re: [PATCH] gitlab-ci.d/buildtest: Mark the aarch64 and ppc64-s390x CFI jobs as manual

2021-07-30 Thread Daniele Buono
I agree, making these manual tasks until we find a fix for this is the 
only solution I can think of too.


Daniele

On 7/28/2021 3:51 AM, Thomas Huth wrote:

These two jobs are currently failing very often - the linker seems to
get killed due to out-of-memory problems. Since apparently nobody has
currently an idea how to fix that nicely, let's mark the jobs as manual
for the time being until someone comes up with a proper fix.

Signed-off-by: Thomas Huth 
---
  .gitlab-ci.d/buildtest.yml | 12 
  1 file changed, 12 insertions(+)

diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 63f1903f07..3537c6f1a1 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -416,6 +416,12 @@ build-cfi-aarch64:
  expire_in: 2 days
  paths:
- build
+  rules:
+# FIXME: This job is often failing, likely due to out-of-memory problems in
+# the constraint containers of the shared runners. Thus this is marked as
+# manual until the situation has been solved.
+- when: manual
+  allow_failure: true

  check-cfi-aarch64:
extends: .native_test_job_template
@@ -452,6 +458,12 @@ build-cfi-ppc64-s390x:
  expire_in: 2 days
  paths:
- build
+  rules:
+# FIXME: This job is often failing, likely due to out-of-memory problems in
+# the constraint containers of the shared runners. Thus this is marked as
+# manual until the situation has been solved.
+- when: manual
+  allow_failure: true

  check-cfi-ppc64-s390x:
extends: .native_test_job_template





Re: [PULL v2 04/15] gitlab-ci.yml: Add jobs to test CFI flags

2021-03-22 Thread Daniele Buono

Hi Philippe,

I'm looking at the public QEMU pipelines and it seems that that job
usually takes between 50 and 55 minutes, but there are higher spikes at
56, 57 and one where it failed at 1h.

We could perhaps set the timeout a bit higher, like 1h 10m, to not
terminate the outliers immediately?
The job you linked was almost over, there were just about 20-ish tests
to be linked, so it was probably next to completion.

On 3/22/2021 9:39 AM, Philippe Mathieu-Daudé wrote:

+build-cfi-x86_64:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: x86_64-softmmu
+MAKE_CHECK_ARGS: check-build
+  artifacts:
+expire_in: 2 days
+paths:
+  - build

FYI this job is timeouting:

ERROR: Job failed: execution took longer than 1h0m0s seconds

https://gitlab.com/qemu-project/qemu/-/jobs/1112829128





Re: [PATCH] meson: Stop if cfi is enabled with system slirp

2021-03-08 Thread Daniele Buono

On 3/5/2021 12:18 PM, Paolo Bonzini wrote:




Ok, so let's go with your patch for now.  Independently we could change 
libslirp to:


- add a separate callback (timer_new_v2?) in SlirpCb.  If it is set, we 
use it and pass an enum instead of the SlirpTimerCb cb.


- add a function slirp_timer_expired(enum SlirpTimerId timer_id, void 
*cb_opaque) that does the indirection but without passing around an 
arbitrary function pointer.


In 6.1 we will update the internal libslirp to a version that supports 
the new API, through a patch very similar to mine above.  By requiring 
that new version as the minimum supported one, enabling CFI will be 
possible even with system slirp.


You can open a slirp merge request at 
https://gitlab.freedesktop.org/slirp/libslirp.


Hi Paolo,
sounds like a good plan!

I'll start working on this.

Regards,
Daniele



Re: [PATCH] meson: Stop if cfi is enabled with system slirp

2021-03-08 Thread Daniele Buono

On 3/8/2021 6:19 AM, Daniel P. Berrangé wrote:

My concern is that libslirp is just showing us one known example of
the problem. QEMU links to many more external libraries, which might
exhibit similar issues. If we need to rebuild all the dependancies
with CFI too, to be confident that the combined work will operate
correctly, then this is quite a significant implication. Overall I
think this is going to be a problem for the changes of distros adopting
the use of CFI, especially if they're not using CLang as their toolchain.


In my opinion, there's no need to rebuild everything with CFI. There
will be libraries that will benefit more from CFI, such as libslirp
IMHO. But that still doesn't even mean that we need a CFI-enabled
version to operate correctly.

From a functional point of view, there are plenty of ways to have a CFI-
enabled binary work with shared libraries that do not support CFI (or
cross-dso CFI).

From a security point of view it will be a trade-off. So I think we
should study it on a per-library case to find out the best way forward.
I believe in most cases, an approach like the one discussed with Paolo
will be more than enough to get a good security level in QEMU,
especially if the feature provided by the library is not used at
runtime.



Regards,
Daniel




Re: [PATCH] meson: Stop if cfi is enabled with system slirp

2021-03-05 Thread Daniele Buono

On 3/4/2021 5:37 AM, Daniel P. Berrangé wrote:

Is there work being done, or at least an active plan, for fixing this ?

Distros generally won't want to static link slirp to QEMU when there is
a shared slirp available. It increases the security burden to maintain
slirp twice, especially as slirp has a history of CVEs.

IOW, the inability to use shared slirp may well prevent CFI from being
used in distros.


Daniel,
Adoption is a very good point. We don't want to have multiple versions
of the same library hanging around the O.S., unless strictly necessary.

The problem (if I wear my security hat) is that, as you pointed out,
slirp is known to have a history of CVEs, and it also rely heavily on
callbacks and function pointers. So it would be one of the best
candidates for CFI support.

A (long-term) solution could be to compile libslirp as a shared library,
WITH Control-Flow Integrity. Clang does have an experimental support for
Cross-DSO CFI. However, it is not viable at the moment because:
1. It is still considered Experimental
2. It is not compatible with pointer type generalization (which we need
because of Glib and other uses in QEMU).
Cross-DSO CFI also have some performance implications but I think that
would be a very small price to pay, and only in corner-case conditions.

I don't want to bore anyone too much with the details of the 
implementation... Yet. I'd be happy to explain the Cross-DSO mechanism 
implemented by Clang if it is considered interesting here.

The details can also be found here:
https://clang.llvm.org/docs/ControlFlowIntegrity.html#shared-library-support
And
https://clang.llvm.org/docs/ControlFlowIntegrityDesign.html
(Section "Shared library support")

I think this would be the best long-term solution to improve security
because it would allow to use CFI virtually on every library we consider 
security-sensitive, but not on the others. But it would require some

help and work from/to the Clang community.

In the short term, we should work out something similar to Paolo's
approach. I'll add a few comments to his email.



Re: [PATCH] meson: Stop if cfi is enabled with system slirp

2021-03-05 Thread Daniele Buono

On 3/4/2021 5:56 AM, Paolo Bonzini wrote:

On 04/03/21 11:37, Daniel P. Berrangé wrote:

On Wed, Mar 03, 2021 at 09:59:38PM -0500, Daniele Buono wrote:
For CFI, we need to compile slirp as a static library together with 
qemu.
This is because we register slirp functions as callbacks for QEMU 
Timers.

When using a system-wide shared libslirp, the type information for the
callback is missing and the timer call produces a false positive with 
CFI.


Is there work being done, or at least an active plan, for fixing this ?


Daniele, would this work (uncompiled even)?


Basically, yes it would work, but I'd be worried of the effectiveness of 
CFI. Timers in QEMU are one of the easiest ways to change control flow 
when you get arbitrary write permissions, and were used in at least a 
couple of VM escape demos last year. CFI as before would stop that 
attack vector. With this patch, we would leave the attack vector 
essentially open. More comments (and a couple of suggestions to make it 
harder) later.




diff --git a/net/slirp.c b/net/slirp.c
index be914c0be0..82e05d2c01 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -174,23 +174,42 @@ static int64_t net_slirp_clock_get_ns(void *opaque)
  return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  }

+typedef struct SlirpTimer {
+    QEMUTimer t;
+    SlirpTimerCb cb;
+    void *cb_opaque;
+} SlirpTimer;
+
+static void slirp_timer_cb(void *opaque)
+{
+    SlirpTimer *st = opaque;
+    st->cb(st->cb_opaque);
+}


This call is still violating CFI (st->cb is a pointer in libslirp), but
now that we have a specific callback for slirp, we can easily add a
"QEMU_DISABLE_CFI" decorator to disable CFI only on `slirp_timer_cb`.

The problem is that an attack on the timer is as easy now as it was
without CFI. You just have to change the timer entry to call
slirp_timer_cb, and the opaque pointer to a SlirpTimer struct you
created, anywhere in memory, with a pointer to your own function and
your own parameters. The call to slirp_timer_cb is valid for CFI, while
the call to st->cb is not checked anymore.

I believe we can "fix" this by manually (i.e. in the code) making sure
that st->cb is a valid callback. I think there's a limited number of
(possibly only one right now) callbacks that slirp will use on a timer.
We could create a R/O array that contains the pointers to the allowed
functions, and here check that st->cb is a pointer to one of those.

A more generic alternative could be to try to use dladdr, to resolve the
pointer to a symbol, and make sure that st->cb points to a symbol in 
libslirp. Not sure it will work (we are not opening libslirp with

dlopen), and definitely heavy from a performance point of view, but
would be probably a solution generic enough for all possible future
cases.

I can try to provide RFC patches for both cases, if you guys are 
interested, to see how the code would look like.



+
  static void *net_slirp_timer_new(SlirpTimerCb cb,
   void *cb_opaque, void *opaque)
  {
-    return timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
-  SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
-  cb, cb_opaque);
+    SlirpTimer *st = g_new(SlirpTimer, 1);
+    st->cb = cb;
+    st->cb_opaque = cb_opaque;
+    timer_init_full(>t, NULL, QEMU_CLOCK_VIRTUAL,
+    SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
+    slirp_timer_cb, st);
+    return st;
  }

  static void net_slirp_timer_free(void *timer, void *opaque)
  {
-    timer_free(timer);
+    SlirpTimer *st = timer;
+    timer_del(>t);
+    g_free(st);
  }

  static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
  void *opaque)
  {
-    timer_mod(timer, expire_timer);
+    SlirpTimer *st = timer;
+    timer_mod(>t, expire_timer);
  }

  static void net_slirp_register_poll_fd(int fd, void *opaque)





[PATCH v3 2/2] gitlab-ci.yml: Add jobs to test CFI flags

2021-03-03 Thread Daniele Buono
QEMU has had options to enable control-flow integrity features
for a few months now. Add two sets of build/check/acceptance
jobs to ensure the binary produced is working fine.

The three sets allow testing of x86_64 binaries for x86_64, s390x,
ppc64 and aarch64 targets

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 119 +
 1 file changed, 119 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 814f51873f..7b1f25c92e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -483,6 +483,125 @@ clang-user:
   --extra-cflags=-fsanitize=undefined 
--extra-cflags=-fno-sanitize-recover=undefined
 MAKE_CHECK_ARGS: check-unit check-tcg
 
+# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of 
memory.
+# On gitlab runners, default value sometimes end up calling 2 lds concurrently 
and
+# triggers an Out-Of-Memory error
+#
+# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled 
together
+# with QEMU and linked as a static library to avoid false positives in CFI 
checks.
+# This can be accomplished by using -enable-slirp=git, which avoids the use of
+# a system-wide version of the library
+#
+# Split in three sets of build/check/acceptance to limit the execution time of 
each
+# job
+build-cfi-arm:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: aarch64-softmmu
+MAKE_CHECK_ARGS: check-build
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-arm:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-arm
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-arm:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-arm
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
+build-cfi-ibm:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: ppc64-softmmu s390x-softmmu
+MAKE_CHECK_ARGS: check-build
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-ibm:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-ibm
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-ibm:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-ibm
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
+build-cfi-intel:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: x86_64-softmmu
+MAKE_CHECK_ARGS: check-build
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-intel:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-intel
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-intel:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-intel
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
 tsan-build:
   <<: *native_build_job_definition
   variables:
-- 
2.30.0




[PATCH v3 1/2] gitlab-ci.yml: Allow custom # of parallel linkers

2021-03-03 Thread Daniele Buono
Define a new variable LD_JOBS, that can be used to select
the maximum number of linking jobs to be executed in parallel.
If the variable is not defined, maintain the default given by
make -j

Currently, make parallelism at build time is based on the number
of cpus available.

This doesn't work well with LTO at linking, because with LTO the
linker has to load in memory all the intermediate object files
for optimization.
The end result is that, if the gitlab runner happens to run two
linking processes at the same time, the job will fail with an
out-of-memory error,

This patch leverages the ability to maintain high parallelism at
compile time, but limit the number of linkers executed in parallel.

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 4 
 1 file changed, 4 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8b6d495288..814f51873f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,6 +27,10 @@ include:
   else
 ../configure --enable-werror $CONFIGURE_ARGS ;
   fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
+- if test -n "$LD_JOBS";
+  then
+meson configure . -Dbackend_max_links="$LD_JOBS" ;
+  fi || exit 1;
 - make -j"$JOBS"
 - if test -n "$MAKE_CHECK_ARGS";
   then
-- 
2.30.0




[PATCH v3 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-03 Thread Daniele Buono
For a few months now QEMU has had options to enable compiler-based
control-flow integrity if built with clang.

While this feature has a low maintenance, It's probably still better to
add tests to the CI environment to check that an update doesn't break it.

The patchset allow gitlab testing of:
* --enable-cfi: forward-edge cfi (function pointers)
* --enable-safe-stack: backward-edge cfi (return pointers)
As an added benefit, this also inherently tests LTO. 

The first patch allows a custom selection for linker parallelism.
Currently, make parallelism at build time is based on the number
of cpus available.
This doesn't work well with LTO at linking, because the linker has to
load in memory all the intermediate object files for optimization.
If the gitlab runner happens to run two linking processes at the same
time, the job will fail with an out-of-memory error,
The patch leverages the ability to maintain high parallelism at
compile time, but limit the number of linkers executed in parallel.

The second patch introduces the ci/cd jobs in the gitlab pipeline.
To maintain a limited number of short jobs, Daniel suggested to only
test targets where KVM is available. This restricted the jobs to
x86_64, ppc64, aarch64 and s390x. To keep the jobs under 1 hour, I
created three chains of build -> check -> acceptance jobs, divided by
architecture vendor (Intel, ARM, IBM).

For build, we have to select --enable-slirp=git, because CFI needs a
statically linked version of slirp, with CFI information. More info on
this can be found in a comment in .gitlab-ci.yml, or on a patch for
mason currently in ML:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg787636.html

Test runs of the full pipeline are here (cfi-ci-v3 branch):
https://gitlab.com/dbuono/qemu/-/pipelines/264484574

v3:
- Restricted the targets to x86_64, ppc64, aarch64 and s390x, under
  suggestion from Daniel.

v2:
- More details in the code about the issue of using system-wide slirp
- Use meson to only limit linker parallelism instead of forcing no
  parallelism on the whole compilation process.

Daniele Buono (2):
  gitlab-ci.yml: Allow custom # of parallel linkers
  gitlab-ci.yml: Add jobs to test CFI flags

 .gitlab-ci.yml | 123 +
 1 file changed, 123 insertions(+)

-- 
2.30.0




[PATCH] meson: Stop if cfi is enabled with system slirp

2021-03-03 Thread Daniele Buono
For CFI, we need to compile slirp as a static library together with qemu.
This is because we register slirp functions as callbacks for QEMU Timers.
When using a system-wide shared libslirp, the type information for the
callback is missing and the timer call produces a false positive with CFI.

With this patch, meson will stop if CFI is enabled with system-wide slirp

Signed-off-by: Daniele Buono 
---
 meson.build | 12 
 1 file changed, 12 insertions(+)

diff --git a/meson.build b/meson.build
index f3db83e974..e1ec5020ac 100644
--- a/meson.build
+++ b/meson.build
@@ -1569,6 +1569,18 @@ if have_system
   endif
 endif
 
+# For CFI, we need to compile slirp as a static library together with qemu.
+# This is because we register slirp functions as callbacks for QEMU Timers.
+# When using a system-wide shared libslirp, the type information for the
+# callback is missing and the timer call produces a false positive with CFI.
+#
+# Now that slirp_opt has been defined, check if the selected slirp is 
compatible
+# with control-flow integrity.
+if get_option('cfi') and slirp_opt == 'system'
+  error('Control-Flow Integrity is not compatible with system-wide slirp.' \
+ + ' Please configure with --enable-slirp=git')
+endif
+
 fdt = not_found
 fdt_opt = get_option('fdt')
 if have_system
-- 
2.30.0




Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-02 Thread Daniele Buono

On 3/2/2021 11:40 AM, Daniel P. Berrangé wrote:

The CFI protection is something I'd say is relevant to virtualization
use cases, not to emulation use cases

https://qemu-project.gitlab.io/qemu/system/security.html

IOW, the targets that are important to test are the ones where KVM
is available.

So that's  s390x, ppc, x86, mips, and arm.

I think we can probably ignore mips as that's fairly niche.
We can also reasonably limit ourselves to only test the 64-bit
variants of the target, on the basis that 32-bit is increasingly
legacy/niche too.

So that gives us  ppc64le, x86_64, aarch64 and s390x as the
targets we should get CI coverage for CFI.


Thanks Daniel,
I'll start working on a V3 that only contains those 4 targets, probably 
in two sets of build/check/acceptance to maintain the jobs below the 
hour mark.


These would still be x86 binaries that are not testing KVM, however,
because of the capabilities of the shared gitlab runners.

I see that there's some work from Cleber Rosa to allow running custom 
jobs on aarch64 and s390x systems. I think that, when the infrastructure 
is ready, having a KVM-based CFI test there would help a lot in terms of 
coverage for those architectures.




Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-02 Thread Daniele Buono



On 3/2/2021 10:38 AM, Daniel P. Berrangé wrote:

Is this scenario going to upset  CFI, or is it happy that 'void *'
is compatible with 'mytype *', and ok with the intermediate casts
to/from GCallback ?


This is a valid scenario. LLVM does offer the ability of considering all 
pointer types compatible, and it is being enabled in QEMU. So void* is 
compatible to any type* and that would not be considered a fault.


Intermediate casts are also fine since you are just passing the pointer 
but not using it. The check will happen only when the function is 
called, at which point it was cast back to something compatible.




Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-02 Thread Daniele Buono

On 3/2/2021 5:30 AM, Daniel P. Berrangé wrote:

On Mon, Mar 01, 2021 at 03:39:42PM -0500, Daniele Buono wrote:

Hi Daniel,

On 3/1/2021 10:08 AM, Daniel P. Berrangé wrote:

What are the unique failure scenarios for CFI that these jobs are
likely to expose ? Is it likely that we'll have cases where
CFI succeeds in say, x86_64 target, but fails in aarch64 target ?

For CFI to fail (even if it shouldn't) you'll need code that is calling a
function pointer that was not well defined at compile time. Although
unlikely, that could happen everywhere in the code.

What does "was not well defined" mean here ?



At high level, the compiler creates metadata for every function. Before
jumping to a function pointer, it makes sure that the pointer and the
pointee have matching types.
Not well defined means one of these two cases:
1. The function has a different type than the pointer -> Most likely an
error
2. The function was not available at compile time so the compiler could
not create the related metadata -> Most likely a false positive.

Thanks,
Daniele



Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-01 Thread Daniele Buono

Hi Daniel,

On 3/1/2021 10:08 AM, Daniel P. Berrangé wrote:

What are the unique failure scenarios for CFI that these jobs are
likely to expose ? Is it likely that we'll have cases where
CFI succeeds in say, x86_64 target, but fails in aarch64 target ?


For CFI to fail (even if it shouldn't) you'll need code that is calling 
a function pointer that was not well defined at compile time. Although

unlikely, that could happen everywhere in the code.

So by just testing one (or few) targets we are are not covering the code 
in the TCG frontend used to compile the target ISA to tcg ops, which 
should be the in target/, and the architecture-dependent code in linux-user.


That code seems unlikely (at least to me) to cause a false positive with 
CFI. Examples that I've seen in QEMU so far are:

- Calling code that was JIT-ed at runtime
- Callbacks to functions that were loaded from shared libraries
- Signal Handlers
And none of those should happen there IMHO. But you know, corner cases 
are still possible, and it's quite difficult to predict what new code 
may bring.


We could also consider always testing one or two targets, and keep an 
optional job to test them all when deemed necessary. I'm thinking for
example full testing when code in target/ or linux-user/ is considered, 
or for testing pre-release code. Would be nice to have this automated 
but I am not sure that's possible.


Regards,
Daniele



Re: [PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-03-01 Thread Daniele Buono

Hi Daniel,

On 3/1/2021 5:06 AM, Daniel P. Berrangé wrote:

On Fri, Feb 26, 2021 at 10:21:06AM -0500, Daniele Buono wrote:

Build jobs are on the longer side (about 2h and 20m), but I thought it
would be better to just have 6 large jobs than tens of smaller ones.


IMHO that is a not viable.

Our longest job today is approx 60 minutes, and that is already
painfully long when developers are repeatedly testing their
patch series to find and fix bugs before posting them for review.
I can perhaps get through 5-6 test cycles in a day. If we have a
2 hour 20 min job, then I'll get 2-3 test cycles a day.

I don't want to see any new jobs added which increase the longest
job execution time. We want to reduce our max job time if anything.




I totally understand the argument.

We could build two targets per job. That would create build jobs that
take 40 to 60-ish minutes. If that's the case, however, I would not
recommend testing all the possible targets but limit them to what
is considered a set of most common targets. I have an example of the
resulting pipeline here:

https://gitlab.com/dbuono/qemu/-/pipelines/258983262

I selected intel, power, arm and s390 as "common" targets. Would
something like this be a viable alternative? Perhaps after
due thinking of what targets should be tested?


Regards,
Daniel





[PATCH v2 1/2] gitlab-ci.yml: Allow custom # of parallel linkers

2021-02-26 Thread Daniele Buono
Define a new variable LD_JOBS, that can be used to select
the maximum number of linking jobs to be executed in parallel.
If the variable is not defined, maintain the default given by
make -j

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 4 
 1 file changed, 4 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8b6d495288..814f51873f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,6 +27,10 @@ include:
   else
 ../configure --enable-werror $CONFIGURE_ARGS ;
   fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
+- if test -n "$LD_JOBS";
+  then
+meson configure . -Dbackend_max_links="$LD_JOBS" ;
+  fi || exit 1;
 - make -j"$JOBS"
 - if test -n "$MAKE_CHECK_ARGS";
   then
-- 
2.30.0




[PATCH v2 2/2] gitlab-ci.yml: Add jobs to test CFI flags

2021-02-26 Thread Daniele Buono
QEMU has had options to enable control-flow integrity features
for a few months now. Add two sets of build/check/acceptance
jobs to ensure the binary produced is working fine.

The two sets allow testing of x86_64 binaries for every target
that is not deprecated.

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 93 ++
 1 file changed, 93 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 814f51873f..15641abe63 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -483,6 +483,99 @@ clang-user:
   --extra-cflags=-fsanitize=undefined 
--extra-cflags=-fno-sanitize-recover=undefined
 MAKE_CHECK_ARGS: check-unit check-tcg
 
+# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of 
memory.
+# On gitlab runners, default value sometimes end up calling 2 lds concurrently 
and
+# triggers an Out-Of-Memory error
+#
+# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled 
together
+# with QEMU and linked as a static library to avoid false positives in CFI 
checks.
+# This can be accomplished by using -enable-slirp=git, which avoids the use of
+# a system-wide version of the library
+#
+# Split in two sets of build/check/acceptance because a single build job for 
every
+# target creates an artifact archive too big to be uploaded
+build-cfi-set1:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: aarch64-softmmu arm-softmmu alpha-softmmu i386-softmmu ppc-softmmu
+  ppc64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu sparc-softmmu
+  sparc64-softmmu x86_64-softmmu
+  aarch64-linux-user aarch64_be-linux-user arm-linux-user i386-linux-user
+  ppc64-linux-user ppc64le-linux-user s390x-linux-user x86_64-linux-user
+MAKE_CHECK_ARGS: check-build
+  timeout: 2h 30m
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-set1:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set1
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-set1:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set1
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
+build-cfi-set2:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+LD_JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
+  microblaze-softmmu microblazeel-softmmu mips-softmmu mips64-softmmu
+  mips64el-softmmu mipsel-softmmu moxie-softmmu nios2-softmmu or1k-softmmu
+  rx-softmmu sh4-softmmu sh4eb-softmmu tricore-softmmu xtensa-softmmu
+  xtensaeb-softmmu
+MAKE_CHECK_ARGS: check-build
+  timeout: 2h 30m
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-set2:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set2
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-set2:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set2
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
 tsan-build:
   <<: *native_build_job_definition
   variables:
-- 
2.30.0




[PATCH v2 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-02-26 Thread Daniele Buono
For a few months now QEMU has had options to enable compiler-based
control-flow integrity if built with clang.

While this feature has a low maintenance, It's probably still better to
add tests to the CI environment to check that an update doesn't break it.

The patchset allow gitlab testing of:
* --enable-cfi: forward-edge cfi (function pointers)
* --enable-safe-stack: backward-edge cfi (return pointers)
As an added benefit, this also inherently tests LTO. 

The first patch allows a custom selection for linker parallelism.
Currently, make parallelism at build time is based on the number
of cpus available.
This doesn't work well with LTO at linking, because the linker has to
load in memory all the intermediate object files for optimization.
If the gitlab runner happens to run two linking processes at the same
time, the job will fail with an out-of-memory error,
The patch leverages the ability to maintain high parallelism at
compile time, but limit the number of linkers executed in parallel.

The second patch introduces the ci/cd jobs in the gitlab pipeline.
My original intention was to create a single chain of
build -> check -> acceptance, with all the targets compiled by default.
Unfortunately, the resulting artifact is too big and won't be uploaded.
So I split the test in two chains, that should cover all non-deprecated
targets as of today.
Build jobs are on the longer side (about 2h and 20m), but I thought it
would be better to just have 6 large jobs than tens of smaller ones.
For build, we have to select --enable-slirp=git, because CFI needs a
statically linked version of slirp, with CFI information. More info on
this can be found in a comment in .gitlab-ci.yml.

Test runs of the full pipeline are here (cfi-ci-v2 branch):
https://gitlab.com/dbuono/qemu/-/pipelines/261311362

v2:
- More details in the code about the issue of using system-wide slirp
- Use meson to only limit linker parallelism instead of forcing no
  parallelism on the whole compilation process.

Daniele Buono (2):
  gitlab-ci.yml: Allow custom # of parallel linkers
  gitlab-ci.yml: Add jobs to test CFI flags

 .gitlab-ci.yml | 97 ++
 1 file changed, 97 insertions(+)

-- 
2.30.0




Re: [PATCH 1/2] gitlab-ci.yml: Allow custom make parallelism

2021-02-24 Thread Daniele Buono




On 2/24/2021 2:44 AM, Paolo Bonzini wrote:

On 23/02/21 20:34, Daniele Buono wrote:

This works, but setting this value to 1 for everybody seems a bit too
restrictive. While the gitlab ci runners don't have enough memory for
this, that's not necessarily true for every build platform, and linking
multiple targets in parallel with LTO can result in a big save in time,
so I'd prefer a customizable way.

How about adding a flag `--max-ld-procs` to configure to manually set
backend_max_links?


Another possibility is to invoke "meson configure build 
-Dbackend_max_links=1" after configure.


I like this, I'll send a v2 soon where I replace this patch with one
just for linking.

Daniele



Re: [PATCH 2/2] gitlab-ci.yml: Add jobs to test CFI flags

2021-02-24 Thread Daniele Buono

On 2/23/2021 3:11 AM, Paolo Bonzini wrote:

On 23/02/21 00:01, Daniele Buono wrote:
+# Set JOBS=1 because this requires LTO and ld consumes a large amount 
of memory.
+# On gitlab runners, default JOBS of 2 sometimes end up calling 2 lds 
concurrently

+# and triggers an Out-Of-Memory error


Does it make sense to test only one target instead?


I'd prefer grouping multiple targets per job so that the number of jobs 
doesn't explode, and stopping ninja from linking in parallel does solve 
the issue.


There's also the issue that tests are also compiled here so you may end
up with two linkers anyway. However the chance that this will end up in
an out-of-memory error is quite smaller (possibly zero) since tests
don't link that many object files together.



+# Because of how slirp is used in QEMU, we need to have CFI also on 
libslirp.
+# System-wide version in fedora is not compiled with CFI so we 
recompile it using

+# -enable-slirp=git


Can you explain what you mean, and perhaps add a check or warning for 
incompatible settings?


Certainly. The issue here is that there is a function in libslirp that
is used as callbacks for QEMU Timers: ra_timer_handler
(There may be others, but of this one I'm sure because I traced it).

This is not an issue when you compile slirp with qemu, since the whole
library now has CFI informations and is statically linked in the QEMU
binary. It becomes an issue if you are dynamically linking a system-wide
libslirp, as it happens on Fedora.

I'd be happy to add a check on configure/meson that ends the configure
step with an error when this happens, but that would technically be an
independent patch that I'd work on in parallel to this one.
I would prefer to not automatically select the git-based libslirp
because that may go unnoticed when configuring.



Paolo





Re: [PATCH 1/2] gitlab-ci.yml: Allow custom make parallelism

2021-02-23 Thread Daniele Buono

This works, but setting this value to 1 for everybody seems a bit too
restrictive. While the gitlab ci runners don't have enough memory for
this, that's not necessarily true for every build platform, and linking
multiple targets in parallel with LTO can result in a big save in time,
so I'd prefer a customizable way.

How about adding a flag `--max-ld-procs` to configure to manually set
backend_max_links?

This would also allow setting it up to any specific number above 1,
which looking at the Makefile seems to not be possible now: because of
how the -j flag is passed from make to ninja, a compilation is either
sequential or parallel based on #cpus

On 2/23/2021 3:12 AM, Paolo Bonzini wrote:

On 23/02/21 00:01, Daniele Buono wrote:
Currently, make parallelism at build time is defined as #cpus+1. Some 
build jobs may need (or benefit from) a different number. An example 
is builds with LTO where, because of the huge demand of memory at link 
time, gitlab runners fails if two linkers are run concurrently This 
patch retains the default value of #cpus+1 but allows setting the 
"JOBS" variable to a different number when applying the template


As I just found out, you can add -Dbackend_max_links=1 to the meson 
command line instead if LTO is enabled.


Paolo





[PATCH 0/2] gitlab-ci.yml: Add jobs to test CFI

2021-02-22 Thread Daniele Buono
For a few months now QEMU has had options to enable compiler-based
control-flow integrity if built with clang.

While this feature has a low maintenance, It's probably still better to
add tests to the CI environment to check that an update doesn't break it.

As an added benefit, this also inherently tests LTO. The patch allow
gitlab testing of:
* --enable-cfi: forward-edge cfi (function pointers)
* --enable-safe-stack: backward-edge cfi (return pointers)

My original intention was to create a single chain of
build -> check -> acceptance, with all the targets compiled by default.
Unfortunately, the resulting artifact is too big and won't be uploaded.

So I split the test in two chains, that should cover all non-deprecated
targets as of today.

I also had to add a small patch to allow a custom selection for make
parallelism. This is because the gitlab runner nodes only have ~3.5GB of
ram, and with the default parallelism (2), in some cases two ld
instances will start working on two binaries and exaust the memory.
By only forcing one make job at a time, this is avoided.

Test runs of the full pipeline are here (cfi-ci branch):
https://gitlab.com/dbuono/qemu/-/pipelines/259931154

Daniele Buono (2):
  gitlab-ci.yml: Allow custom make parallelism
  gitlab-ci.yml: Add jobs to test CFI flags

 .gitlab-ci.yml | 94 +-
 1 file changed, 93 insertions(+), 1 deletion(-)

-- 
2.30.0




[PATCH 2/2] gitlab-ci.yml: Add jobs to test CFI flags

2021-02-22 Thread Daniele Buono
QEMU has had options to enable control-flow integrity features
for a few months now. Add two sets of build/check/acceptance
jobs to ensure the binary produced is working fine.

The two sets allow testing of x86_64 binaries for every target
that is not deprecated.

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 92 ++
 1 file changed, 92 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5c198f05d4..f2fea8e2eb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -479,6 +479,98 @@ clang-user:
   --extra-cflags=-fsanitize=undefined 
--extra-cflags=-fno-sanitize-recover=undefined
 MAKE_CHECK_ARGS: check-unit check-tcg
 
+# Set JOBS=1 because this requires LTO and ld consumes a large amount of 
memory.
+# On gitlab runners, default JOBS of 2 sometimes end up calling 2 lds 
concurrently
+# and triggers an Out-Of-Memory error
+#
+# Because of how slirp is used in QEMU, we need to have CFI also on libslirp.
+# System-wide version in fedora is not compiled with CFI so we recompile it 
using
+# -enable-slirp=git
+#
+# Split in two sets of build/check/acceptance because a single build job for 
every
+# target creates an artifact archive too big to be uploaded
+build-cfi-set1:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: aarch64-softmmu arm-softmmu alpha-softmmu i386-softmmu ppc-softmmu
+  ppc64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu sparc-softmmu
+  sparc64-softmmu x86_64-softmmu
+  aarch64-linux-user aarch64_be-linux-user arm-linux-user i386-linux-user
+  ppc64-linux-user ppc64le-linux-user s390x-linux-user x86_64-linux-user
+MAKE_CHECK_ARGS: check-build
+  timeout: 3h
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-set1:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set1
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-set1:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set1
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
+build-cfi-set2:
+  <<: *native_build_job_definition
+  needs:
+  - job: amd64-fedora-container
+  variables:
+JOBS: 1
+AR: llvm-ar
+IMAGE: fedora
+CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+  --enable-safe-stack --enable-slirp=git
+TARGETS: avr-softmmu cris-softmmu hppa-softmmu m68k-softmmu
+  microblaze-softmmu microblazeel-softmmu mips-softmmu mips64-softmmu
+  mips64el-softmmu mipsel-softmmu moxie-softmmu nios2-softmmu or1k-softmmu
+  rx-softmmu sh4-softmmu sh4eb-softmmu tricore-softmmu xtensa-softmmu
+  xtensaeb-softmmu
+MAKE_CHECK_ARGS: check-build
+  timeout: 3h
+  artifacts:
+expire_in: 2 days
+paths:
+  - build
+
+check-cfi-set2:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set2
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check
+
+acceptance-cfi-set2:
+  <<: *native_test_job_definition
+  needs:
+- job: build-cfi-set2
+  artifacts: true
+  variables:
+IMAGE: fedora
+MAKE_CHECK_ARGS: check-acceptance
+  <<: *acceptance_definition
+
 tsan-build:
   <<: *native_build_job_definition
   variables:
-- 
2.30.0




[PATCH 1/2] gitlab-ci.yml: Allow custom make parallelism

2021-02-22 Thread Daniele Buono
Currently, make parallelism at build time is defined as #cpus+1.
Some build jobs may need (or benefit from) a different number.

An example is builds with LTO where, because of the huge demand
of memory at link time, gitlab runners fails if two linkers are
run concurrently

This patch retains the default value of #cpus+1 but allows setting
the "JOBS" variable to a different number when applying the template

Signed-off-by: Daniele Buono 
---
 .gitlab-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8b6d495288..5c198f05d4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -17,7 +17,7 @@ include:
   stage: build
   image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
   before_script:
-- JOBS=$(expr $(nproc) + 1)
+- JOBS=${JOBS:-$(expr $(nproc) + 1)}
   script:
 - mkdir build
 - cd build
-- 
2.30.0




Re: [PATCH 0/1] tests/acceptance/boot_linux: Switch to Fedora 32

2021-01-28 Thread Daniele Buono

On 1/28/2021 3:19 PM, Wainer dos Santos Moschetta wrote:

Hi,

On 1/26/21 10:09 PM, Daniele Buono wrote:

Local acceptance tests run with "make check-acceptance" are now
showing some cases canceled like the following:

(01/39) 
tests/acceptance/boot_linux.py:BootLinuxX8664.test_pc_i440fx_tcg: 
CANCEL: Failed to download/prepare boot image (0.25 s)


Turns out, every full-vm test in boot_linux.py is trying to use a
Fedora 31 cloud image and is failing, with Avocado refusing to download
it, presumably because Fedora 31 is EOL.

This patch moves to Fedora 32, which is still supported. And seem to
work fine


While ago it was discussed about updating the Fedora version which, in 
my opinion, ended up without a conclusion. Please see the complete 
thread in:


https://www.mail-archive.com/qemu-devel@nongnu.org/msg763986.html


Oops, didn't notice the previous thread. Apologies for the duplicate!



I'm CC'ing Daniel Berrrangé so that, perhaps, we could resume the 
discussion.


Thanks!

- Wainer



The script has the image checksums hardcoded. I downloaded and verified
the checksums with the Fedora 32 GPG key, but I would feel more
confident if someone else wants to verify it too.

The checksum files are here:
https://download-ib01.fedoraproject.org/pub/fedora-secondary/releases/32/Cloud/ppc64le/images/Fedora-Cloud-32-1.6-ppc64le-CHECKSUM 

https://download-ib01.fedoraproject.org/pub/fedora-secondary/releases/32/Cloud/s390x/images/Fedora-Cloud-32-1.6-s390x-CHECKSUM 

https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/32/Cloud/aarch64/images/Fedora-Cloud-32-1.6-aarch64-CHECKSUM 

https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/32/Cloud/x86_64/images/Fedora-Cloud-32-1.6-x86_64-CHECKSUM 


and the GPG keys are available here:
https://getfedora.org/en/security/

NOTE: I tried moving to Fedora 33, but the aarch64 VM cannot boot
properly. May be worth investigating but I have no experience with ARM
so I'll leave that to someone else, if interested.

Daniele Buono (1):
   tests/acceptance/boot_linux: Switch to Fedora 32

  tests/acceptance/boot_linux.py | 11 +--
  1 file changed, 5 insertions(+), 6 deletions(-)







[PATCH 0/1] tests/acceptance/boot_linux: Switch to Fedora 32

2021-01-26 Thread Daniele Buono
Local acceptance tests run with "make check-acceptance" are now
showing some cases canceled like the following:

(01/39) tests/acceptance/boot_linux.py:BootLinuxX8664.test_pc_i440fx_tcg: 
CANCEL: Failed to download/prepare boot image (0.25 s)

Turns out, every full-vm test in boot_linux.py is trying to use a
Fedora 31 cloud image and is failing, with Avocado refusing to download
it, presumably because Fedora 31 is EOL.

This patch moves to Fedora 32, which is still supported. And seem to
work fine

The script has the image checksums hardcoded. I downloaded and verified
the checksums with the Fedora 32 GPG key, but I would feel more
confident if someone else wants to verify it too.

The checksum files are here:
https://download-ib01.fedoraproject.org/pub/fedora-secondary/releases/32/Cloud/ppc64le/images/Fedora-Cloud-32-1.6-ppc64le-CHECKSUM
https://download-ib01.fedoraproject.org/pub/fedora-secondary/releases/32/Cloud/s390x/images/Fedora-Cloud-32-1.6-s390x-CHECKSUM
https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/32/Cloud/aarch64/images/Fedora-Cloud-32-1.6-aarch64-CHECKSUM
https://download-ib01.fedoraproject.org/pub/fedora/linux/releases/32/Cloud/x86_64/images/Fedora-Cloud-32-1.6-x86_64-CHECKSUM
and the GPG keys are available here:
https://getfedora.org/en/security/

NOTE: I tried moving to Fedora 33, but the aarch64 VM cannot boot
properly. May be worth investigating but I have no experience with ARM
so I'll leave that to someone else, if interested.

Daniele Buono (1):
  tests/acceptance/boot_linux: Switch to Fedora 32

 tests/acceptance/boot_linux.py | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

-- 
2.30.0




[PATCH 1/1] tests/acceptance/boot_linux: Switch to Fedora 32

2021-01-26 Thread Daniele Buono
Some acceptance test require a full VM image.
The tests were using Fedora 31, which is now EOL.
Probably as a consequence, the Avocado framework is not
able to download such images anymore.

Switch to Fedora 32, which is still supported.

Signed-off-by: Daniele Buono 
---
 tests/acceptance/boot_linux.py | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py
index 1da4a53d6a..b954f95f0b 100644
--- a/tests/acceptance/boot_linux.py
+++ b/tests/acceptance/boot_linux.py
@@ -48,7 +48,7 @@ class BootLinuxBase(Test):
 image_arch = 'ppc64le'
 try:
 boot = vmimage.get(
-'fedora', arch=image_arch, version='31',
+'fedora', arch=image_arch, version='32',
 checksum=self.chksum,
 algorithm='sha256',
 cache_dir=self.cache_dirs[0],
@@ -111,7 +111,7 @@ class BootLinuxX8664(BootLinux):
 :avocado: tags=arch:x86_64
 """
 
-chksum = 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0'
+chksum = '423a4ce32fa32c50c11e3d3ff392db97a762533b81bef9d00599de518a7469c8'
 
 def test_pc_i440fx_tcg(self):
 """
@@ -160,8 +160,7 @@ class BootLinuxAarch64(BootLinux):
 :avocado: tags=machine:virt
 :avocado: tags=machine:gic-version=2
 """
-
-chksum = '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49'
+chksum = 'b367755c664a2d7a26955bbfff985855adfa2ca15e908baf15b4b176d68d3967'
 
 def add_common_args(self):
 self.vm.add_args('-bios',
@@ -217,7 +216,7 @@ class BootLinuxPPC64(BootLinux):
 :avocado: tags=arch:ppc64
 """
 
-chksum = '7c3528b85a3df4b2306e892199a9e1e43f991c506f2cc390dc4efa2026ad2f58'
+chksum = 'dd989a078d641713c55720ba3e4320b204ade6954e2bfe4570c8058dc36e2e5d'
 
 def test_pseries_tcg(self):
 """
@@ -235,7 +234,7 @@ class BootLinuxS390X(BootLinux):
 :avocado: tags=arch:s390x
 """
 
-chksum = '4caaab5a434fd4d1079149a072fdc7891e354f834d355069ca982fdcaf5a122d'
+chksum = '93e49b98fa016797a6864a95cbb7beaec86ffd61dbcd42a951158ae732dae1ec'
 
 @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab')
 def test_s390_ccw_virtio_tcg(self):
-- 
2.30.0




Re: [PATCH-for-5.2? v3 3/9] hw/usb: reorder fields in UASStatus

2021-01-14 Thread Daniele Buono

On 1/14/2021 3:17 AM, Marc-André Lureau wrote:


Any update on this patch?
thanks


Hi,
I had been waiting for a feedback on my previous message.
I don't know the UAS subsystem that well, but can't find where the
variable-sized field that is causing the issue is actually used.

If it helps, I can send an RFC for converting

struct UASStatus {
uint32_t  stream;
uas_iustatus;
uint32_t  length;
QTAILQ_ENTRY(UASStatus)   next;
};

to

struct UASStatus {
uint32_t  stream;
uas_iu*status;
uint32_t  length;
QTAILQ_ENTRY(UASStatus)   next;
};

And discuss it at that point.

Thanks,
Daniele



Re: [PATCH] decodetree: Open files with encoding='utf-8'

2021-01-08 Thread Daniele Buono

I had a similar issue in the past with the acceptance tests.
Some VMs send UTF-8 output in their console and the acceptance test
script would bail out if the locale was not UTF-8.

I sent a patch on the ml but it probably got lost:
https://lists.gnu.org/archive/html/qemu-devel/2020-07/msg06086.html

I can re-spin it if you guys are interested


On 1/8/2021 10:16 AM, Philippe Mathieu-Daudé wrote:

When decodetree.py was added in commit 568ae7efae7, QEMU was
using Python 2 which happily reads UTF-8 files in text mode.
Python 3 requires either UTF-8 locale or an explicit encoding
passed to open(). Now that Python 3 is required, explicit
UTF-8 encoding for decodetree sources.

This fixes:

   $ /usr/bin/python3 scripts/decodetree.py test.decode
   Traceback (most recent call last):
 File "scripts/decodetree.py", line 1397, in 
   main()
 File "scripts/decodetree.py", line 1308, in main
   parse_file(f, toppat)
 File "scripts/decodetree.py", line 994, in parse_file
   for line in f:
 File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
   return codecs.ascii_decode(input, self.errors)[0]
   UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 80:
   ordinal not in range(128)

Reported-by: Peter Maydell 
Signed-off-by: Philippe Mathieu-Daudé 
---
  scripts/decodetree.py | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 47aa9caf6d1..fa40903cff1 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -1304,7 +1304,7 @@ def main():

  for filename in args:
  input_file = filename
-f = open(filename, 'r')
+f = open(filename, 'r', encoding='utf-8')
  parse_file(f, toppat)
  f.close()





[PATCH v4 4/5] configure,meson: support Control-Flow Integrity

2020-12-04 Thread Daniele Buono
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 
---
 configure | 21 -
 meson.build   | 45 +
 meson_options.txt |  4 
 3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index fee118518b..c4e5d92167 100755
--- a/configure
+++ b/configure
@@ -400,6 +400,8 @@ coroutine=""
 coroutine_pool=""
 debug_stack_usage="no"
 crypto_afalg="no"
+cfi="disabled"
+cfi_debug="disabled"
 seccomp=""
 glusterfs=""
 glusterfs_xlator_opt="no"
@@ -1180,6 +1182,16 @@ for opt do
   ;;
   --disable-safe-stack) safe_stack="no"
   ;;
+  --enable-cfi)
+  cfi="enabled";
+  lto="true";
+  ;;
+  --disable-cfi) cfi="disabled"
+  ;;
+  --enable-cfi-debug) cfi_debug="enabled"
+  ;;
+  --disable-cfi-debug) cfi_debug="disabled"
+  ;;
   --disable-curses) curses="disabled"
   ;;
   --enable-curses) curses="enabled"
@@ -1760,6 +1772,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
@@ -7020,7 +7039,7 @@ NINJA=$ninja $meson setup \
 -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\
 -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
 -Dvhost_user_blk_server=$vhost_user_blk_server \
--Db_lto=$lto \
+-Db_lto=$lto -Dcfi=$cfi -Dcfi_debug=$cfi_debug \
 $cross_arg \
 "$PWD" "$source_path"
 
diff --git a/meson.build b/meson.build
index ebd1c690e0..e1ae6521e0 100644
--- a/meson.build
+++ b/meson.build
@@ -773,6 +773,48 @@ elif get_option('vhost_user_blk_server').disabled() or not 
have_system
 have_vhost_user_blk_server = false
 endif
 
+if get_option('cfi').enabled()
+  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').enabled()
+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_

[PATCH v4 5/5] docs: Add CFI Documentation

2020-12-04 Thread Daniele Buono
Document how to compile with CFI and how to maintain CFI-safe code

Signed-off-by: Daniele Buono 
---
 docs/devel/control-flow-integrity.rst | 137 ++
 1 file changed, 137 insertions(+)
 create mode 100644 docs/devel/control-flow-integrity.rst

diff --git a/docs/devel/control-flow-integrity.rst 
b/docs/devel/control-flow-integrity.rst
new file mode 100644
index 00..ec54d16a42
--- /dev/null
+++ b/docs/devel/control-flow-integrity.rst
@@ -0,0 +1,137 @@
+
+Control-Flow Integrity (CFI)
+
+
+This document describes the current control-flow integrity (CFI) mechanism in
+QEMU. How it can be enabled, its benefits and deficiencies, and how it affects
+new and existing code in QEMU
+
+Basics
+--
+
+CFI is a hardening technique that focusing on guaranteeing that indirect
+function calls have not been altered by an attacker.
+The type used in QEMU is a forward-edge control-flow integrity that ensures
+function calls performed through function pointers, always call a "compatible"
+function. A compatible function is a function with the same signature of the
+function pointer declared in the source code.
+
+This type of CFI is entirely compiler-based and relies on the compiler knowing
+the signature of every function and every function pointer used in the code.
+As of now, the only compiler that provides support for CFI is Clang.
+
+CFI is best used on production binaries, to protect against unknown attack
+vectors.
+
+In case of a CFI violation (i.e. call to a non-compatible function) QEMU will
+terminate abruptly, to stop the possible attack.
+
+Building with CFI
+-
+
+NOTE: CFI requires the use of link-time optimization. Therefore, when CFI is
+selected, LTO will be automatically enabled.
+
+To build with CFI, the minimum requirement is Clang 6+. If you
+are planning to also enable fuzzing, then Clang 11+ is needed (more on this
+later).
+
+Given the use of LTO, a version of AR that supports LLVM IR is required.
+The easies way of doing this is by selecting the AR provided by LLVM::
+
+ AR=llvm-ar-9 CC=clang-9 CXX=lang++-9 /path/to/configure --enable-cfi
+
+CFI is enabled on every binary produced.
+
+If desired, an additional flag to increase the verbosity of the output in case
+of a CFI violation is offered (``--enable-debug-cfi``).
+
+Using QEMU built with CFI
+-
+
+A binary with CFI will work exactly like a standard binary. In case of a CFI
+violation, the binary will terminate with an illegal instruction signal.
+
+Incompatible code with CFI
+--
+
+As mentioned above, CFI is entirely compiler-based and therefore relies on
+compile-time knowledge of the code. This means that, while generally supported
+for most code, some specific use pattern can break CFI compatibility, and
+create false-positives. The two main patterns that can cause issues are:
+
+* Just-in-time compiled code: since such code is created at runtime, the jump
+  to the buffer containing JIT code will fail.
+
+* Libraries loaded dynamically, e.g. with dlopen/dlsym, since the library was
+  not known at compile time.
+
+Current areas of QEMU that are not entirely compatible with CFI are:
+
+1. TCG, since the idea of TCG is to pre-compile groups of instructions at
+   runtime to speed-up interpretation, quite similarly to a JIT compiler
+
+2. TCI, where the interpreter has to interpret the generic *call* operation
+
+3. Plugins, since a plugin is implemented as an external library
+
+4. Modules, since they are implemented as an external library
+
+5. Directly calling signal handlers from the QEMU source code, since the
+   signal handler may have been provided by an external library or even plugged
+   at runtime.
+
+Disabling CFI for a specific function
+-
+
+If you are working on function that is performing a call using an
+incompatible way, as described before, you can selectively disable CFI checks
+for such function by using the decorator ``QEMU_DISABLE_CFI`` at function
+definition, and add an explanation on why the function is not compatible
+with CFI. An example of the use of ``QEMU_DISABLE_CFI`` is provided here::
+
+   /*
+* Disable CFI checks.
+* TCG creates binary blobs at runtime, with the transformed code.
+* A TB is a blob of binary code, created at runtime and called with an
+* indirect function call. Since such function did not exist at compile 
time,
+* the CFI runtime has no way to verify its signature and would fail.
+* TCG is not considered a security-sensitive part of QEMU so this does 
not
+* affect the impact of CFI in environment with high security 
requirements
+*/
+   QEMU_DISABLE_CFI
+   static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, 
TranslationBlock *itb)
+
+NOTE: CFI needs to be disabled at the **caller** function, (i.e. a compa

[PATCH v4 1/5] configure,meson: add option to enable LTO

2020-12-04 Thread Daniele Buono
This patch allows to compile QEMU with link-time optimization (LTO).
Compilation with LTO is handled directly by meson. This patch only
adds the option in configure and forwards the request to meson

Tested with all major versions of clang from 6 to 12

Signed-off-by: Daniele Buono 
---
 configure   | 7 +++
 meson.build | 1 +
 2 files changed, 8 insertions(+)

diff --git a/configure b/configure
index 18c26e0389..fee118518b 100755
--- a/configure
+++ b/configure
@@ -242,6 +242,7 @@ host_cc="cc"
 audio_win_int=""
 libs_qga=""
 debug_info="yes"
+lto="false"
 stack_protector=""
 safe_stack=""
 use_containers="yes"
@@ -1167,6 +1168,10 @@ for opt do
   ;;
   --disable-werror) werror="no"
   ;;
+  --enable-lto) lto="true"
+  ;;
+  --disable-lto) lto="false"
+  ;;
   --enable-stack-protector) stack_protector="yes"
   ;;
   --disable-stack-protector) stack_protector="no"
@@ -1751,6 +1756,7 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   module-upgrades try to load modules from alternate paths for upgrades
   debug-tcg   TCG debugging (default is disabled)
   debug-info  debugging information
+  lto Enable Link-Time Optimization.
   sparse  sparse checker
   safe-stack  SafeStack Stack Smash Protection. Depends on
   clang/llvm >= 3.7 and requires coroutine backend ucontext.
@@ -7014,6 +7020,7 @@ NINJA=$ninja $meson setup \
 -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\
 -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
 -Dvhost_user_blk_server=$vhost_user_blk_server \
+-Db_lto=$lto \
 $cross_arg \
 "$PWD" "$source_path"
 
diff --git a/meson.build b/meson.build
index e3386196ba..ebd1c690e0 100644
--- a/meson.build
+++ b/meson.build
@@ -2044,6 +2044,7 @@ summary_info += {'gprof enabled': 
config_host.has_key('CONFIG_GPROF')}
 summary_info += {'sparse enabled':sparse.found()}
 summary_info += {'strip binaries':get_option('strip')}
 summary_info += {'profiler':  config_host.has_key('CONFIG_PROFILER')}
+summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
 summary_info += {'static build':  config_host.has_key('CONFIG_STATIC')}
 if targetos == 'darwin'
   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
-- 
2.17.1




[PATCH v4 3/5] check-block: enable iotests with cfi-icall

2020-12-04 Thread Daniele Buono
cfi-icall is a form of Control-Flow Integrity for indirect function
calls implemented by llvm. It is enabled with a -fsanitize flag.

iotests are currently disabled when -fsanitize options is used, with the
exception of SafeStack.

This patch implements a generic filtering mechanism to allow iotests
with a set of known-to-be-safe -fsanitize option. Then marks SafeStack
and the new options used for cfi-icall safe for iotests

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index f6b1bda7b9..fb4c1baae9 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -21,14 +21,18 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; 
then
 exit 0
 fi
 
-# 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}"
+# Disable tests with any sanitizer except for specific ones
+SANITIZE_FLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null )
+ALLOWED_SANITIZE_FLAGS="safe-stack cfi-icall"
+#Remove all occurrencies of allowed Sanitize flags
+for j in ${ALLOWED_SANITIZE_FLAGS}; do
+TMP_FLAGS=${SANITIZE_FLAGS}
+SANITIZE_FLAGS=""
+for i in ${TMP_FLAGS}; do
+if ! echo ${i} | grep -q "${j}" 2>/dev/null; then
+SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}"
 fi
+done
 done
 if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then
 # Have a sanitize flag that is not allowed, stop
-- 
2.17.1




[PATCH v4 2/5] cfi: Initial support for cfi-icall in QEMU

2020-12-04 Thread Daniele Buono
LLVM/Clang, supports runtime checks for forward-edge Control-Flow
Integrity (CFI).

CFI on indirect function calls (cfi-icall) ensures that, in indirect
function calls, the function called is of the right signature for the
pointer type defined at compile time.

For this check to work, the code must always respect the function
signature when using function pointer, the function must be defined
at compile time, and be compiled with link-time optimization.

This rules out, for example, shared libraries that are dynamically loaded
(given that functions are not known at compile time), and code that is
dynamically generated at run-time.

This patch:

1) Introduces the CONFIG_CFI flag to support cfi in QEMU

2) Introduces a decorator to allow the definition of "sensitive"
functions, where a non-instrumented function may be called at runtime
through a pointer. The decorator will take care of disabling cfi-icall
checks on such functions, when cfi is enabled.

3) Marks functions currently in QEMU that exhibit such behavior,
in particular:
- The function in TCG that calls pre-compiled TBs
- The function in TCI that interprets instructions
- Functions in the plugin infrastructures that jump to callbacks
- Functions in util that directly call a signal handler

Signed-off-by: Daniele Buono 
Acked-by: Alex Bennée env_ptr;
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index c76281f354..c87c242063 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -243,4 +243,16 @@ extern void QEMU_NORETURN QEMU_ERROR("code path is 
reachable")
 #define qemu_build_not_reached()  g_assert_not_reached()
 #endif
 
+#ifdef CONFIG_CFI
+/*
+ * If CFI is enabled, use an attribute to disable cfi-icall on the following
+ * function
+ */
+#define QEMU_DISABLE_CFI __attribute__((no_sanitize("cfi-icall")))
+#else
+/* If CFI is not enabled, use an empty define to not change the behavior */
+#define QEMU_DISABLE_CFI
+#endif
+
+
 #endif /* COMPILER_H */
diff --git a/plugins/core.c b/plugins/core.c
index 51bfc94787..87b823bbc4 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -31,6 +31,7 @@
 #include "tcg/tcg-op.h"
 #include "trace/mem-internal.h" /* mem_info macros */
 #include "plugin.h"
+#include "qemu/compiler.h"
 
 struct qemu_plugin_cb {
 struct qemu_plugin_ctx *ctx;
@@ -90,6 +91,12 @@ void plugin_unregister_cb__locked(struct qemu_plugin_ctx 
*ctx,
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -111,6 +118,12 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum 
qemu_plugin_event ev)
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_cb__simple(enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -128,6 +141,12 @@ static void plugin_cb__simple(enum qemu_plugin_event ev)
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_cb__udata(enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -325,6 +344,12 @@ void plugin_register_vcpu_mem_cb(GArray **arr,
 dyn_cb->f.generic = cb;
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -339,6 +364,12 @@ void qemu_plugin_tb_trans_cb(CPUState *cpu, struct 
qemu_plugin_tb *tb)
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 void
 qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, uint64_t a1, uint64_t a2,
  uint64_t a3, uint64_t a4, uint64_t a5,
@@ -358,6 +389,12 @@ qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, 
uint64_t a1, uint64_t a2,
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret)
 {
 struct qemu_plugin_cb *cb, *next;
diff --git a/plugins/loader.c b/plugins/loader.c
index 8ac5dbc20f..fd491961de 100644
--- a/plugins/loader.c
+++ b/plugins/loader.c
@@ -32,6 +32,7 @@
 #ifndef CONFIG_USER_ONLY
 #include "hw/boards.h"
 #endif
+#include "qemu/compiler.h"
 
 #include "plugin.h"
 
@@ -150,6 +151,12 @@ static uint64_t xorshift64star(uint64_t x)

[PATCH v4 0/5] Add support for Control-Flow Integrity

2020-12-04 Thread Daniele Buono
This patch adds supports for Control-Flow Integrity checks
on indirect function calls.

Requires the use of clang, and link-time optimizations

Since it's been a month, and some of the patches are being
merged independently, I thought of rebasing, retesting
and sending an updated version. Also, added a documentation
in docs/devel to explain CFI and how to handle CFI-sensitive
code.

Changes in v4:
- Removed patches to avoid clang warnings, since they are
being merged independently and are not really necessary
for CFI
- Added documentation in docs/devel to explain how to
compile with CFI, and how to disable CFI for incompatible
functions

Changes in v3:

- clang 11+ warnings are now handled directly at the source,
instead of disabling specific warnings for the whole code.
Some more work may be needed here to polish the patch, I
would kindly ask for a review from the corresponding
maintainers
- Remove configure-time checks for toolchain compatibility
with LTO.
- the decorator to disable cfi checks on functions has
been renamed and moved to include/qemu/compiler.h
- configure-time checks for cfi support and dependencies
has been moved from configure to meson

Link to v3: https://www.mail-archive.com/qemu-devel@nongnu.org/msg757930.html
Link to v2: https://www.mail-archive.com/qemu-devel@nongnu.org/msg753675.html
Link to v1: https://www.mail-archive.com/qemu-devel@nongnu.org/msg718786.html

Daniele Buono (5):
  configure,meson: add option to enable LTO
  cfi: Initial support for cfi-icall in QEMU
  check-block: enable iotests with cfi-icall
  configure,meson: support Control-Flow Integrity
  docs: Add CFI Documentation

 accel/tcg/cpu-exec.c  |  11 +++
 configure |  26 +
 docs/devel/control-flow-integrity.rst | 137 ++
 include/qemu/compiler.h   |  12 +++
 meson.build   |  46 +
 meson_options.txt |   4 +
 plugins/core.c|  37 +++
 plugins/loader.c  |   7 ++
 tcg/tci.c |   7 ++
 tests/check-block.sh  |  18 ++--
 util/main-loop.c  |  11 +++
 util/oslib-posix.c|  11 +++
 12 files changed, 320 insertions(+), 7 deletions(-)
 create mode 100644 docs/devel/control-flow-integrity.rst

-- 
2.17.1




Re: [PATCH v3 1/9] fuzz: Make fork_fuzz.ld compatible with LLVM's LLD

2020-11-19 Thread Daniele Buono

Thanks Alex,
do you think you could also give it a try linking with LLD?

just add --extra-ldflags="-fuse-ld=lld"

I do see some small differences when moving from BFD ro LLD, but they 
should not be of importance. The position of the data.fuzz* is kept.


size -A on qemu-fuzz-i386, LTO DISABLED:

BFD
section  size   addr
[...]
.got10704   29849128
.data 1160800   29859840
__sancov_pcs  3362992   31020640
.data.fuzz_start   210187   34385920
.data.fuzz_ordered 211456   34596352
.bss  9659608   34807808
.comment  225  0
[...]

BFD
section  size   addr
[...]
.got  816   27824632
.got.plt 9992   27825448
.data 1160808   27839536
.data.fuzz_start   210187   29003776
.data.fuzz_ordered 211456   29214208
.data.fuzz_end  0   29425664
.tm_clone_table 0   29425664
__sancov_pcs  3362992   29425664
.bss  9659624   32788672

I tried running the fuzzer and didn't seem to have any issues, but I
haven't tried a test-build with OSS-Fuzz. Is there a info somewhere
on how to do that?

Thanks,
Daniele

On 11/6/2020 9:50 AM, Alexander Bulekov wrote:

On 201105 1718, Daniele Buono wrote:

LLVM's linker, LLD, supports the keyword "INSERT AFTER", starting with
version 11.
However, when multiple sections are defined in the same "INSERT AFTER",
they are added in a reversed order, compared to BFD's LD.

This patch makes fork_fuzz.ld generic enough to work with both linkers.
Each section now has its own "INSERT AFTER" keyword, so proper ordering is
defined between the sections added.



Hi Daniele,
Good to know that LLVM now has support for "INSERT AFTER" :)

I compared the resulting symbols between __FUZZ_COUNTERS_{START,END}
(after linking with BFD) before/after this patch, and they look good. I
also ran a test-build with OSS-Fuzz container and confirmed that the
resulting binary also had proper symbols.

Reviewed-by: Alexander Bulekov 
Tested-by: Alexander Bulekov 

Thanks


Signed-off-by: Daniele Buono 
---
  tests/qtest/fuzz/fork_fuzz.ld | 12 +++-
  1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
index bfb667ed06..cfb88b7fdb 100644
--- a/tests/qtest/fuzz/fork_fuzz.ld
+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -16,6 +16,11 @@ SECTIONS
/* Lowest stack counter */
*(__sancov_lowest_stack);
}
+}
+INSERT AFTER .data;
+
+SECTIONS
+{
.data.fuzz_ordered :
{
/*
@@ -34,6 +39,11 @@ SECTIONS
 */
 *(.bss._ZN6fuzzer3TPCE);
}
+}
+INSERT AFTER .data.fuzz_start;
+
+SECTIONS
+{
.data.fuzz_end : ALIGN(4K)
{
__FUZZ_COUNTERS_END = .;
@@ -43,4 +53,4 @@ SECTIONS
   * Don't overwrite the SECTIONS in the default linker script. Instead insert 
the
   * above into the default script
   */
-INSERT AFTER .data;
+INSERT AFTER .data.fuzz_ordered;
--
2.17.1







Re: [PATCH v3 0/9] Add support for Control-Flow Integrity

2020-11-19 Thread Daniele Buono

Hi Alex,

Yeah I assumed it was an older version because the errors triggered by
clang11 stop the compilation.

I checked again and for oss-fuzz, you disable failing on warnings.
So again, these patches are not directly connected to CFI and therefore 
could land independently.


On 11/6/2020 9:58 AM, Alexander Bulekov wrote:

I think oss-fuzz is using a bleeding edge version of Clang, so that
might not be a problem.
Here is the oss-fuzz build-log from earlier today:
https://oss-fuzz-build-logs.storage.googleapis.com/log-1747e14f-6b87-43e0-96aa-07ea159e7eb2.txt

...
Step #4: C compiler for the host machine: clang (clang 12.0.0 "clang version 12.0.0 
(https://github.com/llvm/llvm-project.git  
c9f69ee7f94cfefc373c3c6cae08e51b11e6d3c2)")
Step #4: C linker for the host machine: clang ld.bfd 2.26.1
Step #4: Host machine cpu family: x86_64
...


Yeah I assumed it was an older version because the errors triggered by
clang11 stop the compilation.

I checked again and for oss-fuzz, you disable failing on warnings.
So again, these patches are not directly connected to CFI and therefore 
could land independently.




Re: [PATCH-for-5.2? v3 5/9] scsi: fix overflow in scsi_disk_new_request_dump

2020-11-19 Thread Daniele Buono

Hi Philippe,
Since you have a patch upcoming, may I drop this patch
from this set?

Daniele

On 11/9/2020 8:26 AM, Philippe Mathieu-Daudé wrote:

I did it. Will post later as this is 6.0 material.




Re: [PATCH-for-5.2? v3 3/9] hw/usb: reorder fields in UASStatus

2020-11-19 Thread Daniele Buono

Hi Philippe,

On 11/6/2020 9:28 AM, Philippe Mathieu-Daudé wrote:

On 11/5/20 11:18 PM, Daniele Buono wrote:

The UASStatus data structure has a variable sized field inside of type uas_iu,
that however is not placed at the end of the data structure.

This placement triggers a warning with clang 11, and while not a bug right now,
(the status is never a uas_iu_command, which is the variable-sized case),
it could become one in the future.


The problem is uas_iu_command::add_cdb, indeed.



../qemu-base/hw/usb/dev-uas.c:157:31: error: field 'status' with variable sized 
type 'uas_iu' not at the end of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]


If possible remove the "../qemu-base/" as it does not provide
any useful information.


Sure, will do at the next cycle

 uas_iustatus;
   ^
1 error generated.

Fix this by moving uas_iu at the end of the struct


Your patch silents the warning, but the problem is the same.
It would be safer/cleaner to make 'status' a pointer on the heap IMO.


I'm thinking of moving 'status' in a pointer with the following code
changes:

UASStatus is allocated in `usb_uas_alloc_status`, which currently does
not take a type or size for the union field. I'm thinking of adding
requested size for the status, like this:

static UASStatus *usb_uas_alloc_status(UASDevice *uas, uint8_t id,
uint16_t tag, size_t size);

and the common call would be
usb_uas_alloc_status([...],sizeof(uas_iu));

Also we'd need a double free when the object is freed. Right now
it's handled in the code when the object is not used anymore with a
`g_free(st);`.
I'd have to replace it with
`g_free(st->status); g_free(st);`. Would you suggest doing it place
or by adding a usb_uas_dealloc_status() function?

---

However, I am confused by the use of that variable-lenght field.
I'm looking at what seems the only place where a command is
parsed, in `usb_uas_handle_data`.

uas_iu iu;
[...]
switch (p->ep->nr) {
case UAS_PIPE_ID_COMMAND:
length = MIN(sizeof(iu), p->iov.size);
usb_packet_copy(p, , length);
[...]
break;
[...]

It would seem that the copy is limited to at most sizeof(uas_iu),
so even if we had anything in add_cdb[], that wouldn't be copied
here?

Is this intended?





Signed-off-by: Daniele Buono 
---
  hw/usb/dev-uas.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index cec071d96c..5ef3f4fec9 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -154,9 +154,9 @@ struct UASRequest {
  
  struct UASStatus {

  uint32_t  stream;
-uas_iustatus;
  uint32_t  length;
  QTAILQ_ENTRY(UASStatus)   next;
+uas_iustatus;
  };
  
  /* - */








Re: [PATCH v3 0/9] Add support for Control-Flow Integrity

2020-11-06 Thread Daniele Buono

Hi Cornelia,

I don't have a real preference either way.

So if it is acceptable to have the clang11+ patches separated and
handled by the maintainers for the proper subsystem, I'd say whatever
the maintainers prefer.

In my opinion, the patches for clang11+ support may be merged
separately.

I'm saying this because, from my tests, the only feature that needs
clang11+ to compile with Control-Flow Integrity is fuzzing.
However, the main way we're fuzzing QEMU is through OSSfuzz, and I don't
think their infrastructure is using a compiler that new, so we wouldn't
be able to enable it anyway. (Alex can chip in to confirm this)
On the other hand, if someone is looking for temporary support in-house,
they can just add -Wno-[...] as extra-cflags until the additional
patches land. (Assuming CFI lands before the clang11+ patches).

Regards,
Daniele

On 11/6/2020 7:47 AM, Cornelia Huck wrote:

On Thu,  5 Nov 2020 17:18:56 -0500
Daniele Buono  wrote:


This patch adds supports for Control-Flow Integrity checks
on indirect function calls.

Requires the use of clang, and link-time optimizations

Changes in v3:

- clang 11+ warnings are now handled directly at the source,
instead of disabling specific warnings for the whole code.
Some more work may be needed here to polish the patch, I
would kindly ask for a review from the corresponding
maintainers


Process question :)

Would you prefer to have this series merged in one go, or should
maintainers pick the patches for their subsystem?


- Remove configure-time checks for toolchain compatibility
with LTO.
- the decorator to disable cfi checks on functions has
been renamed and moved to include/qemu/compiler.h
- configure-time checks for cfi support and dependencies
has been moved from configure to meson

Link to v2: https://www.mail-archive.com/qemu-devel@nongnu.org/msg753675.html
Link to v1: https://www.mail-archive.com/qemu-devel@nongnu.org/msg718786.html

Daniele Buono (9):
   fuzz: Make fork_fuzz.ld compatible with LLVM's LLD
   s390x: fix clang 11 warnings in cpu_models.c
   hw/usb: reorder fields in UASStatus
   s390x: Avoid variable size warning in ipl.h
   scsi: fix overflow in scsi_disk_new_request_dump
   configure,meson: add option to enable LTO
   cfi: Initial support for cfi-icall in QEMU
   check-block: enable iotests with cfi-icall
   configure/meson: support Control-Flow Integrity

  accel/tcg/cpu-exec.c  | 11 +
  configure | 26 
  hw/s390x/ipl.h|  4 +--
  hw/scsi/scsi-disk.c   |  4 +++
  hw/usb/dev-uas.c  |  2 +-
  include/qemu/compiler.h   | 12 +
  meson.build   | 46 +++
  meson_options.txt |  4 +++
  plugins/core.c| 37 
  plugins/loader.c  |  7 ++
  target/s390x/cpu_models.c |  8 +++---
  tcg/tci.c |  7 ++
  tests/check-block.sh  | 18 --
  tests/qtest/fuzz/fork_fuzz.ld | 12 -
  util/main-loop.c  | 11 +
  util/oslib-posix.c| 11 +
  16 files changed, 205 insertions(+), 15 deletions(-)








[PATCH v3 3/9] hw/usb: reorder fields in UASStatus

2020-11-05 Thread Daniele Buono
The UASStatus data structure has a variable sized field inside of type uas_iu,
that however is not placed at the end of the data structure.

This placement triggers a warning with clang 11, and while not a bug right now,
(the status is never a uas_iu_command, which is the variable-sized case),
it could become one in the future.

../qemu-base/hw/usb/dev-uas.c:157:31: error: field 'status' with variable sized 
type 'uas_iu' not at the end of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]
uas_iustatus;
  ^
1 error generated.

Fix this by moving uas_iu at the end of the struct

Signed-off-by: Daniele Buono 
---
 hw/usb/dev-uas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index cec071d96c..5ef3f4fec9 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -154,9 +154,9 @@ struct UASRequest {
 
 struct UASStatus {
 uint32_t  stream;
-uas_iustatus;
 uint32_t  length;
 QTAILQ_ENTRY(UASStatus)   next;
+uas_iustatus;
 };
 
 /* - */
-- 
2.17.1




[PATCH v3 9/9] configure,meson: support Control-Flow Integrity

2020-11-05 Thread Daniele Buono
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 
---
 configure | 21 -
 meson.build   | 45 +
 meson_options.txt |  4 
 3 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 7115655fe4..020c5a6aff 100755
--- a/configure
+++ b/configure
@@ -399,6 +399,8 @@ coroutine=""
 coroutine_pool=""
 debug_stack_usage="no"
 crypto_afalg="no"
+cfi="disabled"
+cfi_debug="disabled"
 seccomp=""
 glusterfs=""
 glusterfs_xlator_opt="no"
@@ -1179,6 +1181,16 @@ for opt do
   ;;
   --disable-safe-stack) safe_stack="no"
   ;;
+  --enable-cfi)
+  cfi="enabled";
+  lto="true";
+  ;;
+  --disable-cfi) cfi="disabled"
+  ;;
+  --enable-cfi-debug) cfi_debug="enabled"
+  ;;
+  --disable-cfi-debug) cfi_debug="disabled"
+  ;;
   --disable-curses) curses="disabled"
   ;;
   --enable-curses) curses="enabled"
@@ -1753,6 +1765,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
@@ -6997,7 +7016,7 @@ NINJA=$ninja $meson setup \
 -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \
 -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\
 -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
--Db_lto=$lto \
+-Db_lto=$lto -Dcfi=$cfi -Dcfi_debug=$cfi_debug \
 $cross_arg \
 "$PWD" "$source_path"
 
diff --git a/meson.build b/meson.build
index 99c7ab1d38..49a301888e 100644
--- a/meson.build
+++ b/meson.build
@@ -751,6 +751,48 @@ statx_test = '''
 
 has_statx = cc.links(statx_test)
 
+if get_option('cfi').enabled()
+  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').enabled()
+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_

[PATCH v3 5/9] scsi: fix overflow in scsi_disk_new_request_dump

2020-11-05 Thread Daniele Buono
scsi_disk_new_request_dump is used to dump the content of a scsi request
for tracing. It does that by decoding the command to get the size of the
command buffer, and then printing the content of such buffer on a string.

When using gcc with link-time optimizations, it warns that the argument of
malloc may be too large.

In function 'scsi_disk_new_request_dump',
inlined from 'scsi_new_request' at 
../qemu-cfi-v3/hw/scsi/scsi-disk.c:2588:9:
../qemu-cfi-v3/hw/scsi/scsi-disk.c:2562:17: warning: argument 1 value 
'18446744073709551612' exceeds maximum object size 9223372036854775807 
[-Walloc-size-larger-than=]
 line_buffer = g_malloc(len * 5 + 1);
 ^
../qemu-cfi-v3/hw/scsi/scsi-disk.c: In function 'scsi_new_request':
/usr/include/glib-2.0/glib/gmem.h:78:10: note: in a call to allocation function 
'g_malloc' declared here
 gpointer g_malloc (gsize  n_bytes) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);

len is a signed integer filled up by scsi_cdb_length which can return -1
if it can't decode the command. In this case, g_malloc would probably fail.
However, an unknown command here is a possibility, and since this is used for
tracing, we should try to print the command anyway, for debugging purposes.

Since knowing the size of the command in the buffer is impossible (could not
decode the command), only print the header by setting len=1 if scsi_cdb_length
returned -1

Signed-off-by: Daniele Buono 
---
If we had a way to know the (maximum) size of the buffer, we could
alternatively dump the whole buffer, instead of dumping only the
first byte. Not sure if this can be done, nor if it is considered
a better option.

We could also produce an error instead/in addition to just dumping
the buffer, if the command cannot be decoded.

 hw/scsi/scsi-disk.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index e859534eaf..d70dfdd9dc 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2559,6 +2559,10 @@ static void scsi_disk_new_request_dump(uint32_t lun, 
uint32_t tag, uint8_t *buf)
 int len = scsi_cdb_length(buf);
 char *line_buffer, *p;
 
+if (len < 0) {
+len = 1;
+}
+
 line_buffer = g_malloc(len * 5 + 1);
 
 for (i = 0, p = line_buffer; i < len; i++) {
-- 
2.17.1




[PATCH v3 8/9] check-block: enable iotests with cfi-icall

2020-11-05 Thread Daniele Buono
cfi-icall is a form of Control-Flow Integrity for indirect function
calls implemented by llvm. It is enabled with a -fsanitize flag.

iotests are currently disabled when -fsanitize options is used, with the
exception of SafeStack.

This patch implements a generic filtering mechanism to allow iotests
with a set of known-to-be-safe -fsanitize option. Then marks SafeStack
and the new options used for cfi-icall safe for iotests

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index f6b1bda7b9..fb4c1baae9 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -21,14 +21,18 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; 
then
 exit 0
 fi
 
-# 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}"
+# Disable tests with any sanitizer except for specific ones
+SANITIZE_FLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null )
+ALLOWED_SANITIZE_FLAGS="safe-stack cfi-icall"
+#Remove all occurrencies of allowed Sanitize flags
+for j in ${ALLOWED_SANITIZE_FLAGS}; do
+TMP_FLAGS=${SANITIZE_FLAGS}
+SANITIZE_FLAGS=""
+for i in ${TMP_FLAGS}; do
+if ! echo ${i} | grep -q "${j}" 2>/dev/null; then
+SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}"
 fi
+done
 done
 if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then
 # Have a sanitize flag that is not allowed, stop
-- 
2.17.1




[PATCH v3 2/9] s390x: fix clang 11 warnings in cpu_models.c

2020-11-05 Thread Daniele Buono
There are void * pointers that get casted to enums, in cpu_models.c
Such casts can result in a small integer type and are caught as
warnings with clang, starting with version 11:

Clang 11 finds a bunch of spots in the code that trigger this new warnings:

../qemu-base/target/s390x/cpu_models.c:985:21: error: cast to smaller integer 
type 'S390Feat' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390Feat feat = (S390Feat) opaque;
^
../qemu-base/target/s390x/cpu_models.c:1002:21: error: cast to smaller integer 
type 'S390Feat' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390Feat feat = (S390Feat) opaque;
^
../qemu-base/target/s390x/cpu_models.c:1036:27: error: cast to smaller integer 
type 'S390FeatGroup' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390FeatGroup group = (S390FeatGroup) opaque;
  ^~
../qemu-base/target/s390x/cpu_models.c:1057:27: error: cast to smaller integer 
type 'S390FeatGroup' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390FeatGroup group = (S390FeatGroup) opaque;
  ^~
4 errors generated.

Avoid this warning by casting the pointer to uintptr_t first.

Signed-off-by: Daniele Buono 
---
 target/s390x/cpu_models.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 461e0b8f4a..b5abff8bef 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -986,7 +986,7 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp)
 static void get_feature(Object *obj, Visitor *v, const char *name,
 void *opaque, Error **errp)
 {
-S390Feat feat = (S390Feat) opaque;
+S390Feat feat = (S390Feat) (uintptr_t) opaque;
 S390CPU *cpu = S390_CPU(obj);
 bool value;
 
@@ -1003,7 +1003,7 @@ static void get_feature(Object *obj, Visitor *v, const 
char *name,
 static void set_feature(Object *obj, Visitor *v, const char *name,
 void *opaque, Error **errp)
 {
-S390Feat feat = (S390Feat) opaque;
+S390Feat feat = (S390Feat) (uintptr_t) opaque;
 DeviceState *dev = DEVICE(obj);
 S390CPU *cpu = S390_CPU(obj);
 bool value;
@@ -1037,7 +1037,7 @@ static void set_feature(Object *obj, Visitor *v, const 
char *name,
 static void get_feature_group(Object *obj, Visitor *v, const char *name,
   void *opaque, Error **errp)
 {
-S390FeatGroup group = (S390FeatGroup) opaque;
+S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque;
 const S390FeatGroupDef *def = s390_feat_group_def(group);
 S390CPU *cpu = S390_CPU(obj);
 S390FeatBitmap tmp;
@@ -1058,7 +1058,7 @@ static void get_feature_group(Object *obj, Visitor *v, 
const char *name,
 static void set_feature_group(Object *obj, Visitor *v, const char *name,
   void *opaque, Error **errp)
 {
-S390FeatGroup group = (S390FeatGroup) opaque;
+S390FeatGroup group = (S390FeatGroup) (uintptr_t) opaque;
 const S390FeatGroupDef *def = s390_feat_group_def(group);
 DeviceState *dev = DEVICE(obj);
 S390CPU *cpu = S390_CPU(obj);
-- 
2.17.1




[PATCH v3 6/9] configure,meson: add option to enable LTO

2020-11-05 Thread Daniele Buono
This patch allows to compile QEMU with link-time optimization (LTO).
Compilation with LTO is handled directly by meson. This patch only
adds the option in configure and forwards the request to meson

Tested with all major versions of clang from 6 to 12

Signed-off-by: Daniele Buono 
---
 configure   | 7 +++
 meson.build | 1 +
 2 files changed, 8 insertions(+)

diff --git a/configure b/configure
index 2c3c69f118..7115655fe4 100755
--- a/configure
+++ b/configure
@@ -242,6 +242,7 @@ host_cc="cc"
 audio_win_int=""
 libs_qga=""
 debug_info="yes"
+lto="false"
 stack_protector=""
 safe_stack=""
 use_containers="yes"
@@ -1166,6 +1167,10 @@ for opt do
   ;;
   --disable-werror) werror="no"
   ;;
+  --enable-lto) lto="true"
+  ;;
+  --disable-lto) lto="false"
+  ;;
   --enable-stack-protector) stack_protector="yes"
   ;;
   --disable-stack-protector) stack_protector="no"
@@ -1744,6 +1749,7 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   module-upgrades try to load modules from alternate paths for upgrades
   debug-tcg   TCG debugging (default is disabled)
   debug-info  debugging information
+  lto Enable Link-Time Optimization.
   sparse  sparse checker
   safe-stack  SafeStack Stack Smash Protection. Depends on
   clang/llvm >= 3.7 and requires coroutine backend ucontext.
@@ -6991,6 +6997,7 @@ NINJA=$ninja $meson setup \
 -Dcapstone=$capstone -Dslirp=$slirp -Dfdt=$fdt \
 -Diconv=$iconv -Dcurses=$curses -Dlibudev=$libudev\
 -Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
+-Db_lto=$lto \
 $cross_arg \
 "$PWD" "$source_path"
 
diff --git a/meson.build b/meson.build
index 39ac5cf6d8..99c7ab1d38 100644
--- a/meson.build
+++ b/meson.build
@@ -2023,6 +2023,7 @@ summary_info += {'gprof enabled': 
config_host.has_key('CONFIG_GPROF')}
 summary_info += {'sparse enabled':sparse.found()}
 summary_info += {'strip binaries':get_option('strip')}
 summary_info += {'profiler':  config_host.has_key('CONFIG_PROFILER')}
+summary_info += {'link-time optimization (LTO)': get_option('b_lto')}
 summary_info += {'static build':  config_host.has_key('CONFIG_STATIC')}
 if targetos == 'darwin'
   summary_info += {'Cocoa support': config_host.has_key('CONFIG_COCOA')}
-- 
2.17.1




[PATCH v3 4/9] s390x: Avoid variable size warning in ipl.h

2020-11-05 Thread Daniele Buono
S390IPLState contains two IplParameterBlock, which may in turn have
either a IPLBlockPV or a IplBlockFcp, both ending with a variable
sized field (an array).

This causes a warning with clang 11 or greater, which checks that
variable sized type are only allocated at the end of the struct:

In file included from ../qemu-cfi-v3/target/s390x/diag.c:21:
../qemu-cfi-v3/hw/s390x/ipl.h:161:23: error: field 'iplb' with variable sized 
type 'IplParameterBlock' (aka 'union IplParameterBlock') not at the end of a 
struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]
IplParameterBlock iplb;
  ^
../qemu-cfi-v3/hw/s390x/ipl.h:162:23: error: field 'iplb_pv' with variable 
sized type 'IplParameterBlock' (aka 'union IplParameterBlock') not at the end 
of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]
IplParameterBlock iplb_pv;

In this case, however, the warning is a false positive, because
IPLBlockPV and IplBlockFcp are allocated in a union wrapped at 4K,
making the union non-variable sized.

Fix the warning by turning the two variable sized arrays into arrays
of size 0. This avoids the compiler error and should produce the
same code.

Signed-off-by: Daniele Buono 
---
There is the possibility of removing  IplBlockFcp from
IplParameterBlock, since it is not actually used.
This would also allow to entirely remove the definition of
IplBlockFcp, but we may want to keep it for completeness.

 hw/s390x/ipl.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 9e90169695..dfc6dfd89c 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -32,7 +32,7 @@ struct IPLBlockPV {
 uint32_t num_comp;  /* 0x74 */
 uint64_t pv_header_addr;/* 0x78 */
 uint64_t pv_header_len; /* 0x80 */
-struct IPLBlockPVComp components[];
+struct IPLBlockPVComp components[0];
 } QEMU_PACKED;
 typedef struct IPLBlockPV IPLBlockPV;
 
@@ -63,7 +63,7 @@ struct IplBlockFcp {
 uint64_t br_lba;
 uint32_t scp_data_len;
 uint8_t  reserved6[260];
-uint8_t  scp_data[];
+uint8_t  scp_data[0];
 } QEMU_PACKED;
 typedef struct IplBlockFcp IplBlockFcp;
 
-- 
2.17.1




[PATCH v3 1/9] fuzz: Make fork_fuzz.ld compatible with LLVM's LLD

2020-11-05 Thread Daniele Buono
LLVM's linker, LLD, supports the keyword "INSERT AFTER", starting with
version 11.
However, when multiple sections are defined in the same "INSERT AFTER",
they are added in a reversed order, compared to BFD's LD.

This patch makes fork_fuzz.ld generic enough to work with both linkers.
Each section now has its own "INSERT AFTER" keyword, so proper ordering is
defined between the sections added.

Signed-off-by: Daniele Buono 
---
 tests/qtest/fuzz/fork_fuzz.ld | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
index bfb667ed06..cfb88b7fdb 100644
--- a/tests/qtest/fuzz/fork_fuzz.ld
+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -16,6 +16,11 @@ SECTIONS
   /* Lowest stack counter */
   *(__sancov_lowest_stack);
   }
+}
+INSERT AFTER .data;
+
+SECTIONS
+{
   .data.fuzz_ordered :
   {
   /*
@@ -34,6 +39,11 @@ SECTIONS
*/
*(.bss._ZN6fuzzer3TPCE);
   }
+}
+INSERT AFTER .data.fuzz_start;
+
+SECTIONS
+{
   .data.fuzz_end : ALIGN(4K)
   {
   __FUZZ_COUNTERS_END = .;
@@ -43,4 +53,4 @@ SECTIONS
  * Don't overwrite the SECTIONS in the default linker script. Instead insert 
the
  * above into the default script
  */
-INSERT AFTER .data;
+INSERT AFTER .data.fuzz_ordered;
-- 
2.17.1




[PATCH v3 7/9] cfi: Initial support for cfi-icall in QEMU

2020-11-05 Thread Daniele Buono
LLVM/Clang, supports runtime checks for forward-edge Control-Flow
Integrity (CFI).

CFI on indirect function calls (cfi-icall) ensures that, in indirect
function calls, the function called is of the right signature for the
pointer type defined at compile time.

For this check to work, the code must always respect the function
signature when using function pointer, the function must be defined
at compile time, and be compiled with link-time optimization.

This rules out, for example, shared libraries that are dynamically loaded
(given that functions are not known at compile time), and code that is
dynamically generated at run-time.

This patch:

1) Introduces the CONFIG_CFI flag to support cfi in QEMU

2) Introduces a decorator to allow the definition of "sensitive"
functions, where a non-instrumented function may be called at runtime
through a pointer. The decorator will take care of disabling cfi-icall
checks on such functions, when cfi is enabled.

3) Marks functions currently in QEMU that exhibit such behavior,
in particular:
- The function in TCG that calls pre-compiled TBs
- The function in TCI that interprets instructions
- Functions in the plugin infrastructures that jump to callbacks
- Functions in util that directly call a signal handler

Signed-off-by: Daniele Buono 
Acked-by: Alex Bennée  for plugins
---
 accel/tcg/cpu-exec.c| 11 +++
 include/qemu/compiler.h | 12 
 plugins/core.c  | 37 +
 plugins/loader.c|  7 +++
 tcg/tci.c   |  7 +++
 util/main-loop.c| 11 +++
 util/oslib-posix.c  | 11 +++
 7 files changed, 96 insertions(+)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 58aea605d8..ffe0e1e3fb 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -26,6 +26,7 @@
 #include "exec/exec-all.h"
 #include "tcg/tcg.h"
 #include "qemu/atomic.h"
+#include "qemu/compiler.h"
 #include "sysemu/qtest.h"
 #include "qemu/timer.h"
 #include "qemu/rcu.h"
@@ -144,6 +145,16 @@ static void init_delay_params(SyncClocks *sc, const 
CPUState *cpu)
 #endif /* CONFIG USER ONLY */
 
 /* Execute a TB, and fix up the CPU state afterwards if necessary */
+/*
+ * Disable CFI checks.
+ * TCG creates binary blobs at runtime, with the transformed code.
+ * A TB is a blob of binary code, created at runtime and called with an
+ * indirect function call. Since such function did not exist at compile time,
+ * the CFI runtime has no way to verify its signature and would fail.
+ * TCG is not considered a security-sensitive part of QEMU so this does not
+ * affect the impact of CFI in environment with high security requirements
+ */
+QEMU_DISABLE_CFI
 static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock 
*itb)
 {
 CPUArchState *env = cpu->env_ptr;
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index c76281f354..c87c242063 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -243,4 +243,16 @@ extern void QEMU_NORETURN QEMU_ERROR("code path is 
reachable")
 #define qemu_build_not_reached()  g_assert_not_reached()
 #endif
 
+#ifdef CONFIG_CFI
+/*
+ * If CFI is enabled, use an attribute to disable cfi-icall on the following
+ * function
+ */
+#define QEMU_DISABLE_CFI __attribute__((no_sanitize("cfi-icall")))
+#else
+/* If CFI is not enabled, use an empty define to not change the behavior */
+#define QEMU_DISABLE_CFI
+#endif
+
+
 #endif /* COMPILER_H */
diff --git a/plugins/core.c b/plugins/core.c
index 51bfc94787..87b823bbc4 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -31,6 +31,7 @@
 #include "tcg/tcg-op.h"
 #include "trace/mem-internal.h" /* mem_info macros */
 #include "plugin.h"
+#include "qemu/compiler.h"
 
 struct qemu_plugin_cb {
 struct qemu_plugin_ctx *ctx;
@@ -90,6 +91,12 @@ void plugin_unregister_cb__locked(struct qemu_plugin_ctx 
*ctx,
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -111,6 +118,12 @@ static void plugin_vcpu_cb__simple(CPUState *cpu, enum 
qemu_plugin_event ev)
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_cb__simple(enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;
@@ -128,6 +141,12 @@ static void plugin_cb__simple(enum qemu_plugin_event ev)
 }
 }
 
+/*
+ * Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information
+ */
+QEMU_DISABLE_CFI
 static void plugin_cb__udata(enum qemu_plugin

[PATCH v3 0/9] Add support for Control-Flow Integrity

2020-11-05 Thread Daniele Buono
This patch adds supports for Control-Flow Integrity checks
on indirect function calls.

Requires the use of clang, and link-time optimizations

Changes in v3:

- clang 11+ warnings are now handled directly at the source,
instead of disabling specific warnings for the whole code.
Some more work may be needed here to polish the patch, I
would kindly ask for a review from the corresponding
maintainers
- Remove configure-time checks for toolchain compatibility
with LTO.
- the decorator to disable cfi checks on functions has
been renamed and moved to include/qemu/compiler.h
- configure-time checks for cfi support and dependencies
has been moved from configure to meson

Link to v2: https://www.mail-archive.com/qemu-devel@nongnu.org/msg753675.html
Link to v1: https://www.mail-archive.com/qemu-devel@nongnu.org/msg718786.html

Daniele Buono (9):
  fuzz: Make fork_fuzz.ld compatible with LLVM's LLD
  s390x: fix clang 11 warnings in cpu_models.c
  hw/usb: reorder fields in UASStatus
  s390x: Avoid variable size warning in ipl.h
  scsi: fix overflow in scsi_disk_new_request_dump
  configure,meson: add option to enable LTO
  cfi: Initial support for cfi-icall in QEMU
  check-block: enable iotests with cfi-icall
  configure/meson: support Control-Flow Integrity

 accel/tcg/cpu-exec.c  | 11 +
 configure | 26 
 hw/s390x/ipl.h|  4 +--
 hw/scsi/scsi-disk.c   |  4 +++
 hw/usb/dev-uas.c  |  2 +-
 include/qemu/compiler.h   | 12 +
 meson.build   | 46 +++
 meson_options.txt |  4 +++
 plugins/core.c| 37 
 plugins/loader.c  |  7 ++
 target/s390x/cpu_models.c |  8 +++---
 tcg/tci.c |  7 ++
 tests/check-block.sh  | 18 --
 tests/qtest/fuzz/fork_fuzz.ld | 12 -
 util/main-loop.c  | 11 +
 util/oslib-posix.c| 11 +
 16 files changed, 205 insertions(+), 15 deletions(-)

-- 
2.17.1




Re: [PATCH v2 3/6] configure: add option to enable LTO

2020-10-28 Thread Daniele Buono

On 10/28/2020 5:35 AM, Alex Bennée wrote:

Breakage in both system and linux-user emulation probably points at
something in the instruction decode being broken. Shame we don't have a
working risu setup for sparc64 to give the instruction handling a proper
work out.


This is what I'm thinking too. Interesting bit is that sparc32
seem to work fine, and it should be the same codebase.

I played a bit with a couple of days but couldn't isolate the faulty
instruction.  But I'd be happy to work on this issue with someone,
perhaps from the sparc maintainers, to see if we can find out what's
happening



Re: [PATCH v2 3/6] configure: add option to enable LTO

2020-10-28 Thread Daniele Buono

If LTO is enabled with the wrong linker/ar:
- with the checks, it will exit at configure with an error. I can change 
this in a warning and disabling LTO if preferred.

- without the checks compilation will fail

If LTO is enabled with the wrong compiler (e.g. old gcc), you may get a 
bunch of warnings at compile time, and a binary that won't pass some of 
the tests in make check.


On 10/28/2020 2:44 AM, Paolo Bonzini wrote:

On 27/10/20 21:42, Daniele Buono wrote:

Ok, no problem. I can definitely disable the check on GCC.

Paolo, would you like me to disable checks on AR/linker for lto too?
If so, should I add some of this information on a document, perhaps
docs/devel/lto.rst, so it is written somewhere for future uses?


I am not sure of the effects.  Does it simply effectively disable LTO or
is it something worse?

I'll look into the SCSI issue.

Paolo





Re: [PATCH v2 3/6] configure: add option to enable LTO

2020-10-27 Thread Daniele Buono

Ok, no problem. I can definitely disable the check on GCC.

Paolo, would you like me to disable checks on AR/linker for lto too?
If so, should I add some of this information on a document, perhaps
docs/devel/lto.rst, so it is written somewhere for future uses?

--

Btw, using lto with gcc I found another interesting warning here
(adding scsi maintainer so they can chip in on the solution):

In function 'scsi_disk_new_request_dump',
inlined from 'scsi_new_request' at 
../qemu-cfi-v3/hw/scsi/scsi-disk.c:2588:9:
../qemu-cfi-v3/hw/scsi/scsi-disk.c:2562:17: warning: argument 1 value 
'18446744073709551612' exceeds maximum object size 9223372036854775807 
[-Walloc-size-larger-than=]

 line_buffer = g_malloc(len * 5 + 1);
 ^
../qemu-cfi-v3/hw/scsi/scsi-disk.c: In function 'scsi_new_request':
/usr/include/glib-2.0/glib/gmem.h:78:10: note: in a call to allocation 
function 'g_malloc' declared here
 gpointer g_malloc (gsize  n_bytes) G_GNUC_MALLOC 
G_GNUC_ALLOC_SIZE(1);


This seems like a bug to me. len is a signed integer filled up by
scsi_cdb_length which can return -1 if it can't decode the command.
What would probably happen is that we try a g_malloc with something too
big and that would fail. However, scsi_disk_new_request_dump is used for
tracing and:

a) I believe an unknown command here is a possibility, and is
handled by the caller - scsi_new_request - that has the following:

command = buf[0];
ops = scsi_disk_reqops_dispatch[command];
if (!ops) {
ops = _disk_emulate_reqops;
}

so a termination here on the malloc is probably not desired.

b) In the tracing, we should probably print the content of the buffer
anyway, so that the unknown command can be debugged. However, I don't
know what size I should use here.
I'm thinking either 1, to print just the command header in the buffer,
or the max size of the buffer, which I am not sure how to get.

Ideas or you prefer having an initial patch and then discuss it there?

On 10/27/2020 11:17 AM, Daniel P. Berrangé wrote:

On Tue, Oct 27, 2020 at 10:57:14AM -0400, Daniele Buono wrote:

In terms of ar and linker, if you don't have the right mix it will just
stop at link time with an error.

In terms of using gcc the errors may be a bit more subtle, similar to
what Daniel mentioned. Succesfully compiling but then showing issues at
runtime or in the test suite.

I'm using ubuntu 18.04 and the stock compiler (based on gcc 7.5) issues
a bunch of warnings but compile succesfully with LTO.
However, the tcg binary for sparc64 is broken. System-wide emulation
stops in OpenFirmware with an exception. User emulation triggers a
segmentation fault in some of the test cases. If I compile QEMU with
--enable-debug the tests magically work.

I briefly tested with gcc-9 and that seemed to work ok, buy your mileage
may vary


This why we shouldn't artificially block use of LTO with GCC in
the configure script. It blocks completely legitimate usage of
LTO with GCC versions where it works.

The user can detect if their version of GCC is broken by running the
test suite during their build process, which is best practice already,
and actually testing the result.



On 10/26/2020 11:50 AM, Daniel P. Berrangé wrote:

On Mon, Oct 26, 2020 at 10:51:43AM +0100, Paolo Bonzini wrote:

On 23/10/20 22:06, Daniele Buono wrote:

This patch allows to compile QEMU with link-time optimization (LTO).
Compilation with LTO is handled directly by meson. This patch adds checks
in configure to make sure the toolchain supports LTO.

Currently, allow LTO only with clang, since I have found a couple of issues
with gcc-based LTO.

In case fuzzing is enabled, automatically switch to llvm's linker (lld).
The standard bfd linker has a bug where function wrapping (used by the fuzz*
targets) is used in conjunction with LTO.

Tested with all major versions of clang from 6 to 12

Signed-off-by: Daniele Buono 


What are the problems like if you have GCC or you ar/linker are not up
to the job?  I wouldn't mind omitting the tests since this has to be
enabled explicitly by the user.


We temporarily disabled LTO in Fedora rawhide due to GCC bugs causing
wierd test suite asserts. Those were pre-release versions of GCC/binutils
though. I've just tested again and LTO works correctly, so I've enabled
LTO once again.

Regards,
Daniel





Regards,
Daniel





Re: [PATCH v2 2/6] configure: avoid new clang 11+ warnings

2020-10-27 Thread Daniele Buono

So what I would do for the warning in IplParameterBlock is the following
(if I got the comments right):

- Remove IplBlockFcp from IplParameterBlock
- Keep IPLBlockPV and, in its declaration, use
struct IPLBlockPVComp components[0];

Now for the IplBlockFcp struct declaration, it does not seem to be used
anywhere now.
I could either keep it as it was before (with the variable-size array)
or remove it entirely.
I guess this is more a question for the maintainers, what is your
preference here?

Daniele

On 10/27/2020 7:38 AM, Cornelia Huck wrote:

On Tue, 27 Oct 2020 12:26:21 +0100
Thomas Huth  wrote:


On 26/10/2020 16.12, Paolo Bonzini wrote:

On 26/10/20 16:03, Daniele Buono wrote:

Hi Paolo,
I reorganized UASStatus to put uas_iu at the end and it works fine.
Unfortunately, this uncovered another part of the code with a similar
issue (variable sized type not at the end of the struct), here:

In file included from ../qemu-cfi-v3/target/s390x/diag.c:21:
../qemu-cfi-v3/hw/s390x/ipl.h:161:23: error: field 'iplb' with variable
sized type 'IplParameterBlock' (aka 'union IplParameterBlock') not at
the end of a struct or class is a GNU extension
[-Werror,-Wgnu-variable-sized-type-not-at-end]
     IplParameterBlock iplb;
   ^
../qemu-cfi-v3/hw/s390x/ipl.h:162:23: error: field 'iplb_pv' with
variable sized type 'IplParameterBlock' (aka 'union IplParameterBlock')
not at the end of a struct or class is a GNU extension
[-Werror,-Wgnu-variable-sized-type-not-at-end]
     IplParameterBlock iplb_pv;

My understanding is that each of these IplParameterBlock may contain
either a IPLBlockPV or a IplBlockFcp, which both end with a variable
sized field (an array).

Adding maintainers of s390x to see if they have a suggested solution to
avoid disabling the warning.


This one seems okay because the union constrains the size to 4K. If
"[0]" is enough to shut up the compiler, I'd say do that.


The "IplBlockFcp fcp" part seems to be completely unused, so I think you
could even remove that IplBlockFcp struct. For IPLBlockPV I agree with
Paolo, it's likely easiest to use [0] for that struct.


The fcp block had probably been added for completeness' sake, but we do
not support list-directed IPL anyway. Not sure if we actually want it,
as we use a different mechanism for IPLing from SCSI devices. So yes,
maybe we should just drop it.






Re: [PATCH v2 3/6] configure: add option to enable LTO

2020-10-27 Thread Daniele Buono

In terms of ar and linker, if you don't have the right mix it will just
stop at link time with an error.

In terms of using gcc the errors may be a bit more subtle, similar to
what Daniel mentioned. Succesfully compiling but then showing issues at
runtime or in the test suite.

I'm using ubuntu 18.04 and the stock compiler (based on gcc 7.5) issues
a bunch of warnings but compile succesfully with LTO.
However, the tcg binary for sparc64 is broken. System-wide emulation
stops in OpenFirmware with an exception. User emulation triggers a
segmentation fault in some of the test cases. If I compile QEMU with
--enable-debug the tests magically work.

I briefly tested with gcc-9 and that seemed to work ok, buy your mileage
may vary

On 10/26/2020 11:50 AM, Daniel P. Berrangé wrote:

On Mon, Oct 26, 2020 at 10:51:43AM +0100, Paolo Bonzini wrote:

On 23/10/20 22:06, Daniele Buono wrote:

This patch allows to compile QEMU with link-time optimization (LTO).
Compilation with LTO is handled directly by meson. This patch adds checks
in configure to make sure the toolchain supports LTO.

Currently, allow LTO only with clang, since I have found a couple of issues
with gcc-based LTO.

In case fuzzing is enabled, automatically switch to llvm's linker (lld).
The standard bfd linker has a bug where function wrapping (used by the fuzz*
targets) is used in conjunction with LTO.

Tested with all major versions of clang from 6 to 12

Signed-off-by: Daniele Buono 


What are the problems like if you have GCC or you ar/linker are not up
to the job?  I wouldn't mind omitting the tests since this has to be
enabled explicitly by the user.


We temporarily disabled LTO in Fedora rawhide due to GCC bugs causing
wierd test suite asserts. Those were pre-release versions of GCC/binutils
though. I've just tested again and LTO works correctly, so I've enabled
LTO once again.

Regards,
Daniel





Re: [PATCH v2 2/6] configure: avoid new clang 11+ warnings

2020-10-26 Thread Daniele Buono

Using an array of length 0 seems to be enough to avoid the warning
Will use that solution in v3.

Thanks,
Daniele

On 10/26/2020 11:12 AM, Paolo Bonzini wrote:

On 26/10/20 16:03, Daniele Buono wrote:

Hi Paolo,
I reorganized UASStatus to put uas_iu at the end and it works fine.
Unfortunately, this uncovered another part of the code with a similar
issue (variable sized type not at the end of the struct), here:

In file included from ../qemu-cfi-v3/target/s390x/diag.c:21:
../qemu-cfi-v3/hw/s390x/ipl.h:161:23: error: field 'iplb' with variable
sized type 'IplParameterBlock' (aka 'union IplParameterBlock') not at
the end of a struct or class is a GNU extension
[-Werror,-Wgnu-variable-sized-type-not-at-end]
     IplParameterBlock iplb;
   ^
../qemu-cfi-v3/hw/s390x/ipl.h:162:23: error: field 'iplb_pv' with
variable sized type 'IplParameterBlock' (aka 'union IplParameterBlock')
not at the end of a struct or class is a GNU extension
[-Werror,-Wgnu-variable-sized-type-not-at-end]
     IplParameterBlock iplb_pv;

My understanding is that each of these IplParameterBlock may contain
either a IPLBlockPV or a IplBlockFcp, which both end with a variable
sized field (an array).

Adding maintainers of s390x to see if they have a suggested solution to
avoid disabling the warning.


This one seems okay because the union constrains the size to 4K. If
"[0]" is enough to shut up the compiler, I'd say do that.

Paolo





Re: [PATCH v2 2/6] configure: avoid new clang 11+ warnings

2020-10-26 Thread Daniele Buono

Hi Paolo,
I reorganized UASStatus to put uas_iu at the end and it works fine.
Unfortunately, this uncovered another part of the code with a similar
issue (variable sized type not at the end of the struct), here:

In file included from ../qemu-cfi-v3/target/s390x/diag.c:21:
../qemu-cfi-v3/hw/s390x/ipl.h:161:23: error: field 'iplb' with variable 
sized type 'IplParameterBlock' (aka 'union IplParameterBlock') not at 
the end of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]

IplParameterBlock iplb;
  ^
../qemu-cfi-v3/hw/s390x/ipl.h:162:23: error: field 'iplb_pv' with 
variable sized type 'IplParameterBlock' (aka 'union IplParameterBlock') 
not at the end of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]

IplParameterBlock iplb_pv;

My understanding is that each of these IplParameterBlock may contain
either a IPLBlockPV or a IplBlockFcp, which both end with a variable
sized field (an array).

Adding maintainers of s390x to see if they have a suggested solution to
avoid disabling the warning.

On 10/26/2020 5:50 AM, Paolo Bonzini wrote:

On 23/10/20 22:06, Daniele Buono wrote:

1 error generated.

The data structure is UASStatus, which must end with a QTAILQ_ENTRY, so
I believe we cannot have uas_iu at the end. Since this is a gnu
extension but CLANG supports it, just add
-Wno-gnu-variable-sized-type-not-at-end


This is potentially a real bug, in this case it works only because
UASStatus's packet is never uas_iu_command (which has the variable sized
type).

The QTAILQ_ENTRY need not be at the end, please rearrange UASStatus's
field so that the "usb_ui status" field is the last.

Thanks,

Paolo





Re: [PATCH v2 2/6] configure: avoid new clang 11+ warnings

2020-10-24 Thread Daniele Buono

On 10/24/2020 1:17 AM, Thomas Huth wrote:

Compiling all code with -Wno-void-pointer-to-enum-cast sounds like the wrong
approach to me, since this might hide some real bugs in other spots instead.

Could you please try to cast the value through (uintptr_t) first, e.g. :

 S390Feat feat = (S390Feat)(uintptr_t) opaque;

It's a little bit ugly, but still better than to disable the warning
globally, I think.

  Thomas


Hi Thomas,
I did a quick check and casting to a uintptr_t seem to be a working
solution to the issue. I will fix this in v3

Thanks,
Daniele



Re: [PATCH v2 0/6] Add support for Control-Flow Integrity

2020-10-24 Thread Daniele Buono

On 10/23/2020 4:33 PM, Eric Blake wrote:

On 10/23/20 3:06 PM, Daniele Buono wrote:

v2: Several months (and structural changes in QEMU) have passed since v1.
While the spirit of the patch is similar, the implementation is changed
in multiple points, and should address most if not all the comments
received in v1.



5) Most of the logic to enable CFI goes in the configure, since it's
just a matter of checking for dependencies and incompatible options.
However, I had to disable CFI checks for a few TCG functions.
This can only be done through a blacklist file. I added a file in the
root of QEMU, called cfi-blacklist.txt for such purpose. I am open to
suggestions on where the file should go, and I am willing to become the
maintainer of it, if deemed necessary.


In the meantime, we have commits like:

commit b199c682f1f0aaee22b2170a5fb885250057eec2
Author: Philippe Mathieu-Daudé 
Date:   Thu Sep 10 09:01:31 2020 +0200

 target/i386/kvm: Rename host_tsx_blacklisted() as host_tsx_broken()

 In order to use inclusive terminology, rename host_tsx_blacklisted()
 as host_tsx_broken().

which may help you in coming up with a more appropriate name for the new
file.



  MAINTAINERS   |   5 +
  accel/tcg/cpu-exec.c  |   9 ++
  configure | 214 ++
  include/qemu/sanitizers.h |  22 
  meson.build   |   3 +
  plugins/core.c|  25 
  plugins/loader.c  |   5 +
  tcg/tci.c |   5 +
  tests/check-block.sh  |  18 +--
  tests/qtest/fuzz/fork_fuzz.ld |  12 +-
  util/main-loop.c  |   9 ++
  util/oslib-posix.c|   9 ++
  12 files changed, 328 insertions(+), 8 deletions(-)
  create mode 100644 include/qemu/sanitizers.h


although I don't see a new file by that name here, so perhaps the v1
overview is now stale?


Correct, the v1 overview is stale on that regard. V2 is not using a
"broken" file anymore. CFI is now disabled by using an attribute
directly on the code.

From the v2 overview:
* Instead of disabling CFI in specific functions by using a filter file,
  disable cfi by using a new decorator to be prefixed to the function
  definition.

Beside the removal of a non-inclusive term, I believe this is a better
way to track functions, since it is directly inside the code so everyone
working on those functions will see it immediately. It's safer with
regards of function naming changes and, hopefully, this will make
maintaining cfi easier.



[PATCH v2 5/6] check-block: enable iotests with cfi-icall

2020-10-23 Thread Daniele Buono
cfi-icall is a form of Control-Flow Integrity for indirect function
calls implemented by llvm. It is enabled with a -fsanitize flag.

iotests are currently disabled when -fsanitize options is used, with the
exception of SafeStack.

This patch implements a generic filtering mechanism to allow iotests
with a set of known-to-be-safe -fsanitize option. Then marks SafeStack
and the new options used for cfi-icall safe for iotests

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index f6b1bda7b9..fb4c1baae9 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -21,14 +21,18 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; 
then
 exit 0
 fi
 
-# 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}"
+# Disable tests with any sanitizer except for specific ones
+SANITIZE_FLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null )
+ALLOWED_SANITIZE_FLAGS="safe-stack cfi-icall"
+#Remove all occurrencies of allowed Sanitize flags
+for j in ${ALLOWED_SANITIZE_FLAGS}; do
+TMP_FLAGS=${SANITIZE_FLAGS}
+SANITIZE_FLAGS=""
+for i in ${TMP_FLAGS}; do
+if ! echo ${i} | grep -q "${j}" 2>/dev/null; then
+SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}"
 fi
+done
 done
 if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then
 # Have a sanitize flag that is not allowed, stop
-- 
2.17.1




[PATCH v2 4/6] cfi: Initial support for cfi-icall in QEMU

2020-10-23 Thread Daniele Buono
LLVM/Clang, supports runtime checks for forward-edge Control-Flow
Integrity (CFI).

CFI on indirect function calls (cfi-icall) ensures that, in indirect
function calls, the function called is of the right signature for the
pointer type defined at compile time.

For this check to work, the code must always respect the function
signature when using function pointer, the function must be defined
at compile time, and be compiled with link-time optimization.

This rules out, for example, shared libraries that are dynamically loaded
(given that functions are not known at compile time), and code that is
dynamically generated at run-time.

This patch:

1) Introduces the CONFIG_CFI flag to support cfi in QEMU

2) Introduces a decorator to allow the definition of "sensitive"
functions, where a non-instrumented function may be called at runtime
through a pointer. The decorator will take care of disabling cfi-icall
checks on such functions, when cfi is enabled.

3) Marks functions currently in QEMU that exhibit such behavior,
in particular:
- The function in TCG that calls pre-compiled TBs
- The function in TCI that interprets instructions
- Functions in the plugin infrastructures that jump to callbacks
- Functions in util that directly call a signal handler

4) Add a new section in MAINTAINERS with me as a maintainer for
include/qemu/sanitizers.h, in case a maintainer is deemed
necessary for this feature

Signed-off-by: Daniele Buono 
---
 MAINTAINERS   |  5 +
 accel/tcg/cpu-exec.c  |  9 +
 include/qemu/sanitizers.h | 22 ++
 plugins/core.c| 25 +
 plugins/loader.c  |  5 +
 tcg/tci.c |  5 +
 util/main-loop.c  |  9 +
 util/oslib-posix.c|  9 +
 8 files changed, 89 insertions(+)
 create mode 100644 include/qemu/sanitizers.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6a197bd358..93b2b52b88 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3094,6 +3094,11 @@ S: Maintained
 F: hw/semihosting/
 F: include/hw/semihosting/
 
+Control Flow Integrity
+M: Daniele Buono 
+S: Maintained
+F: include/qemu/sanitizers.h
+
 Build and test automation
 -
 Build and test automation
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 58aea605d8..efa01c51db 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -26,6 +26,7 @@
 #include "exec/exec-all.h"
 #include "tcg/tcg.h"
 #include "qemu/atomic.h"
+#include "qemu/sanitizers.h"
 #include "sysemu/qtest.h"
 #include "qemu/timer.h"
 #include "qemu/rcu.h"
@@ -144,6 +145,14 @@ static void init_delay_params(SyncClocks *sc, const 
CPUState *cpu)
 #endif /* CONFIG USER ONLY */
 
 /* Execute a TB, and fix up the CPU state afterwards if necessary */
+/* Disable CFI checks.
+ * TCG creates binary blobs at runtime, with the transformed code.
+ * A TB is a blob of binary code, created at runtime and called with an
+ * indirect function call. Since such function did not exist at compile time,
+ * the CFI runtime has no way to verify its signature and would fail.
+ * TCG is not considered a security-sensitive part of QEMU so this does not
+ * affect the impact of CFI in environment with high security requirements */
+__disable_cfi__
 static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock 
*itb)
 {
 CPUArchState *env = cpu->env_ptr;
diff --git a/include/qemu/sanitizers.h b/include/qemu/sanitizers.h
new file mode 100644
index 00..31e404d58d
--- /dev/null
+++ b/include/qemu/sanitizers.h
@@ -0,0 +1,22 @@
+/*
+ * Decorators to disable sanitizers on specific functions
+ *
+ * Copyright IBM Corp., 2020
+ *
+ * Author:
+ *  Daniele Buono 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifdef CONFIG_CFI
+/* If CFI is enabled, use an attribute to disable cfi-icall on the following
+ * function */
+#define __disable_cfi__ __attribute__((no_sanitize("cfi-icall")))
+#else
+/* If CFI is not enabled, use an empty define to not change the behavior */
+#define __disable_cfi__
+#endif
+
diff --git a/plugins/core.c b/plugins/core.c
index 51bfc94787..9b712ca4ac 100644
--- a/plugins/core.c
+++ b/plugins/core.c
@@ -31,6 +31,7 @@
 #include "tcg/tcg-op.h"
 #include "trace/mem-internal.h" /* mem_info macros */
 #include "plugin.h"
+#include "qemu/sanitizers.h"
 
 struct qemu_plugin_cb {
 struct qemu_plugin_ctx *ctx;
@@ -90,6 +91,10 @@ void plugin_unregister_cb__locked(struct qemu_plugin_ctx 
*ctx,
 }
 }
 
+/* Disable CFI checks.
+ * The callback function has been loaded from an external library so we do not
+ * have type information */
+__disable_cfi__
 static void plugin_vcpu_cb__simple(CPUState *cpu, enum qemu_plugin_event ev)
 {
 struct qemu_plugin_cb *cb, *next;

[PATCH v2 6/6] configure: add support for Control-Flow Integrity

2020-10-23 Thread Daniele Buono
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.

Signed-off-by: Daniele Buono 
---
 configure   | 84 +
 meson.build |  2 ++
 2 files changed, 86 insertions(+)

diff --git a/configure b/configure
index e964040522..f996c4462e 100755
--- a/configure
+++ b/configure
@@ -272,6 +272,8 @@ debug_info="yes"
 lto="false"
 stack_protector=""
 safe_stack=""
+cfi="no"
+cfi_debug="no"
 use_containers="yes"
 gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
 
@@ -1199,6 +1201,16 @@ for opt do
   ;;
   --disable-safe-stack) safe_stack="no"
   ;;
+  --enable-cfi)
+  cfi="yes" ;
+  lto="true" ;
+  ;;
+  --disable-cfi) cfi="no"
+  ;;
+  --enable-cfi-debug) cfi_debug="yes"
+  ;;
+  --disable-cfi-debug) cfi_debug="no"
+  ;;
   --disable-curses) curses="disabled"
   ;;
   --enable-curses) curses="enabled"
@@ -1772,6 +1784,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
@@ -5312,6 +5331,64 @@ EOF
   CONFIGURE_CFLAGS="$QEMU_CFLAGS -flto"
   CONFIGURE_LDFLAGS="$QEMU_LDFLAGS -flto"
 fi
+
+
+# cfi (Control Flow Integrity)
+
+if test "$cfi" = "yes"; then
+  # Compiler/Linker Flags that needs to be added for cfi:
+  # -fsanitize=cfi-icall to enable control-flow integrity checks on
+  #indirect function calls.
+  # -fsanitize-cfi-icall-generalize-pointers to allow indirect function calls
+  #with pointers of a different type (i.e. pass a void* to a
+  #function that expects a char*). Used in some spots in QEMU,
+  #with compile-time type checks done by macros
+  # -fno-sanitize-trap=cfi-icall, when debug is enabled, to display the
+  #position in the code that triggered a CFI violation
+
+  # Make sure that LTO is enabled
+  if test "$lto" != "true"; then
+error_exit "Control Flow Integrity requires Link-Time Optimization (LTO)"
+  fi
+
+  test_cflag="-fsanitize=cfi-icall -fsanitize-cfi-icall-generalize-pointers"
+  test_ldflag="-fsanitize=cfi-icall"
+
+  if test "$cfi_debug" = "yes"; then
+# Disable the default trap mechanism so that a error message is displayed
+# when a CFI violation happens. The code is still terminated after the
+# message
+test_cflag="${test_cflag} -fno-sanitize-trap=cfi-icall"
+test_ldflag="${test_ldflag} -fno-sanitize-trap=cfi-icall"
+  fi
+
+  # Check that cfi is supported.
+  cat > $TMPC << EOF
+int main(int argc, char *argv[]) {
+  return 0;
+}
+EOF
+  # Manually add -flto because even if is enabled, flags for it will be
+  # set up later by meson
+  if ! compile_prog "-Werror $test_cflag" "$test_ldflag"; then
+error_exit "Control Flow Integrity is not supported by your compiler"
+  fi
+
+  # Check for incompatible options
+  if test "$modules" = "yes"; then
+error_exit "Control Flow Integrity is not compatible with modules"
+  fi
+
+   All good, add the flags for CFI to our CFLAGS and LDFLAGS
+  # Flag needed both at compilation and at linking
+  QEMU_CFLAGS="$QEMU_CFLAGS $test_cflag"
+  QEMU_LDFLAGS="$QEMU_LDFLAGS $test_ldflag"
+else
+  if test "$cfi_debug" = "

[PATCH v2 2/6] configure: avoid new clang 11+ warnings

2020-10-23 Thread Daniele Buono
Clang 11 finds a couple of spots in the code that trigger new warnings:

../qemu-base/hw/usb/dev-uas.c:157:31: error: field 'status' with variable sized 
type 'uas_iu' not at the end of a struct or class is a GNU extension 
[-Werror,-Wgnu-variable-sized-type-not-at-end]
uas_iustatus;
  ^
1 error generated.

The data structure is UASStatus, which must end with a QTAILQ_ENTRY, so
I believe we cannot have uas_iu at the end. Since this is a gnu
extension but CLANG supports it, just add
-Wno-gnu-variable-sized-type-not-at-end
to remove the warning.

../qemu-base/target/s390x/cpu_models.c:985:21: error: cast to smaller integer 
type 'S390Feat' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390Feat feat = (S390Feat) opaque;
^
../qemu-base/target/s390x/cpu_models.c:1002:21: error: cast to smaller integer 
type 'S390Feat' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390Feat feat = (S390Feat) opaque;
^
../qemu-base/target/s390x/cpu_models.c:1036:27: error: cast to smaller integer 
type 'S390FeatGroup' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390FeatGroup group = (S390FeatGroup) opaque;
  ^~
../qemu-base/target/s390x/cpu_models.c:1057:27: error: cast to smaller integer 
type 'S390FeatGroup' from 'void *' [-Werror,-Wvoid-pointer-to-enum-cast]
S390FeatGroup group = (S390FeatGroup) opaque;
  ^~
4 errors generated.

These are void * that get casted to enums, which are (or can be)
smaller than a 64bit pointer.
A code reorg may be better on the long term, but for now will
fix this adding
-Wno-void-pointer-to-enum-cast

Signed-off-by: Daniele Buono 
---
 configure | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configure b/configure
index e6754c1e87..9dc05cfb8a 100755
--- a/configure
+++ b/configure
@@ -2000,6 +2000,8 @@ add_to nowarn_flags -Wno-shift-negative-value
 add_to nowarn_flags -Wno-string-plus-int
 add_to nowarn_flags -Wno-typedef-redefinition
 add_to nowarn_flags -Wno-tautological-type-limit-compare
+add_to nowarn_flags -Wno-gnu-variable-sized-type-not-at-end
+add_to nowarn_flags -Wno-void-pointer-to-enum-cast
 add_to nowarn_flags -Wno-psabi
 
 gcc_flags="$warn_flags $nowarn_flags"
-- 
2.17.1




[PATCH v2 3/6] configure: add option to enable LTO

2020-10-23 Thread Daniele Buono
This patch allows to compile QEMU with link-time optimization (LTO).
Compilation with LTO is handled directly by meson. This patch adds checks
in configure to make sure the toolchain supports LTO.

Currently, allow LTO only with clang, since I have found a couple of issues
with gcc-based LTO.

In case fuzzing is enabled, automatically switch to llvm's linker (lld).
The standard bfd linker has a bug where function wrapping (used by the fuzz*
targets) is used in conjunction with LTO.

Tested with all major versions of clang from 6 to 12

Signed-off-by: Daniele Buono 
---
 configure   | 128 
 meson.build |   1 +
 2 files changed, 129 insertions(+)

diff --git a/configure b/configure
index 9dc05cfb8a..e964040522 100755
--- a/configure
+++ b/configure
@@ -76,6 +76,7 @@ fi
 TMPB="qemu-conf"
 TMPC="${TMPDIR1}/${TMPB}.c"
 TMPO="${TMPDIR1}/${TMPB}.o"
+TMPA="${TMPDIR1}/lib${TMPB}.a"
 TMPCXX="${TMPDIR1}/${TMPB}.cxx"
 TMPE="${TMPDIR1}/${TMPB}.exe"
 TMPTXT="${TMPDIR1}/${TMPB}.txt"
@@ -180,6 +181,32 @@ compile_prog() {
   $LDFLAGS $CONFIGURE_LDFLAGS $QEMU_LDFLAGS $local_ldflags
 }
 
+do_run_filter() {
+# Run a generic program, capturing its output to the log,
+# but also filtering the output with grep.
+# Returns the return value of grep.
+# First argument is the filter string.
+# Second argument is binary to execute.
+local filter="$1"
+local filter_pattern=""
+if test "$filter" = "yes"; then
+  shift
+  filter_pattern="$1"
+fi
+shift
+local program="$1"
+shift
+echo $program $@ >> config.log
+$program $@ >> config.log 2>&1 || return $?
+if test "$filter" = "yes"; then
+  $program $@ 2>&1 | grep "${filter_pattern}" >> /dev/null || return $?
+fi
+}
+
+create_library() {
+  do_run_filter "no" "$ar" -rc${1} $TMPA $TMPO
+}
+
 # symbolically link $1 to $2.  Portable version of "ln -sf".
 symlink() {
   rm -rf "$2"
@@ -242,6 +269,7 @@ host_cc="cc"
 audio_win_int=""
 libs_qga=""
 debug_info="yes"
+lto="false"
 stack_protector=""
 safe_stack=""
 use_containers="yes"
@@ -1159,6 +1187,10 @@ for opt do
   ;;
   --disable-werror) werror="no"
   ;;
+  --enable-lto) lto="true"
+  ;;
+  --disable-lto) lto="false"
+  ;;
   --enable-stack-protector) stack_protector="yes"
   ;;
   --disable-stack-protector) stack_protector="no"
@@ -1735,6 +1767,8 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   module-upgrades try to load modules from alternate paths for upgrades
   debug-tcg   TCG debugging (default is disabled)
   debug-info  debugging information
+  lto Enable Link-Time Optimization.
+  Depends on clang/llvm >=6.0
   sparse  sparse checker
   safe-stack  SafeStack Stack Smash Protection. Depends on
   clang/llvm >= 3.7 and requires coroutine backend ucontext.
@@ -5222,6 +5256,62 @@ if  test "$plugins" = "yes" &&
 fi
 
 
+# lto (Link-Time Optimization)
+
+if test "$lto" = "true"; then
+  # Test compiler/ar/linker support for lto.
+  # compilation with lto is handled by meson. Just make sure that compiler
+  # support is fully functional, and add additional compatibility flags
+  # if necessary.
+
+  if ! echo | $cc -dM -E - | grep __clang__ > /dev/null 2>&1 ; then
+# LTO with GCC and other compilers is not tested, and possibly broken
+error_exit "QEMU only supports LTO with CLANG"
+  fi
+
+  # Check that lto is supported.
+  # Need to check for:
+  # - Valid compiler, that supports lto flags
+  # - Valid ar, able to support intermediate code
+  # - Valid linker, able to support intermediate code
+
+   Check for a valid *ar* for link-time optimization.
+  # Test it by creating a static library and linking it
+  # Compile an object first
+  cat > $TMPC << EOF
+int fun(int val);
+
+int fun(int val) {
+return val;
+}
+EOF
+  if ! compile_object "-Werror -flto"; then
+error_exit "LTO is not supported by your compiler"
+  fi
+  # Create a library out of it
+  if ! create_library "s" ; then
+error_exit "LTO is not supported by ar. This usually happens when mixing 
GNU and LLVM toolchain."
+  fi
+  # Now create a binary using the library
+  cat > $TMPC << EOF
+int fun(int val);
+
+int main(int argc, char *argv[]) {
+  return fun(0);
+}
+EOF
+  if ! compile_prog "-Werror" "$test_ldflag -flto ${TMPA}"; then
+error_exit "LTO is not supported by ar or t

[PATCH v2 0/6] Add support for Control-Flow Integrity

2020-10-23 Thread Daniele Buono
with Clang v9.

There is also a possible performance issue, since for every indirect
function call, and additional address check is performed, followed by
an additional indirect call to the trampoline function.
However, especially in the case of KVM-based virtualization, the impact
should be minimal, since indirect function pointers should be used mostly
for device emulation.

I used Kata Container's metrics tests since that is a simple,
reproducible set of tests to stress storage and network between VMs,
and run a Lifecycle test to measure VM startup times under a specific
workload. A full report is available here [4].

The difference between LLVM with and without CFI is generally low.
Sometimes CFI is actually offering better performance, which may be
explained by having a different binary layout because of LTO.
Lifecycle and network do not seem to be affected much. With storage,
the situation is a bit more variable, but the oscillations seem to be
more related to the benchmark variability than the CFI overhead.

I also run a quick check-acceptance on full system VMs with and without CFI,
the results are at [4] and show comparable results, with CFI slightly
outperforming the default binary produced by LLVM.



[1] Mehdi Talbi and Paul Fariello. VM escape - QEMU Case Study
[2] Nelson Elhage. Virtunoid: Breaking out of KVM
[3] Marco Grassi and Kira. Vulnerability Discovery and Exploitation
of Virtualization Solutions for Cloud Computing and Desktops
[4] https://github.com/dbuono/QEMU-CFI-Performance

*** BLURB HERE ***

Daniele Buono (6):
  fuzz: Make fork_fuzz.ld compatible with LLVM's LLD
  configure: avoid new clang 11+ warnings
  configure: add option to enable LTO
  cfi: Initial support for cfi-icall in QEMU
  check-block: enable iotests with cfi-icall
  configure: add support for Control-Flow Integrity

 MAINTAINERS   |   5 +
 accel/tcg/cpu-exec.c  |   9 ++
 configure | 214 ++
 include/qemu/sanitizers.h |  22 
 meson.build   |   3 +
 plugins/core.c|  25 
 plugins/loader.c  |   5 +
 tcg/tci.c |   5 +
 tests/check-block.sh  |  18 +--
 tests/qtest/fuzz/fork_fuzz.ld |  12 +-
 util/main-loop.c  |   9 ++
 util/oslib-posix.c|   9 ++
 12 files changed, 328 insertions(+), 8 deletions(-)
 create mode 100644 include/qemu/sanitizers.h

-- 
2.17.1




[PATCH v2 1/6] fuzz: Make fork_fuzz.ld compatible with LLVM's LLD

2020-10-23 Thread Daniele Buono
LLVM's linker, LLD, supports the keyword "INSERT AFTER", starting with
version 11.
However, when multiple sections are defined in the same "INSERT AFTER",
they are added in a reversed order, compared to BFD's LD.

This patch makes fork_fuzz.ld generic enough to work with both linkers.
Each section now has its own "INSERT AFTER" keyword, so proper ordering is
defined between the sections added.

Signed-off-by: Daniele Buono 
---
 tests/qtest/fuzz/fork_fuzz.ld | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/fuzz/fork_fuzz.ld b/tests/qtest/fuzz/fork_fuzz.ld
index bfb667ed06..cfb88b7fdb 100644
--- a/tests/qtest/fuzz/fork_fuzz.ld
+++ b/tests/qtest/fuzz/fork_fuzz.ld
@@ -16,6 +16,11 @@ SECTIONS
   /* Lowest stack counter */
   *(__sancov_lowest_stack);
   }
+}
+INSERT AFTER .data;
+
+SECTIONS
+{
   .data.fuzz_ordered :
   {
   /*
@@ -34,6 +39,11 @@ SECTIONS
*/
*(.bss._ZN6fuzzer3TPCE);
   }
+}
+INSERT AFTER .data.fuzz_start;
+
+SECTIONS
+{
   .data.fuzz_end : ALIGN(4K)
   {
   __FUZZ_COUNTERS_END = .;
@@ -43,4 +53,4 @@ SECTIONS
  * Don't overwrite the SECTIONS in the default linker script. Instead insert 
the
  * above into the default script
  */
-INSERT AFTER .data;
+INSERT AFTER .data.fuzz_ordered;
-- 
2.17.1




Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-08-13 Thread Daniele Buono

Yes, Something like that, probably with a small python script.

On 8/10/2020 5:33 PM, Alexander Bulekov wrote:

On 200810 2139, Paolo Bonzini wrote:

On 10/08/20 21:01, Daniele Buono wrote:

So I'm thinking of adding a check in configure. If gold is the linker,
automatically create (somehow, still working on it) the full link script
by obtaining the default bfd script and add the required parts. Would
that work for you?


Maybe even do it unconditionally?


I agree.

I can try a respin of my compiler-rt/libFuzzer patches to add a built-in
fork-server to libFuzzer, so we can avoid the linker-script madness
altogether. Don't know how soon I can get to this, but I do think it is
worth another try.

TIL about these differences between ld.bfd and ld.gold.
So the idea is to use something like:
"ld --verbose | grep -n ".*:" | grep -A1 "\s.data\s" | tail -n1"
and insert the existing linker-script before that line?
Thanks
-Alex


Paolo







Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-08-10 Thread Daniele Buono

Hi Alex, Paolo
Hitting a small issue while adding support for lto (and therefore cfi) 
to the fuzzer.


The fuzzer requires a modified linker script to place all of the stuff 
that needs to persist across fuzzing runs into a contiguous section of 
memory.


It does that by inserting three new sections after the .data section of 
the binary. Instead of rewriting a full linker script, it's using the 
*INSERT* keyword to add this to the default linker script.


Now, LTO with LLVM requires to use the gold linker, which does not have 
a default linker script and therefore does not support the *INSERT* keyword.
This can be fixed by taking the default script from the bdf linker, 
adding the additional sections and ask gold to use the full script.


However, I don't like the idea of replacing the small, self-contained 
script snippet that is currently used, with a full script (which is 
probably also dependent on the bfd/os version). So I'm thinking of 
adding a check in configure. If gold is the linker, automatically create 
(somehow, still working on it) the full link script by obtaining the 
default bfd script and add the required parts. Would that work for you?


Cheers,
Daniele

On 7/2/2020 11:43 AM, Daniele Buono wrote:

Hey Alex!

I agree, in most cases (possibly all of them), a wrong indirect function 
call will end up with something that is catched by ASan or UBSan.
This way, however, you may catch it earlier and it may make debug easier 
(especially with --enable-cfi-debug which is printing an error with the 
calling and, most times, the called function).


UBSan does have a similar feature, -fsanitize=function, but 
unfortunately it works only on C++ code, and therefore is not good in 
the QEMU case.


And, of course, it will also be used to weed out missing functions in 
the CFI filter.


On 7/2/2020 9:38 AM, Alexander Bulekov wrote:

Can't wait to try this out!

On 200702 1459, Paolo Bonzini wrote:

On 02/07/20 14:50, Daniele Buono wrote:

I also wonder if this is something that could be put in the fuzzing
environment. It would probably also help in finding coding error in
corner cases quicker.


Yes, fuzzing and tests/docker/test-debug should enable CFI.  Also,
tests/docker/test-clang should enable LTO.

Paolo


I believe CFI is most-useful as an active defensive measure. I can't
think of many cases where a fuzzer/test could raise a CFI alert that
wouldn't also be caught by something like canaries, ASan or UBsan,
though maybe I'm missing something. Maybe testing/fuzzing with CFI could
be useful to weed out any errors due to e.g. an incomplete
cfi-blacklist.txt

-Alex







[PATCH 0/1] tests/acceptance: set VM socket encoding to UTF-8

2020-07-21 Thread Daniele Buono
Some of the acceptance tests were failing for me with an error while
decoding characters coming from the VMs running for the test.

The error looked like this:

(30/36) 
tests/acceptance/boot_linux_console.py:BootLinuxConsole.test_nios2_10m50: 
ERROR: 'ascii' codec can't decode byte 0xc2 in position 36: ordinal not in 
range(128) (1.29 s)

The very same test is running fine on GitLab CI

An investigation of the issue shows that the socket we are using between
QEMU and AVOCADO is using the default encoding of the host OS. In my
case, locale was set to plain ASCII with LANG=C. Setting it to a UTF-8
locale fixed the issue, but a safer approach should be to just tell
Python to always use a UTF-8 charset for the socket. This is what the
patch does.

Daniele Buono (1):
  tests/acceptance: set VM socket encoding to UTF-8

 tests/acceptance/avocado_qemu/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.26.2




[PATCH 1/1] tests/acceptance: set VM socket encoding to UTF-8

2020-07-21 Thread Daniele Buono
The OS of some VM used by acceptance tests sends messages in UTF-8
encoding.

The socket used to communicate between the VM and the host by the
AVOCADO framework uses the default host encoding. This is not generally
a problem since most distributions default to UTF. However, if for some
reason the host is using a plain ASCII encoding, the VM test will fail
with an error. This patch explicitly sets the encoding to be UTF-8.

Signed-off-by: Daniele Buono 
---
 tests/acceptance/avocado_qemu/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/acceptance/avocado_qemu/__init__.py 
b/tests/acceptance/avocado_qemu/__init__.py
index 77d1c1d9ff..5f7ef0a2f2 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -73,7 +73,7 @@ def _console_interaction(test, success_message, 
failure_message,
 assert not keep_sending or send_string
 if vm is None:
 vm = test.vm
-console = vm.console_socket.makefile()
+console = vm.console_socket.makefile(encoding='UTF-8')
 console_logger = logging.getLogger('console')
 while True:
 if send_string:
-- 
2.26.2




Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-16 Thread Daniele Buono

On 7/2/2020 5:52 AM, Daniel P. Berrangé wrote:

The need to maintain this list of functions makes me feel very
uneasy.

How can we have any confidence that this list of functions is
accurate ? How will maintainers ensure that they correctly update
it as they are writing/changing code, and how will they test the
result ?


Hi Daniel,

I gave it some thought and studied more of clang's options. It is 
possible to disable cfi on specific functions by using an __attribute__ 
keyword, instead of providing a list in an external file.
In terms of maintaining, this is much better since we are removing the 
need to update the list. I would suggest defining a macro, 
__disable_cfi__, that can be prepended to a function. The macro would 
expand to nothing if cfi is disabled, or to the proper attribute if it 
is enabled. Here's example code snippet


/* Disable CFI checks.
 * The callback function has been loaded from an external library so we 
do not

 * have type information */
__disable_cfi__
void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret)
{
...
}

This would take care of renaming and removal of functions that need cfi.
It would also probably be beneficial to the developers since they can 
see immediately that the function they are working with needs to have 
CFI checks disabled, and why.


If you think this is a better approach, I'll submit v2 with this 
approach instead of the external function list.



For new code, however, the best thing is proper education and testing.
I'll work on a document for docs/devel to detail what it is and how to 
make code cfi-safe.
A good approach should be to test code changes with CFI enabled. CFI is, 
after all, a sanitizer and therefore it makes sense to use it also 
during development, together with ASan, UBSan and the likes. 
Unfortunately, since it works only with clang, I don't think this can 
ever be a hard requirement.


Daniele



Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-02 Thread Daniele Buono

Hey Alex!

I agree, in most cases (possibly all of them), a wrong indirect function 
call will end up with something that is catched by ASan or UBSan.
This way, however, you may catch it earlier and it may make debug easier 
(especially with --enable-cfi-debug which is printing an error with the 
calling and, most times, the called function).


UBSan does have a similar feature, -fsanitize=function, but 
unfortunately it works only on C++ code, and therefore is not good in 
the QEMU case.


And, of course, it will also be used to weed out missing functions in 
the CFI filter.


On 7/2/2020 9:38 AM, Alexander Bulekov wrote:

Can't wait to try this out!

On 200702 1459, Paolo Bonzini wrote:

On 02/07/20 14:50, Daniele Buono wrote:

I also wonder if this is something that could be put in the fuzzing
environment. It would probably also help in finding coding error in
corner cases quicker.


Yes, fuzzing and tests/docker/test-debug should enable CFI.  Also,
tests/docker/test-clang should enable LTO.

Paolo


I believe CFI is most-useful as an active defensive measure. I can't
think of many cases where a fuzzer/test could raise a CFI alert that
wouldn't also be caught by something like canaries, ASan or UBsan,
though maybe I'm missing something. Maybe testing/fuzzing with CFI could
be useful to weed out any errors due to e.g. an incomplete
cfi-blacklist.txt

-Alex





Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-02 Thread Daniele Buono

On 7/2/2020 9:12 AM, Daniel P. Berrangé wrote:

On Thu, Jul 02, 2020 at 08:50:08AM -0400, Daniele Buono wrote:



On 7/2/2020 5:52 AM, Daniel P. Berrangé wrote:

On Thu, Jul 02, 2020 at 01:49:48AM -0400, Daniele Buono wrote:

This patch adds a flag to enable/disable control flow integrity checks
on indirect function calls. This feature is only provided by LLVM/Clang
v3.9 or higher, and only allows indirect function calls to functions
with compatible signatures.

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.

We introduce a blacklist file, to disable CFI checks in a limited number
of TCG functions.

The feature relies on link-time optimization (lto), which requires the
use of the gold linker, and the LLVM versions of ar, ranlib and nm.
This patch take care of checking that all the compiler toolchain
dependencies are met.

Signed-off-by: Daniele Buono 
---
   cfi-blacklist.txt |  27 +++
   configure | 177 ++
   2 files changed, 204 insertions(+)
   create mode 100644 cfi-blacklist.txt

diff --git a/cfi-blacklist.txt b/cfi-blacklist.txt
new file mode 100644
index 00..bf804431a5
--- /dev/null
+++ b/cfi-blacklist.txt
@@ -0,0 +1,27 @@
+# List of functions that should not be compiled with Control-Flow Integrity
+
+[cfi-icall]
+# TCG creates binary blobs at runtime, with the transformed code.
+# When it's time to execute it, the code is called with an indirect function
+# call. Since such function did not exist at compile time, the runtime has no
+# way to verify its signature. Disable CFI checks in the function that calls
+# the binary blob
+fun:cpu_tb_exec
+
+# TCI (Tiny Compiler Interpreter) is an interpreter for TCG pseudo code.
+# One possible operation in the pseudo code is a call to binary code.
+# Therefore, disable CFI checks in the interpreter function
+fun:tcg_qemu_tb_exec
+
+# TCG Plugins Callback Functions. The mechanism rely on opening external
+# shared libraries at runtime and get pointers to functions in such libraries
+# Since these pointers are external to the QEMU binary, the runtime cannot
+# verify their signature. Disable CFI Checks in all the functions that use
+# such pointers.
+fun:plugin_vcpu_cb__simple
+fun:plugin_cb__simple
+fun:plugin_cb__udata
+fun:qemu_plugin_tb_trans_cb
+fun:qemu_plugin_vcpu_syscall
+fun:qemu_plugin_vcpu_syscall_ret
+fun:plugin_load


The need to maintain this list of functions makes me feel very
uneasy.

How can we have any confidence that this list of functions is
accurate ? How will maintainers ensure that they correctly update
it as they are writing/changing code, and how will they test the
result ?

It feels like it has the same general maint problem as the original
seccomp code we used, where we were never confident we had added
the right exceptions to let QEMU run without crashing when users
tickled some feature we forgot about.


Regards,
Daniel



I agree with you that keeping that list updated is a daunting task. In my
opinion, however, it is not as difficult as a seccomp filter, for the
following reasons:

1) Seccomp covers everything that runs in your process, including shared
libraries that you have no control over. CFI covers only the code in the
QEMU binary. So at least we don't have to guess what other libraries used by
QEMU will or won't do during execution.

2) With seccomp you have to filter behavior that, while admissible, should
not happen in your code. CFI can be seen as a run-time type checking system;
if the signature of the function is wrong, that is a coding error... in
theory. In practice, there is a corner-case because the type checking
doesn't know the signature of code loaded or written at run-time, and that
is why you have to use a CFI filter.


Can you elaborate on this function signature rules here ? Is this referring
to scenarios where you cast between 2 different function prototypes ?


It is, partially. A CFI check, however, is done at the moment you call 
the function pointer. So if you cast a function pointer to a different 
type (say gboolean (*)(void *) ), but cast it back to the original type 
before you call it, it's going to be fine.


Chances are you are doing this anyway, since you really want to pass 
those parameters to the callback.


I'm wondering if this applies to the way GLib's main loop source callbacks
are registered.

eg the g_source_set_callback method takes a callback with a signature
of "GSourceFunc" which is

   gboolean (*)(void *)

but the way GSources are implemented means that each implementation gets
to define its own custom callback signature. So for example, in QIOChannel
we use

   int (*)(struct QIOChannel *, en

Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-02 Thread Daniele Buono




On 7/2/2020 5:52 AM, Daniel P. Berrangé wrote:

On Thu, Jul 02, 2020 at 01:49:48AM -0400, Daniele Buono wrote:

This patch adds a flag to enable/disable control flow integrity checks
on indirect function calls. This feature is only provided by LLVM/Clang
v3.9 or higher, and only allows indirect function calls to functions
with compatible signatures.

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.

We introduce a blacklist file, to disable CFI checks in a limited number
of TCG functions.

The feature relies on link-time optimization (lto), which requires the
use of the gold linker, and the LLVM versions of ar, ranlib and nm.
This patch take care of checking that all the compiler toolchain
dependencies are met.

Signed-off-by: Daniele Buono 
---
  cfi-blacklist.txt |  27 +++
  configure | 177 ++
  2 files changed, 204 insertions(+)
  create mode 100644 cfi-blacklist.txt

diff --git a/cfi-blacklist.txt b/cfi-blacklist.txt
new file mode 100644
index 00..bf804431a5
--- /dev/null
+++ b/cfi-blacklist.txt
@@ -0,0 +1,27 @@
+# List of functions that should not be compiled with Control-Flow Integrity
+
+[cfi-icall]
+# TCG creates binary blobs at runtime, with the transformed code.
+# When it's time to execute it, the code is called with an indirect function
+# call. Since such function did not exist at compile time, the runtime has no
+# way to verify its signature. Disable CFI checks in the function that calls
+# the binary blob
+fun:cpu_tb_exec
+
+# TCI (Tiny Compiler Interpreter) is an interpreter for TCG pseudo code.
+# One possible operation in the pseudo code is a call to binary code.
+# Therefore, disable CFI checks in the interpreter function
+fun:tcg_qemu_tb_exec
+
+# TCG Plugins Callback Functions. The mechanism rely on opening external
+# shared libraries at runtime and get pointers to functions in such libraries
+# Since these pointers are external to the QEMU binary, the runtime cannot
+# verify their signature. Disable CFI Checks in all the functions that use
+# such pointers.
+fun:plugin_vcpu_cb__simple
+fun:plugin_cb__simple
+fun:plugin_cb__udata
+fun:qemu_plugin_tb_trans_cb
+fun:qemu_plugin_vcpu_syscall
+fun:qemu_plugin_vcpu_syscall_ret
+fun:plugin_load


The need to maintain this list of functions makes me feel very
uneasy.

How can we have any confidence that this list of functions is
accurate ? How will maintainers ensure that they correctly update
it as they are writing/changing code, and how will they test the
result ?

It feels like it has the same general maint problem as the original
seccomp code we used, where we were never confident we had added
the right exceptions to let QEMU run without crashing when users
tickled some feature we forgot about.


Regards,
Daniel



I agree with you that keeping that list updated is a daunting task. In 
my opinion, however, it is not as difficult as a seccomp filter, for the 
following reasons:


1) Seccomp covers everything that runs in your process, including shared 
libraries that you have no control over. CFI covers only the code in the 
QEMU binary. So at least we don't have to guess what other libraries 
used by QEMU will or won't do during execution.


2) With seccomp you have to filter behavior that, while admissible, 
should not happen in your code. CFI can be seen as a run-time type 
checking system; if the signature of the function is wrong, that is a 
coding error... in theory. In practice, there is a corner-case because 
the type checking doesn't know the signature of code loaded or written 
at run-time, and that is why you have to use a CFI filter.


So yes, there is risk, but IMHO it's not as high as in seccomp.

I think with a bit of education, it would be easy to spot red flags in 
new code.
As for education/testing... I can definitely work on a doc to be put in 
docs/devel.
Testing for CFI violations may be more difficult, however if a test code 
that exercises it is written in tests/, compiling QEMU with CFI and 
running the test should be sufficient to hit the violation.
I also wonder if this is something that could be put in the fuzzing 
environment. It would probably also help in finding coding error in 
corner cases quicker.


Regards,
Daniele



Re: [PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-02 Thread Daniele Buono

On 7/2/2020 5:45 AM, Paolo Bonzini wrote:

On 02/07/20 07:49, Daniele Buono wrote:

This patch adds a flag to enable/disable control flow integrity checks
on indirect function calls. This feature is only provided by LLVM/Clang
v3.9 or higher, and only allows indirect function calls to functions
with compatible signatures.

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.

We introduce a blacklist file, to disable CFI checks in a limited number
of TCG functions.

The feature relies on link-time optimization (lto), which requires the
use of the gold linker, and the LLVM versions of ar, ranlib and nm.
This patch take care of checking that all the compiler toolchain
dependencies are met.

Signed-off-by: Daniele Buono 


Can you split this option in two parts, --enable-lto to enable link-time
optimization (perhaps also for GCC) and --enable-cfi which implies
--enable-lto?

This is because in the future we are considering switching to Meson,
where LTO support is built-in; having a separate switch would make it
easier to find the relevant code.

Paolo


Sure, that shouldn't be a big deal.

Thanks,
Daniele




---
  cfi-blacklist.txt |  27 +++
  configure | 177 ++
  2 files changed, 204 insertions(+)
  create mode 100644 cfi-blacklist.txt

diff --git a/cfi-blacklist.txt b/cfi-blacklist.txt
new file mode 100644
index 00..bf804431a5
--- /dev/null
+++ b/cfi-blacklist.txt
@@ -0,0 +1,27 @@
+# List of functions that should not be compiled with Control-Flow Integrity
+
+[cfi-icall]
+# TCG creates binary blobs at runtime, with the transformed code.
+# When it's time to execute it, the code is called with an indirect function
+# call. Since such function did not exist at compile time, the runtime has no
+# way to verify its signature. Disable CFI checks in the function that calls
+# the binary blob
+fun:cpu_tb_exec
+
+# TCI (Tiny Compiler Interpreter) is an interpreter for TCG pseudo code.
+# One possible operation in the pseudo code is a call to binary code.
+# Therefore, disable CFI checks in the interpreter function
+fun:tcg_qemu_tb_exec
+
+# TCG Plugins Callback Functions. The mechanism rely on opening external
+# shared libraries at runtime and get pointers to functions in such libraries
+# Since these pointers are external to the QEMU binary, the runtime cannot
+# verify their signature. Disable CFI Checks in all the functions that use
+# such pointers.
+fun:plugin_vcpu_cb__simple
+fun:plugin_cb__simple
+fun:plugin_cb__udata
+fun:qemu_plugin_tb_trans_cb
+fun:qemu_plugin_vcpu_syscall
+fun:qemu_plugin_vcpu_syscall_ret
+fun:plugin_load
diff --git a/configure b/configure
index 4a22dcd563..86fb0f390c 100755
--- a/configure
+++ b/configure
@@ -27,6 +27,7 @@ fi
  TMPB="qemu-conf"
  TMPC="${TMPDIR1}/${TMPB}.c"
  TMPO="${TMPDIR1}/${TMPB}.o"
+TMPA="${TMPDIR1}/lib${TMPB}.a"
  TMPCXX="${TMPDIR1}/${TMPB}.cxx"
  TMPE="${TMPDIR1}/${TMPB}.exe"
  TMPMO="${TMPDIR1}/${TMPB}.mo"
@@ -134,6 +135,43 @@ compile_prog() {
do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $QEMU_LDFLAGS $local_ldflags
  }
  
+do_run() {

+# Run a generic program, capturing its output to the log.
+# First argument is binary to execute.
+local program="$1"
+shift
+echo $program $@ >> config.log
+$program $@ >> config.log 2>&1 || return $?
+}
+
+do_run_filter() {
+# Run a generic program, capturing its output to the log,
+# but also filtering the output with grep.
+# Returns the return value of grep.
+# First argument is the filter string.
+# Second argument is binary to execute.
+local filter="$1"
+shift
+local program="$1"
+shift
+echo $program $@ >> config.log
+$program $@ >> config.log 2>&1
+$program $@ 2>&1 | grep ${filter} >> /dev/null || return $?
+
+}
+
+create_library() {
+  do_run "$ar" -rc${1} $TMPA $TMPO
+}
+
+create_index() {
+  do_run "$ranlib" $TMPA
+}
+
+find_library_symbol() {
+  do_run_filter ${1} "$nm" $TMPA
+}
+
  # symbolically link $1 to $2.  Portable version of "ln -sf".
  symlink() {
rm -rf "$2"
@@ -306,6 +344,8 @@ libs_tools=""
  audio_win_int=""
  libs_qga=""
  debug_info="yes"
+cfi="no"
+cfi_debug="no"
  stack_protector=""
  safe_stack=""
  use_containers="yes"
@@ -1285,6 +1325,14 @@ for opt do
;;
--disable-werror) werror="no"
;;
+  --enable-cfi) cfi="yes"
+  ;;
+  --disabl

[PATCH 2/2] configure: add support for Control-Flow Integrity

2020-07-01 Thread Daniele Buono
This patch adds a flag to enable/disable control flow integrity checks
on indirect function calls. This feature is only provided by LLVM/Clang
v3.9 or higher, and only allows indirect function calls to functions
with compatible signatures.

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.

We introduce a blacklist file, to disable CFI checks in a limited number
of TCG functions.

The feature relies on link-time optimization (lto), which requires the
use of the gold linker, and the LLVM versions of ar, ranlib and nm.
This patch take care of checking that all the compiler toolchain
dependencies are met.

Signed-off-by: Daniele Buono 
---
 cfi-blacklist.txt |  27 +++
 configure | 177 ++
 2 files changed, 204 insertions(+)
 create mode 100644 cfi-blacklist.txt

diff --git a/cfi-blacklist.txt b/cfi-blacklist.txt
new file mode 100644
index 00..bf804431a5
--- /dev/null
+++ b/cfi-blacklist.txt
@@ -0,0 +1,27 @@
+# List of functions that should not be compiled with Control-Flow Integrity
+
+[cfi-icall]
+# TCG creates binary blobs at runtime, with the transformed code.
+# When it's time to execute it, the code is called with an indirect function
+# call. Since such function did not exist at compile time, the runtime has no
+# way to verify its signature. Disable CFI checks in the function that calls
+# the binary blob
+fun:cpu_tb_exec
+
+# TCI (Tiny Compiler Interpreter) is an interpreter for TCG pseudo code.
+# One possible operation in the pseudo code is a call to binary code.
+# Therefore, disable CFI checks in the interpreter function
+fun:tcg_qemu_tb_exec
+
+# TCG Plugins Callback Functions. The mechanism rely on opening external
+# shared libraries at runtime and get pointers to functions in such libraries
+# Since these pointers are external to the QEMU binary, the runtime cannot
+# verify their signature. Disable CFI Checks in all the functions that use
+# such pointers.
+fun:plugin_vcpu_cb__simple
+fun:plugin_cb__simple
+fun:plugin_cb__udata
+fun:qemu_plugin_tb_trans_cb
+fun:qemu_plugin_vcpu_syscall
+fun:qemu_plugin_vcpu_syscall_ret
+fun:plugin_load
diff --git a/configure b/configure
index 4a22dcd563..86fb0f390c 100755
--- a/configure
+++ b/configure
@@ -27,6 +27,7 @@ fi
 TMPB="qemu-conf"
 TMPC="${TMPDIR1}/${TMPB}.c"
 TMPO="${TMPDIR1}/${TMPB}.o"
+TMPA="${TMPDIR1}/lib${TMPB}.a"
 TMPCXX="${TMPDIR1}/${TMPB}.cxx"
 TMPE="${TMPDIR1}/${TMPB}.exe"
 TMPMO="${TMPDIR1}/${TMPB}.mo"
@@ -134,6 +135,43 @@ compile_prog() {
   do_cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $QEMU_LDFLAGS $local_ldflags
 }
 
+do_run() {
+# Run a generic program, capturing its output to the log.
+# First argument is binary to execute.
+local program="$1"
+shift
+echo $program $@ >> config.log
+$program $@ >> config.log 2>&1 || return $?
+}
+
+do_run_filter() {
+# Run a generic program, capturing its output to the log,
+# but also filtering the output with grep.
+# Returns the return value of grep.
+# First argument is the filter string.
+# Second argument is binary to execute.
+local filter="$1"
+shift
+local program="$1"
+shift
+echo $program $@ >> config.log
+$program $@ >> config.log 2>&1
+$program $@ 2>&1 | grep ${filter} >> /dev/null || return $?
+
+}
+
+create_library() {
+  do_run "$ar" -rc${1} $TMPA $TMPO
+}
+
+create_index() {
+  do_run "$ranlib" $TMPA
+}
+
+find_library_symbol() {
+  do_run_filter ${1} "$nm" $TMPA
+}
+
 # symbolically link $1 to $2.  Portable version of "ln -sf".
 symlink() {
   rm -rf "$2"
@@ -306,6 +344,8 @@ libs_tools=""
 audio_win_int=""
 libs_qga=""
 debug_info="yes"
+cfi="no"
+cfi_debug="no"
 stack_protector=""
 safe_stack=""
 use_containers="yes"
@@ -1285,6 +1325,14 @@ for opt do
   ;;
   --disable-werror) werror="no"
   ;;
+  --enable-cfi) cfi="yes"
+  ;;
+  --disable-cfi) cfi="no"
+  ;;
+  --enable-cfi-debug) cfi_debug="yes"
+  ;;
+  --disable-cfi-debug) cfi_debug="no"
+  ;;
   --enable-stack-protector) stack_protector="yes"
   ;;
   --disable-stack-protector) stack_protector="no"
@@ -1838,6 +1886,10 @@ disabled with --disable-FEATURE, default is enabled if 
available:
   module-upgrades try to load modules from alternate paths for upgrades
   debug-tcg   TCG debugging (default is disabled)
   debug-info  

[PATCH 1/2] check-block: enable iotests with cfi-icall

2020-07-01 Thread Daniele Buono
cfi-icall is a form of Control-Flow Integrity for indirect function
calls implemented by llvm. It is enabled with a -fsanitize flag.

iotests are currently disabled when -fsanitize options is used, with the
exception of SafeStack.

This patch implements a generic filtering mechanism to allow iotests
with a set of known-to-be-safe -fsanitize option. Then mark SafeStack
and the new options used for cfi-icall safe for iotests

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index 8e29c868e5..7691213bd9 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -21,14 +21,18 @@ if grep -q "CONFIG_GPROF=y" config-host.mak 2>/dev/null ; 
then
 exit 0
 fi
 
-# 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}"
+# Disable tests with any sanitizer except for specific ones
+SANITIZE_FLAGS=$( grep "CFLAGS.*-fsanitize" config-host.mak 2>/dev/null )
+ALLOWED_SANITIZE_FLAGS="safe-stack cfi-icall sanitize-blacklist"
+#Remove all occurrencies of allowed Sanitize flags
+for j in ${ALLOWED_SANITIZE_FLAGS}; do
+TMP_FLAGS=${SANITIZE_FLAGS}
+SANITIZE_FLAGS=""
+for i in ${TMP_FLAGS}; do
+if ! echo ${i} | grep -q "${j}" 2>/dev/null; then
+SANITIZE_FLAGS="${SANITIZE_FLAGS} ${i}"
 fi
+done
 done
 if echo ${SANITIZE_FLAGS} | grep -q "\-fsanitize" 2>/dev/null; then
 # Have a sanitize flag that is not allowed, stop
-- 
2.26.2




[PATCH 0/2] Add support for Control-Flow Integrity

2020-07-01 Thread Daniele Buono
LLVM/Clang, starting from v3.9, supports runtime checks for forward-edge
Control-Flow Integrity (CFI).

CFI on indirect function calls can have a huge impact in enhancing QEMU
security, by significantly limiting one of the most used attack vectors
for VM Escape. Attacks demonstrated in [1],[2] and [3] will, at some
point, change a function pointer in a QEMU data structure.

At high level, LLVM's implementation relies on compile-time information
to create a range of consecutive trampolines for "compatible functions".
At runtime, if the pointer is not in the valid range, it is assumed that
the control flow was hijacked, and the process is terminated with an
"Illegal Instruction" exception.

CAVEATS:

1) For this CFI check to work, the code must always respect the function
signature when using function pointer. While this is generally true
in QEMU, there are a few instances where pointers are handled as
generic void* from the caller. Since this is a common approach, Clang
offer a flag to relax pointer checks and consider all pointer types
to be compatible.

2) Since CFI relies on compile-time information, it requires using
link-time optimization (LTO) to support CFI across compilation units.
This adds a requirement for the gold linker, and LLVM's versions of
static libraries tools (ar, ranlib, nm).

3) CFI checks cannot be performed on shared libraries (given that functions
are not known at compile time). This means that indirect function calls
will fail if the function pointer belong to a shared library.
This does not seem to be a big issue for a standard QEMU deployment today,
but QEMU modules won't be able to work when CFI is enabled.
There is a way to allow shared library pointers, but it is experimental
in LLVM, requires some work and reduces performance and security. For
these reasons, I think it's best to start with this version, and discuss
an extension for modules later.

4) CFI cannot be fully applied to TCG. The purpose of TCG is to transform
code on-the-fly from one ISA to another. In doing so, binary blobs of
executable code are created and called with function pointers.
Since the code did not exist at compile time, runtime CFI checks find such
functions illegal. To allow the code to keep running, CFI checks are not
performed in the core function of TCG/TCI, and in the code that
implements TCG plugins.
This does not affect QEMU when executed with KVM, and all the device
emulation code is always protected, even when using TCG.

5) Most of the logic to enable CFI goes in the configure, since it's
just a matter of checking for dependencies and incompatible options.
However, I had to disable CFI checks for a few TCG functions.
This can only be done through a blacklist file. I added a file in the
root of QEMU, called cfi-blacklist.txt for such purpose. I am open to
suggestions on where the file should go, and I am willing to become the
maintainer of it, if deemed necessary.

PERFORMANCE:

Enabling CFI creates a larger binary, which may be an issue in some use
cases. However, the increase is not exceptionally large. On my Ubuntu
system, with default options, I see an increase of stripped size from
14MiB to 15.3MiB when enabling CFI with Clang v9.

There is also a possible performance issue, since for every indirect
function call, and additional address check is performed, followed by
an additional indirect call to the trampoline function.
However, especially in the case of KVM-based virtualization, the impact
should be minimal, since indirect function pointers should be used mostly
for device emulation.

I used Kata Container's metrics tests since that is a simple,
reproducible set of tests to stress storage and network between VMs,
and run a Lifecycle test to measure VM startup times under a specific
workload. A full report is available here [4].

The difference between LLVM with and without CFI is generally low.
Sometimes CFI is actually offering better performance, which may be
explained by having a different binary layout because of LTO.
Lifecycle and network do not seem to be affected much. With storage,
the situation is a bit more variable, but the oscillations seem to be
more related to the benchmark variability than the CFI overhead.

I also run a quick check-acceptance on full system VMs with and without CFI,
the results are at [4] and show comparable results, with CFI slightly
outperforming the default binary produced by LLVM.



[1] Mehdi Talbi and Paul Fariello. VM escape - QEMU Case Study
[2] Nelson Elhage. Virtunoid: Breaking out of KVM
[3] Marco Grassi and Kira. Vulnerability Discovery and Exploitation
of Virtualization Solutions for Cloud Computing and Desktops
[4] https://github.com/dbuono/QEMU-CFI-Performance

Daniele Buono (2):
  check-block: enable iotests with cfi-icall
  configure: add support for Control-Flow Integrity

 cfi-blacklist.txt|  27 +++
 configure| 177 +++
 tests/check-block.sh 

Re: [PATCH v2 0/4] Add support for SafeStack

2020-06-15 Thread Daniele Buono

Ping?

On 5/29/2020 4:51 PM, Daniele Buono wrote:

LLVM supports SafeStack instrumentation to protect against stack buffer
overflows, since version 3.7


From https://clang.llvm.org/docs/SafeStack.html:

"It works by separating the program stack into two distinct regions: the
safe stack and the unsafe stack. The safe stack stores return addresses,
register spills, and local variables that are always accessed in a safe
way, while the unsafe stack stores everything else. This separation
ensures that buffer overflows on the unsafe stack cannot be used to
overwrite anything on the safe stack."

Unfortunately, the use of two stack regions does not cope well with
QEMU's coroutines. The second stack region is not properly set up with
both ucontext and sigaltstack, so multiple coroutines end up sharing the
same memory area for the unsafe stack, causing undefined behaviors at
runtime (and most iochecks to fail).

This patch series fixes the implementation of the ucontext backend and
make sure that sigaltstack is never used if the compiler is applying
the SafeStack instrumentation. It also adds a configure flag to enable
SafeStack, and enables iotests when SafeStack is used.

Changes since v1:
  - CONFIG_SAFESTACK is now set up in configure, and not in the code
  - Added option for a --disable-safe-stack in configure
  - Configure checks if SafeStack is enabled by default in the compiler,
and set the CONFIG_SAFESTACK accordingly
  - Updated some comments in the code and the commit log

NOTE: I kept configure as Patch #3.
The reason is that the code changes will not be enabled without the
configure, making the code fully functional if only Patches #1 or #2 are
applied.
On the other hand, the configure patch will produce incorrect code if we
request SafeStack and the other patches are not applied.

Daniele Buono (4):
   coroutine: support SafeStack in ucontext backend
   coroutine: add check for SafeStack in sigaltstack
   configure: add flags to support SafeStack
   check-block: enable iotests with SafeStack

  configure| 73 
  include/qemu/coroutine_int.h |  5 +++
  tests/check-block.sh | 12 +-
  util/coroutine-sigaltstack.c |  4 ++
  util/coroutine-ucontext.c| 26 +
  5 files changed, 119 insertions(+), 1 deletion(-)





[PATCH v2 4/4] check-block: enable iotests with SafeStack

2020-05-29 Thread Daniele Buono
SafeStack is a stack protection technique implemented in llvm. It is
enabled with a -fsanitize flag.
iotests are currently disabled when any -fsanitize option is used,
because such options tend to produce additional warnings and false
positives.

While common -fsanitize options are used to verify the code and not
added in production, SafeStack's main use is in production environments
to protect against stack smashing.

Since SafeStack does not print any warning or false positive, enable
iotests when SafeStack is the only -fsanitize option used.
This is likely going to be a production binary and we want to make sure
it works correctly.

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index ad320c21ba..8e29c868e5 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -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
-- 
2.26.2




[PATCH v2 3/4] configure: add flags to support SafeStack

2020-05-29 Thread Daniele Buono
This patch adds a flag to enable/disable the SafeStack instrumentation
provided by LLVM.

On enable, make sure that the compiler supports the flags, and that we
are using the proper coroutine implementation (coroutine-ucontext).
On disable, explicitly disable the option if it was enabled by default.

While SafeStack is supported only on Linux, NetBSD, FreeBSD and macOS,
we are not checking for the O.S. since this is already done by LLVM.

Signed-off-by: Daniele Buono 
---
 configure | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/configure b/configure
index b969dee675..260772b2d5 100755
--- a/configure
+++ b/configure
@@ -302,6 +302,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")
 
@@ -1275,6 +1276,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"
@@ -1804,6 +1809,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
@@ -5517,6 +5524,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
@@ -6611,6 +6679,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
@@ -8195,6 +8264,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
-- 
2.26.2




[PATCH v2 1/4] coroutine: support SafeStack in ucontext backend

2020-05-29 Thread Daniele Buono
LLVM's SafeStack instrumentation does not yet support programs that make
use of the APIs in ucontext.h
With the current implementation of coroutine-ucontext, the resulting
binary is incorrect, with different coroutines sharing the same unsafe
stack and producing undefined behavior at runtime.
This fix allocates an additional unsafe stack area for each coroutine,
and sets the new unsafe stack pointer before calling swapcontext() in
qemu_coroutine_new.
This is the only place where the pointer needs to be manually updated,
since sigsetjmp/siglongjmp are already instrumented by LLVM to properly
support SafeStack.
The additional stack is then freed in qemu_coroutine_delete.

Signed-off-by: Daniele Buono 
---
 include/qemu/coroutine_int.h |  5 +
 util/coroutine-ucontext.c| 26 ++
 2 files changed, 31 insertions(+)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index bd6b0468e1..1da148552f 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -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 {
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index bd593e61bc..9108eb1294 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -41,6 +41,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;
 
 #ifdef CONFIG_VALGRIND_H
@@ -140,6 +145,10 @@ Coroutine *qemu_coroutine_new(void)
 co = g_malloc0(sizeof(*co));
 co->stack_size = COROUTINE_STACK_SIZE;
 co->stack = qemu_alloc_stack(>stack_size);
+#ifdef CONFIG_SAFESTACK
+co->unsafe_stack_size = COROUTINE_STACK_SIZE;
+co->unsafe_stack = qemu_alloc_stack(>unsafe_stack_size);
+#endif
 co->base.entry_arg = _env; /* stash away our jmp_buf */
 
 uc.uc_link = _uc;
@@ -160,6 +169,20 @@ Coroutine *qemu_coroutine_new(void)
 /* swapcontext() in, siglongjmp() back out */
 if (!sigsetjmp(old_env, 0)) {
 start_switch_fiber(_stack_save, co->stack, co->stack_size);
+#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(_uc, );
 }
 
@@ -192,6 +215,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);
 }
 
-- 
2.26.2




[PATCH v2 2/4] coroutine: add check for SafeStack in sigaltstack

2020-05-29 Thread Daniele Buono
Current implementation of LLVM's SafeStack is not compatible with
code that uses an alternate stack created with sigaltstack().
Since coroutine-sigaltstack relies on sigaltstack(), it is not
compatible with SafeStack. The resulting binary is incorrect, with
different coroutines sharing the same unsafe stack and producing
undefined behavior at runtime.

In the future LLVM may provide a SafeStack implementation compatible with
sigaltstack(). In the meantime, if SafeStack is desired, the coroutine
implementation from coroutine-ucontext should be used.
As a safety check, add a control in coroutine-sigaltstack to throw a
preprocessor #error if SafeStack is enabled and we are trying to
use coroutine-sigaltstack to implement coroutines.

Signed-off-by: Daniele Buono 
---
 util/coroutine-sigaltstack.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index f6fc49a0e5..aade82afb8 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -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;
-- 
2.26.2




[PATCH v2 0/4] Add support for SafeStack

2020-05-29 Thread Daniele Buono
LLVM supports SafeStack instrumentation to protect against stack buffer
overflows, since version 3.7

>From https://clang.llvm.org/docs/SafeStack.html:
"It works by separating the program stack into two distinct regions: the
safe stack and the unsafe stack. The safe stack stores return addresses,
register spills, and local variables that are always accessed in a safe
way, while the unsafe stack stores everything else. This separation
ensures that buffer overflows on the unsafe stack cannot be used to
overwrite anything on the safe stack."

Unfortunately, the use of two stack regions does not cope well with
QEMU's coroutines. The second stack region is not properly set up with
both ucontext and sigaltstack, so multiple coroutines end up sharing the
same memory area for the unsafe stack, causing undefined behaviors at
runtime (and most iochecks to fail).

This patch series fixes the implementation of the ucontext backend and
make sure that sigaltstack is never used if the compiler is applying
the SafeStack instrumentation. It also adds a configure flag to enable
SafeStack, and enables iotests when SafeStack is used.

Changes since v1:
 - CONFIG_SAFESTACK is now set up in configure, and not in the code
 - Added option for a --disable-safe-stack in configure
 - Configure checks if SafeStack is enabled by default in the compiler,
   and set the CONFIG_SAFESTACK accordingly
 - Updated some comments in the code and the commit log

NOTE: I kept configure as Patch #3. 
The reason is that the code changes will not be enabled without the
configure, making the code fully functional if only Patches #1 or #2 are
applied.
On the other hand, the configure patch will produce incorrect code if we
request SafeStack and the other patches are not applied.

Daniele Buono (4):
  coroutine: support SafeStack in ucontext backend
  coroutine: add check for SafeStack in sigaltstack
  configure: add flags to support SafeStack
  check-block: enable iotests with SafeStack

 configure| 73 
 include/qemu/coroutine_int.h |  5 +++
 tests/check-block.sh | 12 +-
 util/coroutine-sigaltstack.c |  4 ++
 util/coroutine-ucontext.c| 26 +
 5 files changed, 119 insertions(+), 1 deletion(-)

-- 
2.26.2




Re: [PATCH 2/4] coroutine: Add check for SafeStack in sigalstack

2020-05-27 Thread Daniele Buono

Sorry, missed the question at the end of the email.
Will change the commit and error message to explain better in v2.

Similar to the ucontext, case, sigaltstack does not work out of the box
because it requires a stack to be allocated by the user.

I'll be honest, I didn't check the details of how sigaltstack is used in
coroutine-sigaltstack. It is very possible that this coroutine version
can also be adapted to run properly with SafeStack.
coroutine_trampoline is probably the place where we can set the usp so
that, when coroutine_bootstrap is called, it is done with the new unsafe
stack.

My initial focus was on the ucontext implementation since that is the
default one and mostly used. For now, I am just blocking the user from
using coroutine-sigaltstack with SafeStack.

However, if you are interested, Ican try to add support to sigaltstack
in the future.

On 5/21/2020 5:49 AM, Stefan Hajnoczi wrote:

On Wed, Apr 29, 2020 at 03:44:18PM -0400, Daniele Buono wrote:

s/sigalstack/sigaltstack/ in the commit message.


LLVM's SafeStack instrumentation cannot be used inside signal handlers
that make use of sigaltstack().
Since coroutine-sigaltstack relies on sigaltstack(), it is not
compatible with SafeStack. The resulting binary is incorrect, with
different coroutines sharing the same unsafe stack and producing
undefined behavior at runtime.
To avoid this, we add a check in coroutine-sigaltstack that throws a
preprocessor #error and interrupt the compilation if SafeStack is
enabled.

Signed-off-by: Daniele Buono 
---
  util/coroutine-sigaltstack.c | 4 
  1 file changed, 4 insertions(+)

diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index f6fc49a0e5..b7cdc959f8 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -30,6 +30,10 @@
  #include "qemu-common.h"
  #include "qemu/coroutine_int.h"
  
+#ifdef CONFIG_SAFESTACK

+#error "SafeStack does not work with sigaltstack's implementation"
+#endif


Neither the commit description nor the #error message explain why it
doesn't work. Could it work in the future or is there a fundamental
reason why it will never work?

Stefan





Re: [PATCH 3/4] configure: add flag to enable SafeStack

2020-05-27 Thread Daniele Buono

Hi Stefan, a quick clarification on configure:

right now, in configure, there's
* "Advanced Options (experts only)"
which usually don't have both enable and disable for each option, and
* "Optional features, enabled with --enable-FEATURE and
disabled with --disable-FEATURE, default is enabled if available:"

How do you think SafeStack should be classified?
* If we do it as Advanced option, we should probably force it disabled
unless --enable-safe-stack is provided. In this case
--disable-safe-stack is not really necessary.
* If we do it as optional feature, I have two ways to handle the default:
1. enable/disable based on the compilation flags given to configure
2. enable every time the provided compiler supports it

On 5/27/2020 7:12 AM, Stefan Hajnoczi wrote:

On Fri, May 22, 2020 at 11:24:46AM -0400, Daniele Buono wrote:

I would feel more confident by adding another check in configure to make
sure that the user didn't enable SafeStack manually through other means,
like manually setting the option through extra_cflags.
What do you think?


Sure, a compile_prog call could check if SafeStack is enable when it
shouldn't be.

This can be done together with a --disable option.

Stefan





Re: [PATCH 4/4] check-block: Enable iotests with SafeStack

2020-05-22 Thread Daniele Buono



On 5/21/2020 5:59 AM, Stefan Hajnoczi wrote:

On Wed, Apr 29, 2020 at 03:44:20PM -0400, Daniele Buono wrote:

SafeStack is a stack protection technique implemented in llvm. It is
enabled with a -fsanitize flag.
iotests are currently disabled when any -fsanitize option is used.
Since SafeStack is useful on production environments, and its
implementation may break the binary, filter it out when the check is
performed, so that if SafeStack was the only -fsanitize option, iotests
are still performed.


I can't parse this sentence. What does "its implementation may break the
binary" mean? Do you mean it's worth running tests with SafeStack
enabled because it exposes failures that go unnoticed without SafeStack?


What I meant is that, without proper changes, SafeStack breaks 
co-routines. Since they are heavily used in the io subsystem, this is 
probably the best class of tests to make sure co-routines are working 
fine with SafeStack.


I initially re-enabled the iotests for my internal testing.

Since I wasn't seeing any issue, I thought it would be useful to keep 
running this to make sure future implementations of SafeStack won't 
break co-routines again.






Signed-off-by: Daniele Buono 
---
  tests/check-block.sh | 12 +++-
  1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index ad320c21ba..8e29c868e5 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -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


The commit that disabled check-block.sh with sanitizers said:

   The sanitizers (especially the address sanitizer from Clang) are
   sometimes printing out warnings or false positives - this spoils
   the output of the iotests, causing some of the tests to fail.

It seems fine to allow SafeStack if check-block.sh currently passes with
it enabled. Does it pass and produce no extra output?

Yes, that was the idea. SafeStack should pass the tests without extra 
output.


It did (pass) on my testing machine. However I don't remember if I did 
the full (slow) check or only the partial one.


Will check again before I submit v2

Stefan





Re: [PATCH 3/4] configure: add flag to enable SafeStack

2020-05-22 Thread Daniele Buono

Hi Stefan,

I would feel more confident by adding another check in configure to make
sure that the user didn't enable SafeStack manually through other means,
like manually setting the option through extra_cflags.
What do you think?

On 5/21/2020 5:52 AM, Stefan Hajnoczi wrote:

On Wed, Apr 29, 2020 at 03:44:19PM -0400, Daniele Buono wrote:

This patch adds a flag to enable the SafeStack instrumentation provided
by LLVM.
The checks make sure that the compiler supports the flags, and that we
are using the proper coroutine implementation (coroutine-ucontext).
While SafeStack is supported only on Linux, NetBSD, FreeBSD and macOS,
we are not checking for the O.S. since this is already done by LLVM.

Signed-off-by: Daniele Buono 
---
  configure | 29 +
  1 file changed, 29 insertions(+)


Great, this can become Patch 1 and it can set CONFIG_SAFESTACK as
mentioned in my earlier reply.


diff --git a/configure b/configure
index 23b5e93752..f37e4ae0bd 100755
--- a/configure
+++ b/configure
@@ -302,6 +302,7 @@ audio_win_int=""
  libs_qga=""
  debug_info="yes"
  stack_protector=""
+safe_stack="no"


The comment above this says:

   # Always add --enable-foo and --disable-foo command line args.

Please add --disable-safe-stack.





Re: [PATCH 1/4] coroutine: support SafeStack in ucontext backend

2020-05-22 Thread Daniele Buono

Hi Stefan,
thank you so much for reviewing this.
See my answers below:

On 5/21/2020 5:44 AM, Stefan Hajnoczi wrote:

On Wed, Apr 29, 2020 at 03:44:17PM -0400, Daniele Buono wrote:

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index bd6b0468e1..2ffd75ddbe 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,6 +28,12 @@
  #include "qemu/queue.h"
  #include "qemu/coroutine.h"
  
+#if defined(__has_feature) && __has_feature(safe_stack)

+#define CONFIG_SAFESTACK 1


Please perform this feature check in ./configure. That way
CONFIG_SAFESTACK will be defined alongside all the other CONFIG_* values
and be available to C and Makefiles via config-host.h and
config-host.mak.



Sure, will do this in v2.


@@ -160,6 +169,19 @@ Coroutine *qemu_coroutine_new(void)
  /* swapcontext() in, siglongjmp() back out */
  if (!sigsetjmp(old_env, 0)) {
  start_switch_fiber(_stack_save, co->stack, co->stack_size);
+#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 it afterwards because sigsetjmp was
+ * called with the original usp. Since we are not coming back with a
+ * swapcontext, but with a siglongjmp, when we are back here we
+ * already have usp restored to the valid one for this function


I don't understand this comment. __safestack_unsafe_stack_ptr is a
thread-local variable, not a CPU register. How will siglongjmp()
automatically restore it?


Correct, setjmp/longjmp have no visibility of the unsafe stack. What I
meant is that it is not automatically restored by the longjmp itself,
but by code the compiler adds around the sigsetjmp.

Specifically, every sigsetjmp/sigjmp is intercepted by the compiler, the
current value of __safestack_unsafe_stack_ptr is saved on the normal
(safe) stack.
Right after the sigsetjmp call it is then restored.

I will change the comment to make it clearer.

In practice, this is what happens:

Original clang implementation in qemu_coroutine_new:

40130c:  callq  4008d0 <__sigsetjmp@plt>
401311:  cmp$0x0,%eax
401314:  jne40132d 

Clang Implementation with safestack:

4027a7:  mov%rdx,-0x38(%rbp) <- Save unsafe ptr onto the safe stack
[...]
40289c:  callq  401410 <__sigsetjmp@plt>
4028a1:  mov0x201738(%rip),%rdi# 603fe0 
<__safestack_unsafe_stack_ptr@@Base+0x603fe0>

4028a8:  mov-0x38(%rbp),%rbx
4028ac:  mov%rbx,%fs:(%rdi) <- Restore the unsafe ptr
4028b0:  cmp$0x0,%eax
4028b3:  jne4028d9 



+ */
+void *usp = co->unsafe_stack + co->unsafe_stack_size;
+__safestack_unsafe_stack_ptr = usp;
+#endif
  swapcontext(_uc, );
  }
  




Re: [PATCH 0/4] Add support for SafeStack

2020-05-13 Thread Daniele Buono

Hello everybody, just pinging since it it's been a few days.

On 5/5/2020 9:56 AM, Philippe Mathieu-Daudé wrote:

On 5/5/20 3:31 PM, Daniel P. Berrangé wrote:

On Tue, May 05, 2020 at 03:15:18PM +0200, Philippe Mathieu-Daudé wrote:

+Alex & Daniel who keep track on CI stuff.

On 4/29/20 9:44 PM, Daniele Buono wrote:

LLVM supports SafeStack instrumentation to protect against stack buffer
overflows, since version 3.7

  From https://clang.llvm.org/docs/SafeStack.html:
"It works by separating the program stack into two distinct regions: 
the
safe stack and the unsafe stack. The safe stack stores return 
addresses,

register spills, and local variables that are always accessed in a safe
way, while the unsafe stack stores everything else. This separation
ensures that buffer overflows on the unsafe stack cannot be used to
overwrite anything on the safe stack."

Unfortunately, the use of two stack regions does not cope well with
QEMU's coroutines. The second stack region is not properly set up with
both ucontext and sigaltstack, so multiple coroutines end up sharing 
the

same memory area for the unsafe stack, causing undefined behaviors at
runtime (and most iochecks to fail).

This patch series fixes the implementation of the ucontext backend and
make sure that sigaltstack is never used if the compiler is applying
the SafeStack instrumentation. It also adds a configure flag to enable
SafeStack, and enables iotests when SafeStack is used.

This is an RFC mainly because of the low-level use of the SafeStack
runtime.
When running swapcontext(), we have to manually set the unsafe stack
pointer to the new area allocated for the coroutine. LLVM does not 
allow
this by using builtin, so we have to use implementation details that 
may

change in the future.
This patch has been tested briefly ( make check on an x86 system ) with
clang v3.9, v4.0, v5.0, v6.0
Heavier testing, with make check-acceptance has been performed with
clang v7.0


I noticed building using SafeStack is slower, and running with it is 
even
slwer. It makes sense to have this integrated if we use it 
regularly. Do

you have plan for this? Using public CI doesn't seem reasonable.


The runtime behaviour is rather odd, given the docs they provide:

"The performance overhead of the SafeStack instrumentation is
  less than 0.1% on average across a variety of benchmarks
  This is mainly because most small functions do not have any
  variables that require the unsafe stack and, hence, do not
  need unsafe stack frames to be created. The cost of creating
  unsafe stack frames for large functions is amortized by the
  cost of executing the function.

   In some cases, SafeStack actually improves the performance"


I'm sorry I was testing this with a single core instead of all of 
them... Thanks for looking at the doc.




Regards,
Daniel








[PATCH v2 0/1] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

2020-05-05 Thread Daniele Buono
This patch fixes a compilation error with Clang v9 and higher in
target/ppc/translate.c, on a comparison that is always true in PPC32
because of type sizes.

More information about the issue are in the first version of the patch.

v2, changed to avoid the nested ifdef/conditional solution of v1, and
keep a code structure more similar to the original.

Daniele Buono (1):
  target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

 target/ppc/translate.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

-- 
2.26.2




[PATCH v2 1/1] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

2020-05-05 Thread Daniele Buono
Starting with Clang v9, -Wtype-limits is implemented and triggers a
few "result of comparison is always true" errors when compiling PPC32
targets.

The comparisons seem to be necessary only on PPC64, since the
else branch in PPC32 only has a "g_assert_not_reached();" in all cases.

This patch restructures the code so that the actual if/else is done on a
local flag variable, that is set accordingly for PPC64, and always
true for PPC32.

Signed-off-by: Daniele Buono 
---
 target/ppc/translate.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 807d14faaa..338529879f 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1882,6 +1882,7 @@ static void gen_rlwimi(DisasContext *ctx)
 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
 } else {
 target_ulong mask;
+bool mask_in_32b = true;
 TCGv t1;
 
 #if defined(TARGET_PPC64)
@@ -1890,8 +1891,13 @@ static void gen_rlwimi(DisasContext *ctx)
 #endif
 mask = MASK(mb, me);
 
+#if defined(TARGET_PPC64)
+if (mask > 0xu) {
+mask_in_32b = false;
+}
+#endif
 t1 = tcg_temp_new();
-if (mask <= 0xu) {
+if (mask_in_32b) {
 TCGv_i32 t0 = tcg_temp_new_i32();
 tcg_gen_trunc_tl_i32(t0, t_rs);
 tcg_gen_rotli_i32(t0, t0, sh);
@@ -1933,12 +1939,18 @@ static void gen_rlwinm(DisasContext *ctx)
 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
 } else {
 target_ulong mask;
+bool mask_in_32b = true;
 #if defined(TARGET_PPC64)
 mb += 32;
 me += 32;
 #endif
 mask = MASK(mb, me);
-if (mask <= 0xu) {
+#if defined(TARGET_PPC64)
+if (mask > 0xu) {
+mask_in_32b = false;
+}
+#endif
+if (mask_in_32b) {
 if (sh == 0) {
 tcg_gen_andi_tl(t_ra, t_rs, mask);
 } else {
@@ -1973,6 +1985,7 @@ static void gen_rlwnm(DisasContext *ctx)
 uint32_t mb = MB(ctx->opcode);
 uint32_t me = ME(ctx->opcode);
 target_ulong mask;
+bool mask_in_32b = true;
 
 #if defined(TARGET_PPC64)
 mb += 32;
@@ -1980,7 +1993,12 @@ static void gen_rlwnm(DisasContext *ctx)
 #endif
 mask = MASK(mb, me);
 
-if (mask <= 0xu) {
+#if defined(TARGET_PPC64)
+if (mask > 0xu) {
+mask_in_32b = false;
+}
+#endif
+if (mask_in_32b) {
 TCGv_i32 t0 = tcg_temp_new_i32();
 TCGv_i32 t1 = tcg_temp_new_i32();
 tcg_gen_trunc_tl_i32(t0, t_rb);
-- 
2.26.2




Re: [PATCH 1/1] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

2020-05-05 Thread Daniele Buono

On 5/5/2020 1:08 AM, David Gibson wrote:

On Fri, May 01, 2020 at 03:09:13PM -0400, Daniele Buono wrote:

Starting with Clang v9, -Wtype-limits is implemented and triggers a
few "result of comparison is always true" errors when compiling PPC32
targets.

The comparisons seem to be necessary only on PPC64, since the
else branch in PPC32 only has a "g_assert_not_reached();" in all cases.

This patch restructures the code so that PPC32 does not execute the
check, while PPC64 works like before

Signed-off-by: Daniele Buono 


Urgh.  #ifdefs intertangled with if statements gets pretty ugly.  But,
then, it's already pretty ugly, so, applied.

Agreed, it's very ugly. After I sent the patch I thought of an 
alternative that looks like this:


bool mask_in_32b = true;

#if defined(TARGET_PPC64)
if (mask > 0xu)
  mask_in_32b = false;
#endif

if (mask_in_32b) {
/* Original if-else untouched using mask_in_32b instead of mask*/

It does have an additional if, but with a bit of luck the compiler may 
optimize it out (at least for the 32bit case).
If you think the final outcome may be better, let me know and I'll send 
a patch v2 like that.



---
  target/ppc/translate.c | 34 +++---
  1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 807d14faaa..9400fa2c7c 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1882,6 +1882,7 @@ static void gen_rlwimi(DisasContext *ctx)
  tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
  } else {
  target_ulong mask;
+TCGv_i32 t0;
  TCGv t1;
  
  #if defined(TARGET_PPC64)

@@ -1891,20 +1892,20 @@ static void gen_rlwimi(DisasContext *ctx)
  mask = MASK(mb, me);
  
  t1 = tcg_temp_new();

+#if defined(TARGET_PPC64)
  if (mask <= 0xu) {
-TCGv_i32 t0 = tcg_temp_new_i32();
+#endif
+t0 = tcg_temp_new_i32();
  tcg_gen_trunc_tl_i32(t0, t_rs);
  tcg_gen_rotli_i32(t0, t0, sh);
  tcg_gen_extu_i32_tl(t1, t0);
  tcg_temp_free_i32(t0);
-} else {
  #if defined(TARGET_PPC64)
+} else {
  tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
  tcg_gen_rotli_i64(t1, t1, sh);
-#else
-g_assert_not_reached();
-#endif
  }
+#endif
  
  tcg_gen_andi_tl(t1, t1, mask);

  tcg_gen_andi_tl(t_ra, t_ra, ~mask);
@@ -1938,7 +1939,9 @@ static void gen_rlwinm(DisasContext *ctx)
  me += 32;
  #endif
  mask = MASK(mb, me);
+#if defined(TARGET_PPC64)
  if (mask <= 0xu) {
+#endif
  if (sh == 0) {
  tcg_gen_andi_tl(t_ra, t_rs, mask);
  } else {
@@ -1949,15 +1952,13 @@ static void gen_rlwinm(DisasContext *ctx)
  tcg_gen_extu_i32_tl(t_ra, t0);
  tcg_temp_free_i32(t0);
  }
-} else {
  #if defined(TARGET_PPC64)
+} else {
  tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
  tcg_gen_rotli_i64(t_ra, t_ra, sh);
  tcg_gen_andi_i64(t_ra, t_ra, mask);
-#else
-g_assert_not_reached();
-#endif
  }
+#endif
  }
  if (unlikely(Rc(ctx->opcode) != 0)) {
  gen_set_Rc0(ctx, t_ra);
@@ -1972,6 +1973,9 @@ static void gen_rlwnm(DisasContext *ctx)
  TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
  uint32_t mb = MB(ctx->opcode);
  uint32_t me = ME(ctx->opcode);
+TCGv_i32 t0;
+TCGv_i32 t1;
+
  target_ulong mask;
  
  #if defined(TARGET_PPC64)

@@ -1980,9 +1984,11 @@ static void gen_rlwnm(DisasContext *ctx)
  #endif
  mask = MASK(mb, me);
  
+#if defined(TARGET_PPC64)

  if (mask <= 0xu) {
-TCGv_i32 t0 = tcg_temp_new_i32();
-TCGv_i32 t1 = tcg_temp_new_i32();
+#endif
+t0 = tcg_temp_new_i32();
+t1 = tcg_temp_new_i32();
  tcg_gen_trunc_tl_i32(t0, t_rb);
  tcg_gen_trunc_tl_i32(t1, t_rs);
  tcg_gen_andi_i32(t0, t0, 0x1f);
@@ -1990,17 +1996,15 @@ static void gen_rlwnm(DisasContext *ctx)
  tcg_gen_extu_i32_tl(t_ra, t1);
  tcg_temp_free_i32(t0);
  tcg_temp_free_i32(t1);
-} else {
  #if defined(TARGET_PPC64)
+} else {
  TCGv_i64 t0 = tcg_temp_new_i64();
  tcg_gen_andi_i64(t0, t_rb, 0x1f);
  tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
  tcg_gen_rotl_i64(t_ra, t_ra, t0);
  tcg_temp_free_i64(t0);
-#else
-g_assert_not_reached();
-#endif
  }
+#endif
  
  tcg_gen_andi_tl(t_ra, t_ra, mask);
  






[PATCH 0/1] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

2020-05-01 Thread Daniele Buono
Until Clang v8, -Wtype-limits was kept for GCC compatibility but had no
effect. With Clang v9, the flag is now implemented ( see 
https://tinyurl.com/clang8-manual vs https://tinyurl.com/clang9-manual )

Starting with Clang v9, compiling with -Wtype-limits (default for QEMU)
triggers the following errors on the ppc-softmmu and ppc-linux-user
targets:
   
/root/qemu/target/ppc/translate.c:1894:18: error: result of comparison
'target_ulong' (aka 'unsigned int') <= 4294967295 is always true
[-Werror,-Wtautological-type-limit-compare]
if (mask <= 0xu) {
 ^  ~~~
/root/qemu/target/ppc/translate.c:1941:18: error: result of comparison
'target_ulong' (aka 'unsigned int') <= 4294967295 is always true
[-Werror,-Wtautological-type-limit-compare]
if (mask <= 0xu) {
 ^  ~~~
/root/qemu/target/ppc/translate.c:1983:14: error: result of comparison
'target_ulong' (aka 'unsigned int') <= 4294967295 is always true
[-Werror,-Wtautological-type-limit-compare]
if (mask <= 0xu) {
 ^  ~~~

The same error can be triggered with this small repro:
int main() {
unsigned int x = 1;
if ( x <= 0xu) return 1;
return 0;
}

$ gcc test.c -Wtype-limits
[nothing]
$ clang-9 test.c -Wtype-limits
test.c:3:12: warning: result of comparison 'unsigned int' <= 4294967295 
is always true [-Wtautological-type-limit-compare]
if ( x <= 0xu) 
 ~ ^  ~~~
1 warning generated.
$ clang-9 test.c -Wtype-limits -Wno-tautological-type-limit-compare
[nothing]

We could get away with the compilation error by adding the flag
"-Wno-tautological-type-limit-compare", but I think we should avoid that
to make sure the checks are applied to the rest of the code and warn us
for logical errors in the future.

Looking at the code, the comparison is only needed for PPC64, since
the else branch in PPC32 only has a "g_assert_not_reached();"
This patch restructures the code so that PPC32 always runs the "true"
branch.

I tried to keep the changes to a minimum, to make sure to not affect the
semantics of the instructions. However, considering the target
architecture, my testing has been limited. check-acceptance seems to be
able to properly start a few linux kernels succesfully, and make check
didn't complain on both ppc-softmmu and ppc64-softmmu.

Daniele Buono (1):
  target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

 target/ppc/translate.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

-- 
2.26.2




[PATCH 1/1] target-ppc: fix rlwimi, rlwinm, rlwnm for Clang-9

2020-05-01 Thread Daniele Buono
Starting with Clang v9, -Wtype-limits is implemented and triggers a
few "result of comparison is always true" errors when compiling PPC32
targets.

The comparisons seem to be necessary only on PPC64, since the
else branch in PPC32 only has a "g_assert_not_reached();" in all cases.

This patch restructures the code so that PPC32 does not execute the
check, while PPC64 works like before

Signed-off-by: Daniele Buono 
---
 target/ppc/translate.c | 34 +++---
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 807d14faaa..9400fa2c7c 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1882,6 +1882,7 @@ static void gen_rlwimi(DisasContext *ctx)
 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
 } else {
 target_ulong mask;
+TCGv_i32 t0;
 TCGv t1;
 
 #if defined(TARGET_PPC64)
@@ -1891,20 +1892,20 @@ static void gen_rlwimi(DisasContext *ctx)
 mask = MASK(mb, me);
 
 t1 = tcg_temp_new();
+#if defined(TARGET_PPC64)
 if (mask <= 0xu) {
-TCGv_i32 t0 = tcg_temp_new_i32();
+#endif
+t0 = tcg_temp_new_i32();
 tcg_gen_trunc_tl_i32(t0, t_rs);
 tcg_gen_rotli_i32(t0, t0, sh);
 tcg_gen_extu_i32_tl(t1, t0);
 tcg_temp_free_i32(t0);
-} else {
 #if defined(TARGET_PPC64)
+} else {
 tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
 tcg_gen_rotli_i64(t1, t1, sh);
-#else
-g_assert_not_reached();
-#endif
 }
+#endif
 
 tcg_gen_andi_tl(t1, t1, mask);
 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
@@ -1938,7 +1939,9 @@ static void gen_rlwinm(DisasContext *ctx)
 me += 32;
 #endif
 mask = MASK(mb, me);
+#if defined(TARGET_PPC64)
 if (mask <= 0xu) {
+#endif
 if (sh == 0) {
 tcg_gen_andi_tl(t_ra, t_rs, mask);
 } else {
@@ -1949,15 +1952,13 @@ static void gen_rlwinm(DisasContext *ctx)
 tcg_gen_extu_i32_tl(t_ra, t0);
 tcg_temp_free_i32(t0);
 }
-} else {
 #if defined(TARGET_PPC64)
+} else {
 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
 tcg_gen_rotli_i64(t_ra, t_ra, sh);
 tcg_gen_andi_i64(t_ra, t_ra, mask);
-#else
-g_assert_not_reached();
-#endif
 }
+#endif
 }
 if (unlikely(Rc(ctx->opcode) != 0)) {
 gen_set_Rc0(ctx, t_ra);
@@ -1972,6 +1973,9 @@ static void gen_rlwnm(DisasContext *ctx)
 TCGv t_rb = cpu_gpr[rB(ctx->opcode)];
 uint32_t mb = MB(ctx->opcode);
 uint32_t me = ME(ctx->opcode);
+TCGv_i32 t0;
+TCGv_i32 t1;
+
 target_ulong mask;
 
 #if defined(TARGET_PPC64)
@@ -1980,9 +1984,11 @@ static void gen_rlwnm(DisasContext *ctx)
 #endif
 mask = MASK(mb, me);
 
+#if defined(TARGET_PPC64)
 if (mask <= 0xu) {
-TCGv_i32 t0 = tcg_temp_new_i32();
-TCGv_i32 t1 = tcg_temp_new_i32();
+#endif
+t0 = tcg_temp_new_i32();
+t1 = tcg_temp_new_i32();
 tcg_gen_trunc_tl_i32(t0, t_rb);
 tcg_gen_trunc_tl_i32(t1, t_rs);
 tcg_gen_andi_i32(t0, t0, 0x1f);
@@ -1990,17 +1996,15 @@ static void gen_rlwnm(DisasContext *ctx)
 tcg_gen_extu_i32_tl(t_ra, t1);
 tcg_temp_free_i32(t0);
 tcg_temp_free_i32(t1);
-} else {
 #if defined(TARGET_PPC64)
+} else {
 TCGv_i64 t0 = tcg_temp_new_i64();
 tcg_gen_andi_i64(t0, t_rb, 0x1f);
 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
 tcg_gen_rotl_i64(t_ra, t_ra, t0);
 tcg_temp_free_i64(t0);
-#else
-g_assert_not_reached();
-#endif
 }
+#endif
 
 tcg_gen_andi_tl(t_ra, t_ra, mask);
 
-- 
2.26.2




[PATCH 3/4] configure: add flag to enable SafeStack

2020-04-29 Thread Daniele Buono
This patch adds a flag to enable the SafeStack instrumentation provided
by LLVM.
The checks make sure that the compiler supports the flags, and that we
are using the proper coroutine implementation (coroutine-ucontext).
While SafeStack is supported only on Linux, NetBSD, FreeBSD and macOS,
we are not checking for the O.S. since this is already done by LLVM.

Signed-off-by: Daniele Buono 
---
 configure | 29 +
 1 file changed, 29 insertions(+)

diff --git a/configure b/configure
index 23b5e93752..f37e4ae0bd 100755
--- a/configure
+++ b/configure
@@ -302,6 +302,7 @@ audio_win_int=""
 libs_qga=""
 debug_info="yes"
 stack_protector=""
+safe_stack="no"
 use_containers="yes"
 gdb_bin=$(command -v "gdb")
 
@@ -1275,6 +1276,8 @@ for opt do
   ;;
   --disable-stack-protector) stack_protector="no"
   ;;
+  --enable-safe-stack) safe_stack="yes"
+  ;;
   --disable-curses) curses="no"
   ;;
   --enable-curses) curses="yes"
@@ -1774,6 +1777,8 @@ Advanced options (experts only):
   --with-coroutine=BACKEND coroutine backend. Supported options:
ucontext, sigaltstack, windows
   --enable-gcovenable test coverage analysis with gcov
+  --enable-safe-stack  enable the SafeStack stack protection. Depends on
+   clang/llvm >= 3.7 and coroutine backend ucontext.
   --gcov=GCOV  use specified gcov [$gcov_tool]
   --disable-blobs  disable installing provided firmware blobs
   --with-vss-sdk=SDK-path  enable Windows VSS support in QEMU Guest Agent
@@ -5501,6 +5506,29 @@ if test "$debug_stack_usage" = "yes"; then
   fi
 fi
 
+##
+# Check if SafeStack is enabled and supported
+
+if test "$safe_stack" = "yes"; then
+  cat > $TMPC << EOF
+int main(int argc, char *argv[])
+{
+return 0;
+}
+EOF
+  flag="-fsanitize=safe-stack"
+  # Check that safe-stack is supported.
+  if compile_prog "-Werror $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
+fi
 
 ##
 # check if we have open_by_handle_at
@@ -6595,6 +6623,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
-- 
2.26.2




[PATCH 2/4] coroutine: Add check for SafeStack in sigalstack

2020-04-29 Thread Daniele Buono
LLVM's SafeStack instrumentation cannot be used inside signal handlers
that make use of sigaltstack().
Since coroutine-sigaltstack relies on sigaltstack(), it is not
compatible with SafeStack. The resulting binary is incorrect, with
different coroutines sharing the same unsafe stack and producing
undefined behavior at runtime.
To avoid this, we add a check in coroutine-sigaltstack that throws a
preprocessor #error and interrupt the compilation if SafeStack is
enabled.

Signed-off-by: Daniele Buono 
---
 util/coroutine-sigaltstack.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/util/coroutine-sigaltstack.c b/util/coroutine-sigaltstack.c
index f6fc49a0e5..b7cdc959f8 100644
--- a/util/coroutine-sigaltstack.c
+++ b/util/coroutine-sigaltstack.c
@@ -30,6 +30,10 @@
 #include "qemu-common.h"
 #include "qemu/coroutine_int.h"
 
+#ifdef CONFIG_SAFESTACK
+#error "SafeStack does not work with sigaltstack's implementation"
+#endif
+
 typedef struct {
 Coroutine base;
 void *stack;
-- 
2.26.2




[PATCH 4/4] check-block: Enable iotests with SafeStack

2020-04-29 Thread Daniele Buono
SafeStack is a stack protection technique implemented in llvm. It is
enabled with a -fsanitize flag.
iotests are currently disabled when any -fsanitize option is used.
Since SafeStack is useful on production environments, and its
implementation may break the binary, filter it out when the check is
performed, so that if SafeStack was the only -fsanitize option, iotests
are still performed.

Signed-off-by: Daniele Buono 
---
 tests/check-block.sh | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/tests/check-block.sh b/tests/check-block.sh
index ad320c21ba..8e29c868e5 100755
--- a/tests/check-block.sh
+++ b/tests/check-block.sh
@@ -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
-- 
2.26.2




[PATCH 1/4] coroutine: support SafeStack in ucontext backend

2020-04-29 Thread Daniele Buono
LLVM's SafeStack instrumentation does not yet support programs that make
use of the APIs in ucontext.h
With the current implementation of coroutine-ucontext, the resulting
binary is incorrect, with different coroutines sharing the same unsafe
stack and producing undefined behavior at runtime.
This fix allocates an additional unsafe stack area for each coroutine,
and sets the new unsafe stack pointer before calling swapcontext() in
qemu_coroutine_new.
This is the only place where the pointer needs to be manually updated,
since sigsetjmp/siglongjmp are already instrumented by LLVM to properly
support SafeStack.
The additional stack is then freed in qemu_coroutine_delete.

Signed-off-by: Daniele Buono 
---
 include/qemu/coroutine_int.h |  6 ++
 util/coroutine-ucontext.c| 25 +
 2 files changed, 31 insertions(+)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index bd6b0468e1..2ffd75ddbe 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,6 +28,12 @@
 #include "qemu/queue.h"
 #include "qemu/coroutine.h"
 
+#if defined(__has_feature) && __has_feature(safe_stack)
+#define CONFIG_SAFESTACK 1
+/* 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 {
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index bd593e61bc..b79e9df9eb 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -41,6 +41,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;
 
 #ifdef CONFIG_VALGRIND_H
@@ -140,6 +145,10 @@ Coroutine *qemu_coroutine_new(void)
 co = g_malloc0(sizeof(*co));
 co->stack_size = COROUTINE_STACK_SIZE;
 co->stack = qemu_alloc_stack(>stack_size);
+#ifdef CONFIG_SAFESTACK
+co->unsafe_stack_size = COROUTINE_STACK_SIZE;
+co->unsafe_stack = qemu_alloc_stack(>unsafe_stack_size);
+#endif
 co->base.entry_arg = _env; /* stash away our jmp_buf */
 
 uc.uc_link = _uc;
@@ -160,6 +169,19 @@ Coroutine *qemu_coroutine_new(void)
 /* swapcontext() in, siglongjmp() back out */
 if (!sigsetjmp(old_env, 0)) {
 start_switch_fiber(_stack_save, co->stack, co->stack_size);
+#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 it afterwards because sigsetjmp was
+ * called with the original usp. Since we are not coming back with a
+ * swapcontext, but with a siglongjmp, when we are back here we
+ * already have usp restored to the valid one for this function
+ */
+void *usp = co->unsafe_stack + co->unsafe_stack_size;
+__safestack_unsafe_stack_ptr = usp;
+#endif
 swapcontext(_uc, );
 }
 
@@ -192,6 +214,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);
 }
 
-- 
2.26.2




  1   2   >