public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
@ 2024-07-19 16:49 Mirsad Todorovac
  2024-07-19 17:21 ` Sean Christopherson
  0 siblings, 1 reply; 7+ messages in thread
From: Mirsad Todorovac @ 2024-07-19 16:49 UTC (permalink / raw)
  To: kvm
  Cc: Sean Christopherson, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, x86, H. Peter Anvin, linux-kernel,
	Like Xu

Hi,

In the build of 6.10.0 from stable tree, the following error was detected.

You see that the function get_fixed_pmc() can return NULL pointer as a result
if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.

kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
as the argument, which expands to .../pmu.h

#define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)

which is a NULL pointer dereference in that speculative case.

arch/x86/kvm/vmx/pmu_intel.c
----------------------------
 37 static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
 38 {
 39         struct kvm_pmc *pmc;
 40         u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
 41         int i;
 42 
 43         pmu->fixed_ctr_ctrl = data;
 44         for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
 45                 u8 new_ctrl = fixed_ctrl_field(data, i);
 46                 u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
 47 
 48                 if (old_ctrl == new_ctrl)
 49                         continue;
 50 
 51 →               pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
 52 
 53                 __set_bit(KVM_FIXED_PMC_BASE_IDX + i, pmu->pmc_in_use);
 54 →               kvm_pmu_request_counter_reprogram(pmc);
 55         }
 56 }
----------------------------

arch/x86/kvm/vmx/../pmu.h
-------------------------
 11 #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
.
.
.
152 /* returns fixed PMC with the specified MSR */
153 static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr)
154 {
155         int base = MSR_CORE_PERF_FIXED_CTR0;
156 
157         if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
158                 u32 index = array_index_nospec(msr - base,
159                                                pmu->nr_arch_fixed_counters);
160 
161                 return &pmu->fixed_counters[index];
162         }
163 
164         return NULL;
165 }
.
.
.
228 static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc)
229 {
230         set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
231         kvm_make_request(KVM_REQ_PMU, pmc->vcpu);
232 }
.
.
.
-------------------------
76d287b2342e1
Offending commits are: 76d287b2342e1 and 4fa5843d81fdc.

I am not familiar with this subset of code, so I do not know the right code to implement
for the case get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i) returns NULL.

Hope this helps.

Best regards,
Mirsad Todorovac

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 16:49 [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476] Mirsad Todorovac
@ 2024-07-19 17:21 ` Sean Christopherson
  2024-07-19 19:02   ` Mirsad Todorovac
  0 siblings, 1 reply; 7+ messages in thread
From: Sean Christopherson @ 2024-07-19 17:21 UTC (permalink / raw)
  To: Mirsad Todorovac
  Cc: kvm, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, linux-kernel, Like Xu

On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
> Hi,
> 
> In the build of 6.10.0 from stable tree, the following error was detected.
> 
> You see that the function get_fixed_pmc() can return NULL pointer as a result
> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
> 
> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
> as the argument, which expands to .../pmu.h
> 
> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
> 
> which is a NULL pointer dereference in that speculative case.

I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
dereference, are you speculating that there's a bug, or did you find some speculation
issue with the CPU?

It should be impossible for get_fixed_pmc() to return NULL in this case.  The
loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
ranage [0..pmu->nr_arch_fixed_counters).

And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:

	if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
	    MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)

i.e. is guaranteed to evaluate true.

Am I missing something?

> arch/x86/kvm/vmx/pmu_intel.c
> ----------------------------
>  37 static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
>  38 {
>  39         struct kvm_pmc *pmc;
>  40         u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
>  41         int i;
>  42 
>  43         pmu->fixed_ctr_ctrl = data;
>  44         for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
>  45                 u8 new_ctrl = fixed_ctrl_field(data, i);
>  46                 u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
>  47 
>  48                 if (old_ctrl == new_ctrl)
>  49                         continue;
>  50 
>  51 →               pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
>  52 
>  53                 __set_bit(KVM_FIXED_PMC_BASE_IDX + i, pmu->pmc_in_use);
>  54 →               kvm_pmu_request_counter_reprogram(pmc);
>  55         }
>  56 }
> ----------------------------
> 
> arch/x86/kvm/vmx/../pmu.h
> -------------------------
>  11 #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
> .
> .
> .
> 152 /* returns fixed PMC with the specified MSR */
> 153 static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr)
> 154 {
> 155         int base = MSR_CORE_PERF_FIXED_CTR0;
> 156 
> 157         if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
> 158                 u32 index = array_index_nospec(msr - base,
> 159                                                pmu->nr_arch_fixed_counters);
> 160 
> 161                 return &pmu->fixed_counters[index];
> 162         }
> 163 
> 164         return NULL;
> 165 }
> .
> .
> .
> 228 static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc)
> 229 {
> 230         set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
> 231         kvm_make_request(KVM_REQ_PMU, pmc->vcpu);
> 232 }
> .
> .
> .
> -------------------------
> 76d287b2342e1
> Offending commits are: 76d287b2342e1 and 4fa5843d81fdc.
> 
> I am not familiar with this subset of code, so I do not know the right code to implement
> for the case get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i) returns NULL.
> 
> Hope this helps.
> 
> Best regards,
> Mirsad Todorovac

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 17:21 ` Sean Christopherson
@ 2024-07-19 19:02   ` Mirsad Todorovac
  2024-07-19 19:22     ` Sean Christopherson
  0 siblings, 1 reply; 7+ messages in thread
From: Mirsad Todorovac @ 2024-07-19 19:02 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: kvm, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, linux-kernel, Like Xu



On 7/19/24 19:21, Sean Christopherson wrote:
> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
>> Hi,
>>
>> In the build of 6.10.0 from stable tree, the following error was detected.
>>
>> You see that the function get_fixed_pmc() can return NULL pointer as a result
>> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
>>
>> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
>> as the argument, which expands to .../pmu.h
>>
>> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
>>
>> which is a NULL pointer dereference in that speculative case.
> 
> I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
> dereference, are you speculating that there's a bug, or did you find some speculation
> issue with the CPU?
> 
> It should be impossible for get_fixed_pmc() to return NULL in this case.  The
> loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
> ranage [0..pmu->nr_arch_fixed_counters).
> 
> And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:
> 
> 	if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
> 	    MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)
> 
> i.e. is guaranteed to evaluate true.
> 
> Am I missing something?

Hi Sean,

Thank you for replying promptly.

Perhaps I should have provided the GCC error report in the first place. It seems that GCC 12.3.0
cannot track dependencies that deep, so it assumes that code

157         if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
158                 u32 index = array_index_nospec(msr - base,
159                                                pmu->nr_arch_fixed_counters);
160 
161                 return &pmu->fixed_counters[index];
162         }
163 
164         return NULL;

can end up returning NULL, resulting in NULL pointer dereference.

The analyzer sees pmu->nr_arch_fixed_counters, but I am not sure that GCC can search
changes that deep.

Maybe if clause in arch/x86/kvm/vmx/../pmu.h:157 is always true, but GCC cannot see that?

Best regards,
Mirsad Todorovac

---------------------------------------------------------------------------------------
In file included from arch/x86/kvm/vmx/capabilities.h:9,
                 from arch/x86/kvm/vmx/vmcs.h:12,
                 from arch/x86/kvm/vmx/vmcs12.h:7,
                 from arch/x86/kvm/vmx/hyperv.h:6,
                 from arch/x86/kvm/vmx/nested.h:6,
                 from arch/x86/kvm/vmx/pmu_intel.c:20:
arch/x86/kvm/vmx/../pmu.h: In function ‘kvm_pmu_request_counter_reprogram’:
arch/x86/kvm/vmx/../pmu.h:11:34: error: dereference of NULL ‘pmc’ [CWE-476] [-Werror=analyzer-null-dereference]
   11 | #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
      |                             ~~~~~^~~~~~
arch/x86/kvm/vmx/../pmu.h:230:27: note: in expansion of macro ‘pmc_to_pmu’
  230 |         set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
      |                           ^~~~~~~~~~
  ‘reprogram_fixed_counters’: events 1-4
    |
    |arch/x86/kvm/vmx/pmu_intel.c:37:13:
    |   37 | static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
    |      |             ^~~~~~~~~~~~~~~~~~~~~~~~
    |      |             |
    |      |             (1) entry to ‘reprogram_fixed_counters’
    |......
    |   44 |         for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
    |      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                       |
    |      |                       (2) following ‘true’ branch...
    |   45 |                 u8 new_ctrl = fixed_ctrl_field(data, i);
    |      |                 ~~ ~~~~~~~~
    |      |                 |  |
    |      |                 |  (4) following ‘false’ branch...
    |      |                 (3) ...to here
    |
  ‘reprogram_fixed_counters’: event 5
    |
    |arch/x86/kvm/vmx/../pmu.h:17:54:
    |   17 | #define fixed_ctrl_field(ctrl_reg, idx) (((ctrl_reg) >> ((idx)*4)) & 0xf)
    |      |                                                      ^~
    |      |                                                      |
    |      |                                                      (5) ...to here
arch/x86/kvm/vmx/pmu_intel.c:45:31: note: in expansion of macro ‘fixed_ctrl_field’
    |   45 |                 u8 new_ctrl = fixed_ctrl_field(data, i);
    |      |                               ^~~~~~~~~~~~~~~~
    |
  ‘reprogram_fixed_counters’: event 6
    |
    |   46 |                 u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
    |      |                    ^~~~~~~~
    |      |                    |
    |      |                    (6) following ‘false’ branch...
    |
  ‘reprogram_fixed_counters’: event 7
    |
    |arch/x86/kvm/vmx/../pmu.h:17:54:
    |   17 | #define fixed_ctrl_field(ctrl_reg, idx) (((ctrl_reg) >> ((idx)*4)) & 0xf)
    |      |                                                      ^~
    |      |                                                      |
    |      |                                                      (7) ...to here
arch/x86/kvm/vmx/pmu_intel.c:46:31: note: in expansion of macro ‘fixed_ctrl_field’
    |   46 |                 u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
    |      |                               ^~~~~~~~~~~~~~~~
    |
  ‘reprogram_fixed_counters’: events 8-9
    |
    |   48 |                 if (old_ctrl == new_ctrl)
    |      |                    ^
    |      |                    |
    |      |                    (8) following ‘false’ branch...
    |......
    |   51 |                 pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
    |      |                 ~~~ 
    |      |                 |
    |      |                 (9) ...to here
    |
  ‘reprogram_fixed_counters’: events 10-12
    |
    |arch/x86/kvm/vmx/../pmu.h:157:12:
    |  157 |         if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
    |      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |            |            |                  |
    |      |            |            |                  (11) ...to here
    |      |            |            (12) following ‘false’ branch...
    |      |            (10) following ‘true’ branch...
    |
  ‘reprogram_fixed_counters’: events 13-14
    |
    |arch/x86/kvm/vmx/pmu_intel.c:51:23:
    |   51 |                 pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
    |      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                       |
    |      |                       (13) ...to here
    |......
    |   54 |                 kvm_pmu_request_counter_reprogram(pmc);
    |      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |                 |
    |      |                 (14) calling ‘kvm_pmu_request_counter_reprogram’ from ‘reprogram_fixed_counters’
    |
    +--> ‘kvm_pmu_request_counter_reprogram’: event 15
           |
           |arch/x86/kvm/vmx/../pmu.h:228:20:
           |  228 | static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc)
           |      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |                    |
           |      |                    (15) entry to ‘kvm_pmu_request_counter_reprogram’
           |
         ‘kvm_pmu_request_counter_reprogram’: event 16
           |
           |   11 | #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
           |      |                             ~~~~~^~~~~~
           |      |                                  |
           |      |                                  (16) dereference of NULL ‘pmc’
arch/x86/kvm/vmx/../pmu.h:230:27: note: in expansion of macro ‘pmc_to_pmu’
           |  230 |         set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
           |      |                           ^~~~~~~~~~
           |
cc1: all warnings being treated as errors


>> arch/x86/kvm/vmx/pmu_intel.c
>> ----------------------------
>>  37 static void reprogram_fixed_counters(struct kvm_pmu *pmu, u64 data)
>>  38 {
>>  39         struct kvm_pmc *pmc;
>>  40         u64 old_fixed_ctr_ctrl = pmu->fixed_ctr_ctrl;
>>  41         int i;
>>  42 
>>  43         pmu->fixed_ctr_ctrl = data;
>>  44         for (i = 0; i < pmu->nr_arch_fixed_counters; i++) {
>>  45                 u8 new_ctrl = fixed_ctrl_field(data, i);
>>  46                 u8 old_ctrl = fixed_ctrl_field(old_fixed_ctr_ctrl, i);
>>  47 
>>  48                 if (old_ctrl == new_ctrl)
>>  49                         continue;
>>  50 
>>  51 →               pmc = get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i);
>>  52 
>>  53                 __set_bit(KVM_FIXED_PMC_BASE_IDX + i, pmu->pmc_in_use);
>>  54 →               kvm_pmu_request_counter_reprogram(pmc);
>>  55         }
>>  56 }
>> ----------------------------
>>
>> arch/x86/kvm/vmx/../pmu.h
>> -------------------------
>>  11 #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
>> .
>> .
>> .
>> 152 /* returns fixed PMC with the specified MSR */
>> 153 static inline struct kvm_pmc *get_fixed_pmc(struct kvm_pmu *pmu, u32 msr)
>> 154 {
>> 155         int base = MSR_CORE_PERF_FIXED_CTR0;
>> 156 
>> 157         if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
>> 158                 u32 index = array_index_nospec(msr - base,
>> 159                                                pmu->nr_arch_fixed_counters);
>> 160 
>> 161                 return &pmu->fixed_counters[index];
>> 162         }
>> 163 
>> 164         return NULL;
>> 165 }
>> .
>> .
>> .
>> 228 static inline void kvm_pmu_request_counter_reprogram(struct kvm_pmc *pmc)
>> 229 {
>> 230         set_bit(pmc->idx, pmc_to_pmu(pmc)->reprogram_pmi);
>> 231         kvm_make_request(KVM_REQ_PMU, pmc->vcpu);
>> 232 }
>> .
>> .
>> .
>> -------------------------
>> 76d287b2342e1
>> Offending commits are: 76d287b2342e1 and 4fa5843d81fdc.
>>
>> I am not familiar with this subset of code, so I do not know the right code to implement
>> for the case get_fixed_pmc(pmu, MSR_CORE_PERF_FIXED_CTR0 + i) returns NULL.
>>
>> Hope this helps.
>>
>> Best regards,
>> Mirsad Todorovac

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 19:02   ` Mirsad Todorovac
@ 2024-07-19 19:22     ` Sean Christopherson
  2024-07-19 19:41       ` Mirsad Todorovac
  0 siblings, 1 reply; 7+ messages in thread
From: Sean Christopherson @ 2024-07-19 19:22 UTC (permalink / raw)
  To: Mirsad Todorovac
  Cc: kvm, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, linux-kernel, Like Xu

On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
> On 7/19/24 19:21, Sean Christopherson wrote:
> > On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
> >> Hi,
> >>
> >> In the build of 6.10.0 from stable tree, the following error was detected.
> >>
> >> You see that the function get_fixed_pmc() can return NULL pointer as a result
> >> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
> >>
> >> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
> >> as the argument, which expands to .../pmu.h
> >>
> >> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
> >>
> >> which is a NULL pointer dereference in that speculative case.
> > 
> > I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
> > dereference, are you speculating that there's a bug, or did you find some speculation
> > issue with the CPU?
> > 
> > It should be impossible for get_fixed_pmc() to return NULL in this case.  The
> > loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
> > ranage [0..pmu->nr_arch_fixed_counters).
> > 
> > And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:
> > 
> > 	if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
> > 	    MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)
> > 
> > i.e. is guaranteed to evaluate true.
> > 
> > Am I missing something?
> 
> Hi Sean,
> 
> Thank you for replying promptly.
> 
> Perhaps I should have provided the GCC error report in the first place.

Yes, though the report itself is somewhat secondary, what matters the most is how
you found the bug and how to reproduce the failure.  Critically, IIUC, this requires
analyzer-null-dereference, which AFAIK isn't even enabled by W=1, let alone a base
build.

Please see the 0-day bot's reports[*] for a fantastic example of how to report
things that are found by non-standard (by kernel standards) means.

In general, I suspect that analyzer-null-dereference will generate a _lot_ of
false positives, and is probably not worth reporting unless you are absolutely
100% certain there's a real bug.  I (and most maintainers) am happy to deal with
false positives here and there _if_ the signal to noise ratio is high.  But if
most reports are false positives, they'll likely all end up getting ignored.

[*] https://lore.kernel.org/all/202406111250.d8XtA9SC-lkp@intel.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 19:22     ` Sean Christopherson
@ 2024-07-19 19:41       ` Mirsad Todorovac
  2024-07-19 20:14         ` Jim Mattson
  0 siblings, 1 reply; 7+ messages in thread
From: Mirsad Todorovac @ 2024-07-19 19:41 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: kvm, Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, linux-kernel, Like Xu



On 7/19/24 21:22, Sean Christopherson wrote:
> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
>> On 7/19/24 19:21, Sean Christopherson wrote:
>>> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
>>>> Hi,
>>>>
>>>> In the build of 6.10.0 from stable tree, the following error was detected.
>>>>
>>>> You see that the function get_fixed_pmc() can return NULL pointer as a result
>>>> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
>>>>
>>>> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
>>>> as the argument, which expands to .../pmu.h
>>>>
>>>> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
>>>>
>>>> which is a NULL pointer dereference in that speculative case.
>>>
>>> I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
>>> dereference, are you speculating that there's a bug, or did you find some speculation
>>> issue with the CPU?
>>>
>>> It should be impossible for get_fixed_pmc() to return NULL in this case.  The
>>> loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
>>> ranage [0..pmu->nr_arch_fixed_counters).
>>>
>>> And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:
>>>
>>> 	if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
>>> 	    MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)
>>>
>>> i.e. is guaranteed to evaluate true.
>>>
>>> Am I missing something?
>>
>> Hi Sean,
>>
>> Thank you for replying promptly.
>>
>> Perhaps I should have provided the GCC error report in the first place.
> 
> Yes, though the report itself is somewhat secondary, what matters the most is how
> you found the bug and how to reproduce the failure.  Critically, IIUC, this requires
> analyzer-null-dereference, which AFAIK isn't even enabled by W=1, let alone a base
> build.
> 
> Please see the 0-day bot's reports[*] for a fantastic example of how to report
> things that are found by non-standard (by kernel standards) means.
> 
> In general, I suspect that analyzer-null-dereference will generate a _lot_ of
> false positives, and is probably not worth reporting unless you are absolutely
> 100% certain there's a real bug.  I (and most maintainers) am happy to deal with
> false positives here and there _if_ the signal to noise ratio is high.  But if
> most reports are false positives, they'll likely all end up getting ignored.
> 
> [*] https://lore.kernel.org/all/202406111250.d8XtA9SC-lkp@intel.com

I think I understood the meaning between the lines.

However, to repeat the obvious, reducing the global dependencies simplifies the readability
and the logical proof of the code. :-/

Needless to say, dividing into pure functions and const functions reduces the number of
dependencies, as it is N × (N - 1), sqr (N).

For example, if a condition is always true, but the compiler cannot deduce it from code,
there is something odd.

CONCLUSION: If this generated 5 out of 5 false positives, then I might be giving up on this
as a waste of your time.

However, it was great fun analysing x86 KVM code. :-)

Sort of cool that you guys on Google consider bug report from nobody admins from the
universities ;-)

Best regards,
Mirsad Todorovac

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 19:41       ` Mirsad Todorovac
@ 2024-07-19 20:14         ` Jim Mattson
  2024-07-22 13:44           ` Mirsad Todorovac
  0 siblings, 1 reply; 7+ messages in thread
From: Jim Mattson @ 2024-07-19 20:14 UTC (permalink / raw)
  To: Mirsad Todorovac
  Cc: Sean Christopherson, kvm, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	linux-kernel, Like Xu

On Fri, Jul 19, 2024 at 12:41 PM Mirsad Todorovac
<mtodorovac69@gmail.com> wrote:
>
>
>
> On 7/19/24 21:22, Sean Christopherson wrote:
> > On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
> >> On 7/19/24 19:21, Sean Christopherson wrote:
> >>> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
> >>>> Hi,
> >>>>
> >>>> In the build of 6.10.0 from stable tree, the following error was detected.
> >>>>
> >>>> You see that the function get_fixed_pmc() can return NULL pointer as a result
> >>>> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
> >>>>
> >>>> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
> >>>> as the argument, which expands to .../pmu.h
> >>>>
> >>>> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
> >>>>
> >>>> which is a NULL pointer dereference in that speculative case.
> >>>
> >>> I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
> >>> dereference, are you speculating that there's a bug, or did you find some speculation
> >>> issue with the CPU?
> >>>
> >>> It should be impossible for get_fixed_pmc() to return NULL in this case.  The
> >>> loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
> >>> ranage [0..pmu->nr_arch_fixed_counters).
> >>>
> >>> And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:
> >>>
> >>>     if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
> >>>         MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)
> >>>
> >>> i.e. is guaranteed to evaluate true.
> >>>
> >>> Am I missing something?
> >>
> >> Hi Sean,
> >>
> >> Thank you for replying promptly.
> >>
> >> Perhaps I should have provided the GCC error report in the first place.
> >
> > Yes, though the report itself is somewhat secondary, what matters the most is how
> > you found the bug and how to reproduce the failure.  Critically, IIUC, this requires
> > analyzer-null-dereference, which AFAIK isn't even enabled by W=1, let alone a base
> > build.
> >
> > Please see the 0-day bot's reports[*] for a fantastic example of how to report
> > things that are found by non-standard (by kernel standards) means.
> >
> > In general, I suspect that analyzer-null-dereference will generate a _lot_ of
> > false positives, and is probably not worth reporting unless you are absolutely
> > 100% certain there's a real bug.  I (and most maintainers) am happy to deal with
> > false positives here and there _if_ the signal to noise ratio is high.  But if
> > most reports are false positives, they'll likely all end up getting ignored.
> >
> > [*] https://lore.kernel.org/all/202406111250.d8XtA9SC-lkp@intel.com
>
> I think I understood the meaning between the lines.
>
> However, to repeat the obvious, reducing the global dependencies simplifies the readability
> and the logical proof of the code. :-/

Comments would also help. :)

> Needless to say, dividing into pure functions and const functions reduces the number of
> dependencies, as it is N × (N - 1), sqr (N).
>
> For example, if a condition is always true, but the compiler cannot deduce it from code,
> there is something odd.
>
> CONCLUSION: If this generated 5 out of 5 false positives, then I might be giving up on this
> as a waste of your time.
>
> However, it was great fun analysing x86 KVM code. :-)

I assure you that there are plenty of actual bugs in KVM. This tool
just isn't finding them.

> Sort of cool that you guys on Google consider bug report from nobody admins from the
> universities ;-)
>
> Best regards,
> Mirsad Todorovac
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476]
  2024-07-19 20:14         ` Jim Mattson
@ 2024-07-22 13:44           ` Mirsad Todorovac
  0 siblings, 0 replies; 7+ messages in thread
From: Mirsad Todorovac @ 2024-07-22 13:44 UTC (permalink / raw)
  To: Jim Mattson
  Cc: Sean Christopherson, kvm, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	linux-kernel, Like Xu



On 7/19/24 22:14, Jim Mattson wrote:
> On Fri, Jul 19, 2024 at 12:41 PM Mirsad Todorovac
> <mtodorovac69@gmail.com> wrote:
>>
>>
>>
>> On 7/19/24 21:22, Sean Christopherson wrote:
>>> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
>>>> On 7/19/24 19:21, Sean Christopherson wrote:
>>>>> On Fri, Jul 19, 2024, Mirsad Todorovac wrote:
>>>>>> Hi,
>>>>>>
>>>>>> In the build of 6.10.0 from stable tree, the following error was detected.
>>>>>>
>>>>>> You see that the function get_fixed_pmc() can return NULL pointer as a result
>>>>>> if msr is outside of [base, base + pmu->nr_arch_fixed_counters) interval.
>>>>>>
>>>>>> kvm_pmu_request_counter_reprogram(pmc) is then called with that NULL pointer
>>>>>> as the argument, which expands to .../pmu.h
>>>>>>
>>>>>> #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
>>>>>>
>>>>>> which is a NULL pointer dereference in that speculative case.
>>>>>
>>>>> I'm somewhat confused.  Did you actually hit a BUG() due to a NULL-pointer
>>>>> dereference, are you speculating that there's a bug, or did you find some speculation
>>>>> issue with the CPU?
>>>>>
>>>>> It should be impossible for get_fixed_pmc() to return NULL in this case.  The
>>>>> loop iteration is fully controlled by KVM, i.e. 'i' is guaranteed to be in the
>>>>> ranage [0..pmu->nr_arch_fixed_counters).
>>>>>
>>>>> And the input @msr is "MSR_CORE_PERF_FIXED_CTR0 +i", so the if-statement expands to:
>>>>>
>>>>>     if (MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) >= MSR_CORE_PERF_FIXED_CTR0 &&
>>>>>         MSR_CORE_PERF_FIXED_CTR0 + [0..pmu->nr_arch_fixed_counters) < MSR_CORE_PERF_FIXED_CTR0 + pmu->nr_arch_fixed_counters)
>>>>>
>>>>> i.e. is guaranteed to evaluate true.
>>>>>
>>>>> Am I missing something?
>>>>
>>>> Hi Sean,
>>>>
>>>> Thank you for replying promptly.
>>>>
>>>> Perhaps I should have provided the GCC error report in the first place.
>>>
>>> Yes, though the report itself is somewhat secondary, what matters the most is how
>>> you found the bug and how to reproduce the failure.  Critically, IIUC, this requires
>>> analyzer-null-dereference, which AFAIK isn't even enabled by W=1, let alone a base
>>> build.
>>>
>>> Please see the 0-day bot's reports[*] for a fantastic example of how to report
>>> things that are found by non-standard (by kernel standards) means.
>>>
>>> In general, I suspect that analyzer-null-dereference will generate a _lot_ of
>>> false positives, and is probably not worth reporting unless you are absolutely
>>> 100% certain there's a real bug.  I (and most maintainers) am happy to deal with
>>> false positives here and there _if_ the signal to noise ratio is high.  But if
>>> most reports are false positives, they'll likely all end up getting ignored.
>>>
>>> [*] https://lore.kernel.org/all/202406111250.d8XtA9SC-lkp@intel.com
>>
>> I think I understood the meaning between the lines.
>>
>> However, to repeat the obvious, reducing the global dependencies simplifies the readability
>> and the logical proof of the code. :-/
> 
> Comments would also help. :)
> 
>> Needless to say, dividing into pure functions and const functions reduces the number of
>> dependencies, as it is N × (N - 1), sqr (N).
>>
>> For example, if a condition is always true, but the compiler cannot deduce it from code,
>> there is something odd.
>>
>> CONCLUSION: If this generated 5 out of 5 false positives, then I might be giving up on this
>> as a waste of your time.
>>
>> However, it was great fun analysing x86 KVM code. :-)
> 
> I assure you that there are plenty of actual bugs in KVM. This tool
> just isn't finding them.

Well, this series of reports did not target KVM. It was accidental that GCC static analyser
reported those dubious false positives first.

Best regards,
Mirsad Todorovac
 
>> Sort of cool that you guys on Google consider bug report from nobody admins from the
>> universities ;-)
>>
>> Best regards,
>> Mirsad Todorovac
>>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-07-22 13:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-19 16:49 [BUG] arch/x86/kvm/vmx/pmu_intel.c:54: error: dereference of NULL ‘pmc’ [CWE-476] Mirsad Todorovac
2024-07-19 17:21 ` Sean Christopherson
2024-07-19 19:02   ` Mirsad Todorovac
2024-07-19 19:22     ` Sean Christopherson
2024-07-19 19:41       ` Mirsad Todorovac
2024-07-19 20:14         ` Jim Mattson
2024-07-22 13:44           ` Mirsad Todorovac

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox