Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'devicetree/merge' of git://git.kernel.org/pub/scm/linux/kernel/git/glikely/linux

Pull devicetree bugfix from Grant Likely:
"One buffer overflow bug that shouldn't be left around"

* 'devicetree/merge' of git://git.kernel.org/pub/scm/linux/kernel/git/glikely/linux:
of: Fix overflow bug in string property parsing functions

+154 -86
+22 -66
drivers/of/base.c
··· 1280 1280 EXPORT_SYMBOL_GPL(of_property_read_string); 1281 1281 1282 1282 /** 1283 - * of_property_read_string_index - Find and read a string from a multiple 1284 - * strings property. 1285 - * @np: device node from which the property value is to be read. 1286 - * @propname: name of the property to be searched. 1287 - * @index: index of the string in the list of strings 1288 - * @out_string: pointer to null terminated return string, modified only if 1289 - * return value is 0. 1290 - * 1291 - * Search for a property in a device tree node and retrieve a null 1292 - * terminated string value (pointer to data, not a copy) in the list of strings 1293 - * contained in that property. 1294 - * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if 1295 - * property does not have a value, and -EILSEQ if the string is not 1296 - * null-terminated within the length of the property data. 1297 - * 1298 - * The out_string pointer is modified only if a valid string can be decoded. 1299 - */ 1300 - int of_property_read_string_index(struct device_node *np, const char *propname, 1301 - int index, const char **output) 1302 - { 1303 - struct property *prop = of_find_property(np, propname, NULL); 1304 - int i = 0; 1305 - size_t l = 0, total = 0; 1306 - const char *p; 1307 - 1308 - if (!prop) 1309 - return -EINVAL; 1310 - if (!prop->value) 1311 - return -ENODATA; 1312 - if (strnlen(prop->value, prop->length) >= prop->length) 1313 - return -EILSEQ; 1314 - 1315 - p = prop->value; 1316 - 1317 - for (i = 0; total < prop->length; total += l, p += l) { 1318 - l = strlen(p) + 1; 1319 - if (i++ == index) { 1320 - *output = p; 1321 - return 0; 1322 - } 1323 - } 1324 - return -ENODATA; 1325 - } 1326 - EXPORT_SYMBOL_GPL(of_property_read_string_index); 1327 - 1328 - /** 1329 1283 * of_property_match_string() - Find string in a list and return index 1330 1284 * @np: pointer to node containing string list property 1331 1285 * @propname: string list property name ··· 1305 1351 end = p + prop->length; 1306 1352 1307 1353 for (i = 0; p < end; i++, p += l) { 1308 - l = strlen(p) + 1; 1354 + l = strnlen(p, end - p) + 1; 1309 1355 if (p + l > end) 1310 1356 return -EILSEQ; 1311 1357 pr_debug("comparing %s with %s\n", string, p); ··· 1317 1363 EXPORT_SYMBOL_GPL(of_property_match_string); 1318 1364 1319 1365 /** 1320 - * of_property_count_strings - Find and return the number of strings from a 1321 - * multiple strings property. 1366 + * of_property_read_string_util() - Utility helper for parsing string properties 1322 1367 * @np: device node from which the property value is to be read. 1323 1368 * @propname: name of the property to be searched. 1369 + * @out_strs: output array of string pointers. 1370 + * @sz: number of array elements to read. 1371 + * @skip: Number of strings to skip over at beginning of list. 1324 1372 * 1325 - * Search for a property in a device tree node and retrieve the number of null 1326 - * terminated string contain in it. Returns the number of strings on 1327 - * success, -EINVAL if the property does not exist, -ENODATA if property 1328 - * does not have a value, and -EILSEQ if the string is not null-terminated 1329 - * within the length of the property data. 1373 + * Don't call this function directly. It is a utility helper for the 1374 + * of_property_read_string*() family of functions. 1330 1375 */ 1331 - int of_property_count_strings(struct device_node *np, const char *propname) 1376 + int of_property_read_string_helper(struct device_node *np, const char *propname, 1377 + const char **out_strs, size_t sz, int skip) 1332 1378 { 1333 1379 struct property *prop = of_find_property(np, propname, NULL); 1334 - int i = 0; 1335 - size_t l = 0, total = 0; 1336 - const char *p; 1380 + int l = 0, i = 0; 1381 + const char *p, *end; 1337 1382 1338 1383 if (!prop) 1339 1384 return -EINVAL; 1340 1385 if (!prop->value) 1341 1386 return -ENODATA; 1342 - if (strnlen(prop->value, prop->length) >= prop->length) 1343 - return -EILSEQ; 1344 - 1345 1387 p = prop->value; 1388 + end = p + prop->length; 1346 1389 1347 - for (i = 0; total < prop->length; total += l, p += l, i++) 1348 - l = strlen(p) + 1; 1349 - 1350 - return i; 1390 + for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 1391 + l = strnlen(p, end - p) + 1; 1392 + if (p + l > end) 1393 + return -EILSEQ; 1394 + if (out_strs && i >= skip) 1395 + *out_strs++ = p; 1396 + } 1397 + i -= skip; 1398 + return i <= 0 ? -ENODATA : i; 1351 1399 } 1352 - EXPORT_SYMBOL_GPL(of_property_count_strings); 1400 + EXPORT_SYMBOL_GPL(of_property_read_string_helper); 1353 1401 1354 1402 void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1355 1403 {
+60 -6
drivers/of/selftest.c
··· 339 339 selftest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); 340 340 } 341 341 342 - static void __init of_selftest_property_match_string(void) 342 + static void __init of_selftest_property_string(void) 343 343 { 344 + const char *strings[4]; 344 345 struct device_node *np; 345 346 int rc; 346 347 ··· 358 357 rc = of_property_match_string(np, "phandle-list-names", "third"); 359 358 selftest(rc == 2, "third expected:0 got:%i\n", rc); 360 359 rc = of_property_match_string(np, "phandle-list-names", "fourth"); 361 - selftest(rc == -ENODATA, "unmatched string; rc=%i", rc); 360 + selftest(rc == -ENODATA, "unmatched string; rc=%i\n", rc); 362 361 rc = of_property_match_string(np, "missing-property", "blah"); 363 - selftest(rc == -EINVAL, "missing property; rc=%i", rc); 362 + selftest(rc == -EINVAL, "missing property; rc=%i\n", rc); 364 363 rc = of_property_match_string(np, "empty-property", "blah"); 365 - selftest(rc == -ENODATA, "empty property; rc=%i", rc); 364 + selftest(rc == -ENODATA, "empty property; rc=%i\n", rc); 366 365 rc = of_property_match_string(np, "unterminated-string", "blah"); 367 - selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc); 366 + selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); 367 + 368 + /* of_property_count_strings() tests */ 369 + rc = of_property_count_strings(np, "string-property"); 370 + selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); 371 + rc = of_property_count_strings(np, "phandle-list-names"); 372 + selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); 373 + rc = of_property_count_strings(np, "unterminated-string"); 374 + selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); 375 + rc = of_property_count_strings(np, "unterminated-string-list"); 376 + selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); 377 + 378 + /* of_property_read_string_index() tests */ 379 + rc = of_property_read_string_index(np, "string-property", 0, strings); 380 + selftest(rc == 0 && !strcmp(strings[0], "foobar"), "of_property_read_string_index() failure; rc=%i\n", rc); 381 + strings[0] = NULL; 382 + rc = of_property_read_string_index(np, "string-property", 1, strings); 383 + selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); 384 + rc = of_property_read_string_index(np, "phandle-list-names", 0, strings); 385 + selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); 386 + rc = of_property_read_string_index(np, "phandle-list-names", 1, strings); 387 + selftest(rc == 0 && !strcmp(strings[0], "second"), "of_property_read_string_index() failure; rc=%i\n", rc); 388 + rc = of_property_read_string_index(np, "phandle-list-names", 2, strings); 389 + selftest(rc == 0 && !strcmp(strings[0], "third"), "of_property_read_string_index() failure; rc=%i\n", rc); 390 + strings[0] = NULL; 391 + rc = of_property_read_string_index(np, "phandle-list-names", 3, strings); 392 + selftest(rc == -ENODATA && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); 393 + strings[0] = NULL; 394 + rc = of_property_read_string_index(np, "unterminated-string", 0, strings); 395 + selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); 396 + rc = of_property_read_string_index(np, "unterminated-string-list", 0, strings); 397 + selftest(rc == 0 && !strcmp(strings[0], "first"), "of_property_read_string_index() failure; rc=%i\n", rc); 398 + strings[0] = NULL; 399 + rc = of_property_read_string_index(np, "unterminated-string-list", 2, strings); /* should fail */ 400 + selftest(rc == -EILSEQ && strings[0] == NULL, "of_property_read_string_index() failure; rc=%i\n", rc); 401 + strings[1] = NULL; 402 + 403 + /* of_property_read_string_array() tests */ 404 + rc = of_property_read_string_array(np, "string-property", strings, 4); 405 + selftest(rc == 1, "Incorrect string count; rc=%i\n", rc); 406 + rc = of_property_read_string_array(np, "phandle-list-names", strings, 4); 407 + selftest(rc == 3, "Incorrect string count; rc=%i\n", rc); 408 + rc = of_property_read_string_array(np, "unterminated-string", strings, 4); 409 + selftest(rc == -EILSEQ, "unterminated string; rc=%i\n", rc); 410 + /* -- An incorrectly formed string should cause a failure */ 411 + rc = of_property_read_string_array(np, "unterminated-string-list", strings, 4); 412 + selftest(rc == -EILSEQ, "unterminated string array; rc=%i\n", rc); 413 + /* -- parsing the correctly formed strings should still work: */ 414 + strings[2] = NULL; 415 + rc = of_property_read_string_array(np, "unterminated-string-list", strings, 2); 416 + selftest(rc == 2 && strings[2] == NULL, "of_property_read_string_array() failure; rc=%i\n", rc); 417 + strings[1] = NULL; 418 + rc = of_property_read_string_array(np, "phandle-list-names", strings, 1); 419 + selftest(rc == 1 && strings[1] == NULL, "Overwrote end of string array; rc=%i, str='%s'\n", rc, strings[1]); 368 420 } 369 421 370 422 #define propcmp(p1, p2) (((p1)->length == (p2)->length) && \ ··· 935 881 of_selftest_find_node_by_name(); 936 882 of_selftest_dynamic(); 937 883 of_selftest_parse_phandle_with_args(); 938 - of_selftest_property_match_string(); 884 + of_selftest_property_string(); 939 885 of_selftest_property_copy(); 940 886 of_selftest_changeset(); 941 887 of_selftest_parse_interrupts();
+2
drivers/of/testcase-data/tests-phandle.dtsi
··· 39 39 phandle-list-bad-args = <&provider2 1 0>, 40 40 <&provider3 0>; 41 41 empty-property; 42 + string-property = "foobar"; 42 43 unterminated-string = [40 41 42 43]; 44 + unterminated-string-list = "first", "second", [40 41 42 43]; 43 45 }; 44 46 }; 45 47 };
+70 -14
include/linux/of.h
··· 267 267 extern int of_property_read_string(struct device_node *np, 268 268 const char *propname, 269 269 const char **out_string); 270 - extern int of_property_read_string_index(struct device_node *np, 271 - const char *propname, 272 - int index, const char **output); 273 270 extern int of_property_match_string(struct device_node *np, 274 271 const char *propname, 275 272 const char *string); 276 - extern int of_property_count_strings(struct device_node *np, 277 - const char *propname); 273 + extern int of_property_read_string_helper(struct device_node *np, 274 + const char *propname, 275 + const char **out_strs, size_t sz, int index); 278 276 extern int of_device_is_compatible(const struct device_node *device, 279 277 const char *); 280 278 extern int of_device_is_available(const struct device_node *device); ··· 484 486 return -ENOSYS; 485 487 } 486 488 487 - static inline int of_property_read_string_index(struct device_node *np, 488 - const char *propname, int index, 489 - const char **out_string) 490 - { 491 - return -ENOSYS; 492 - } 493 - 494 - static inline int of_property_count_strings(struct device_node *np, 495 - const char *propname) 489 + static inline int of_property_read_string_helper(struct device_node *np, 490 + const char *propname, 491 + const char **out_strs, size_t sz, int index) 496 492 { 497 493 return -ENOSYS; 498 494 } ··· 657 665 const char *propname) 658 666 { 659 667 return of_property_count_elems_of_size(np, propname, sizeof(u64)); 668 + } 669 + 670 + /** 671 + * of_property_read_string_array() - Read an array of strings from a multiple 672 + * strings property. 673 + * @np: device node from which the property value is to be read. 674 + * @propname: name of the property to be searched. 675 + * @out_strs: output array of string pointers. 676 + * @sz: number of array elements to read. 677 + * 678 + * Search for a property in a device tree node and retrieve a list of 679 + * terminated string values (pointer to data, not a copy) in that property. 680 + * 681 + * If @out_strs is NULL, the number of strings in the property is returned. 682 + */ 683 + static inline int of_property_read_string_array(struct device_node *np, 684 + const char *propname, const char **out_strs, 685 + size_t sz) 686 + { 687 + return of_property_read_string_helper(np, propname, out_strs, sz, 0); 688 + } 689 + 690 + /** 691 + * of_property_count_strings() - Find and return the number of strings from a 692 + * multiple strings property. 693 + * @np: device node from which the property value is to be read. 694 + * @propname: name of the property to be searched. 695 + * 696 + * Search for a property in a device tree node and retrieve the number of null 697 + * terminated string contain in it. Returns the number of strings on 698 + * success, -EINVAL if the property does not exist, -ENODATA if property 699 + * does not have a value, and -EILSEQ if the string is not null-terminated 700 + * within the length of the property data. 701 + */ 702 + static inline int of_property_count_strings(struct device_node *np, 703 + const char *propname) 704 + { 705 + return of_property_read_string_helper(np, propname, NULL, 0, 0); 706 + } 707 + 708 + /** 709 + * of_property_read_string_index() - Find and read a string from a multiple 710 + * strings property. 711 + * @np: device node from which the property value is to be read. 712 + * @propname: name of the property to be searched. 713 + * @index: index of the string in the list of strings 714 + * @out_string: pointer to null terminated return string, modified only if 715 + * return value is 0. 716 + * 717 + * Search for a property in a device tree node and retrieve a null 718 + * terminated string value (pointer to data, not a copy) in the list of strings 719 + * contained in that property. 720 + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if 721 + * property does not have a value, and -EILSEQ if the string is not 722 + * null-terminated within the length of the property data. 723 + * 724 + * The out_string pointer is modified only if a valid string can be decoded. 725 + */ 726 + static inline int of_property_read_string_index(struct device_node *np, 727 + const char *propname, 728 + int index, const char **output) 729 + { 730 + int rc = of_property_read_string_helper(np, propname, output, 1, index); 731 + return rc < 0 ? rc : 0; 660 732 } 661 733 662 734 /**