* [pushed] analyzer: look through casts in taint sanitization [PR112974,PR112975]
@ 2024-03-22 15:01 David Malcolm
0 siblings, 0 replies; only message in thread
From: David Malcolm @ 2024-03-22 15:01 UTC (permalink / raw)
To: gcc-patches; +Cc: David Malcolm
PR analyzer/112974 and PR analyzer/112975 record false positives
from the analyzer's taint detection where sanitization of the form
if (VALUE CMP VALUE-OF-WIDER-TYPE)
happens, but wasn't being "noticed" by the taint checker, due to the
test being:
(WIDER_TYPE)VALUE CMP VALUE-OF-WIDER-TYPE
at the gimple level, and thus taint_state_machine recording
sanitization of (WIDER_TYPE)VALUE, but not of VALUE.
Fix by stripping casts in taint_state_machine::on_condition so that
the state machine records sanitization of the underlying value.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r14-9625-gc6cf5789135236.
gcc/analyzer/ChangeLog:
PR analyzer/112974
PR analyzer/112975
* sm-taint.cc (taint_state_machine::on_condition): Strip away
casts before considering LHS and RHS, to increase the chance of
detecting places where sanitization of a value may have happened.
gcc/testsuite/ChangeLog:
PR analyzer/112974
PR analyzer/112975
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add
taint-pr112974.c and taint-pr112975.c to analyzer_kernel_plugin.c.
* gcc.dg/plugin/taint-pr112974.c: New test.
* gcc.dg/plugin/taint-pr112975.c: New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
gcc/analyzer/sm-taint.cc | 8 +++
gcc/testsuite/gcc.dg/plugin/plugin.exp | 2 +
gcc/testsuite/gcc.dg/plugin/taint-pr112974.c | 59 ++++++++++++++++++++
gcc/testsuite/gcc.dg/plugin/taint-pr112975.c | 53 ++++++++++++++++++
4 files changed, 122 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
create mode 100644 gcc/testsuite/gcc.dg/plugin/taint-pr112975.c
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index c873c9ebd333..1d1e208fdf49 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -1109,6 +1109,14 @@ taint_state_machine::on_condition (sm_context *sm_ctxt,
return;
}
+ /* Strip away casts before considering LHS and RHS, to increase the
+ chance of detecting places where sanitization of a value may have
+ happened. */
+ if (const svalue *inner = lhs->maybe_undo_cast ())
+ lhs = inner;
+ if (const svalue *inner = rhs->maybe_undo_cast ())
+ rhs = inner;
+
// TODO
switch (op)
{
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index c26dda1f324b..933f9a5850bc 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -172,6 +172,8 @@ set plugin_test_list [list \
taint-pr112850-too-complex.c \
taint-pr112850-unsanitized.c \
taint-pr112927.c \
+ taint-pr112974.c \
+ taint-pr112975.c \
taint-pr112977.c } \
{ analyzer_cpython_plugin.c \
cpython-plugin-test-no-Python-h.c \
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
new file mode 100644
index 000000000000..1af505326c78
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112974.c
@@ -0,0 +1,59 @@
+/* Reduced from false positive in Linux kernel in
+ drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c. */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+extern unsigned int __max_logical_packages;
+extern unsigned long
+copy_from_user(void* to, const void* from, unsigned long n);
+extern unsigned long
+copy_to_user(void* to, const void* from, unsigned long n);
+struct isst_tpmi_instance_count
+{
+ __u8 socket_id;
+ __u8 count;
+ __u16 valid_mask;
+};
+struct tpmi_per_power_domain_info
+{
+ void* sst_base;
+};
+struct tpmi_sst_struct
+{
+ int number_of_power_domains;
+ struct tpmi_per_power_domain_info* power_domain_info;
+};
+struct tpmi_sst_common_struct
+{
+ int max_index;
+ struct tpmi_sst_struct** sst_inst;
+};
+static struct tpmi_sst_common_struct isst_common;
+int
+isst_if_get_tpmi_instance_count(void* argp)
+{
+ struct isst_tpmi_instance_count tpmi_inst;
+ struct tpmi_sst_struct* sst_inst;
+ int i;
+ if (copy_from_user(&tpmi_inst, argp, sizeof(tpmi_inst)))
+ return -14;
+ if (tpmi_inst.socket_id >= (__max_logical_packages))
+ return -22;
+ tpmi_inst.count =
+ isst_common.sst_inst[tpmi_inst.socket_id]->number_of_power_domains; /* { dg-bogus "use of attacker-controlled value as offset without upper-bounds checking" } */
+ sst_inst = isst_common.sst_inst[tpmi_inst.socket_id];
+ tpmi_inst.valid_mask = 0;
+ for (i = 0; i < sst_inst->number_of_power_domains; ++i) {
+ struct tpmi_per_power_domain_info* pd_info;
+ pd_info = &sst_inst->power_domain_info[i];
+ if (pd_info->sst_base)
+ tpmi_inst.valid_mask |= ((((1UL))) << (i));
+ }
+ if (copy_to_user(argp, &tpmi_inst, sizeof(tpmi_inst)))
+ return -14;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/taint-pr112975.c b/gcc/testsuite/gcc.dg/plugin/taint-pr112975.c
new file mode 100644
index 000000000000..9f312cb33487
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/taint-pr112975.c
@@ -0,0 +1,53 @@
+/* Reduced from false positive in Linux kernel in
+ drivers/xen/privcmd.c. */
+
+/* { dg-do compile } */
+/* { dg-options "-fanalyzer" } */
+/* { dg-require-effective-target analyzer } */
+
+typedef __SIZE_TYPE__ size_t;
+typedef unsigned short __u16;
+typedef unsigned int gfp_t;
+void
+kfree(const void* objp);
+
+extern void *
+__attribute__((__alloc_size__(1, 2)))
+__attribute__((__malloc__))
+kcalloc(size_t n, size_t size, gfp_t flags);
+
+extern unsigned long
+copy_from_user(void*, const void*, unsigned long);
+
+typedef __u16 domid_t;
+struct privcmd_dm_op_buf
+{
+ void* uptr;
+ size_t size;
+};
+struct privcmd_dm_op
+{
+ domid_t dom;
+ __u16 num;
+};
+static unsigned int privcmd_dm_op_max_num = 16;
+long
+privcmd_ioctl_dm_op(void* udata)
+{
+ struct privcmd_dm_op kdata;
+ struct privcmd_dm_op_buf* kbufs;
+ if (copy_from_user(&kdata, udata, sizeof(kdata)))
+ return -14;
+ if (kdata.num == 0)
+ return 0;
+ if (kdata.num > privcmd_dm_op_max_num)
+ return -7;
+ kbufs =
+ kcalloc(kdata.num, /* { dg-bogus "attacker-controlled value" } */
+ sizeof(*kbufs),
+ (((gfp_t)(0x400u | 0x800u)) | ((gfp_t)0x40u) | ((gfp_t)0x80u)));
+ if (!kbufs)
+ return -12;
+ kfree(kbufs);
+ return 0;
+}
--
2.26.3
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-03-22 15:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-22 15:01 [pushed] analyzer: look through casts in taint sanitization [PR112974,PR112975] David Malcolm
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).