trailofbits / multiplier

Code auditing productivity multiplier.
Apache License 2.0
430 stars 27 forks source link

Look for escape hatches that could mask integer overflows #167

Open pgoodman opened 2 years ago

pgoodman commented 2 years ago

At the core of this blog post is an integer overflow, guarded by an insufficient check:

image

I did some quick attempts at Weggli queries in multiplier on the tinyconfig for the Linux kernel. Here's what I tried:

if (($a * $b) > $c) goto $d;
if (($a + $b) > $c) goto $d;

The latter got me a hit. For some reason it got the same one twice.. 🤷

image

This suggests it's 512. Unfortunately this only seems to be used with offset 0 and size 512:

image

This could be due to other indexing failures, i.e. we were missing a bunch of stuff, or just that this function is only used once. Anyway, this all makes me think that looking for this pattern could possibly be interesting.

Another thing that this makes me think about is finding other uses by hash consing. In Clang, there is a way of profiling Statements, which does a recursive hash of the statement datastructures. It could be interesting to have a .structurally_similar_statements() or something like that that can find those.

pgoodman commented 2 years ago

This regex ends up being pretty reasonable: if\s*\(\(([^*{]+)\s*\*\s*([^{)]*)\)\s*[<>][=]?\s*([^)]+)\)\s*([{\n])

Gets these types of results, for example:

2305843009213802407 /home/user/workspace/linux/drivers/clk/clk-si544.c
    [0] =   if (((u64)frequency * tmp) >= FVCO_MIN)

    [1] =   (u64)frequency 
    [2] =   tmp
    [3] =   FVCO_MIN
    [4] =   

2305843009213817692 /home/user/workspace/linux/drivers/scsi/FlashPoint.c
    [0] =   if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
                    pCurrSCCB->DataLength) {
    [1] =   u32)(pCurrSCCB->Sccb_sgseg 
    [2] =   SG_ELEMENT_SIZE
    [3] =   pCurrSCCB->DataLength
    [4] =   {

2305843009213833471 /home/user/workspace/linux/drivers/scsi/lpfc/lpfc_hbadisc.c
    [0] =   if ((fcf_cnt * rand_num) < 0xFFFF)

    [1] =   fcf_cnt 
    [2] =   rand_num
    [3] =   0xFFFF
    [4] =   

2305843009213833505 /home/user/workspace/linux/drivers/scsi/lpfc/lpfc_hbadisc.c
    [0] =   if ((vport->vmid_inactivity_timeout *
                     JIFFIES_PER_HR) > difftime) {
    [1] =   vport->vmid_inactivity_timeout 
    [2] =   JIFFIES_PER_HR
    [3] =   difftime
    [4] =   {