diff options
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 88 |
1 files changed, 20 insertions, 68 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 185b6d300ebc..26559bdb4c49 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -27,7 +27,6 @@ #include <linux/uaccess.h> #include <linux/ioport.h> #include <linux/dcache.h> -#include <linux/cred.h> #include <net/addrconf.h> #include <asm/page.h> /* for PAGE_SIZE */ @@ -1155,30 +1154,6 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr, return number(buf, end, *(const netdev_features_t *)addr, spec); } -static noinline_for_stack -char *address_val(char *buf, char *end, const void *addr, - struct printf_spec spec, const char *fmt) -{ - unsigned long long num; - - spec.flags |= SPECIAL | SMALL | ZEROPAD; - spec.base = 16; - - switch (fmt[1]) { - case 'd': - num = *(const dma_addr_t *)addr; - spec.field_width = sizeof(dma_addr_t) * 2 + 2; - break; - case 'p': - default: - num = *(const phys_addr_t *)addr; - spec.field_width = sizeof(phys_addr_t) * 2 + 2; - break; - } - - return number(buf, end, num, spec); -} - int kptr_restrict __read_mostly; /* @@ -1242,10 +1217,7 @@ int kptr_restrict __read_mostly; * N no separator * The maximum supported length is 64 bytes of the input. Consider * to use print_hex_dump() for the larger input. - * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives - * (default assumed to be phys_addr_t, passed by reference) - * - 'd[234]' For a dentry name (optionally 2-4 last components) - * - 'D[234]' Same as 'd' but for a struct file + * - 'a' For a phys_addr_t type and its derivative types (passed by reference) * * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a @@ -1340,37 +1312,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, spec.field_width = default_width; return string(buf, end, "pK-error", spec); } - - switch (kptr_restrict) { - case 0: - /* Always print %pK values */ - break; - case 1: { - /* - * Only print the real pointer value if the current - * process has CAP_SYSLOG and is running with the - * same credentials it started with. This is because - * access to files is checked at open() time, but %pK - * checks permission at read() time. We don't want to - * leak pointer values if a binary opens a file using - * %pK and then elevates privileges before reading it. - */ - const struct cred *cred = current_cred(); - - if (!has_capability_noaudit(current, CAP_SYSLOG) || - !uid_eq(cred->euid, cred->uid) || - !gid_eq(cred->egid, cred->gid)) - ptr = NULL; - break; - } - case 2: - default: - /* Always print 0's for %pK */ + if (!((kptr_restrict == 0) || + (kptr_restrict == 1 && + has_capability_noaudit(current, CAP_SYSLOG)))) ptr = NULL; - break; - } break; - case 'N': switch (fmt[1]) { case 'F': @@ -1378,7 +1324,11 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, } break; case 'a': - return address_val(buf, end, ptr, spec, fmt); + spec.flags |= SPECIAL | SMALL | ZEROPAD; + spec.field_width = sizeof(phys_addr_t) * 2 + 2; + spec.base = 16; + return number(buf, end, + (unsigned long long) *((phys_addr_t *)ptr), spec); case 'd': return dentry_name(buf, end, ptr, spec, fmt); case 'D': @@ -1733,16 +1683,18 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) break; case FORMAT_TYPE_NRCHARS: { - /* - * Since %n poses a greater security risk than - * utility, ignore %n and skip its argument. - */ - void *skip_arg; - - WARN_ONCE(1, "Please remove ignored %%n in '%s'\n", - old_fmt); + u8 qualifier = spec.qualifier; - skip_arg = va_arg(args, void *); + if (qualifier == 'l') { + long *ip = va_arg(args, long *); + *ip = (str - buf); + } else if (_tolower(qualifier) == 'z') { + size_t *ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int *ip = va_arg(args, int *); + *ip = (str - buf); + } break; } |