summaryrefslogtreecommitdiff
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c88
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;
}