Printing kernel pointers via %pK has a minor defect when kptr_restrict is set to 2: the pointer may be emitted as "pK-error" instead of all 0's when in an interrupt. Fix this defect, neaten the code, and correct the sysctl documentation. Add missing documentation for 2 other uses: %pNF and %pV. Trivially reduces vsprintf.o object size: $ size lib/vsprintf.o* text data bss dec hex filename 14536 6 0 14542 38ce lib/vsprintf.o.new 14568 6 0 14574 38ee lib/vsprintf.o.old Signed-off-by: Joe Perches <joe@xxxxxxxxxxx> --- Documentation/sysctl/kernel.txt | 17 +++++++++-------- lib/vsprintf.c | 38 ++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 9d4c1d1..c17d5ca 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -289,14 +289,15 @@ Default value is "/sbin/hotplug". kptr_restrict: -This toggle indicates whether restrictions are placed on -exposing kernel addresses via /proc and other interfaces. When -kptr_restrict is set to (0), there are no restrictions. When -kptr_restrict is set to (1), the default, kernel pointers -printed using the %pK format specifier will be replaced with 0's -unless the user has CAP_SYSLOG. When kptr_restrict is set to -(2), kernel pointers printed using %pK will be replaced with 0's -regardless of privileges. +This toggle indicates whether restrictions are placed on exposing kernel +addresses via /proc and other interfaces. + +When kptr_restrict is set to (0), the default, there are no restrictions. +When kptr_restrict is set to (1), kernel pointers printed using the %pK +format specifier will be replaced with 0's unless the user has CAP_SYSLOG +and effective user and group ids are equal to the real ids. +When kptr_restrict is set to (2), kernel pointers printed using %pK will +be replaced with 0's regardless of privileges. ============================================================== diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 26559bd..ce55f52 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1301,21 +1301,28 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, va_end(va); return buf; } - case 'K': - /* - * %pK cannot be used in IRQ context because its test - * for CAP_SYSLOG would be meaningless. - */ - if (kptr_restrict && (in_irq() || in_serving_softirq() || - in_nmi())) { - if (spec.field_width == -1) - spec.field_width = default_width; - return string(buf, end, "pK-error", spec); - } - if (!((kptr_restrict == 0) || - (kptr_restrict == 1 && - has_capability_noaudit(current, CAP_SYSLOG)))) + case 'K': /* see: Documentation/sysctl/kernel.txt */ + switch (kptr_restrict) { + case 0: /* None (default) */ + break; + case 1: /* Restricted */ + if (in_irq() || in_serving_softirq() || in_nmi()) { + /* + * This cannot be used in IRQ context because + * the test for CAP_SYSLOG would be meaningless + */ + if (spec.field_width == -1) + spec.field_width = default_width; + return string(buf, end, "pK-error", spec); + } + if (!has_capability_noaudit(current, CAP_SYSLOG)) + ptr = NULL; + break; + case 2: /* Never - Always emit 0 */ + default: ptr = NULL; + break; + } break; case 'N': switch (fmt[1]) { @@ -1574,6 +1581,9 @@ qualifier: * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper * case. + * %pV recurse and output a struct va_format (const char *fmt, va_list *) + * %pK output a kernel address or 0 depending on sysctl kptr_restrict + * %NF output a netdev_features_t * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 * bytes of the input) * %n is ignored -- 1.8.1.2.459.gbcd45b4.dirty -- To unsubscribe from this list: send the line "unsubscribe linux-doc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html