]>
Commit | Line | Data |
---|---|---|
84ab5c28 GKH |
1 | From foo@baz Fri Dec 11 03:42:15 PM CET 2020 |
2 | From: Lukas Wunner <lukas@wunner.de> | |
3 | Date: Thu, 10 Dec 2020 20:20:01 +0100 | |
4 | Subject: spi: bcm2835aux: Fix use-after-free on unbind | |
5 | To: Greg Kroah-Hartman <gregkh@linuxfoundation.com> | |
6 | Cc: Mark Brown <broonie@kernel.org>, Sudip Mukherjee <sudipm.mukherjee@gmail.com>, Sasha Levin <sashal@kernel.org>, Nathan Chancellor <natechancellor@gmail.com>, stable@vger.kernel.org | |
7 | Message-ID: <6a940079e894346e8ee00878ef844decd216e695.1607626808.git.lukas@wunner.de> | |
8 | ||
9 | From: Lukas Wunner <lukas@wunner.de> | |
10 | ||
11 | [ Upstream commit e13ee6cc4781edaf8c7321bee19217e3702ed481 ] | |
12 | ||
13 | bcm2835aux_spi_remove() accesses the driver's private data after calling | |
14 | spi_unregister_master() even though that function releases the last | |
15 | reference on the spi_master and thereby frees the private data. | |
16 | ||
17 | Fix by switching over to the new devm_spi_alloc_master() helper which | |
18 | keeps the private data accessible until the driver has unbound. | |
19 | ||
20 | Fixes: b9dd3f6d4172 ("spi: bcm2835aux: Fix controller unregister order") | |
21 | Signed-off-by: Lukas Wunner <lukas@wunner.de> | |
22 | Cc: <stable@vger.kernel.org> # v4.4+: 5e844cc37a5c: spi: Introduce device-managed SPI controller allocation | |
23 | Cc: <stable@vger.kernel.org> # v4.4+: b9dd3f6d4172: spi: bcm2835aux: Fix controller unregister order | |
24 | Cc: <stable@vger.kernel.org> # v4.4+ | |
25 | Link: https://lore.kernel.org/r/b290b06357d0c0bdee9cecc539b840a90630f101.1605121038.git.lukas@wunner.de | |
26 | Signed-off-by: Mark Brown <broonie@kernel.org> | |
27 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
28 | --- | |
29 | drivers/spi/spi-bcm2835aux.c | 18 ++++++------------ | |
30 | 1 file changed, 6 insertions(+), 12 deletions(-) | |
31 | ||
32 | --- a/drivers/spi/spi-bcm2835aux.c | |
33 | +++ b/drivers/spi/spi-bcm2835aux.c | |
34 | @@ -381,7 +381,7 @@ static int bcm2835aux_spi_probe(struct p | |
35 | unsigned long clk_hz; | |
36 | int err; | |
37 | ||
38 | - master = spi_alloc_master(&pdev->dev, sizeof(*bs)); | |
39 | + master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs)); | |
40 | if (!master) { | |
41 | dev_err(&pdev->dev, "spi_alloc_master() failed\n"); | |
42 | return -ENOMEM; | |
43 | @@ -411,30 +411,26 @@ static int bcm2835aux_spi_probe(struct p | |
44 | /* the main area */ | |
45 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
46 | bs->regs = devm_ioremap_resource(&pdev->dev, res); | |
47 | - if (IS_ERR(bs->regs)) { | |
48 | - err = PTR_ERR(bs->regs); | |
49 | - goto out_master_put; | |
50 | - } | |
51 | + if (IS_ERR(bs->regs)) | |
52 | + return PTR_ERR(bs->regs); | |
53 | ||
54 | bs->clk = devm_clk_get(&pdev->dev, NULL); | |
55 | if ((!bs->clk) || (IS_ERR(bs->clk))) { | |
56 | - err = PTR_ERR(bs->clk); | |
57 | dev_err(&pdev->dev, "could not get clk: %d\n", err); | |
58 | - goto out_master_put; | |
59 | + return PTR_ERR(bs->clk); | |
60 | } | |
61 | ||
62 | bs->irq = platform_get_irq(pdev, 0); | |
63 | if (bs->irq <= 0) { | |
64 | dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); | |
65 | - err = bs->irq ? bs->irq : -ENODEV; | |
66 | - goto out_master_put; | |
67 | + return bs->irq ? bs->irq : -ENODEV; | |
68 | } | |
69 | ||
70 | /* this also enables the HW block */ | |
71 | err = clk_prepare_enable(bs->clk); | |
72 | if (err) { | |
73 | dev_err(&pdev->dev, "could not prepare clock: %d\n", err); | |
74 | - goto out_master_put; | |
75 | + return err; | |
76 | } | |
77 | ||
78 | /* just checking if the clock returns a sane value */ | |
79 | @@ -467,8 +463,6 @@ static int bcm2835aux_spi_probe(struct p | |
80 | ||
81 | out_clk_disable: | |
82 | clk_disable_unprepare(bs->clk); | |
83 | -out_master_put: | |
84 | - spi_master_put(master); | |
85 | return err; | |
86 | } | |
87 |