Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c145bd6 authored by Tobin C. Harding's avatar Tobin C. Harding Committed by Alistair Strachan
Browse files

BACKPORT: vsprintf: add printk specifier %px



printk specifier %p now hashes all addresses before printing. Sometimes
we need to see the actual unmodified address. This can be achieved using
%lx but then we face the risk that if in future we want to change the
way the Kernel handles printing of pointers we will have to grep through
the already existent 50 000 %lx call sites. Let's add specifier %px as a
clear, opt-in, way to print a pointer and maintain some level of
isolation from all the other hex integer output within the Kernel.

Add printk specifier %px to print the actual unmodified address.

Signed-off-by: default avatarTobin C. Harding <me@tobin.cc>
(cherry picked from commit 7b1924a1d930eb27fc79c4e4e2a6c1c970623e68)
Signed-off-by: default avatarSandeep Patil <sspatil@android.com>

Bug: 78533979
Test: Build and boot cuttlefish
Change-Id: I735db3b72abb318f535d55122f1745d0ead0dbe7
parent ae89bc64
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ Pointer Types:

Pointers printed without a specifier extension (i.e unadorned %p) are
hashed to give a unique identifier without leaking kernel addresses to user
space. On 64 bit machines the first 32 bits are zeroed.
space. On 64 bit machines the first 32 bits are zeroed. If you _really_
want the address see %px below.

	%p	abcdef12 or 00000000abcdef12

@@ -72,6 +73,18 @@ Kernel Pointers:
	users. The behaviour of %pK depends on the kptr_restrict sysctl - see
	Documentation/sysctl/kernel.txt for more details.

Unmodified Addresses:

	%px	01234567 or 0123456789abcdef

	For printing pointers when you _really_ want to print the address. Please
	consider whether or not you are leaking sensitive information about the
	Kernel layout in memory before printing pointers with %px. %px is
	functionally equivalent to %lx. %px is preferred to %lx because it is more
	uniquely grep'able. If, in the future, we need to modify the way the Kernel
	handles printing pointers it will be nice to be able to find the call
	sites.

Struct Resources:

	%pr	[mem 0x60000000-0x6fffffff flags 0x2200] or
+18 −0
Original line number Diff line number Diff line
@@ -1522,6 +1522,20 @@ char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt)
	return format_flags(buf, end, flags, names);
}

static noinline_for_stack
char *pointer_string(char *buf, char *end, const void *ptr,
		     struct printf_spec spec)
{
	spec.base = 16;
	spec.flags |= SMALL;
	if (spec.field_width == -1) {
		spec.field_width = 2 * sizeof(ptr);
		spec.flags |= ZEROPAD;
	}

	return number(buf, end, (unsigned long int)ptr, spec);
}

static bool have_filled_random_ptr_key __read_mostly;
static siphash_key_t ptr_key __read_mostly;

@@ -1681,6 +1695,8 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
 *       g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
 *       v vma flags (VM_*) given as pointer to unsigned long
 *
 * - 'x' For printing the address. Equivalent to "%lx".
 *
 * ** Please update also Documentation/printk-formats.txt when making changes **
 *
 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
@@ -1798,6 +1814,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,

	case 'G':
		return flags_string(buf, end, ptr, fmt);
	case 'x':
		return pointer_string(buf, end, ptr, spec);
	}

	/* default is to _not_ leak addresses, hash before printing */
+26 −0
Original line number Diff line number Diff line
@@ -5621,6 +5621,32 @@ sub process {
			}
		}

		# check for vsprintf extension %p<foo> misuses
		if ($^V && $^V ge 5.10.0 &&
		    defined $stat &&
		    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
		    $1 !~ /^_*volatile_*$/) {
			my $bad_extension = "";
			my $lc = $stat =~ tr@\n@@;
			$lc = $lc + $linenr;
		        for (my $count = $linenr; $count <= $lc; $count++) {
				my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
				$fmt =~ s/%%//g;
				if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGNOx]).)/) {
					$bad_extension = $1;
					last;
				}
			}
			if ($bad_extension ne "") {
				my $stat_real = raw_line($linenr, 0);
				for (my $count = $linenr + 1; $count <= $lc; $count++) {
					$stat_real = $stat_real . "\n" . raw_line($count, 0);
				}
				WARN("VSPRINTF_POINTER_EXTENSION",
				     "Invalid vsprintf pointer extension '$bad_extension'\n" . "$here\n$stat_real\n");
			}
		}

# Check for misused memsets
		if ($^V && $^V ge 5.10.0 &&
		    defined $stat &&