diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c3f36d415bdf..0e337541f005 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -655,6 +655,50 @@ char *resource_string(char *buf, char *end, struct resource *res, | |||
655 | } | 655 | } |
656 | 656 | ||
657 | static noinline_for_stack | 657 | static noinline_for_stack |
658 | char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | ||
659 | const char *fmt) | ||
660 | { | ||
661 | int i, len = 1; /* if we pass '%ph[CDN]', field witdh remains | ||
662 | negative value, fallback to the default */ | ||
663 | char separator; | ||
664 | |||
665 | if (spec.field_width == 0) | ||
666 | /* nothing to print */ | ||
667 | return buf; | ||
668 | |||
669 | if (ZERO_OR_NULL_PTR(addr)) | ||
670 | /* NULL pointer */ | ||
671 | return string(buf, end, NULL, spec); | ||
672 | |||
673 | switch (fmt[1]) { | ||
674 | case 'C': | ||
675 | separator = ':'; | ||
676 | break; | ||
677 | case 'D': | ||
678 | separator = '-'; | ||
679 | break; | ||
680 | case 'N': | ||
681 | separator = 0; | ||
682 | break; | ||
683 | default: | ||
684 | separator = ' '; | ||
685 | break; | ||
686 | } | ||
687 | |||
688 | if (spec.field_width > 0) | ||
689 | len = min_t(int, spec.field_width, 64); | ||
690 | |||
691 | for (i = 0; i < len && buf < end - 1; i++) { | ||
692 | buf = hex_byte_pack(buf, addr[i]); | ||
693 | |||
694 | if (buf < end && separator && i != len - 1) | ||
695 | *buf++ = separator; | ||
696 | } | ||
697 | |||
698 | return buf; | ||
699 | } | ||
700 | |||
701 | static noinline_for_stack | ||
658 | char *mac_address_string(char *buf, char *end, u8 *addr, | 702 | char *mac_address_string(char *buf, char *end, u8 *addr, |
659 | struct printf_spec spec, const char *fmt) | 703 | struct printf_spec spec, const char *fmt) |
660 | { | 704 | { |
@@ -662,15 +706,28 @@ char *mac_address_string(char *buf, char *end, u8 *addr, | |||
662 | char *p = mac_addr; | 706 | char *p = mac_addr; |
663 | int i; | 707 | int i; |
664 | char separator; | 708 | char separator; |
709 | bool reversed = false; | ||
665 | 710 | ||
666 | if (fmt[1] == 'F') { /* FDDI canonical format */ | 711 | switch (fmt[1]) { |
712 | case 'F': | ||
667 | separator = '-'; | 713 | separator = '-'; |
668 | } else { | 714 | break; |
715 | |||
716 | case 'R': | ||
717 | reversed = true; | ||
718 | /* fall through */ | ||
719 | |||
720 | default: | ||
669 | separator = ':'; | 721 | separator = ':'; |
722 | break; | ||
670 | } | 723 | } |
671 | 724 | ||
672 | for (i = 0; i < 6; i++) { | 725 | for (i = 0; i < 6; i++) { |
673 | p = hex_byte_pack(p, addr[i]); | 726 | if (reversed) |
727 | p = hex_byte_pack(p, addr[5 - i]); | ||
728 | else | ||
729 | p = hex_byte_pack(p, addr[i]); | ||
730 | |||
674 | if (fmt[0] == 'M' && i != 5) | 731 | if (fmt[0] == 'M' && i != 5) |
675 | *p++ = separator; | 732 | *p++ = separator; |
676 | } | 733 | } |
@@ -933,6 +990,7 @@ int kptr_restrict __read_mostly; | |||
933 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons | 990 | * - 'm' For a 6-byte MAC address, it prints the hex address without colons |
934 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address | 991 | * - 'MF' For a 6-byte MAC FDDI address, it prints the address |
935 | * with a dash-separated hex notation | 992 | * with a dash-separated hex notation |
993 | * - '[mM]R For a 6-byte MAC address, Reverse order (Bluetooth) | ||
936 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way | 994 | * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way |
937 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) | 995 | * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4) |
938 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's | 996 | * IPv6 uses colon separated network-order 16 bit hex with leading 0's |
@@ -960,6 +1018,13 @@ int kptr_restrict __read_mostly; | |||
960 | * correctness of the format string and va_list arguments. | 1018 | * correctness of the format string and va_list arguments. |
961 | * - 'K' For a kernel pointer that should be hidden from unprivileged users | 1019 | * - 'K' For a kernel pointer that should be hidden from unprivileged users |
962 | * - 'NF' For a netdev_features_t | 1020 | * - 'NF' For a netdev_features_t |
1021 | * - 'h[CDN]' For a variable-length buffer, it prints it as a hex string with | ||
1022 | * a certain separator (' ' by default): | ||
1023 | * C colon | ||
1024 | * D dash | ||
1025 | * N no separator | ||
1026 | * The maximum supported length is 64 bytes of the input. Consider | ||
1027 | * to use print_hex_dump() for the larger input. | ||
963 | * | 1028 | * |
964 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 1029 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
965 | * function pointers are really function descriptors, which contain a | 1030 | * function pointers are really function descriptors, which contain a |
@@ -993,9 +1058,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
993 | case 'R': | 1058 | case 'R': |
994 | case 'r': | 1059 | case 'r': |
995 | return resource_string(buf, end, ptr, spec, fmt); | 1060 | return resource_string(buf, end, ptr, spec, fmt); |
1061 | case 'h': | ||
1062 | return hex_string(buf, end, ptr, spec, fmt); | ||
996 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ | 1063 | case 'M': /* Colon separated: 00:01:02:03:04:05 */ |
997 | case 'm': /* Contiguous: 000102030405 */ | 1064 | case 'm': /* Contiguous: 000102030405 */ |
998 | /* [mM]F (FDDI, bit reversed) */ | 1065 | /* [mM]F (FDDI) */ |
1066 | /* [mM]R (Reverse order; Bluetooth) */ | ||
999 | return mac_address_string(buf, end, ptr, spec, fmt); | 1067 | return mac_address_string(buf, end, ptr, spec, fmt); |
1000 | case 'I': /* Formatted IP supported | 1068 | case 'I': /* Formatted IP supported |
1001 | * 4: 1.2.3.4 | 1069 | * 4: 1.2.3.4 |
@@ -1030,7 +1098,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1030 | * %pK cannot be used in IRQ context because its test | 1098 | * %pK cannot be used in IRQ context because its test |
1031 | * for CAP_SYSLOG would be meaningless. | 1099 | * for CAP_SYSLOG would be meaningless. |
1032 | */ | 1100 | */ |
1033 | if (in_irq() || in_serving_softirq() || in_nmi()) { | 1101 | if (kptr_restrict && (in_irq() || in_serving_softirq() || |
1102 | in_nmi())) { | ||
1034 | if (spec.field_width == -1) | 1103 | if (spec.field_width == -1) |
1035 | spec.field_width = default_width; | 1104 | spec.field_width = default_width; |
1036 | return string(buf, end, "pK-error", spec); | 1105 | return string(buf, end, "pK-error", spec); |
@@ -1280,8 +1349,12 @@ qualifier: | |||
1280 | * %pI6c print an IPv6 address as specified by RFC 5952 | 1349 | * %pI6c print an IPv6 address as specified by RFC 5952 |
1281 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | 1350 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper |
1282 | * case. | 1351 | * case. |
1352 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | ||
1353 | * bytes of the input) | ||
1283 | * %n is ignored | 1354 | * %n is ignored |
1284 | * | 1355 | * |
1356 | * ** Please update Documentation/printk-formats.txt when making changes ** | ||
1357 | * | ||
1285 | * The return value is the number of characters which would | 1358 | * The return value is the number of characters which would |
1286 | * be generated for the given input, excluding the trailing | 1359 | * be generated for the given input, excluding the trailing |
1287 | * '\0', as per ISO C99. If you want to have the exact | 1360 | * '\0', as per ISO C99. If you want to have the exact |