[SPAM][PATCH] iommu/mediatek: Validate number of phandles associated with "mediatek,larbs"

Guenter Roeck linux at roeck-us.net
Wed Dec 15 08:25:34 PST 2021


On Wed, Dec 15, 2021 at 01:30:45PM +0800, Yong Wu wrote:
> On Tue, 2021-12-14 at 07:02 -0800, Guenter Roeck wrote:
> > On 12/13/21 11:31 PM, Yong Wu wrote:
> > > On Fri, 2021-12-10 at 12:57 -0800, Guenter Roeck wrote:
> > > > Since commit baf94e6ebff9 ("iommu/mediatek: Add device link for
> > > > smi-
> > > > common
> > > > and m4u"), the driver assumes that at least one phandle
> > > > associated
> > > > with
> > > > "mediatek,larbs" exists. If that is not the case, for example if
> > > > reason
> > > > "mediatek,larbs" is provided as boolean property, the code will
> > > > use
> > > > an
> > > > uninitialized pointer and may crash. To fix the problem, ensure
> > > > that
> > > > the
> > > > number of phandles associated with "mediatek,larbs" is at least 1
> > > > and
> > > > bail out immediately if that is not the case.
> > > 
> > >  From the dt-binding, "mediatek,larbs" always is a phandle-array. I
> > > assumed the dts should conform to the dt-binding before. Then the
> > > problem is that if we should cover the case that someone
> > > abuses/attacks
> > > the dts. Could you help add more comment in the commit message?
> > > something like: this is for avoid abuse the dt-binding.
> > > 
> > 
> > This doesn't have to be an abuse or attack. It can simply be an error
> > by the person who wrote the devicetree file. Sure, bugs or lack of
> 
> A minor question: If someone wrote error data that don't conform to the
> dtbinding, the error result is expected. He should fix that problem,
> right? If we could avoid abort and show error message at the beginning,
> it's better of course.
> 

Sure. However, such an error should not result in a crash but should be
caught in an error handler.

> > error checking can often be used for attacks, but that doesn't mean
> > that all bad data is an exploit or attack.
> > 
> > > > 
> > > > Cc: Yong Wu <yong.wu at mediatek.com>
> > > > Cc: Tomasz Figa <tfiga at chromium.org>
> > > > Fixes: baf94e6ebff9 ("iommu/mediatek: Add device link for smi-
> > > > common
> > > > and m4u")
> > > > Reported-by: kernel test robot <lkp at intel.com>
> > > > Reported-by: Dan Carpenter <dan.carpenter at oracle.com>
> > > > Signed-off-by: Guenter Roeck <linux at roeck-us.net>
> > > > ---
> > > >   drivers/iommu/mtk_iommu.c | 2 ++
> > > >   1 file changed, 2 insertions(+)
> > > > 
> > > > diff --git a/drivers/iommu/mtk_iommu.c
> > > > b/drivers/iommu/mtk_iommu.c
> > > > index 25b834104790..0bbe32d0a2a6 100644
> > > > --- a/drivers/iommu/mtk_iommu.c
> > > > +++ b/drivers/iommu/mtk_iommu.c
> > > > @@ -828,6 +828,8 @@ static int mtk_iommu_probe(struct
> > > > platform_device
> > > > *pdev)
> > > >   					     "mediatek,larbs",
> > > > NULL);
> > > >   	if (larb_nr < 0)
> > > >   		return larb_nr;
> > > > +	if (larb_nr == 0)
> > > > +		return -EINVAL;
> > > 
> > > Just assigning the larbnode to NULL may be simpler. In this case,
> > > it
> > > won't enter the loop below, and return 0 in the
> > > of_parse_phandle(larbnode, "mediatek,smi", 0).
> > > 
> > > -       struct device_node      *larbnode, *smicomm_node;
> > > +       struct device_node      *larbnode = NULL, *smicomm_node;
> > > 
> > 
> > It is an option, but it would need to be explained and would not be
> > as simple as it looks. And, yes, it would result in unnecessary code
> > execution.
> > 
> > Why does it need to be explained ? I spent quite some additional
> > time with the code trying to understand _why_ it works, and we should
> > make sure that others don't have to spend that time.
> > 
> > Anyway, that additional time made me find additional problems with
> > the code.
> > 
> > The for loop below assigns larbnode to the last node it finds.
> > However, that node can be disabled.
> > 
> > 		if (!of_device_is_available(larbnode)) {
> >                          of_node_put(larbnode);
> >                          continue;
> >                  }
> > 
> > Is such a disabled larbnode, if it is the last one, the node to use
> > when looking for "mediatek,smi" ?
> > 
> > Also, there is
> > 
> > 	ret = of_property_read_u32(larbnode, "mediatek,larb-id", &id);
> >          if (ret)/* The id is consecutive if there is no this
> > property */
> >                  id = i;
> > 
> > There are two problems with this code. First, neither i nor id are
> > range
> > checked, but used later in
> > 
> > 	data->larb_imu[id].dev = &plarbdev->dev;
> > 
> > That means a devicetree with a bad value for "mediatek,larb-id"
> > or more than MTK_LARB_NR_MAX larb nodes will result in writes after
> > the end of struct mtk_iommu_data.
> > 
> > On top of that, the comment states that the nodes are consecutive if
> > there
> > is no "mediatek,larb-id". However, that isn't really the case if
> > there
> > are disabled nodes. If there are disabled nodes, there will be a gap
> > in
> > larb_imu[]. I don't know if that matters; if it doesn't, there should
> > be
> > a comment about it in the code.
> > 
> > Last but not least, it would probably make sense to explain what the
> > "last"
> > larb node is expected to be in more detail. It is the last larb node
> > in
> > the devicetree file, but not the one with the highest id, and not
> > (necessarily) an enabled one. For example, in
> > arch/arm64/boot/dts/mediatek/mt2712e.dtsi, the code would pick
> > <&smi_common0> even though <&smi_common1> is associated with a higher
> > larb id.
> > 
> > One could of course argue that this all doesn't matter because it
> > would
> > suggest that the devicetree data is bad, but it is common practice to
> > validate
> > devicetree data and not just blindly accept it. One could also argue
> > that such bad data would be an "attack", but, again, we don't know
> > that.
> > 
> > In summary,
> 
> Thanks very much for your time to check here. All the issues are
> introduced by the values from dts are untrusted. The detail platform
> informations are replied below.
> 
> > 
> > - The check I introduced should probably be something like
> > 
> > 	if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX)
> > 		return -EINVAL;
> 
> OK. Add a "else" to show it is a block with the "if" above?
> 
>         if (larb_nr < 0)
>              return larb_nr;
>         else if (larb_nr == 0 || larb_nr > MTK_LARB_NR_MAX)
>              return -EINVAL;
> 

Static checkers would complain with "else after return is unnecessary".

> > 
> > - It needs to be clarified if larbnode to use for finding
> > "mediatek,smi"
> >    is indeed always the last one, even if it is disabled. If so, we 
> 
> We could find the "mediatek,smi" with any available larb. Of course it
> should not be a disabled one. The code using the last larb is for
> reusing the variable "larbnode".
> 
> > should
> >    probably also handle the situation that of_node_put(larbnode); was
> > called
> >    on that larbnode. Alternatively, if the last larb node to use is
> > the last
> >    _active_ larb node, we'll probably need a separate variable to
> > save that
> >    larb node pointer for later use.
> 
> A new variable is ok.
> 
Ok, I'll change the code accordingly.

> > 
> > - It needs to be clarified if larb_imu[] may have gaps if there are
> > disabled
> >    larb nodes and "mediatek,larb-id" is not specified. If so, there 
> 
> Yes. It may have gaps. the commit message of this patch may be helpful.
> 
> 50fa3cd33f9d ("dt-bindings: mediatek: Add binding for mt2712 IOMMU and
> SMI")
> 
> > is still the
> >    problem that 'i' and a previous value of "mediatek,larb-id" may be
> > identical
> >    [ eg the first node provides mediatek,larb-id = <1> and the second
> > node
> >      doesn't provide "mediatek,larb-id" ]
> 
> This case did don't meet my expectation. OK, then we add a checking?
> like:
> 
>    if (data->larb_imu[i].dev) {
>          dev_err(dev, "the larb %d exist.", i);
>          return -EEXIST;
>    }         

Makes sense, I'll do that.

> 
> > 
> > - "id" should be range checked.
> 
> It should be [0, MTK_LARB_NR_MAX).
> 

I'll add this check.

> > 
> > - The meaning of "last" larb node to use when looking for
> > mediatek,smi should
> >    be explained in more detail.
> 
> We could use any available larb node to find mediatek,smi.
> 
> Their "mediatek,smi" node must be the same. OK, In this case, they are
> possible different. We should add a checking: return -EINVAL if they
> are not same.
> 
I'll see if and how I can do that without adding too much cmplexity
to the code.

> > 
> > Once we have determined the correct handling of all those situations,
> > I'll
> > be happy to send another revision of this patch (or possibly multiple
> > patches).
> 
> Appreciate for help enhance the safe here. I will test it.
> 
My pleasure.

Thanks,
Guenter

> > 
> > Thanks,
> > Guenter
> > 
> > > >   
> > > >   	for (i = 0; i < larb_nr; i++) {
> > > >   		u32 id;
> > 
> > 



More information about the linux-arm-kernel mailing list