diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 26559bdb4c49..10909c571494 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/dcache.h> | 29 | #include <linux/dcache.h> |
| 30 | #include <linux/cred.h> | ||
| 30 | #include <net/addrconf.h> | 31 | #include <net/addrconf.h> |
| 31 | 32 | ||
| 32 | #include <asm/page.h> /* for PAGE_SIZE */ | 33 | #include <asm/page.h> /* for PAGE_SIZE */ |
| @@ -1218,6 +1219,8 @@ int kptr_restrict __read_mostly; | |||
| 1218 | * The maximum supported length is 64 bytes of the input. Consider | 1219 | * The maximum supported length is 64 bytes of the input. Consider |
| 1219 | * to use print_hex_dump() for the larger input. | 1220 | * to use print_hex_dump() for the larger input. |
| 1220 | * - 'a' For a phys_addr_t type and its derivative types (passed by reference) | 1221 | * - 'a' For a phys_addr_t type and its derivative types (passed by reference) |
| 1222 | * - 'd[234]' For a dentry name (optionally 2-4 last components) | ||
| 1223 | * - 'D[234]' Same as 'd' but for a struct file | ||
| 1221 | * | 1224 | * |
| 1222 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 1225 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 1223 | * function pointers are really function descriptors, which contain a | 1226 | * function pointers are really function descriptors, which contain a |
| @@ -1312,11 +1315,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1312 | spec.field_width = default_width; | 1315 | spec.field_width = default_width; |
| 1313 | return string(buf, end, "pK-error", spec); | 1316 | return string(buf, end, "pK-error", spec); |
| 1314 | } | 1317 | } |
| 1315 | if (!((kptr_restrict == 0) || | 1318 | |
| 1316 | (kptr_restrict == 1 && | 1319 | switch (kptr_restrict) { |
| 1317 | has_capability_noaudit(current, CAP_SYSLOG)))) | 1320 | case 0: |
| 1321 | /* Always print %pK values */ | ||
| 1322 | break; | ||
| 1323 | case 1: { | ||
| 1324 | /* | ||
| 1325 | * Only print the real pointer value if the current | ||
| 1326 | * process has CAP_SYSLOG and is running with the | ||
| 1327 | * same credentials it started with. This is because | ||
| 1328 | * access to files is checked at open() time, but %pK | ||
| 1329 | * checks permission at read() time. We don't want to | ||
| 1330 | * leak pointer values if a binary opens a file using | ||
| 1331 | * %pK and then elevates privileges before reading it. | ||
| 1332 | */ | ||
| 1333 | const struct cred *cred = current_cred(); | ||
| 1334 | |||
| 1335 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
| 1336 | !uid_eq(cred->euid, cred->uid) || | ||
| 1337 | !gid_eq(cred->egid, cred->gid)) | ||
| 1338 | ptr = NULL; | ||
| 1339 | break; | ||
| 1340 | } | ||
| 1341 | case 2: | ||
| 1342 | default: | ||
| 1343 | /* Always print 0's for %pK */ | ||
| 1318 | ptr = NULL; | 1344 | ptr = NULL; |
| 1345 | break; | ||
| 1346 | } | ||
| 1319 | break; | 1347 | break; |
| 1348 | |||
| 1320 | case 'N': | 1349 | case 'N': |
| 1321 | switch (fmt[1]) { | 1350 | switch (fmt[1]) { |
| 1322 | case 'F': | 1351 | case 'F': |
| @@ -1683,18 +1712,16 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) | |||
| 1683 | break; | 1712 | break; |
| 1684 | 1713 | ||
| 1685 | case FORMAT_TYPE_NRCHARS: { | 1714 | case FORMAT_TYPE_NRCHARS: { |
| 1686 | u8 qualifier = spec.qualifier; | 1715 | /* |
| 1716 | * Since %n poses a greater security risk than | ||
| 1717 | * utility, ignore %n and skip its argument. | ||
| 1718 | */ | ||
| 1719 | void *skip_arg; | ||
| 1687 | 1720 | ||
| 1688 | if (qualifier == 'l') { | 1721 | WARN_ONCE(1, "Please remove ignored %%n in '%s'\n", |
| 1689 | long *ip = va_arg(args, long *); | 1722 | old_fmt); |
| 1690 | *ip = (str - buf); | 1723 | |
| 1691 | } else if (_tolower(qualifier) == 'z') { | 1724 | skip_arg = va_arg(args, void *); |
| 1692 | size_t *ip = va_arg(args, size_t *); | ||
| 1693 | *ip = (str - buf); | ||
| 1694 | } else { | ||
| 1695 | int *ip = va_arg(args, int *); | ||
| 1696 | *ip = (str - buf); | ||
| 1697 | } | ||
| 1698 | break; | 1725 | break; |
| 1699 | } | 1726 | } |
| 1700 | 1727 | ||
