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 Alexander Bulekov
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 Paolo Bonzini
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?

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







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 *, enum ,  void *)

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

2020-07-02 Thread Alexander Bulekov
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 Daniel P . Berrangé
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 ?

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 

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

2020-07-02 Thread Paolo Bonzini
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




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"
+  ;;
+  --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 

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

2020-07-02 Thread Daniel P . Berrangé
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
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




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

2020-07-02 Thread Paolo Bonzini
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

> ---
>  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)