* [PATCH] opp: fix a missing check on list iterator
@ 2022-03-27 5:39 Xiaomeng Tong
2022-03-28 3:17 ` Viresh Kumar
0 siblings, 1 reply; 7+ messages in thread
From: Xiaomeng Tong @ 2022-03-27 5:39 UTC (permalink / raw)
To: vireshk
Cc: nm, sboyd, rafael.j.wysocki, linux-pm, linux-kernel,
Xiaomeng Tong, stable
The bug is here:
dev = new_dev->dev;
The list iterator 'new_dev' will point to a bogus position containing
HEAD if the list is empty or no element is found. This case must
be checked before any use of the iterator, otherwise it will lead
to a invalid memory access.
To fix this bug, add an check. Use a new variable 'iter' as the
list iterator, while use the old variable 'new_dev' as a dedicated
pointer to point to the found element.
Cc: stable@vger.kernel.org
Fixes: deaa51465105a ("PM / OPP: Add debugfs support")
Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
---
drivers/opp/debugfs.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index 596c185b5dda..a4476985e4ce 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -187,14 +187,19 @@ void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
static void opp_migrate_dentry(struct opp_device *opp_dev,
struct opp_table *opp_table)
{
- struct opp_device *new_dev;
+ struct opp_device *new_dev = NULL, *iter;
const struct device *dev;
struct dentry *dentry;
/* Look for next opp-dev */
- list_for_each_entry(new_dev, &opp_table->dev_list, node)
- if (new_dev != opp_dev)
+ list_for_each_entry(iter, &opp_table->dev_list, node)
+ if (iter != opp_dev) {
+ new_dev = iter;
break;
+ }
+
+ if (!new_dev)
+ return;
/* new_dev is guaranteed to be valid here */
dev = new_dev->dev;
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-27 5:39 [PATCH] opp: fix a missing check on list iterator Xiaomeng Tong
@ 2022-03-28 3:17 ` Viresh Kumar
2022-03-28 7:43 ` Xiaomeng Tong
0 siblings, 1 reply; 7+ messages in thread
From: Viresh Kumar @ 2022-03-28 3:17 UTC (permalink / raw)
To: Xiaomeng Tong
Cc: vireshk, nm, sboyd, rafael.j.wysocki, linux-pm, linux-kernel, stable
On 27-03-22, 13:39, Xiaomeng Tong wrote:
> The bug is here:
> dev = new_dev->dev;
>
> The list iterator 'new_dev' will point to a bogus position containing
> HEAD if the list is empty or no element is found. This case must
> be checked before any use of the iterator, otherwise it will lead
> to a invalid memory access.
>
> To fix this bug, add an check. Use a new variable 'iter' as the
> list iterator, while use the old variable 'new_dev' as a dedicated
> pointer to point to the found element.
>
> Cc: stable@vger.kernel.org
> Fixes: deaa51465105a ("PM / OPP: Add debugfs support")
> Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
> ---
> drivers/opp/debugfs.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
> index 596c185b5dda..a4476985e4ce 100644
> --- a/drivers/opp/debugfs.c
> +++ b/drivers/opp/debugfs.c
> @@ -187,14 +187,19 @@ void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
> static void opp_migrate_dentry(struct opp_device *opp_dev,
> struct opp_table *opp_table)
> {
> - struct opp_device *new_dev;
> + struct opp_device *new_dev = NULL, *iter;
> const struct device *dev;
> struct dentry *dentry;
>
> /* Look for next opp-dev */
> - list_for_each_entry(new_dev, &opp_table->dev_list, node)
> - if (new_dev != opp_dev)
> + list_for_each_entry(iter, &opp_table->dev_list, node)
> + if (iter != opp_dev) {
> + new_dev = iter;
> break;
> + }
> +
> + if (!new_dev)
> + return;
I think you missed this check in the parent function ?
if (!list_is_singular(&opp_table->dev_list)) {
i.e. this bug can never happen.
--
viresh
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-28 3:17 ` Viresh Kumar
@ 2022-03-28 7:43 ` Xiaomeng Tong
2022-03-28 8:50 ` Viresh Kumar
0 siblings, 1 reply; 7+ messages in thread
From: Xiaomeng Tong @ 2022-03-28 7:43 UTC (permalink / raw)
To: viresh.kumar
Cc: linux-kernel, linux-pm, nm, rafael.j.wysocki, sboyd, stable,
vireshk, xiam0nd.tong
On Mon, 28 Mar 2022 08:47:39 +0530, Viresh Kumar wrote:
> > diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
> > index 596c185b5dda..a4476985e4ce 100644
> > --- a/drivers/opp/debugfs.c
> > +++ b/drivers/opp/debugfs.c
> > @@ -187,14 +187,19 @@ void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
> > static void opp_migrate_dentry(struct opp_device *opp_dev,
> > struct opp_table *opp_table)
> > {
> > - struct opp_device *new_dev;
> > + struct opp_device *new_dev = NULL, *iter;
> > const struct device *dev;
> > struct dentry *dentry;
> >
> > /* Look for next opp-dev */
> > - list_for_each_entry(new_dev, &opp_table->dev_list, node)
> > - if (new_dev != opp_dev)
> > + list_for_each_entry(iter, &opp_table->dev_list, node)
> > + if (iter != opp_dev) {
> > + new_dev = iter;
> > break;
> > + }
> > +
> > + if (!new_dev)
> > + return;
>
> I think you missed this check in the parent function ?
>
> if (!list_is_singular(&opp_table->dev_list)) {
>
>
> i.e. this bug can never happen.
>
No. the conditon to call opp_migrate_dentry(opp_dev, opp_table); is:
if (!list_is_singular(&opp_table->dev_list)),
while list_is_singlular is: !list_empty(head) && (head->next == head->prev);
so the condition is: list_empty(head) || (head->next != head->prev)
if the list is empty, the bug can be triggered.
--
Xiaomeng Tong
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-28 7:43 ` Xiaomeng Tong
@ 2022-03-28 8:50 ` Viresh Kumar
2022-03-28 9:13 ` Xiaomeng Tong
0 siblings, 1 reply; 7+ messages in thread
From: Viresh Kumar @ 2022-03-28 8:50 UTC (permalink / raw)
To: Xiaomeng Tong
Cc: linux-kernel, linux-pm, nm, rafael.j.wysocki, sboyd, stable, vireshk
On 28-03-22, 15:43, Xiaomeng Tong wrote:
> No. the conditon to call opp_migrate_dentry(opp_dev, opp_table); is:
> if (!list_is_singular(&opp_table->dev_list)),
>
> while list_is_singlular is: !list_empty(head) && (head->next == head->prev);
>
> so the condition is: list_empty(head) || (head->next != head->prev)
>
> if the list is empty, the bug can be triggered.
List can't be empty here by design. It will be a huge bug in that
case, which should lead to crash somewhere.
--
viresh
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-28 8:50 ` Viresh Kumar
@ 2022-03-28 9:13 ` Xiaomeng Tong
2022-03-28 9:39 ` Viresh Kumar
0 siblings, 1 reply; 7+ messages in thread
From: Xiaomeng Tong @ 2022-03-28 9:13 UTC (permalink / raw)
To: viresh.kumar
Cc: linux-kernel, linux-pm, nm, rafael.j.wysocki, sboyd, stable,
vireshk, xiam0nd.tong
On Mon, 28 Mar 2022 14:20:57 +0530, Viresh Kumar wrote:
> On 28-03-22, 15:43, Xiaomeng Tong wrote:
> > No. the conditon to call opp_migrate_dentry(opp_dev, opp_table); is:
> > if (!list_is_singular(&opp_table->dev_list)),
> >
> > while list_is_singlular is: !list_empty(head) && (head->next == head->prev);
> >
> > so the condition is: list_empty(head) || (head->next != head->prev)
> >
> > if the list is empty, the bug can be triggered.
>
> List can't be empty here by design. It will be a huge bug in that
> case, which should lead to crash somewhere.
>
There is anther condition to trigger this bug: the list is not empty and
no element found (if (iter != opp_dev)).
--
Xiaomeng Tong
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-28 9:13 ` Xiaomeng Tong
@ 2022-03-28 9:39 ` Viresh Kumar
2022-03-31 2:10 ` Xiaomeng Tong
0 siblings, 1 reply; 7+ messages in thread
From: Viresh Kumar @ 2022-03-28 9:39 UTC (permalink / raw)
To: Xiaomeng Tong
Cc: linux-kernel, linux-pm, nm, rafael.j.wysocki, sboyd, stable, vireshk
On 28-03-22, 17:13, Xiaomeng Tong wrote:
> On Mon, 28 Mar 2022 14:20:57 +0530, Viresh Kumar wrote:
> > On 28-03-22, 15:43, Xiaomeng Tong wrote:
> > > No. the conditon to call opp_migrate_dentry(opp_dev, opp_table); is:
> > > if (!list_is_singular(&opp_table->dev_list)),
> > >
> > > while list_is_singlular is: !list_empty(head) && (head->next == head->prev);
> > >
> > > so the condition is: list_empty(head) || (head->next != head->prev)
> > >
> > > if the list is empty, the bug can be triggered.
> >
> > List can't be empty here by design. It will be a huge bug in that
> > case, which should lead to crash somewhere.
> >
>
> There is anther condition to trigger this bug: the list is not empty and
> no element found (if (iter != opp_dev)).
I suggest reading the code again, considering opp_debug_unregister()
as well.
What's happening here is this:
- Several devices share the OPP table.
- One of them (devX) is going away and opp_debug_unregister() is called for this device.
- If devX is the last device for this OPP table, then we don't migrate
and just release all resources.
- Otherwise, we migrate it to the next element in the list. i.e. any
device which != devX.
Please tell based on this where do you see a possibility of a bug.
Surely there can be one, but I fail to see it at the moment and need
more detail of the same.
Thanks Xiaomeng.
--
viresh
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] opp: fix a missing check on list iterator
2022-03-28 9:39 ` Viresh Kumar
@ 2022-03-31 2:10 ` Xiaomeng Tong
0 siblings, 0 replies; 7+ messages in thread
From: Xiaomeng Tong @ 2022-03-31 2:10 UTC (permalink / raw)
To: viresh.kumar
Cc: linux-kernel, linux-pm, nm, rafael.j.wysocki, sboyd, stable,
vireshk, xiam0nd.tong
On Mon, 28 Mar 2022 15:09:33 +0530, Viresh Kumar wrote:
> On 28-03-22, 17:13, Xiaomeng Tong wrote:
> > On Mon, 28 Mar 2022 14:20:57 +0530, Viresh Kumar wrote:
> > > On 28-03-22, 15:43, Xiaomeng Tong wrote:
> > > > No. the conditon to call opp_migrate_dentry(opp_dev, opp_table); is:
> > > > if (!list_is_singular(&opp_table->dev_list)),
> > > >
> > > > while list_is_singlular is: !list_empty(head) && (head->next == head->prev);
> > > >
> > > > so the condition is: list_empty(head) || (head->next != head->prev)
> > > >
> > > > if the list is empty, the bug can be triggered.
> > >
> > > List can't be empty here by design. It will be a huge bug in that
> > > case, which should lead to crash somewhere.
> > >
> >
> > There is anther condition to trigger this bug: the list is not empty and
> > no element found (if (iter != opp_dev)).
>
> I suggest reading the code again, considering opp_debug_unregister()
> as well.
>
> What's happening here is this:
>
> - Several devices share the OPP table.
> - One of them (devX) is going away and opp_debug_unregister() is called for this device.
> - If devX is the last device for this OPP table, then we don't migrate
> and just release all resources.
> - Otherwise, we migrate it to the next element in the list. i.e. any
> device which != devX.
>
> Please tell based on this where do you see a possibility of a bug.
> Surely there can be one, but I fail to see it at the moment and need
> more detail of the same.
>
Perhaps you are right. Anyway, It is a good choise to use list iterator
only inside the loop as linus suggested [1], to avoid potential risk.
I have also repost another patch with changed commit message. Please
check it, thank you.
[1]:https://lore.kernel.org/lkml/20220301075839.4156-1-xiam0nd.tong@gmail.com/
--
Xiaomeng Tong
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-03-31 2:10 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-27 5:39 [PATCH] opp: fix a missing check on list iterator Xiaomeng Tong
2022-03-28 3:17 ` Viresh Kumar
2022-03-28 7:43 ` Xiaomeng Tong
2022-03-28 8:50 ` Viresh Kumar
2022-03-28 9:13 ` Xiaomeng Tong
2022-03-28 9:39 ` Viresh Kumar
2022-03-31 2:10 ` Xiaomeng Tong
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.