diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 1 | ||||
| -rw-r--r-- | lib/bitmap.c | 50 | ||||
| -rw-r--r-- | lib/kstrtox.c | 6 | ||||
| -rw-r--r-- | lib/strncpy_from_user.c | 2 |
4 files changed, 50 insertions, 9 deletions
diff --git a/lib/Makefile b/lib/Makefile index f3ca8c0ab634..50144a3aeebd 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
| @@ -180,6 +180,7 @@ obj-$(CONFIG_IRQ_POLL) += irq_poll.o | |||
| 180 | 180 | ||
| 181 | obj-$(CONFIG_STACKDEPOT) += stackdepot.o | 181 | obj-$(CONFIG_STACKDEPOT) += stackdepot.o |
| 182 | KASAN_SANITIZE_stackdepot.o := n | 182 | KASAN_SANITIZE_stackdepot.o := n |
| 183 | KCOV_INSTRUMENT_stackdepot.o := n | ||
| 183 | 184 | ||
| 184 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ | 185 | libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ |
| 185 | fdt_empty_tree.o | 186 | fdt_empty_tree.o |
diff --git a/lib/bitmap.c b/lib/bitmap.c index eca88087fa8a..0b66f0e5eb6b 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c | |||
| @@ -496,6 +496,11 @@ EXPORT_SYMBOL(bitmap_print_to_pagebuf); | |||
| 496 | * ranges. Consecutively set bits are shown as two hyphen-separated | 496 | * ranges. Consecutively set bits are shown as two hyphen-separated |
| 497 | * decimal numbers, the smallest and largest bit numbers set in | 497 | * decimal numbers, the smallest and largest bit numbers set in |
| 498 | * the range. | 498 | * the range. |
| 499 | * Optionally each range can be postfixed to denote that only parts of it | ||
| 500 | * should be set. The range will divided to groups of specific size. | ||
| 501 | * From each group will be used only defined amount of bits. | ||
| 502 | * Syntax: range:used_size/group_size | ||
| 503 | * Example: 0-1023:2/256 ==> 0,1,256,257,512,513,768,769 | ||
| 499 | * | 504 | * |
| 500 | * Returns 0 on success, -errno on invalid input strings. | 505 | * Returns 0 on success, -errno on invalid input strings. |
| 501 | * Error values: | 506 | * Error values: |
| @@ -507,16 +512,20 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, | |||
| 507 | int is_user, unsigned long *maskp, | 512 | int is_user, unsigned long *maskp, |
| 508 | int nmaskbits) | 513 | int nmaskbits) |
| 509 | { | 514 | { |
| 510 | unsigned a, b; | 515 | unsigned int a, b, old_a, old_b; |
| 516 | unsigned int group_size, used_size; | ||
| 511 | int c, old_c, totaldigits, ndigits; | 517 | int c, old_c, totaldigits, ndigits; |
| 512 | const char __user __force *ubuf = (const char __user __force *)buf; | 518 | const char __user __force *ubuf = (const char __user __force *)buf; |
| 513 | int at_start, in_range; | 519 | int at_start, in_range, in_partial_range; |
| 514 | 520 | ||
| 515 | totaldigits = c = 0; | 521 | totaldigits = c = 0; |
| 522 | old_a = old_b = 0; | ||
| 523 | group_size = used_size = 0; | ||
| 516 | bitmap_zero(maskp, nmaskbits); | 524 | bitmap_zero(maskp, nmaskbits); |
| 517 | do { | 525 | do { |
| 518 | at_start = 1; | 526 | at_start = 1; |
| 519 | in_range = 0; | 527 | in_range = 0; |
| 528 | in_partial_range = 0; | ||
| 520 | a = b = 0; | 529 | a = b = 0; |
| 521 | ndigits = totaldigits; | 530 | ndigits = totaldigits; |
| 522 | 531 | ||
| @@ -547,6 +556,24 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, | |||
| 547 | if ((totaldigits != ndigits) && isspace(old_c)) | 556 | if ((totaldigits != ndigits) && isspace(old_c)) |
| 548 | return -EINVAL; | 557 | return -EINVAL; |
| 549 | 558 | ||
| 559 | if (c == '/') { | ||
| 560 | used_size = a; | ||
| 561 | at_start = 1; | ||
| 562 | in_range = 0; | ||
| 563 | a = b = 0; | ||
| 564 | continue; | ||
| 565 | } | ||
| 566 | |||
| 567 | if (c == ':') { | ||
| 568 | old_a = a; | ||
| 569 | old_b = b; | ||
| 570 | at_start = 1; | ||
| 571 | in_range = 0; | ||
| 572 | in_partial_range = 1; | ||
| 573 | a = b = 0; | ||
| 574 | continue; | ||
| 575 | } | ||
| 576 | |||
| 550 | if (c == '-') { | 577 | if (c == '-') { |
| 551 | if (at_start || in_range) | 578 | if (at_start || in_range) |
| 552 | return -EINVAL; | 579 | return -EINVAL; |
| @@ -567,15 +594,30 @@ static int __bitmap_parselist(const char *buf, unsigned int buflen, | |||
| 567 | } | 594 | } |
| 568 | if (ndigits == totaldigits) | 595 | if (ndigits == totaldigits) |
| 569 | continue; | 596 | continue; |
| 597 | if (in_partial_range) { | ||
| 598 | group_size = a; | ||
| 599 | a = old_a; | ||
| 600 | b = old_b; | ||
| 601 | old_a = old_b = 0; | ||
| 602 | } | ||
| 570 | /* if no digit is after '-', it's wrong*/ | 603 | /* if no digit is after '-', it's wrong*/ |
| 571 | if (at_start && in_range) | 604 | if (at_start && in_range) |
| 572 | return -EINVAL; | 605 | return -EINVAL; |
| 573 | if (!(a <= b)) | 606 | if (!(a <= b) || !(used_size <= group_size)) |
| 574 | return -EINVAL; | 607 | return -EINVAL; |
| 575 | if (b >= nmaskbits) | 608 | if (b >= nmaskbits) |
| 576 | return -ERANGE; | 609 | return -ERANGE; |
| 577 | while (a <= b) { | 610 | while (a <= b) { |
| 578 | set_bit(a, maskp); | 611 | if (in_partial_range) { |
| 612 | static int pos_in_group = 1; | ||
| 613 | |||
| 614 | if (pos_in_group <= used_size) | ||
| 615 | set_bit(a, maskp); | ||
| 616 | |||
| 617 | if (a == b || ++pos_in_group > group_size) | ||
| 618 | pos_in_group = 1; | ||
| 619 | } else | ||
| 620 | set_bit(a, maskp); | ||
| 579 | a++; | 621 | a++; |
| 580 | } | 622 | } |
| 581 | } while (buflen && c == ','); | 623 | } while (buflen && c == ','); |
diff --git a/lib/kstrtox.c b/lib/kstrtox.c index d8a5cf66c316..b8e2080c1a47 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c | |||
| @@ -48,11 +48,9 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long | |||
| 48 | { | 48 | { |
| 49 | unsigned long long res; | 49 | unsigned long long res; |
| 50 | unsigned int rv; | 50 | unsigned int rv; |
| 51 | int overflow; | ||
| 52 | 51 | ||
| 53 | res = 0; | 52 | res = 0; |
| 54 | rv = 0; | 53 | rv = 0; |
| 55 | overflow = 0; | ||
| 56 | while (*s) { | 54 | while (*s) { |
| 57 | unsigned int val; | 55 | unsigned int val; |
| 58 | 56 | ||
| @@ -71,15 +69,13 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long | |||
| 71 | */ | 69 | */ |
| 72 | if (unlikely(res & (~0ull << 60))) { | 70 | if (unlikely(res & (~0ull << 60))) { |
| 73 | if (res > div_u64(ULLONG_MAX - val, base)) | 71 | if (res > div_u64(ULLONG_MAX - val, base)) |
| 74 | overflow = 1; | 72 | rv |= KSTRTOX_OVERFLOW; |
| 75 | } | 73 | } |
| 76 | res = res * base + val; | 74 | res = res * base + val; |
| 77 | rv++; | 75 | rv++; |
| 78 | s++; | 76 | s++; |
| 79 | } | 77 | } |
| 80 | *p = res; | 78 | *p = res; |
| 81 | if (overflow) | ||
| 82 | rv |= KSTRTOX_OVERFLOW; | ||
| 83 | return rv; | 79 | return rv; |
| 84 | } | 80 | } |
| 85 | 81 | ||
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index 9c5fe8110413..7e35fc450c5b 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <linux/compiler.h> | 1 | #include <linux/compiler.h> |
| 2 | #include <linux/export.h> | 2 | #include <linux/export.h> |
| 3 | #include <linux/kasan-checks.h> | 3 | #include <linux/kasan-checks.h> |
| 4 | #include <linux/thread_info.h> | ||
| 4 | #include <linux/uaccess.h> | 5 | #include <linux/uaccess.h> |
| 5 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 6 | #include <linux/errno.h> | 7 | #include <linux/errno.h> |
| @@ -111,6 +112,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count) | |||
| 111 | long retval; | 112 | long retval; |
| 112 | 113 | ||
| 113 | kasan_check_write(dst, count); | 114 | kasan_check_write(dst, count); |
| 115 | check_object_size(dst, count, false); | ||
| 114 | user_access_begin(); | 116 | user_access_begin(); |
| 115 | retval = do_strncpy_from_user(dst, src, count, max); | 117 | retval = do_strncpy_from_user(dst, src, count, max); |
| 116 | user_access_end(); | 118 | user_access_end(); |
