aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>2014-03-30 01:33:23 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-04-08 22:53:15 -0400
commit6e556b471036b751aaa1a1b5a189eff76b1a2d0b (patch)
tree5bbd8d03d88a9986950961a0d60b7da9b7db3dff /arch/powerpc/platforms
parentfa5c11b790f9e18ec6f69680c4aa728157aef5f5 (diff)
powerpc/book3s: Fix mc_recoverable_range buffer overrun issue.
Currently we wrongly allocate mc_recoverable_range buffer (to hold recoverable ranges) based on size of the property "mcheck-recoverable-ranges". This results in allocating less memory to hold available recoverable range entries from /proc/device-tree/ibm,opal/mcheck-recoverable-ranges. This patch fixes this issue by allocating mc_recoverable_range buffer based on number of entries of recoverable ranges instead of device property size. Without this change we end up allocating less memory and run into memory corruption issue. Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/powernv/opal.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 778a2793e75b..3697772e3759 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -102,13 +102,13 @@ int __init early_init_dt_scan_opal(unsigned long node,
102int __init early_init_dt_scan_recoverable_ranges(unsigned long node, 102int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
103 const char *uname, int depth, void *data) 103 const char *uname, int depth, void *data)
104{ 104{
105 unsigned long i, size; 105 unsigned long i, psize, size;
106 const __be32 *prop; 106 const __be32 *prop;
107 107
108 if (depth != 1 || strcmp(uname, "ibm,opal") != 0) 108 if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
109 return 0; 109 return 0;
110 110
111 prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &size); 111 prop = of_get_flat_dt_prop(node, "mcheck-recoverable-ranges", &psize);
112 112
113 if (!prop) 113 if (!prop)
114 return 1; 114 return 1;
@@ -116,6 +116,23 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
116 pr_debug("Found machine check recoverable ranges.\n"); 116 pr_debug("Found machine check recoverable ranges.\n");
117 117
118 /* 118 /*
119 * Calculate number of available entries.
120 *
121 * Each recoverable address range entry is (start address, len,
122 * recovery address), 2 cells each for start and recovery address,
123 * 1 cell for len, totalling 5 cells per entry.
124 */
125 mc_recoverable_range_len = psize / (sizeof(*prop) * 5);
126
127 /* Sanity check */
128 if (!mc_recoverable_range_len)
129 return 1;
130
131 /* Size required to hold all the entries. */
132 size = mc_recoverable_range_len *
133 sizeof(struct mcheck_recoverable_range);
134
135 /*
119 * Allocate a buffer to hold the MC recoverable ranges. We would be 136 * Allocate a buffer to hold the MC recoverable ranges. We would be
120 * accessing them in real mode, hence it needs to be within 137 * accessing them in real mode, hence it needs to be within
121 * RMO region. 138 * RMO region.
@@ -124,11 +141,7 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
124 ppc64_rma_size)); 141 ppc64_rma_size));
125 memset(mc_recoverable_range, 0, size); 142 memset(mc_recoverable_range, 0, size);
126 143
127 /* 144 for (i = 0; i < mc_recoverable_range_len; i++) {
128 * Each recoverable address entry is an (start address,len,
129 * recover address) pair, * 2 cells each, totalling 4 cells per entry.
130 */
131 for (i = 0; i < size / (sizeof(*prop) * 5); i++) {
132 mc_recoverable_range[i].start_addr = 145 mc_recoverable_range[i].start_addr =
133 of_read_number(prop + (i * 5) + 0, 2); 146 of_read_number(prop + (i * 5) + 0, 2);
134 mc_recoverable_range[i].end_addr = 147 mc_recoverable_range[i].end_addr =
@@ -142,7 +155,6 @@ int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
142 mc_recoverable_range[i].end_addr, 155 mc_recoverable_range[i].end_addr,
143 mc_recoverable_range[i].recover_addr); 156 mc_recoverable_range[i].recover_addr);
144 } 157 }
145 mc_recoverable_range_len = i;
146 return 1; 158 return 1;
147} 159}
148 160