lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20191018160419.rm2ogvh3k3jdx3tn@holly.lan>
Date:   Fri, 18 Oct 2019 17:04:19 +0100
From:   Daniel Thompson <daniel.thompson@...aro.org>
To:     Lee Jones <lee.jones@...aro.org>
Cc:     broonie@...nel.org, linus.walleij@...aro.org, arnd@...db.de,
        linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
        baohua@...nel.org, stephan@...hold.net
Subject: Re: [PATCH 1/2] mfd: mfd-core: Allocate reference counting memory
 directly to the platform device

On Fri, Oct 18, 2019 at 01:26:46PM +0100, Lee Jones wrote:
> MFD provides reference counting (for the 2 consumers who actually use it!)
> via mfd_cell's 'usage_count' member.  However, since MFD cells become
> read-only (const), MFD needs to allocate writable memory and assign it to
> 'usage_count' before first registration.  It currently does this by
> allocating enough memory for all requested child devices (yes, even disabled
> ones - but we'll get to that) and assigning the base pointer plus sub-device
> index to each device in the cell.
> 
> The difficulty comes when trying to free that memory.  During the removal of
> the parent device, MFD unregisters each child device, keeping a tally on the
> lowest memory location pointed to by a child device's 'usage_count'.  Once
> all of the children are unregistered, the lowest memory location must be the
> base address of the previously allocated array, right?
> 
> Well yes, until we try to honour the disabling of devices via Device Tree
> for instance.  If the first child device in the provided batch is disabled,
> simply skipping registration (and consequentially deregistration) will mean
> that the first device's 'usage_count' pointer will not be accounted for when
> attempting to find the base.  In which case, MFD will assume the first non-
> disabled 'usage_count' pointer is the base and subsequently attempt to
> erroneously free it.
> 
> We can avoid all of this hoop jumping by simply allocating memory to each
> single child device before it is considered read-only.  We can then free
> it on a per-device basis during deregistration.
> 
> Signed-off-by: Lee Jones <lee.jones@...aro.org>
> ---
>  drivers/mfd/mfd-core.c | 42 ++++++++++++++++++------------------------
>  1 file changed, 18 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 23276a80e3b4..eafdadd58e8b 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -404,7 +398,7 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
>  		cell_entry.name = clones[i];
>  		/* don't give up if a single call fails; just report error */
>  		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
> -				   cell_entry.usage_count, NULL, 0, NULL))
> +				   NULL, 0, NULL))

I think this change is broken.

Cloned cells are supposed to share the same reference counter as their
template and this change results in each clone having its own counter.
That means the "the 2 consumers who actually use it" will both end up
calling cs5535_mfd_res_enable() (and whichever loses the race will fail
to probe).

To be honest it might be easier to move the request_region() into
cs5535_mfd_probe() and rip out the entire reference counting mechanism
since at that point it would be unused (the other callers of
mfd_cell_enable() look safe w/o a counter).


Daniel.

>  			dev_err(dev, "failed to create platform device '%s'\n",
>  					clones[i]);
>  	}
> -- 
> 2.17.1
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ