@ -1343,6 +1343,59 @@ char *uuid_string(char *buf, char *end, const u8 *addr,
return string ( buf , end , uuid , spec ) ;
}
int kptr_restrict __read_mostly ;
static noinline_for_stack
char * restricted_pointer ( 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 ;
}
switch ( kptr_restrict ) {
case 0 :
/* Always print %pK values */
break ;
case 1 : {
const struct cred * cred ;
/*
* kptr_restrict = = 1 cannot be used in IRQ context
* because its test for CAP_SYSLOG would be meaningless .
*/
if ( in_irq ( ) | | in_serving_softirq ( ) | | in_nmi ( ) )
return string ( buf , end , " pK-error " , spec ) ;
/*
* 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 .
*/
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 ;
}
return number ( buf , end , ( unsigned long ) ptr , spec ) ;
}
static noinline_for_stack
char * netdev_bits ( char * buf , char * end , const void * addr , const char * fmt )
{
@ -1588,8 +1641,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
return widen_string ( buf , buf - buf_start , end , spec ) ;
}
int kptr_restrict __read_mostly ;
/*
* Show a ' % p ' thing . A kernel extension is that the ' % p ' is followed
* by an extra set of alphanumeric characters that are extended format
@ -1789,47 +1840,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
return buf ;
}
case ' K ' :
switch ( kptr_restrict ) {
case 0 :
/* Always print %pK values */
break ;
case 1 : {
const struct cred * cred ;
/*
* kptr_restrict = = 1 cannot be used in IRQ context
* because its test for CAP_SYSLOG would be meaningless .
*/
if ( in_irq ( ) | | in_serving_softirq ( ) | | in_nmi ( ) ) {
if ( spec . field_width = = - 1 )
spec . field_width = default_width ;
return string ( buf , end , " pK-error " , spec ) ;
}
/*
* 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 .
*/
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 ;
return restricted_pointer ( buf , end , ptr , spec ) ;
case ' N ' :
return netdev_bits ( buf , end , ptr , fmt ) ;
case ' a ' :