diff options
Diffstat (limited to 'lib/vsprintf.c')
| -rw-r--r-- | lib/vsprintf.c | 35 | 
1 files changed, 32 insertions, 3 deletions
| diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 26559bdb4c4..48586ac3a62 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -27,6 +27,7 @@  #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 */ @@ -1218,6 +1219,8 @@ int kptr_restrict __read_mostly;   *            The maximum supported length is 64 bytes of the input. Consider   *            to use print_hex_dump() for the larger input.   * - 'a' For a phys_addr_t type and its derivative types (passed by reference) + * - 'd[234]' For a dentry name (optionally 2-4 last components) + * - 'D[234]' Same as 'd' but for a struct file   *   * Note: The difference between 'S' and 'F' is that on ia64 and ppc64   * function pointers are really function descriptors, which contain a @@ -1312,11 +1315,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,  				spec.field_width = default_width;  			return string(buf, end, "pK-error", spec);  		} -		if (!((kptr_restrict == 0) || -		      (kptr_restrict == 1 && -		       has_capability_noaudit(current, CAP_SYSLOG)))) + +		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 */  			ptr = NULL; +			break; +		}  		break; +  	case 'N':  		switch (fmt[1]) {  		case 'F': | 
