b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From 5ae4c4ac2d992afcf4087e5f33ad7e5f7d073fbf Mon Sep 17 00:00:00 2001 |
| 2 | From: Claudiu Manoil <claudiu.manoil@nxp.com> |
| 3 | Date: Wed, 4 Dec 2019 14:36:09 +0200 |
| 4 | Subject: [PATCH] net: dsa: felix: Fix probing allocation and cleanup path |
| 5 | |
| 6 | dsa_switch_alloc() uses managed (devm_alloc) allocation |
| 7 | to alloc 'ds'. kfree()-ing 'ds' results in memory corruption. |
| 8 | kfree(ds) seems harmless on the error path, however for this |
| 9 | particular device, dsa_register_swtich() deffers probing to |
| 10 | allow the enetc driver to probe the master port first. |
| 11 | This results in kfree(ds) being called during the first |
| 12 | probing attempt of felix, followed by a NULL poiter access |
| 13 | crash during enetc driver probing (when accessing its net_device). |
| 14 | |
| 15 | This patch fixes following crash (triggerred in the enetc driver by |
| 16 | the probing routine of the felix driver): |
| 17 | |
| 18 | [ 3.502254] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 |
| 19 | [ 3.511073] Mem abort info: |
| 20 | [ 3.513874] ESR = 0x96000044 |
| 21 | [ 3.516936] EC = 0x25: DABT (current EL), IL = 32 bits |
| 22 | [ 3.522266] SET = 0, FnV = 0 |
| 23 | [ 3.525327] EA = 0, S1PTW = 0 |
| 24 | [ 3.528476] Data abort info: |
| 25 | [ 3.531359] ISV = 0, ISS = 0x00000044 |
| 26 | [ 3.535205] CM = 0, WnR = 1 |
| 27 | [ 3.538182] user pgtable: 4k pages, 48-bit VAs, pgdp=00000020f612d000 |
| 28 | [ 3.544645] [0000000000000000] pgd=0000000000000000 |
| 29 | [ 3.549542] Internal error: Oops: 96000044 [#1] PREEMPT SMP |
| 30 | [ 3.555128] Modules linked in: |
| 31 | [ 3.558189] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.4.0-03552-gfa6e1cd69f80 #1 |
| 32 | [ 3.565781] Hardware name: LS1028A RDB Board (DT) |
| 33 | [ 3.570496] pstate: a0000005 (NzCv daif -PAN -UAO) |
| 34 | [ 3.575303] pc : enetc_pf_probe+0x784/0xba8 |
| 35 | [ 3.579495] lr : enetc_pf_probe+0x6e8/0xba8 |
| 36 | [ 3.583686] sp : ffff80001002ba90 |
| 37 | [ 3.587005] x29: ffff80001002ba90 x28: ffff002076130c08 |
| 38 | [ 3.592331] x27: 0000000000000002 x26: ffff002076130c80 |
| 39 | [ 3.597657] x25: ffff002076130c00 x24: ffff002076130c80 |
| 40 | [ 3.602982] x23: ffffb3f2ab0ec000 x22: ffff0020760d7840 |
| 41 | [ 3.608307] x21: ffff0020760d7000 x20: ffff002076130c00 |
| 42 | [ 3.613632] x19: ffff800010850000 x18: ffffffffffffffff |
| 43 | [ 3.618957] x17: 000000007dee1586 x16: 00000000cb746ba4 |
| 44 | [ 3.624282] x15: ffffb3f2abce9908 x14: 0000000000000000 |
| 45 | [ 3.629608] x13: 0000000000000101 x12: 0000000000010000 |
| 46 | [ 3.634933] x11: 00000000ffffffff x10: ffff4c2dd0136000 |
| 47 | [ 3.640257] x9 : 0000000000000000 x8 : ffff002076122000 |
| 48 | [ 3.645582] x7 : 0000000000000000 x6 : 000000000000003f |
| 49 | [ 3.650908] x5 : 0000000000000040 x4 : 0000000000000001 |
| 50 | [ 3.656234] x3 : ffff800010850000 x2 : ffffb3f2ab0ed868 |
| 51 | [ 3.661560] x1 : 0000000000000000 x0 : 00000000051ca556 |
| 52 | [ 3.666886] Call trace: |
| 53 | [ 3.669333] enetc_pf_probe+0x784/0xba8 |
| 54 | [ 3.673178] local_pci_probe+0x3c/0xa0 |
| 55 | [ 3.676935] pci_device_probe+0x128/0x1c0 |
| 56 | [ 3.680954] really_probe+0x108/0x348 |
| 57 | [ 3.684623] driver_probe_device+0x58/0x100 |
| 58 | [ 3.688815] device_driver_attach+0x6c/0x90 |
| 59 | [ 3.693006] __driver_attach+0x84/0xc8 |
| 60 | [ 3.696762] bus_for_each_dev+0x74/0xc8 |
| 61 | [ 3.700605] driver_attach+0x20/0x28 |
| 62 | [ 3.704186] bus_add_driver+0x148/0x1f0 |
| 63 | [ 3.708029] driver_register+0x60/0x110 |
| 64 | [ 3.711872] __pci_register_driver+0x40/0x48 |
| 65 | [ 3.716153] enetc_pf_driver_init+0x20/0x28 |
| 66 | [ 3.720346] do_one_initcall+0x5c/0x1b0 |
| 67 | [ 3.724189] kernel_init_freeable+0x1a4/0x24c |
| 68 | [ 3.728557] kernel_init+0x10/0x108 |
| 69 | [ 3.732052] ret_from_fork+0x10/0x18 |
| 70 | [ 3.735635] Code: f9400680 f9417ea1 91020000 b9400000 (b9000020) |
| 71 | [ 3.741749] ---[ end trace c8ab43e3d33fed3f ]--- |
| 72 | [ 3.746396] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b |
| 73 | [ 3.748522] ata1: SATA link down (SStatus 0 SControl 300) |
| 74 | [ 3.754077] SMP: stopping secondary CPUs |
| 75 | [ 3.754082] Kernel Offset: 0x33f299c00000 from 0xffff800010000000 |
| 76 | [ 3.754083] PHYS_OFFSET: 0xfffff019c0000000 |
| 77 | [ 3.754086] CPU features: 0x0002,21806008 |
| 78 | [ 3.754088] Memory Limit: none |
| 79 | [ 3.780794] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- |
| 80 | |
| 81 | As a result of the fix, struct felix allocation also needs to |
| 82 | be converted to managed allocation (devm_alloc). |
| 83 | |
| 84 | Fixes: bb849431a970 ("net: dsa: ocelot: alloc memory for dsa switch instance") |
| 85 | |
| 86 | Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com> |
| 87 | --- |
| 88 | drivers/net/dsa/ocelot/felix.c | 7 +------ |
| 89 | 1 file changed, 1 insertion(+), 6 deletions(-) |
| 90 | |
| 91 | --- a/drivers/net/dsa/ocelot/felix.c |
| 92 | +++ b/drivers/net/dsa/ocelot/felix.c |
| 93 | @@ -485,7 +485,7 @@ static int felix_pci_probe(struct pci_de |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | - felix = kzalloc(sizeof(struct felix), GFP_KERNEL); |
| 98 | + felix = devm_kzalloc(&pdev->dev, sizeof(*felix), GFP_KERNEL); |
| 99 | if (!felix) { |
| 100 | err = -ENOMEM; |
| 101 | dev_err(&pdev->dev, "Failed to allocate driver memory\n"); |
| 102 | @@ -532,11 +532,9 @@ static int felix_pci_probe(struct pci_de |
| 103 | return 0; |
| 104 | |
| 105 | err_register_ds: |
| 106 | - kfree(ds); |
| 107 | err_alloc_ds: |
| 108 | err_alloc_irq: |
| 109 | err_alloc_felix: |
| 110 | - kfree(felix); |
| 111 | err_dma: |
| 112 | pci_disable_device(pdev); |
| 113 | err_pci_enable: |
| 114 | @@ -551,9 +549,6 @@ static void felix_pci_remove(struct pci_ |
| 115 | |
| 116 | dsa_unregister_switch(felix->ds); |
| 117 | |
| 118 | - kfree(felix->ds); |
| 119 | - kfree(felix); |
| 120 | - |
| 121 | pci_disable_device(pdev); |
| 122 | } |
| 123 | |