[bug report] MTD: mtdconcat NAND/Sibley support (rev.2)
Dan Carpenter
dan.carpenter at oracle.com
Tue Feb 1 05:05:55 PST 2022
[ I was just going through these warnings and noticed that it had been
eight years since I reported this. :P It still looks valid.
-dan ]
Hi MTD developers,
The patch e8d32937d9f2: "MTD: mtdconcat NAND/Sibley support (rev.2)"
from May 17, 2006, leads to the following Smatch static checker
warning:
drivers/mtd/mtdconcat.c:231 concat_writev()
warn: potentially one past the end of array 'vecs_copy[entry_high]'
drivers/mtd/mtdconcat.c
184 static int
185 concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
186 unsigned long count, loff_t to, size_t * retlen)
187 {
188 struct mtd_concat *concat = CONCAT(mtd);
189 struct kvec *vecs_copy;
190 unsigned long entry_low, entry_high;
191 size_t total_len = 0;
192 int i;
193 int err = -EINVAL;
194
195 /* Calculate total length of data */
196 for (i = 0; i < count; i++)
197 total_len += vecs[i].iov_len;
198
199 /* Check alignment */
200 if (mtd->writesize > 1) {
201 uint64_t __to = to;
202 if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize))
203 return -EINVAL;
204 }
205
206 /* make a copy of vecs */
207 vecs_copy = kmemdup(vecs, sizeof(struct kvec) * count, GFP_KERNEL);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
208 if (!vecs_copy)
209 return -ENOMEM;
210
211 entry_low = 0;
212 for (i = 0; i < concat->num_subdev; i++) {
213 struct mtd_info *subdev = concat->subdev[i];
214 size_t size, wsize, retsize, old_iov_len;
215
216 if (to >= subdev->size) {
217 to -= subdev->size;
218 continue;
219 }
220
221 size = min_t(uint64_t, total_len, subdev->size - to);
222 wsize = size; /* store for future use */
223
224 entry_high = entry_low;
225 while (entry_high < count) {
^^^^^^^^^^^^^^^^^^
If "entry_high == count"
226 if (size <= vecs_copy[entry_high].iov_len)
227 break;
228 size -= vecs_copy[entry_high++].iov_len;
229 }
230
--> 231 old_iov_len = vecs_copy[entry_high].iov_len;
Then this is an off by one.
232 vecs_copy[entry_high].iov_len = size;
233
234 err = mtd_writev(subdev, &vecs_copy[entry_low],
235 entry_high - entry_low + 1, to, &retsize);
236
237 vecs_copy[entry_high].iov_len = old_iov_len - size;
238 vecs_copy[entry_high].iov_base += size;
239
240 entry_low = entry_high;
241
242 if (err)
243 break;
244
245 *retlen += retsize;
246 total_len -= wsize;
247
248 if (total_len == 0)
249 break;
250
251 err = -EINVAL;
252 to = 0;
253 }
254
255 kfree(vecs_copy);
256 return err;
257 }
regards,
dan carpenter
More information about the linux-mtd
mailing list