diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 428 |
1 files changed, 268 insertions, 160 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 791b6fa36905..2f003cfe340e 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -593,15 +593,13 @@ char *widen_string(char *buf, int n, char *end, struct printf_spec spec) | |||
593 | return buf; | 593 | return buf; |
594 | } | 594 | } |
595 | 595 | ||
596 | static noinline_for_stack | 596 | /* Handle string from a well known address. */ |
597 | char *string(char *buf, char *end, const char *s, struct printf_spec spec) | 597 | static char *string_nocheck(char *buf, char *end, const char *s, |
598 | struct printf_spec spec) | ||
598 | { | 599 | { |
599 | int len = 0; | 600 | int len = 0; |
600 | size_t lim = spec.precision; | 601 | size_t lim = spec.precision; |
601 | 602 | ||
602 | if ((unsigned long)s < PAGE_SIZE) | ||
603 | s = "(null)"; | ||
604 | |||
605 | while (lim--) { | 603 | while (lim--) { |
606 | char c = *s++; | 604 | char c = *s++; |
607 | if (!c) | 605 | if (!c) |
@@ -614,9 +612,64 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec) | |||
614 | return widen_string(buf, len, end, spec); | 612 | return widen_string(buf, len, end, spec); |
615 | } | 613 | } |
616 | 614 | ||
615 | /* Be careful: error messages must fit into the given buffer. */ | ||
616 | static char *error_string(char *buf, char *end, const char *s, | ||
617 | struct printf_spec spec) | ||
618 | { | ||
619 | /* | ||
620 | * Hard limit to avoid a completely insane messages. It actually | ||
621 | * works pretty well because most error messages are in | ||
622 | * the many pointer format modifiers. | ||
623 | */ | ||
624 | if (spec.precision == -1) | ||
625 | spec.precision = 2 * sizeof(void *); | ||
626 | |||
627 | return string_nocheck(buf, end, s, spec); | ||
628 | } | ||
629 | |||
630 | /* | ||
631 | * Do not call any complex external code here. Nested printk()/vsprintf() | ||
632 | * might cause infinite loops. Failures might break printk() and would | ||
633 | * be hard to debug. | ||
634 | */ | ||
635 | static const char *check_pointer_msg(const void *ptr) | ||
636 | { | ||
637 | if (!ptr) | ||
638 | return "(null)"; | ||
639 | |||
640 | if ((unsigned long)ptr < PAGE_SIZE || IS_ERR_VALUE(ptr)) | ||
641 | return "(efault)"; | ||
642 | |||
643 | return NULL; | ||
644 | } | ||
645 | |||
646 | static int check_pointer(char **buf, char *end, const void *ptr, | ||
647 | struct printf_spec spec) | ||
648 | { | ||
649 | const char *err_msg; | ||
650 | |||
651 | err_msg = check_pointer_msg(ptr); | ||
652 | if (err_msg) { | ||
653 | *buf = error_string(*buf, end, err_msg, spec); | ||
654 | return -EFAULT; | ||
655 | } | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
617 | static noinline_for_stack | 660 | static noinline_for_stack |
618 | char *pointer_string(char *buf, char *end, const void *ptr, | 661 | char *string(char *buf, char *end, const char *s, |
619 | struct printf_spec spec) | 662 | struct printf_spec spec) |
663 | { | ||
664 | if (check_pointer(&buf, end, s, spec)) | ||
665 | return buf; | ||
666 | |||
667 | return string_nocheck(buf, end, s, spec); | ||
668 | } | ||
669 | |||
670 | static char *pointer_string(char *buf, char *end, | ||
671 | const void *ptr, | ||
672 | struct printf_spec spec) | ||
620 | { | 673 | { |
621 | spec.base = 16; | 674 | spec.base = 16; |
622 | spec.flags |= SMALL; | 675 | spec.flags |= SMALL; |
@@ -701,7 +754,7 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr, | |||
701 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { | 754 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { |
702 | spec.field_width = 2 * sizeof(ptr); | 755 | spec.field_width = 2 * sizeof(ptr); |
703 | /* string length must be less than default_width */ | 756 | /* string length must be less than default_width */ |
704 | return string(buf, end, str, spec); | 757 | return error_string(buf, end, str, spec); |
705 | } | 758 | } |
706 | 759 | ||
707 | #ifdef CONFIG_64BIT | 760 | #ifdef CONFIG_64BIT |
@@ -717,6 +770,55 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr, | |||
717 | return pointer_string(buf, end, (const void *)hashval, spec); | 770 | return pointer_string(buf, end, (const void *)hashval, spec); |
718 | } | 771 | } |
719 | 772 | ||
773 | int kptr_restrict __read_mostly; | ||
774 | |||
775 | static noinline_for_stack | ||
776 | char *restricted_pointer(char *buf, char *end, const void *ptr, | ||
777 | struct printf_spec spec) | ||
778 | { | ||
779 | switch (kptr_restrict) { | ||
780 | case 0: | ||
781 | /* Handle as %p, hash and do _not_ leak addresses. */ | ||
782 | return ptr_to_id(buf, end, ptr, spec); | ||
783 | case 1: { | ||
784 | const struct cred *cred; | ||
785 | |||
786 | /* | ||
787 | * kptr_restrict==1 cannot be used in IRQ context | ||
788 | * because its test for CAP_SYSLOG would be meaningless. | ||
789 | */ | ||
790 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
791 | if (spec.field_width == -1) | ||
792 | spec.field_width = 2 * sizeof(ptr); | ||
793 | return error_string(buf, end, "pK-error", spec); | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * Only print the real pointer value if the current | ||
798 | * process has CAP_SYSLOG and is running with the | ||
799 | * same credentials it started with. This is because | ||
800 | * access to files is checked at open() time, but %pK | ||
801 | * checks permission at read() time. We don't want to | ||
802 | * leak pointer values if a binary opens a file using | ||
803 | * %pK and then elevates privileges before reading it. | ||
804 | */ | ||
805 | cred = current_cred(); | ||
806 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
807 | !uid_eq(cred->euid, cred->uid) || | ||
808 | !gid_eq(cred->egid, cred->gid)) | ||
809 | ptr = NULL; | ||
810 | break; | ||
811 | } | ||
812 | case 2: | ||
813 | default: | ||
814 | /* Always print 0's for %pK */ | ||
815 | ptr = NULL; | ||
816 | break; | ||
817 | } | ||
818 | |||
819 | return pointer_string(buf, end, ptr, spec); | ||
820 | } | ||
821 | |||
720 | static noinline_for_stack | 822 | static noinline_for_stack |
721 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, | 823 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, |
722 | const char *fmt) | 824 | const char *fmt) |
@@ -736,6 +838,11 @@ char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_sp | |||
736 | 838 | ||
737 | rcu_read_lock(); | 839 | rcu_read_lock(); |
738 | for (i = 0; i < depth; i++, d = p) { | 840 | for (i = 0; i < depth; i++, d = p) { |
841 | if (check_pointer(&buf, end, d, spec)) { | ||
842 | rcu_read_unlock(); | ||
843 | return buf; | ||
844 | } | ||
845 | |||
739 | p = READ_ONCE(d->d_parent); | 846 | p = READ_ONCE(d->d_parent); |
740 | array[i] = READ_ONCE(d->d_name.name); | 847 | array[i] = READ_ONCE(d->d_name.name); |
741 | if (p == d) { | 848 | if (p == d) { |
@@ -766,8 +873,12 @@ static noinline_for_stack | |||
766 | char *bdev_name(char *buf, char *end, struct block_device *bdev, | 873 | char *bdev_name(char *buf, char *end, struct block_device *bdev, |
767 | struct printf_spec spec, const char *fmt) | 874 | struct printf_spec spec, const char *fmt) |
768 | { | 875 | { |
769 | struct gendisk *hd = bdev->bd_disk; | 876 | struct gendisk *hd; |
770 | 877 | ||
878 | if (check_pointer(&buf, end, bdev, spec)) | ||
879 | return buf; | ||
880 | |||
881 | hd = bdev->bd_disk; | ||
771 | buf = string(buf, end, hd->disk_name, spec); | 882 | buf = string(buf, end, hd->disk_name, spec); |
772 | if (bdev->bd_part->partno) { | 883 | if (bdev->bd_part->partno) { |
773 | if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) { | 884 | if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) { |
@@ -802,7 +913,7 @@ char *symbol_string(char *buf, char *end, void *ptr, | |||
802 | else | 913 | else |
803 | sprint_symbol_no_offset(sym, value); | 914 | sprint_symbol_no_offset(sym, value); |
804 | 915 | ||
805 | return string(buf, end, sym, spec); | 916 | return string_nocheck(buf, end, sym, spec); |
806 | #else | 917 | #else |
807 | return special_hex_number(buf, end, value, sizeof(void *)); | 918 | return special_hex_number(buf, end, value, sizeof(void *)); |
808 | #endif | 919 | #endif |
@@ -886,29 +997,32 @@ char *resource_string(char *buf, char *end, struct resource *res, | |||
886 | int decode = (fmt[0] == 'R') ? 1 : 0; | 997 | int decode = (fmt[0] == 'R') ? 1 : 0; |
887 | const struct printf_spec *specp; | 998 | const struct printf_spec *specp; |
888 | 999 | ||
1000 | if (check_pointer(&buf, end, res, spec)) | ||
1001 | return buf; | ||
1002 | |||
889 | *p++ = '['; | 1003 | *p++ = '['; |
890 | if (res->flags & IORESOURCE_IO) { | 1004 | if (res->flags & IORESOURCE_IO) { |
891 | p = string(p, pend, "io ", str_spec); | 1005 | p = string_nocheck(p, pend, "io ", str_spec); |
892 | specp = &io_spec; | 1006 | specp = &io_spec; |
893 | } else if (res->flags & IORESOURCE_MEM) { | 1007 | } else if (res->flags & IORESOURCE_MEM) { |
894 | p = string(p, pend, "mem ", str_spec); | 1008 | p = string_nocheck(p, pend, "mem ", str_spec); |
895 | specp = &mem_spec; | 1009 | specp = &mem_spec; |
896 | } else if (res->flags & IORESOURCE_IRQ) { | 1010 | } else if (res->flags & IORESOURCE_IRQ) { |
897 | p = string(p, pend, "irq ", str_spec); | 1011 | p = string_nocheck(p, pend, "irq ", str_spec); |
898 | specp = &default_dec_spec; | 1012 | specp = &default_dec_spec; |
899 | } else if (res->flags & IORESOURCE_DMA) { | 1013 | } else if (res->flags & IORESOURCE_DMA) { |
900 | p = string(p, pend, "dma ", str_spec); | 1014 | p = string_nocheck(p, pend, "dma ", str_spec); |
901 | specp = &default_dec_spec; | 1015 | specp = &default_dec_spec; |
902 | } else if (res->flags & IORESOURCE_BUS) { | 1016 | } else if (res->flags & IORESOURCE_BUS) { |
903 | p = string(p, pend, "bus ", str_spec); | 1017 | p = string_nocheck(p, pend, "bus ", str_spec); |
904 | specp = &bus_spec; | 1018 | specp = &bus_spec; |
905 | } else { | 1019 | } else { |
906 | p = string(p, pend, "??? ", str_spec); | 1020 | p = string_nocheck(p, pend, "??? ", str_spec); |
907 | specp = &mem_spec; | 1021 | specp = &mem_spec; |
908 | decode = 0; | 1022 | decode = 0; |
909 | } | 1023 | } |
910 | if (decode && res->flags & IORESOURCE_UNSET) { | 1024 | if (decode && res->flags & IORESOURCE_UNSET) { |
911 | p = string(p, pend, "size ", str_spec); | 1025 | p = string_nocheck(p, pend, "size ", str_spec); |
912 | p = number(p, pend, resource_size(res), *specp); | 1026 | p = number(p, pend, resource_size(res), *specp); |
913 | } else { | 1027 | } else { |
914 | p = number(p, pend, res->start, *specp); | 1028 | p = number(p, pend, res->start, *specp); |
@@ -919,21 +1033,21 @@ char *resource_string(char *buf, char *end, struct resource *res, | |||
919 | } | 1033 | } |
920 | if (decode) { | 1034 | if (decode) { |
921 | if (res->flags & IORESOURCE_MEM_64) | 1035 | if (res->flags & IORESOURCE_MEM_64) |
922 | p = string(p, pend, " 64bit", str_spec); | 1036 | p = string_nocheck(p, pend, " 64bit", str_spec); |
923 | if (res->flags & IORESOURCE_PREFETCH) | 1037 | if (res->flags & IORESOURCE_PREFETCH) |
924 | p = string(p, pend, " pref", str_spec); | 1038 | p = string_nocheck(p, pend, " pref", str_spec); |
925 | if (res->flags & IORESOURCE_WINDOW) | 1039 | if (res->flags & IORESOURCE_WINDOW) |
926 | p = string(p, pend, " window", str_spec); | 1040 | p = string_nocheck(p, pend, " window", str_spec); |
927 | if (res->flags & IORESOURCE_DISABLED) | 1041 | if (res->flags & IORESOURCE_DISABLED) |
928 | p = string(p, pend, " disabled", str_spec); | 1042 | p = string_nocheck(p, pend, " disabled", str_spec); |
929 | } else { | 1043 | } else { |
930 | p = string(p, pend, " flags ", str_spec); | 1044 | p = string_nocheck(p, pend, " flags ", str_spec); |
931 | p = number(p, pend, res->flags, default_flag_spec); | 1045 | p = number(p, pend, res->flags, default_flag_spec); |
932 | } | 1046 | } |
933 | *p++ = ']'; | 1047 | *p++ = ']'; |
934 | *p = '\0'; | 1048 | *p = '\0'; |
935 | 1049 | ||
936 | return string(buf, end, sym, spec); | 1050 | return string_nocheck(buf, end, sym, spec); |
937 | } | 1051 | } |
938 | 1052 | ||
939 | static noinline_for_stack | 1053 | static noinline_for_stack |
@@ -948,9 +1062,8 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
948 | /* nothing to print */ | 1062 | /* nothing to print */ |
949 | return buf; | 1063 | return buf; |
950 | 1064 | ||
951 | if (ZERO_OR_NULL_PTR(addr)) | 1065 | if (check_pointer(&buf, end, addr, spec)) |
952 | /* NULL pointer */ | 1066 | return buf; |
953 | return string(buf, end, NULL, spec); | ||
954 | 1067 | ||
955 | switch (fmt[1]) { | 1068 | switch (fmt[1]) { |
956 | case 'C': | 1069 | case 'C': |
@@ -997,6 +1110,9 @@ char *bitmap_string(char *buf, char *end, unsigned long *bitmap, | |||
997 | int i, chunksz; | 1110 | int i, chunksz; |
998 | bool first = true; | 1111 | bool first = true; |
999 | 1112 | ||
1113 | if (check_pointer(&buf, end, bitmap, spec)) | ||
1114 | return buf; | ||
1115 | |||
1000 | /* reused to print numbers */ | 1116 | /* reused to print numbers */ |
1001 | spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 }; | 1117 | spec = (struct printf_spec){ .flags = SMALL | ZEROPAD, .base = 16 }; |
1002 | 1118 | ||
@@ -1038,6 +1154,9 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, | |||
1038 | int cur, rbot, rtop; | 1154 | int cur, rbot, rtop; |
1039 | bool first = true; | 1155 | bool first = true; |
1040 | 1156 | ||
1157 | if (check_pointer(&buf, end, bitmap, spec)) | ||
1158 | return buf; | ||
1159 | |||
1041 | rbot = cur = find_first_bit(bitmap, nr_bits); | 1160 | rbot = cur = find_first_bit(bitmap, nr_bits); |
1042 | while (cur < nr_bits) { | 1161 | while (cur < nr_bits) { |
1043 | rtop = cur; | 1162 | rtop = cur; |
@@ -1076,6 +1195,9 @@ char *mac_address_string(char *buf, char *end, u8 *addr, | |||
1076 | char separator; | 1195 | char separator; |
1077 | bool reversed = false; | 1196 | bool reversed = false; |
1078 | 1197 | ||
1198 | if (check_pointer(&buf, end, addr, spec)) | ||
1199 | return buf; | ||
1200 | |||
1079 | switch (fmt[1]) { | 1201 | switch (fmt[1]) { |
1080 | case 'F': | 1202 | case 'F': |
1081 | separator = '-'; | 1203 | separator = '-'; |
@@ -1101,7 +1223,7 @@ char *mac_address_string(char *buf, char *end, u8 *addr, | |||
1101 | } | 1223 | } |
1102 | *p = '\0'; | 1224 | *p = '\0'; |
1103 | 1225 | ||
1104 | return string(buf, end, mac_addr, spec); | 1226 | return string_nocheck(buf, end, mac_addr, spec); |
1105 | } | 1227 | } |
1106 | 1228 | ||
1107 | static noinline_for_stack | 1229 | static noinline_for_stack |
@@ -1264,7 +1386,7 @@ char *ip6_addr_string(char *buf, char *end, const u8 *addr, | |||
1264 | else | 1386 | else |
1265 | ip6_string(ip6_addr, addr, fmt); | 1387 | ip6_string(ip6_addr, addr, fmt); |
1266 | 1388 | ||
1267 | return string(buf, end, ip6_addr, spec); | 1389 | return string_nocheck(buf, end, ip6_addr, spec); |
1268 | } | 1390 | } |
1269 | 1391 | ||
1270 | static noinline_for_stack | 1392 | static noinline_for_stack |
@@ -1275,7 +1397,7 @@ char *ip4_addr_string(char *buf, char *end, const u8 *addr, | |||
1275 | 1397 | ||
1276 | ip4_string(ip4_addr, addr, fmt); | 1398 | ip4_string(ip4_addr, addr, fmt); |
1277 | 1399 | ||
1278 | return string(buf, end, ip4_addr, spec); | 1400 | return string_nocheck(buf, end, ip4_addr, spec); |
1279 | } | 1401 | } |
1280 | 1402 | ||
1281 | static noinline_for_stack | 1403 | static noinline_for_stack |
@@ -1337,7 +1459,7 @@ char *ip6_addr_string_sa(char *buf, char *end, const struct sockaddr_in6 *sa, | |||
1337 | } | 1459 | } |
1338 | *p = '\0'; | 1460 | *p = '\0'; |
1339 | 1461 | ||
1340 | return string(buf, end, ip6_addr, spec); | 1462 | return string_nocheck(buf, end, ip6_addr, spec); |
1341 | } | 1463 | } |
1342 | 1464 | ||
1343 | static noinline_for_stack | 1465 | static noinline_for_stack |
@@ -1372,7 +1494,42 @@ char *ip4_addr_string_sa(char *buf, char *end, const struct sockaddr_in *sa, | |||
1372 | } | 1494 | } |
1373 | *p = '\0'; | 1495 | *p = '\0'; |
1374 | 1496 | ||
1375 | return string(buf, end, ip4_addr, spec); | 1497 | return string_nocheck(buf, end, ip4_addr, spec); |
1498 | } | ||
1499 | |||
1500 | static noinline_for_stack | ||
1501 | char *ip_addr_string(char *buf, char *end, const void *ptr, | ||
1502 | struct printf_spec spec, const char *fmt) | ||
1503 | { | ||
1504 | char *err_fmt_msg; | ||
1505 | |||
1506 | if (check_pointer(&buf, end, ptr, spec)) | ||
1507 | return buf; | ||
1508 | |||
1509 | switch (fmt[1]) { | ||
1510 | case '6': | ||
1511 | return ip6_addr_string(buf, end, ptr, spec, fmt); | ||
1512 | case '4': | ||
1513 | return ip4_addr_string(buf, end, ptr, spec, fmt); | ||
1514 | case 'S': { | ||
1515 | const union { | ||
1516 | struct sockaddr raw; | ||
1517 | struct sockaddr_in v4; | ||
1518 | struct sockaddr_in6 v6; | ||
1519 | } *sa = ptr; | ||
1520 | |||
1521 | switch (sa->raw.sa_family) { | ||
1522 | case AF_INET: | ||
1523 | return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt); | ||
1524 | case AF_INET6: | ||
1525 | return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt); | ||
1526 | default: | ||
1527 | return error_string(buf, end, "(einval)", spec); | ||
1528 | }} | ||
1529 | } | ||
1530 | |||
1531 | err_fmt_msg = fmt[0] == 'i' ? "(%pi?)" : "(%pI?)"; | ||
1532 | return error_string(buf, end, err_fmt_msg, spec); | ||
1376 | } | 1533 | } |
1377 | 1534 | ||
1378 | static noinline_for_stack | 1535 | static noinline_for_stack |
@@ -1387,9 +1544,8 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
1387 | if (spec.field_width == 0) | 1544 | if (spec.field_width == 0) |
1388 | return buf; /* nothing to print */ | 1545 | return buf; /* nothing to print */ |
1389 | 1546 | ||
1390 | if (ZERO_OR_NULL_PTR(addr)) | 1547 | if (check_pointer(&buf, end, addr, spec)) |
1391 | return string(buf, end, NULL, spec); /* NULL pointer */ | 1548 | return buf; |
1392 | |||
1393 | 1549 | ||
1394 | do { | 1550 | do { |
1395 | switch (fmt[count++]) { | 1551 | switch (fmt[count++]) { |
@@ -1435,6 +1591,21 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
1435 | return buf; | 1591 | return buf; |
1436 | } | 1592 | } |
1437 | 1593 | ||
1594 | static char *va_format(char *buf, char *end, struct va_format *va_fmt, | ||
1595 | struct printf_spec spec, const char *fmt) | ||
1596 | { | ||
1597 | va_list va; | ||
1598 | |||
1599 | if (check_pointer(&buf, end, va_fmt, spec)) | ||
1600 | return buf; | ||
1601 | |||
1602 | va_copy(va, *va_fmt->va); | ||
1603 | buf += vsnprintf(buf, end > buf ? end - buf : 0, va_fmt->fmt, va); | ||
1604 | va_end(va); | ||
1605 | |||
1606 | return buf; | ||
1607 | } | ||
1608 | |||
1438 | static noinline_for_stack | 1609 | static noinline_for_stack |
1439 | char *uuid_string(char *buf, char *end, const u8 *addr, | 1610 | char *uuid_string(char *buf, char *end, const u8 *addr, |
1440 | struct printf_spec spec, const char *fmt) | 1611 | struct printf_spec spec, const char *fmt) |
@@ -1445,6 +1616,9 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
1445 | const u8 *index = uuid_index; | 1616 | const u8 *index = uuid_index; |
1446 | bool uc = false; | 1617 | bool uc = false; |
1447 | 1618 | ||
1619 | if (check_pointer(&buf, end, addr, spec)) | ||
1620 | return buf; | ||
1621 | |||
1448 | switch (*(++fmt)) { | 1622 | switch (*(++fmt)) { |
1449 | case 'L': | 1623 | case 'L': |
1450 | uc = true; /* fall-through */ | 1624 | uc = true; /* fall-through */ |
@@ -1473,56 +1647,7 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
1473 | 1647 | ||
1474 | *p = 0; | 1648 | *p = 0; |
1475 | 1649 | ||
1476 | return string(buf, end, uuid, spec); | 1650 | return string_nocheck(buf, end, uuid, spec); |
1477 | } | ||
1478 | |||
1479 | int kptr_restrict __read_mostly; | ||
1480 | |||
1481 | static noinline_for_stack | ||
1482 | char *restricted_pointer(char *buf, char *end, const void *ptr, | ||
1483 | struct printf_spec spec) | ||
1484 | { | ||
1485 | switch (kptr_restrict) { | ||
1486 | case 0: | ||
1487 | /* Always print %pK values */ | ||
1488 | break; | ||
1489 | case 1: { | ||
1490 | const struct cred *cred; | ||
1491 | |||
1492 | /* | ||
1493 | * kptr_restrict==1 cannot be used in IRQ context | ||
1494 | * because its test for CAP_SYSLOG would be meaningless. | ||
1495 | */ | ||
1496 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
1497 | if (spec.field_width == -1) | ||
1498 | spec.field_width = 2 * sizeof(ptr); | ||
1499 | return string(buf, end, "pK-error", spec); | ||
1500 | } | ||
1501 | |||
1502 | /* | ||
1503 | * Only print the real pointer value if the current | ||
1504 | * process has CAP_SYSLOG and is running with the | ||
1505 | * same credentials it started with. This is because | ||
1506 | * access to files is checked at open() time, but %pK | ||
1507 | * checks permission at read() time. We don't want to | ||
1508 | * leak pointer values if a binary opens a file using | ||
1509 | * %pK and then elevates privileges before reading it. | ||
1510 | */ | ||
1511 | cred = current_cred(); | ||
1512 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
1513 | !uid_eq(cred->euid, cred->uid) || | ||
1514 | !gid_eq(cred->egid, cred->gid)) | ||
1515 | ptr = NULL; | ||
1516 | break; | ||
1517 | } | ||
1518 | case 2: | ||
1519 | default: | ||
1520 | /* Always print 0's for %pK */ | ||
1521 | ptr = NULL; | ||
1522 | break; | ||
1523 | } | ||
1524 | |||
1525 | return pointer_string(buf, end, ptr, spec); | ||
1526 | } | 1651 | } |
1527 | 1652 | ||
1528 | static noinline_for_stack | 1653 | static noinline_for_stack |
@@ -1532,24 +1657,31 @@ char *netdev_bits(char *buf, char *end, const void *addr, | |||
1532 | unsigned long long num; | 1657 | unsigned long long num; |
1533 | int size; | 1658 | int size; |
1534 | 1659 | ||
1660 | if (check_pointer(&buf, end, addr, spec)) | ||
1661 | return buf; | ||
1662 | |||
1535 | switch (fmt[1]) { | 1663 | switch (fmt[1]) { |
1536 | case 'F': | 1664 | case 'F': |
1537 | num = *(const netdev_features_t *)addr; | 1665 | num = *(const netdev_features_t *)addr; |
1538 | size = sizeof(netdev_features_t); | 1666 | size = sizeof(netdev_features_t); |
1539 | break; | 1667 | break; |
1540 | default: | 1668 | default: |
1541 | return ptr_to_id(buf, end, addr, spec); | 1669 | return error_string(buf, end, "(%pN?)", spec); |
1542 | } | 1670 | } |
1543 | 1671 | ||
1544 | return special_hex_number(buf, end, num, size); | 1672 | return special_hex_number(buf, end, num, size); |
1545 | } | 1673 | } |
1546 | 1674 | ||
1547 | static noinline_for_stack | 1675 | static noinline_for_stack |
1548 | char *address_val(char *buf, char *end, const void *addr, const char *fmt) | 1676 | char *address_val(char *buf, char *end, const void *addr, |
1677 | struct printf_spec spec, const char *fmt) | ||
1549 | { | 1678 | { |
1550 | unsigned long long num; | 1679 | unsigned long long num; |
1551 | int size; | 1680 | int size; |
1552 | 1681 | ||
1682 | if (check_pointer(&buf, end, addr, spec)) | ||
1683 | return buf; | ||
1684 | |||
1553 | switch (fmt[1]) { | 1685 | switch (fmt[1]) { |
1554 | case 'd': | 1686 | case 'd': |
1555 | num = *(const dma_addr_t *)addr; | 1687 | num = *(const dma_addr_t *)addr; |
@@ -1601,12 +1733,16 @@ char *time_str(char *buf, char *end, const struct rtc_time *tm, bool r) | |||
1601 | } | 1733 | } |
1602 | 1734 | ||
1603 | static noinline_for_stack | 1735 | static noinline_for_stack |
1604 | char *rtc_str(char *buf, char *end, const struct rtc_time *tm, const char *fmt) | 1736 | char *rtc_str(char *buf, char *end, const struct rtc_time *tm, |
1737 | struct printf_spec spec, const char *fmt) | ||
1605 | { | 1738 | { |
1606 | bool have_t = true, have_d = true; | 1739 | bool have_t = true, have_d = true; |
1607 | bool raw = false; | 1740 | bool raw = false; |
1608 | int count = 2; | 1741 | int count = 2; |
1609 | 1742 | ||
1743 | if (check_pointer(&buf, end, tm, spec)) | ||
1744 | return buf; | ||
1745 | |||
1610 | switch (fmt[count]) { | 1746 | switch (fmt[count]) { |
1611 | case 'd': | 1747 | case 'd': |
1612 | have_t = false; | 1748 | have_t = false; |
@@ -1640,9 +1776,9 @@ char *time_and_date(char *buf, char *end, void *ptr, struct printf_spec spec, | |||
1640 | { | 1776 | { |
1641 | switch (fmt[1]) { | 1777 | switch (fmt[1]) { |
1642 | case 'R': | 1778 | case 'R': |
1643 | return rtc_str(buf, end, (const struct rtc_time *)ptr, fmt); | 1779 | return rtc_str(buf, end, (const struct rtc_time *)ptr, spec, fmt); |
1644 | default: | 1780 | default: |
1645 | return ptr_to_id(buf, end, ptr, spec); | 1781 | return error_string(buf, end, "(%ptR?)", spec); |
1646 | } | 1782 | } |
1647 | } | 1783 | } |
1648 | 1784 | ||
@@ -1650,8 +1786,11 @@ static noinline_for_stack | |||
1650 | char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, | 1786 | char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, |
1651 | const char *fmt) | 1787 | const char *fmt) |
1652 | { | 1788 | { |
1653 | if (!IS_ENABLED(CONFIG_HAVE_CLK) || !clk) | 1789 | if (!IS_ENABLED(CONFIG_HAVE_CLK)) |
1654 | return string(buf, end, NULL, spec); | 1790 | return error_string(buf, end, "(%pC?)", spec); |
1791 | |||
1792 | if (check_pointer(&buf, end, clk, spec)) | ||
1793 | return buf; | ||
1655 | 1794 | ||
1656 | switch (fmt[1]) { | 1795 | switch (fmt[1]) { |
1657 | case 'n': | 1796 | case 'n': |
@@ -1659,7 +1798,7 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, | |||
1659 | #ifdef CONFIG_COMMON_CLK | 1798 | #ifdef CONFIG_COMMON_CLK |
1660 | return string(buf, end, __clk_get_name(clk), spec); | 1799 | return string(buf, end, __clk_get_name(clk), spec); |
1661 | #else | 1800 | #else |
1662 | return ptr_to_id(buf, end, clk, spec); | 1801 | return error_string(buf, end, "(%pC?)", spec); |
1663 | #endif | 1802 | #endif |
1664 | } | 1803 | } |
1665 | } | 1804 | } |
@@ -1692,11 +1831,15 @@ char *format_flags(char *buf, char *end, unsigned long flags, | |||
1692 | } | 1831 | } |
1693 | 1832 | ||
1694 | static noinline_for_stack | 1833 | static noinline_for_stack |
1695 | char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt) | 1834 | char *flags_string(char *buf, char *end, void *flags_ptr, |
1835 | struct printf_spec spec, const char *fmt) | ||
1696 | { | 1836 | { |
1697 | unsigned long flags; | 1837 | unsigned long flags; |
1698 | const struct trace_print_flags *names; | 1838 | const struct trace_print_flags *names; |
1699 | 1839 | ||
1840 | if (check_pointer(&buf, end, flags_ptr, spec)) | ||
1841 | return buf; | ||
1842 | |||
1700 | switch (fmt[1]) { | 1843 | switch (fmt[1]) { |
1701 | case 'p': | 1844 | case 'p': |
1702 | flags = *(unsigned long *)flags_ptr; | 1845 | flags = *(unsigned long *)flags_ptr; |
@@ -1713,8 +1856,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt) | |||
1713 | names = gfpflag_names; | 1856 | names = gfpflag_names; |
1714 | break; | 1857 | break; |
1715 | default: | 1858 | default: |
1716 | WARN_ONCE(1, "Unsupported flags modifier: %c\n", fmt[1]); | 1859 | return error_string(buf, end, "(%pG?)", spec); |
1717 | return buf; | ||
1718 | } | 1860 | } |
1719 | 1861 | ||
1720 | return format_flags(buf, end, flags, names); | 1862 | return format_flags(buf, end, flags, names); |
@@ -1736,13 +1878,13 @@ char *device_node_gen_full_name(const struct device_node *np, char *buf, char *e | |||
1736 | 1878 | ||
1737 | /* special case for root node */ | 1879 | /* special case for root node */ |
1738 | if (!parent) | 1880 | if (!parent) |
1739 | return string(buf, end, "/", default_str_spec); | 1881 | return string_nocheck(buf, end, "/", default_str_spec); |
1740 | 1882 | ||
1741 | for (depth = 0; parent->parent; depth++) | 1883 | for (depth = 0; parent->parent; depth++) |
1742 | parent = parent->parent; | 1884 | parent = parent->parent; |
1743 | 1885 | ||
1744 | for ( ; depth >= 0; depth--) { | 1886 | for ( ; depth >= 0; depth--) { |
1745 | buf = string(buf, end, "/", default_str_spec); | 1887 | buf = string_nocheck(buf, end, "/", default_str_spec); |
1746 | buf = string(buf, end, device_node_name_for_depth(np, depth), | 1888 | buf = string(buf, end, device_node_name_for_depth(np, depth), |
1747 | default_str_spec); | 1889 | default_str_spec); |
1748 | } | 1890 | } |
@@ -1770,10 +1912,10 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1770 | str_spec.field_width = -1; | 1912 | str_spec.field_width = -1; |
1771 | 1913 | ||
1772 | if (!IS_ENABLED(CONFIG_OF)) | 1914 | if (!IS_ENABLED(CONFIG_OF)) |
1773 | return string(buf, end, "(!OF)", spec); | 1915 | return error_string(buf, end, "(%pOF?)", spec); |
1774 | 1916 | ||
1775 | if ((unsigned long)dn < PAGE_SIZE) | 1917 | if (check_pointer(&buf, end, dn, spec)) |
1776 | return string(buf, end, "(null)", spec); | 1918 | return buf; |
1777 | 1919 | ||
1778 | /* simple case without anything any more format specifiers */ | 1920 | /* simple case without anything any more format specifiers */ |
1779 | fmt++; | 1921 | fmt++; |
@@ -1814,7 +1956,7 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1814 | tbuf[2] = of_node_check_flag(dn, OF_POPULATED) ? 'P' : '-'; | 1956 | tbuf[2] = of_node_check_flag(dn, OF_POPULATED) ? 'P' : '-'; |
1815 | tbuf[3] = of_node_check_flag(dn, OF_POPULATED_BUS) ? 'B' : '-'; | 1957 | tbuf[3] = of_node_check_flag(dn, OF_POPULATED_BUS) ? 'B' : '-'; |
1816 | tbuf[4] = 0; | 1958 | tbuf[4] = 0; |
1817 | buf = string(buf, end, tbuf, str_spec); | 1959 | buf = string_nocheck(buf, end, tbuf, str_spec); |
1818 | break; | 1960 | break; |
1819 | case 'c': /* major compatible string */ | 1961 | case 'c': /* major compatible string */ |
1820 | ret = of_property_read_string(dn, "compatible", &p); | 1962 | ret = of_property_read_string(dn, "compatible", &p); |
@@ -1825,10 +1967,10 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1825 | has_mult = false; | 1967 | has_mult = false; |
1826 | of_property_for_each_string(dn, "compatible", prop, p) { | 1968 | of_property_for_each_string(dn, "compatible", prop, p) { |
1827 | if (has_mult) | 1969 | if (has_mult) |
1828 | buf = string(buf, end, ",", str_spec); | 1970 | buf = string_nocheck(buf, end, ",", str_spec); |
1829 | buf = string(buf, end, "\"", str_spec); | 1971 | buf = string_nocheck(buf, end, "\"", str_spec); |
1830 | buf = string(buf, end, p, str_spec); | 1972 | buf = string(buf, end, p, str_spec); |
1831 | buf = string(buf, end, "\"", str_spec); | 1973 | buf = string_nocheck(buf, end, "\"", str_spec); |
1832 | 1974 | ||
1833 | has_mult = true; | 1975 | has_mult = true; |
1834 | } | 1976 | } |
@@ -1841,6 +1983,17 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1841 | return widen_string(buf, buf - buf_start, end, spec); | 1983 | return widen_string(buf, buf - buf_start, end, spec); |
1842 | } | 1984 | } |
1843 | 1985 | ||
1986 | static char *kobject_string(char *buf, char *end, void *ptr, | ||
1987 | struct printf_spec spec, const char *fmt) | ||
1988 | { | ||
1989 | switch (fmt[1]) { | ||
1990 | case 'F': | ||
1991 | return device_node_string(buf, end, ptr, spec, fmt + 1); | ||
1992 | } | ||
1993 | |||
1994 | return error_string(buf, end, "(%pO?)", spec); | ||
1995 | } | ||
1996 | |||
1844 | /* | 1997 | /* |
1845 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 1998 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
1846 | * by an extra set of alphanumeric characters that are extended format | 1999 | * by an extra set of alphanumeric characters that are extended format |
@@ -1957,18 +2110,6 @@ static noinline_for_stack | |||
1957 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, | 2110 | char *pointer(const char *fmt, char *buf, char *end, void *ptr, |
1958 | struct printf_spec spec) | 2111 | struct printf_spec spec) |
1959 | { | 2112 | { |
1960 | const int default_width = 2 * sizeof(void *); | ||
1961 | |||
1962 | if (!ptr && *fmt != 'K' && *fmt != 'x') { | ||
1963 | /* | ||
1964 | * Print (null) with the same width as a pointer so it makes | ||
1965 | * tabular output look nice. | ||
1966 | */ | ||
1967 | if (spec.field_width == -1) | ||
1968 | spec.field_width = default_width; | ||
1969 | return string(buf, end, "(null)", spec); | ||
1970 | } | ||
1971 | |||
1972 | switch (*fmt) { | 2113 | switch (*fmt) { |
1973 | case 'F': | 2114 | case 'F': |
1974 | case 'f': | 2115 | case 'f': |
@@ -2004,50 +2145,19 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
2004 | * 4: 001.002.003.004 | 2145 | * 4: 001.002.003.004 |
2005 | * 6: 000102...0f | 2146 | * 6: 000102...0f |
2006 | */ | 2147 | */ |
2007 | switch (fmt[1]) { | 2148 | return ip_addr_string(buf, end, ptr, spec, fmt); |
2008 | case '6': | ||
2009 | return ip6_addr_string(buf, end, ptr, spec, fmt); | ||
2010 | case '4': | ||
2011 | return ip4_addr_string(buf, end, ptr, spec, fmt); | ||
2012 | case 'S': { | ||
2013 | const union { | ||
2014 | struct sockaddr raw; | ||
2015 | struct sockaddr_in v4; | ||
2016 | struct sockaddr_in6 v6; | ||
2017 | } *sa = ptr; | ||
2018 | |||
2019 | switch (sa->raw.sa_family) { | ||
2020 | case AF_INET: | ||
2021 | return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt); | ||
2022 | case AF_INET6: | ||
2023 | return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt); | ||
2024 | default: | ||
2025 | return string(buf, end, "(invalid address)", spec); | ||
2026 | }} | ||
2027 | } | ||
2028 | break; | ||
2029 | case 'E': | 2149 | case 'E': |
2030 | return escaped_string(buf, end, ptr, spec, fmt); | 2150 | return escaped_string(buf, end, ptr, spec, fmt); |
2031 | case 'U': | 2151 | case 'U': |
2032 | return uuid_string(buf, end, ptr, spec, fmt); | 2152 | return uuid_string(buf, end, ptr, spec, fmt); |
2033 | case 'V': | 2153 | case 'V': |
2034 | { | 2154 | return va_format(buf, end, ptr, spec, fmt); |
2035 | va_list va; | ||
2036 | |||
2037 | va_copy(va, *((struct va_format *)ptr)->va); | ||
2038 | buf += vsnprintf(buf, end > buf ? end - buf : 0, | ||
2039 | ((struct va_format *)ptr)->fmt, va); | ||
2040 | va_end(va); | ||
2041 | return buf; | ||
2042 | } | ||
2043 | case 'K': | 2155 | case 'K': |
2044 | if (!kptr_restrict) | ||
2045 | break; | ||
2046 | return restricted_pointer(buf, end, ptr, spec); | 2156 | return restricted_pointer(buf, end, ptr, spec); |
2047 | case 'N': | 2157 | case 'N': |
2048 | return netdev_bits(buf, end, ptr, spec, fmt); | 2158 | return netdev_bits(buf, end, ptr, spec, fmt); |
2049 | case 'a': | 2159 | case 'a': |
2050 | return address_val(buf, end, ptr, fmt); | 2160 | return address_val(buf, end, ptr, spec, fmt); |
2051 | case 'd': | 2161 | case 'd': |
2052 | return dentry_name(buf, end, ptr, spec, fmt); | 2162 | return dentry_name(buf, end, ptr, spec, fmt); |
2053 | case 't': | 2163 | case 't': |
@@ -2064,13 +2174,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
2064 | #endif | 2174 | #endif |
2065 | 2175 | ||
2066 | case 'G': | 2176 | case 'G': |
2067 | return flags_string(buf, end, ptr, fmt); | 2177 | return flags_string(buf, end, ptr, spec, fmt); |
2068 | case 'O': | 2178 | case 'O': |
2069 | switch (fmt[1]) { | 2179 | return kobject_string(buf, end, ptr, spec, fmt); |
2070 | case 'F': | ||
2071 | return device_node_string(buf, end, ptr, spec, fmt + 1); | ||
2072 | } | ||
2073 | break; | ||
2074 | case 'x': | 2180 | case 'x': |
2075 | return pointer_string(buf, end, ptr, spec); | 2181 | return pointer_string(buf, end, ptr, spec); |
2076 | } | 2182 | } |
@@ -2685,11 +2791,13 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args) | |||
2685 | 2791 | ||
2686 | case FORMAT_TYPE_STR: { | 2792 | case FORMAT_TYPE_STR: { |
2687 | const char *save_str = va_arg(args, char *); | 2793 | const char *save_str = va_arg(args, char *); |
2794 | const char *err_msg; | ||
2688 | size_t len; | 2795 | size_t len; |
2689 | 2796 | ||
2690 | if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE | 2797 | err_msg = check_pointer_msg(save_str); |
2691 | || (unsigned long)save_str < PAGE_SIZE) | 2798 | if (err_msg) |
2692 | save_str = "(null)"; | 2799 | save_str = err_msg; |
2800 | |||
2693 | len = strlen(save_str) + 1; | 2801 | len = strlen(save_str) + 1; |
2694 | if (str + len < end) | 2802 | if (str + len < end) |
2695 | memcpy(str, save_str, len); | 2803 | memcpy(str, save_str, len); |