All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: Jakub Jelinek <jakub@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Colin King <colin.king@canonical.com>,
	Ingo Molnar <mingo@redhat.com>,
	linux-kernel@vger.kernel.org, Richard Henderson <rth@twiddle.net>,
	Dan Carpenter <dan.carpenter@oracle.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: Q: why didn't GCC warn about this uninitialized variable? (was: Re: [PATCH] perf tests: initialize sa.sa_flags)
Date: Thu, 3 Mar 2016 14:47:16 +0100	[thread overview]
Message-ID: <20160303134716.GA9860@gmail.com> (raw)
In-Reply-To: <20160303132433.GA9460@gmail.com>


* Ingo Molnar <mingo@kernel.org> wrote:

> So it's all highly inefficient and fragile.
> 
> There's also another cost, the cost of finding the bugs themselves - for example 
> here's a recent upstream kernel fix:
> 
>   commit e01d8718de4170373cd7fbf5cf6f9cb61cebb1e9
>   Author: Peter Zijlstra <peterz@infradead.org>
>   Date:   Wed Jan 27 23:24:29 2016 +0100
> 
>     perf/x86: Fix uninitialized value usage
>     
>     When calling intel_alt_er() with .idx != EXTRA_REG_RSP_* we will not
>     initialize alt_idx and then use this uninitialized value to index an
>     array.
>     
>     When that is not fatal, it can result in an infinite loop in its
>     caller __intel_shared_reg_get_constraints(), with IRQs disabled.
>     
>     Alternative error modes are random memory corruption due to the
>     cpuc->shared_regs->regs[] array overrun, which manifest in either
>     get_constraints or put_constraints doing weird stuff.
>     
>     Only took 6 hours of painful debugging to find this. Neither GCC nor
>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>     Smatch warnings flagged this bug.
>     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
>   --- a/arch/x86/kernel/cpu/perf_event_intel.c
>   +++ b/arch/x86/kernel/cpu/perf_event_intel.c
>   @@ -1960,7 +1960,8 @@ intel_bts_constraints(struct perf_event *event)
>  
>    static int intel_alt_er(int idx, u64 config)
>    {
>   -       int alt_idx;
>   +       int alt_idx = idx;
>   +
>           if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
>                   return idx;
> 
> 6 hours of PeterZ time translates to quite a bit of code restructuring overhead to 
> eliminate false positive warnings...

Btw., here's the wider context of that bug:

static int intel_alt_er(int idx, u64 config)
{
        int alt_idx;

        if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
                return idx;

        if (idx == EXTRA_REG_RSP_0)
                alt_idx = EXTRA_REG_RSP_1;

        if (idx == EXTRA_REG_RSP_1)
                alt_idx = EXTRA_REG_RSP_0;

        if (config & ~x86_pmu.extra_regs[alt_idx].valid_mask)
                return idx;

        return alt_idx;
}

so it's a straightforward uninitialized variable bug.

I tried to distill a testcase out of it, and the following silly hack seems to 
trigger it:

------------------------------->
#include <stdio.h>

#define PMU_FL_HAS_RSP_1 1
#define EXTRA_REG_RSP_1 2
#define EXTRA_REG_RSP_0 4

int global_flags = -1;

static int intel_alt_er(int idx, unsigned long long config)
{
        int alt_idx;
	int uninitialized = 1;

	printf("idx: %d, config: %Ld\n", idx, config);

        if (!(global_flags & PMU_FL_HAS_RSP_1))
                return idx;

        if (idx == EXTRA_REG_RSP_0) {
                alt_idx = EXTRA_REG_RSP_1;
		uninitialized = 0;
	}

        if (idx == EXTRA_REG_RSP_1) {
                alt_idx = EXTRA_REG_RSP_0;
		uninitialized = 0;
	}

        if (config & ~0xff)
                return idx;

	if (uninitialized)
		printf("ugh, using uninitialized alt_idx (%d)!\n", alt_idx);

        return alt_idx;
}

int main(int argc, char **argv)
{
	argv++;

	return intel_alt_er(argc, argc);
}
<-------------------------------

built with:

 gcc -Wbad-function-cast -Wdeclaration-after-statement -Wformat-security -Wformat-y2k \
     -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
     -Wno-system-headers -Wold-style-definition -Wpacked -Wredundant-decls \
     -Wshadow -Wstrict-aliasing=3 -Wstrict-prototypes -Wswitch-default -Wswitch-enum \
     -Wundef -Wwrite-strings -Wformat \
     -Werror -O6 -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 -fstack-protector-all -D_FORTIFY_SOURCE=2 \
     -o uninitialized uninitialized.c

gives:

 triton:~> ./uninitialized 1
 idx: 2, config: 2

 triton:~> ./uninitialized 0 0
 idx: 3, config: 3
 ugh, using uninitialized alt_idx (2)!

I.e. I cannot get GCC to warn about this seemingly trivial bug, using:

  gcc version 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2) 

Thanks,

	Ingo

  parent reply	other threads:[~2016-03-03 13:47 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-02 12:55 [PATCH] perf tests: initialize sa.sa_flags Colin King
2016-03-02 12:59 ` Peter Zijlstra
2016-03-02 13:03   ` Arnaldo Carvalho de Melo
2016-03-02 13:21     ` Peter Zijlstra
2016-03-02 13:23       ` Arnaldo Carvalho de Melo
2016-03-03 12:19         ` Q: why didn't GCC warn about this uninitialized variable? (was: Re: [PATCH] perf tests: initialize sa.sa_flags) Ingo Molnar
2016-03-03 12:25           ` Q: why didn't GCC warn about this uninitialized variable? Colin Ian King
2016-03-03 12:31           ` Måns Rullgård
2016-03-03 12:43             ` Ingo Molnar
2016-03-03 12:49               ` Joe Perches
2016-03-03 12:55           ` Q: why didn't GCC warn about this uninitialized variable? (was: Re: [PATCH] perf tests: initialize sa.sa_flags) Jakub Jelinek
2016-03-03 13:24             ` Ingo Molnar
2016-03-03 13:46               ` Jakub Jelinek
2016-03-03 14:04                 ` Ingo Molnar
2016-03-03 13:47               ` Ingo Molnar [this message]
2016-03-03 14:19                 ` Jakub Jelinek
2016-03-03 14:40                   ` Ingo Molnar
2016-03-03 14:53                   ` Ingo Molnar
2016-03-03 15:04                     ` Ingo Molnar
2016-03-02 13:02 ` [PATCH] perf tests: initialize sa.sa_flags Arnaldo Carvalho de Melo
2016-03-05  8:20 ` [tip:perf/core] perf tests: Initialize sa.sa_flags tip-bot for Colin Ian King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160303134716.GA9860@gmail.com \
    --to=mingo@kernel.org \
    --cc=acme@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=colin.king@canonical.com \
    --cc=dan.carpenter@oracle.com \
    --cc=jakub@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rth@twiddle.net \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.