diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-09-09 17:13:04 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-09-09 17:13:04 -0400 |
commit | c81b60b8c6ff3d4db2e395a628e114df812cfc48 (patch) | |
tree | e1e3715a12fdaf50af93746d0df9ec4c744f8321 /gcc/fortran/f95-lang.cc | |
parent | 07e30160beaa207f56f170900fac0d799c6af410 (diff) | |
download | gcc-c81b60b8c6ff3d4db2e395a628e114df812cfc48.zip gcc-c81b60b8c6ff3d4db2e395a628e114df812cfc48.tar.gz gcc-c81b60b8c6ff3d4db2e395a628e114df812cfc48.tar.bz2 |
analyzer: implement trust boundaries via a plugin for Linux kernel
This is a less ambitious version of:
[PATCH 0/6] RFC: adding support to GCC for detecting trust boundaries
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584372.html
Earlier versions of this patch attempted:
(a) various ways of identifying "untrusted" memory regions
(b) providing a way to support the Linux kernel's "__user" annotation,
either via type attributes, or via custom address spaces
(c) enough attributes to identify "copy_from_user" and "copy_to_user",
(d) wiring all of the above together to detect infoleaks and taint
This patch adds a new -Wanalyzer-exposure-through-uninit-copy, emitted
by -fanalyzer if it detects copying of uninitialized data through
a pointer to an untrusted region, but requires a plugin to tell it when
a copy crosses a trust boundary.
This patch adds a proof-of-concept gcc plugin for the analyzer for use
with the Linux kernel that special-cases calls to "copy_from_user" and
calls to "copy_to_user": calls to copy_to_user are checked for
-Wanalyzer-exposure-through-uninit-copy, and data copied via
copy_from_user is marked as tainted when -fanalyzer-checker=taint is
active.
This is very much just a proof-of-concept. A big limitation is that the
copy_{from,to}_user special-casing only happens if these functions have
no body in the TU being analyzed, which isn't the case for a normal
kernel build. I'd much prefer to provide a more general mechanism for
handling such behavior without resorting to plugins (e.g. via attributes
or custom address spaces), but in the interest of not "letting perfect
be the enemy of the good" this patch at least allows parts of this
"trust boundaries" code to be merged for experimentation with the idea.
The -Wanalyzer-exposure-through-uninit-copy diagnostic uses notes to
express what fields and padding within a struct have not been initialized.
For example:
infoleak-CVE-2011-1078-2.c: In function 'test_1':
infoleak-CVE-2011-1078-2.c:32:9: warning: potential exposure of sensitive
information by copying uninitialized data from stack across trust
boundary [CWE-200] [-Wanalyzer-exposure-through-uninit-copy]
32 | copy_to_user(optval, &cinfo, sizeof(cinfo));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'test_1': events 1-3
|
| 25 | struct sco_conninfo cinfo;
| | ^~~~~
| | |
| | (1) region created on stack here
| | (2) capacity: 6 bytes
|......
| 32 | copy_to_user(optval, &cinfo, sizeof(cinfo));
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) uninitialized data copied from stack here
|
infoleak-CVE-2011-1078-2.c:32:9: note: 1 byte is uninitialized
32 | copy_to_user(optval, &cinfo, sizeof(cinfo));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
infoleak-CVE-2011-1078-2.c:18:15: note: padding after field 'dev_class'
is uninitialized (1 byte)
18 | __u8 dev_class[3];
| ^~~~~~~~~
infoleak-CVE-2011-1078-2.c:25:29: note: suggest forcing
zero-initialization by providing a '{0}' initializer
25 | struct sco_conninfo cinfo;
| ^~~~~
| = {0}
For taint-detection, the patch includes a series of reproducers for
detecting CVE-2011-0521. Unfortunately the analyzer doesn't yet detect
the issue until the code has been significantly simplified from its
original form: currently only in -5.c and -6.c in the series of test
(see notes in the individual cases), such as:
taint-CVE-2011-0521-6.c:33:48: warning: use of attacker-controlled value
'*info.num' in array lookup without bounds checking [CWE-129]
[-Wanalyzer-tainted-array-index]
33 | av7110->ci_slot[info->num].num = info->num;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~
'test_1': events 1-3
|
| 19 | if (copy_from_user(&sbuf, (void __user *)arg, sizeof(sbuf)) != 0)
| | ^
| | |
| | (1) following 'false' branch...
|......
| 23 | struct dvb_device *dvbdev = file->private_data;
| | ~~~~~~
| | |
| | (2) ...to here
|......
| 33 | av7110->ci_slot[info->num].num = info->num;
| | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | (3) use of attacker-controlled value '*info.num' in array lookup without bounds checking
|
The patch also includes various infoleak and taint cases from my
antipatterns.ko kernel module:
https://github.com/davidmalcolm/antipatterns.ko
gcc/analyzer/ChangeLog:
* analyzer.opt (Wanalyzer-exposure-through-uninit-copy): New.
* checker-path.cc (region_creation_event::region_creation_event):
Add "capacity" and "kind" params.
(region_creation_event::get_desc): Generalize to different kinds
of event.
(checker_path::add_region_creation_event): Convert to...
(checker_path::add_region_creation_events): ...this.
* checker-path.h (enum rce_kind): New.
(region_creation_event::region_creation_event): Add "capacity" and
"kind" params.
(region_creation_event::m_capacity): New field.
(region_creation_event::m_rce_kind): New field.
(checker_path::add_region_creation_event): Convert to...
(checker_path::add_region_creation_events): ...this.
* diagnostic-manager.cc (diagnostic_manager::build_emission_path):
Update for multiple region creation events.
(diagnostic_manager::add_event_on_final_node): Likewise.
(diagnostic_manager::add_events_for_eedge): Likewise.
* region-model-impl-calls.cc (call_details::get_logger): New.
* region-model.cc: Define INCLUDE_MEMORY before including
"system.h". Include "gcc-rich-location.h".
(class record_layout): New.
(class exposure_through_uninit_copy): New.
(contains_uninit_p): New.
(region_model::maybe_complain_about_infoleak): New.
* region-model.h (call_details::get_logger): New decl.
(region_model::maybe_complain_about_infoleak): New decl.
(region_model::mark_as_tainted): New decl.
* sm-taint.cc (region_model::mark_as_tainted): New.
gcc/ChangeLog:
* doc/invoke.texi (Static Analyzer Options): Add
-Wanalyzer-exposure-through-uninit-copy.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/analyzer_kernel_plugin.c: New test.
* gcc.dg/plugin/copy_from_user-1.c: New test.
* gcc.dg/plugin/infoleak-1.c: New test.
* gcc.dg/plugin/infoleak-2.c: New test.
* gcc.dg/plugin/infoleak-3.c: New test.
* gcc.dg/plugin/infoleak-CVE-2011-1078-1.c: New test.
* gcc.dg/plugin/infoleak-CVE-2011-1078-2.c: New test.
* gcc.dg/plugin/infoleak-CVE-2014-1446-1.c: New test.
* gcc.dg/plugin/infoleak-CVE-2017-18549-1.c: New test.
* gcc.dg/plugin/infoleak-CVE-2017-18550-1.c: New test.
* gcc.dg/plugin/infoleak-antipatterns-1.c: New test.
* gcc.dg/plugin/infoleak-fixit-1.c: New test.
* gcc.dg/plugin/infoleak-net-ethtool-ioctl.c: New test.
* gcc.dg/plugin/infoleak-vfio_iommu_type1.c: New test.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
analyzer_kernel_plugin.c and the new test cases.
* gcc.dg/plugin/taint-CVE-2011-0521-1-fixed.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-1.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-2-fixed.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-2.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-3-fixed.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-3.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-4.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-5-fixed.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-5.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521-6.c: New test.
* gcc.dg/plugin/taint-CVE-2011-0521.h: New test.
* gcc.dg/plugin/taint-antipatterns-1.c: New test.
* gcc.dg/plugin/test-uaccess.h: New header for tests.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/fortran/f95-lang.cc')
0 files changed, 0 insertions, 0 deletions