diff mbox

acpi: cppc: Prevent cpc_desc_ptr points to the invalid data

Message ID 1464203363-20599-1-git-send-email-hotran@apm.com (mailing list archive)
State Accepted, archived
Delegated to: Rafael Wysocki
Headers show

Commit Message

hotran May 25, 2016, 7:09 p.m. UTC
When CPPC fails to request PCC channel, the CPC data is freed
and cpc_desc_ptr points to the invalid data. This change prevents
this issue by moving cpc_desc_ptr assignment after PCC channel
request.

Signed-off-by: Hoan Tran <hotran@apm.com>
---
 drivers/acpi/cppc_acpi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Ashwin Chaugule May 27, 2016, 4:10 p.m. UTC | #1
On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
> When CPPC fails to request PCC channel, the CPC data is freed
> and cpc_desc_ptr points to the invalid data. This change prevents
> this issue by moving cpc_desc_ptr assignment after PCC channel
> request.
>
> Signed-off-by: Hoan Tran <hotran@apm.com>
> ---
>  drivers/acpi/cppc_acpi.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> index 8adac69..85fd8f7 100644
> --- a/drivers/acpi/cppc_acpi.c
> +++ b/drivers/acpi/cppc_acpi.c
> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>         /* Store CPU Logical ID */
>         cpc_ptr->cpu_id = pr->id;
>
> -       /* Plug it into this CPUs CPC descriptor. */
> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> -
>         /* Parse PSD data for this CPU */
>         ret = acpi_get_psd(cpc_ptr, handle);
>         if (ret)
> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>                         goto out_free;
>         }
>
> +       /* Plug PSD data into this CPUs CPC descriptor. */
> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> +

Are you seeing a real problem without this change? I'm missing where
this pointer is dereferenced if the PCC channel request fails.

Thanks,
Ashwin.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
hotran May 27, 2016, 4:41 p.m. UTC | #2
Hi Ashwin,

Yes, I saw kernel crash.
As cpc_desc_ptr is not NULL, cppc_cpufreq_init() still can pass then
crash during cppc_get_perf_caps() access CPPC shared memory.

It's not only "PCC channel request fail" can create this issue but
"acpi_get_psd() fail" also creates it

Thanks
Hoan

On Fri, May 27, 2016 at 9:10 AM, Ashwin Chaugule
<ashwin.chaugule@linaro.org> wrote:
> On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
>> When CPPC fails to request PCC channel, the CPC data is freed
>> and cpc_desc_ptr points to the invalid data. This change prevents
>> this issue by moving cpc_desc_ptr assignment after PCC channel
>> request.
>>
>> Signed-off-by: Hoan Tran <hotran@apm.com>
>> ---
>>  drivers/acpi/cppc_acpi.c | 6 +++---
>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
>> index 8adac69..85fd8f7 100644
>> --- a/drivers/acpi/cppc_acpi.c
>> +++ b/drivers/acpi/cppc_acpi.c
>> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>         /* Store CPU Logical ID */
>>         cpc_ptr->cpu_id = pr->id;
>>
>> -       /* Plug it into this CPUs CPC descriptor. */
>> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>> -
>>         /* Parse PSD data for this CPU */
>>         ret = acpi_get_psd(cpc_ptr, handle);
>>         if (ret)
>> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>                         goto out_free;
>>         }
>>
>> +       /* Plug PSD data into this CPUs CPC descriptor. */
>> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>> +
>
> Are you seeing a real problem without this change? I'm missing where
> this pointer is dereferenced if the PCC channel request fails.
>
> Thanks,
> Ashwin.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Ashwin Chaugule May 31, 2016, 7:29 p.m. UTC | #3
On 27 May 2016 at 12:41, Hoan Tran <hotran@apm.com> wrote:
> Hi Ashwin,

Hi,

>
> Yes, I saw kernel crash.
> As cpc_desc_ptr is not NULL, cppc_cpufreq_init() still can pass then
> crash during cppc_get_perf_caps() access CPPC shared memory.
>
> It's not only "PCC channel request fail" can create this issue but
> "acpi_get_psd() fail" also creates it
>
> Thanks
> Hoan


Just for future reference. :)

https://web.archive.org/web/20080722025748/http://www.zip.com.au/~akpm/linux/patches/stuff/top-posting.txt


>
> On Fri, May 27, 2016 at 9:10 AM, Ashwin Chaugule
> <ashwin.chaugule@linaro.org> wrote:
>> On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
>>> When CPPC fails to request PCC channel, the CPC data is freed
>>> and cpc_desc_ptr points to the invalid data. This change prevents
>>> this issue by moving cpc_desc_ptr assignment after PCC channel
>>> request.
>>>
>>> Signed-off-by: Hoan Tran <hotran@apm.com>
>>> ---
>>>  drivers/acpi/cppc_acpi.c | 6 +++---
>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
>>> index 8adac69..85fd8f7 100644
>>> --- a/drivers/acpi/cppc_acpi.c
>>> +++ b/drivers/acpi/cppc_acpi.c
>>> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>>         /* Store CPU Logical ID */
>>>         cpc_ptr->cpu_id = pr->id;
>>>
>>> -       /* Plug it into this CPUs CPC descriptor. */
>>> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>>> -
>>>         /* Parse PSD data for this CPU */
>>>         ret = acpi_get_psd(cpc_ptr, handle);
>>>         if (ret)
>>> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>>                         goto out_free;
>>>         }
>>>
>>> +       /* Plug PSD data into this CPUs CPC descriptor. */
>>> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>>> +
>>
>> Are you seeing a real problem without this change? I'm missing where
>> this pointer is dereferenced if the PCC channel request fails.
>>

So, after freeing the cpc_ptr, we need to NULL the per-cpu pointer as
well. Alternately, not assign it until everything passes and rely on
the static declaration, which is the path you've taken here.

Acked-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
hotran May 31, 2016, 7:38 p.m. UTC | #4
Hi Ashwin,


On Tue, May 31, 2016 at 12:29 PM, Ashwin Chaugule
<ashwin.chaugule@linaro.org> wrote:
> On 27 May 2016 at 12:41, Hoan Tran <hotran@apm.com> wrote:
>> Hi Ashwin,
>
> Hi,
>
>>
>> Yes, I saw kernel crash.
>> As cpc_desc_ptr is not NULL, cppc_cpufreq_init() still can pass then
>> crash during cppc_get_perf_caps() access CPPC shared memory.
>>
>> It's not only "PCC channel request fail" can create this issue but
>> "acpi_get_psd() fail" also creates it
>>
>> Thanks
>> Hoan
>
>
> Just for future reference. :)
>
> https://web.archive.org/web/20080722025748/http://www.zip.com.au/~akpm/linux/patches/stuff/top-posting.txt

My mistake and will fix in future :)

>
>
>>
>> On Fri, May 27, 2016 at 9:10 AM, Ashwin Chaugule
>> <ashwin.chaugule@linaro.org> wrote:
>>> On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
>>>> When CPPC fails to request PCC channel, the CPC data is freed
>>>> and cpc_desc_ptr points to the invalid data. This change prevents
>>>> this issue by moving cpc_desc_ptr assignment after PCC channel
>>>> request.
>>>>
>>>> Signed-off-by: Hoan Tran <hotran@apm.com>
>>>> ---
>>>>  drivers/acpi/cppc_acpi.c | 6 +++---
>>>>  1 file changed, 3 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
>>>> index 8adac69..85fd8f7 100644
>>>> --- a/drivers/acpi/cppc_acpi.c
>>>> +++ b/drivers/acpi/cppc_acpi.c
>>>> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>>>         /* Store CPU Logical ID */
>>>>         cpc_ptr->cpu_id = pr->id;
>>>>
>>>> -       /* Plug it into this CPUs CPC descriptor. */
>>>> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>>>> -
>>>>         /* Parse PSD data for this CPU */
>>>>         ret = acpi_get_psd(cpc_ptr, handle);
>>>>         if (ret)
>>>> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
>>>>                         goto out_free;
>>>>         }
>>>>
>>>> +       /* Plug PSD data into this CPUs CPC descriptor. */
>>>> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
>>>> +
>>>
>>> Are you seeing a real problem without this change? I'm missing where
>>> this pointer is dereferenced if the PCC channel request fails.
>>>
>
> So, after freeing the cpc_ptr, we need to NULL the per-cpu pointer as
> well. Alternately, not assign it until everything passes and rely on
> the static declaration, which is the path you've taken here.
>
> Acked-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>

Thanks
Hoan
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
hotran June 24, 2016, 4:35 p.m. UTC | #5
On Tue, May 31, 2016 at 12:29 PM, Ashwin Chaugule
<ashwin.chaugule@linaro.org> wrote:
>
> On 27 May 2016 at 12:41, Hoan Tran <hotran@apm.com> wrote:
> > Hi Ashwin,
>
> Hi,
>
> >
> > Yes, I saw kernel crash.
> > As cpc_desc_ptr is not NULL, cppc_cpufreq_init() still can pass then
> > crash during cppc_get_perf_caps() access CPPC shared memory.
> >
> > It's not only "PCC channel request fail" can create this issue but
> > "acpi_get_psd() fail" also creates it
> >
> > Thanks
> > Hoan
>
>
> Just for future reference. :)
>
> https://web.archive.org/web/20080722025748/http://www.zip.com.au/~akpm/linux/patches/stuff/top-posting.txt
>
>
> >
> > On Fri, May 27, 2016 at 9:10 AM, Ashwin Chaugule
> > <ashwin.chaugule@linaro.org> wrote:
> >> On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
> >>> When CPPC fails to request PCC channel, the CPC data is freed
> >>> and cpc_desc_ptr points to the invalid data. This change prevents
> >>> this issue by moving cpc_desc_ptr assignment after PCC channel
> >>> request.
> >>>
> >>> Signed-off-by: Hoan Tran <hotran@apm.com>
> >>> ---
> >>>  drivers/acpi/cppc_acpi.c | 6 +++---
> >>>  1 file changed, 3 insertions(+), 3 deletions(-)
> >>>
> >>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> >>> index 8adac69..85fd8f7 100644
> >>> --- a/drivers/acpi/cppc_acpi.c
> >>> +++ b/drivers/acpi/cppc_acpi.c
> >>> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
> >>>         /* Store CPU Logical ID */
> >>>         cpc_ptr->cpu_id = pr->id;
> >>>
> >>> -       /* Plug it into this CPUs CPC descriptor. */
> >>> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> >>> -
> >>>         /* Parse PSD data for this CPU */
> >>>         ret = acpi_get_psd(cpc_ptr, handle);
> >>>         if (ret)
> >>> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
> >>>                         goto out_free;
> >>>         }
> >>>
> >>> +       /* Plug PSD data into this CPUs CPC descriptor. */
> >>> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> >>> +
> >>
> >> Are you seeing a real problem without this change? I'm missing where
> >> this pointer is dereferenced if the PCC channel request fails.
> >>
>
> So, after freeing the cpc_ptr, we need to NULL the per-cpu pointer as
> well. Alternately, not assign it until everything passes and rely on
> the static declaration, which is the path you've taken here.
>
> Acked-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>

Hi Rafael,

Do you have plan to apply this patch ?

Thanks
Hoan
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki June 24, 2016, 11:05 p.m. UTC | #6
On Friday, June 24, 2016 09:35:32 AM Hoan Tran wrote:
> On Tue, May 31, 2016 at 12:29 PM, Ashwin Chaugule
> <ashwin.chaugule@linaro.org> wrote:
> >
> > On 27 May 2016 at 12:41, Hoan Tran <hotran@apm.com> wrote:
> > > Hi Ashwin,
> >
> > Hi,
> >
> > >
> > > Yes, I saw kernel crash.
> > > As cpc_desc_ptr is not NULL, cppc_cpufreq_init() still can pass then
> > > crash during cppc_get_perf_caps() access CPPC shared memory.
> > >
> > > It's not only "PCC channel request fail" can create this issue but
> > > "acpi_get_psd() fail" also creates it
> > >
> > > Thanks
> > > Hoan
> >
> >
> > Just for future reference. :)
> >
> > https://web.archive.org/web/20080722025748/http://www.zip.com.au/~akpm/linux/patches/stuff/top-posting.txt
> >
> >
> > >
> > > On Fri, May 27, 2016 at 9:10 AM, Ashwin Chaugule
> > > <ashwin.chaugule@linaro.org> wrote:
> > >> On 25 May 2016 at 15:09, Hoan Tran <hotran@apm.com> wrote:
> > >>> When CPPC fails to request PCC channel, the CPC data is freed
> > >>> and cpc_desc_ptr points to the invalid data. This change prevents
> > >>> this issue by moving cpc_desc_ptr assignment after PCC channel
> > >>> request.
> > >>>
> > >>> Signed-off-by: Hoan Tran <hotran@apm.com>
> > >>> ---
> > >>>  drivers/acpi/cppc_acpi.c | 6 +++---
> > >>>  1 file changed, 3 insertions(+), 3 deletions(-)
> > >>>
> > >>> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> > >>> index 8adac69..85fd8f7 100644
> > >>> --- a/drivers/acpi/cppc_acpi.c
> > >>> +++ b/drivers/acpi/cppc_acpi.c
> > >>> @@ -595,9 +595,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
> > >>>         /* Store CPU Logical ID */
> > >>>         cpc_ptr->cpu_id = pr->id;
> > >>>
> > >>> -       /* Plug it into this CPUs CPC descriptor. */
> > >>> -       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> > >>> -
> > >>>         /* Parse PSD data for this CPU */
> > >>>         ret = acpi_get_psd(cpc_ptr, handle);
> > >>>         if (ret)
> > >>> @@ -610,6 +607,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
> > >>>                         goto out_free;
> > >>>         }
> > >>>
> > >>> +       /* Plug PSD data into this CPUs CPC descriptor. */
> > >>> +       per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
> > >>> +
> > >>
> > >> Are you seeing a real problem without this change? I'm missing where
> > >> this pointer is dereferenced if the PCC channel request fails.
> > >>
> >
> > So, after freeing the cpc_ptr, we need to NULL the per-cpu pointer as
> > well. Alternately, not assign it until everything passes and rely on
> > the static declaration, which is the path you've taken here.
> >
> > Acked-by: Ashwin Chaugule <ashwin.chaugule@linaro.org>
> 
> Hi Rafael,
> 
> Do you have plan to apply this patch ?

I do now. :-)

I've overlooked the Ashwin's ACK, so thanks for the reminder.

Thanks,
Rafael

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 8adac69..85fd8f7 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -595,9 +595,6 @@  int acpi_cppc_processor_probe(struct acpi_processor *pr)
 	/* Store CPU Logical ID */
 	cpc_ptr->cpu_id = pr->id;
 
-	/* Plug it into this CPUs CPC descriptor. */
-	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
-
 	/* Parse PSD data for this CPU */
 	ret = acpi_get_psd(cpc_ptr, handle);
 	if (ret)
@@ -610,6 +607,9 @@  int acpi_cppc_processor_probe(struct acpi_processor *pr)
 			goto out_free;
 	}
 
+	/* Plug PSD data into this CPUs CPC descriptor. */
+	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
+
 	/* Everything looks okay */
 	pr_debug("Parsed CPC struct for CPU: %d\n", pr->id);