diff options
author | Petr Mladek <pmladek@suse.com> | 2019-04-17 07:53:41 -0400 |
---|---|---|
committer | Petr Mladek <pmladek@suse.com> | 2019-04-26 10:18:40 -0400 |
commit | 6eea242f9bcdf828bb56334d8ee5c7cb466e4bcd (patch) | |
tree | 2a734c17749fb2e692e416cbed27de9f0c265277 /lib/vsprintf.c | |
parent | c4703acd6d4a58dc4b31ad2a8f8b14becb898d25 (diff) |
vsprintf: Shuffle restricted_pointer()
This is just a preparation step for further changes.
The patch does not change the code.
Link: http://lkml.kernel.org/r/20190417115350.20479-2-pmladek@suse.com
To: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: "Tobin C . Harding" <me@tobin.cc>
Cc: Joe Perches <joe@perches.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: linux-kernel@vger.kernel.org
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r-- | lib/vsprintf.c | 98 |
1 files changed, 49 insertions, 49 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 791b6fa36905..eb7b4a06e1f0 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -717,6 +717,55 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr, | |||
717 | return pointer_string(buf, end, (const void *)hashval, spec); | 717 | return pointer_string(buf, end, (const void *)hashval, spec); |
718 | } | 718 | } |
719 | 719 | ||
720 | int kptr_restrict __read_mostly; | ||
721 | |||
722 | static noinline_for_stack | ||
723 | char *restricted_pointer(char *buf, char *end, const void *ptr, | ||
724 | struct printf_spec spec) | ||
725 | { | ||
726 | switch (kptr_restrict) { | ||
727 | case 0: | ||
728 | /* Always print %pK values */ | ||
729 | break; | ||
730 | case 1: { | ||
731 | const struct cred *cred; | ||
732 | |||
733 | /* | ||
734 | * kptr_restrict==1 cannot be used in IRQ context | ||
735 | * because its test for CAP_SYSLOG would be meaningless. | ||
736 | */ | ||
737 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
738 | if (spec.field_width == -1) | ||
739 | spec.field_width = 2 * sizeof(ptr); | ||
740 | return string(buf, end, "pK-error", spec); | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * Only print the real pointer value if the current | ||
745 | * process has CAP_SYSLOG and is running with the | ||
746 | * same credentials it started with. This is because | ||
747 | * access to files is checked at open() time, but %pK | ||
748 | * checks permission at read() time. We don't want to | ||
749 | * leak pointer values if a binary opens a file using | ||
750 | * %pK and then elevates privileges before reading it. | ||
751 | */ | ||
752 | cred = current_cred(); | ||
753 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
754 | !uid_eq(cred->euid, cred->uid) || | ||
755 | !gid_eq(cred->egid, cred->gid)) | ||
756 | ptr = NULL; | ||
757 | break; | ||
758 | } | ||
759 | case 2: | ||
760 | default: | ||
761 | /* Always print 0's for %pK */ | ||
762 | ptr = NULL; | ||
763 | break; | ||
764 | } | ||
765 | |||
766 | return pointer_string(buf, end, ptr, spec); | ||
767 | } | ||
768 | |||
720 | static noinline_for_stack | 769 | static noinline_for_stack |
721 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, | 770 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, |
722 | const char *fmt) | 771 | const char *fmt) |
@@ -1476,55 +1525,6 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
1476 | return string(buf, end, uuid, spec); | 1525 | return string(buf, end, uuid, spec); |
1477 | } | 1526 | } |
1478 | 1527 | ||
1479 | int kptr_restrict __read_mostly; | ||
1480 | |||
1481 | static noinline_for_stack | ||
1482 | char *restricted_pointer(char *buf, char *end, const void *ptr, | ||
1483 | struct printf_spec spec) | ||
1484 | { | ||
1485 | switch (kptr_restrict) { | ||
1486 | case 0: | ||
1487 | /* Always print %pK values */ | ||
1488 | break; | ||
1489 | case 1: { | ||
1490 | const struct cred *cred; | ||
1491 | |||
1492 | /* | ||
1493 | * kptr_restrict==1 cannot be used in IRQ context | ||
1494 | * because its test for CAP_SYSLOG would be meaningless. | ||
1495 | */ | ||
1496 | if (in_irq() || in_serving_softirq() || in_nmi()) { | ||
1497 | if (spec.field_width == -1) | ||
1498 | spec.field_width = 2 * sizeof(ptr); | ||
1499 | return string(buf, end, "pK-error", spec); | ||
1500 | } | ||
1501 | |||
1502 | /* | ||
1503 | * Only print the real pointer value if the current | ||
1504 | * process has CAP_SYSLOG and is running with the | ||
1505 | * same credentials it started with. This is because | ||
1506 | * access to files is checked at open() time, but %pK | ||
1507 | * checks permission at read() time. We don't want to | ||
1508 | * leak pointer values if a binary opens a file using | ||
1509 | * %pK and then elevates privileges before reading it. | ||
1510 | */ | ||
1511 | cred = current_cred(); | ||
1512 | if (!has_capability_noaudit(current, CAP_SYSLOG) || | ||
1513 | !uid_eq(cred->euid, cred->uid) || | ||
1514 | !gid_eq(cred->egid, cred->gid)) | ||
1515 | ptr = NULL; | ||
1516 | break; | ||
1517 | } | ||
1518 | case 2: | ||
1519 | default: | ||
1520 | /* Always print 0's for %pK */ | ||
1521 | ptr = NULL; | ||
1522 | break; | ||
1523 | } | ||
1524 | |||
1525 | return pointer_string(buf, end, ptr, spec); | ||
1526 | } | ||
1527 | |||
1528 | static noinline_for_stack | 1528 | static noinline_for_stack |
1529 | char *netdev_bits(char *buf, char *end, const void *addr, | 1529 | char *netdev_bits(char *buf, char *end, const void *addr, |
1530 | struct printf_spec spec, const char *fmt) | 1530 | struct printf_spec spec, const char *fmt) |