All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4] printk: hash addresses printed with %p
@ 2017-10-18  4:21 ` Tobin C. Harding
  0 siblings, 0 replies; 8+ messages in thread
From: Tobin C. Harding @ 2017-10-18  4:21 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Tobin C. Harding, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

Currently there are many places in the kernel where addresses are being
printed using an unadorned %p. Kernel pointers should be printed using
%pK allowing some control via the kptr_restrict sysctl. Exposing addresses
gives attackers sensitive information about the kernel layout in memory.

We can reduce the attack surface by hashing all addresses printed with
%p. This will of course break some users, forcing code printing needed
addresses to be updated.

For what it's worth, usage of unadorned %p can be broken down as
follows (thanks to Joe Perches).

$ git grep -E '%p[^A-Za-z0-9]' | cut -f1 -d"/" | sort | uniq -c
   1084 arch
     20 block
     10 crypto
     32 Documentation
   8121 drivers
   1221 fs
    143 include
    101 kernel
     69 lib
    100 mm
   1510 net
     40 samples
      7 scripts
     11 security
    166 sound
    152 tools
      2 virt

Add function ptr_to_id() to map an address to a 32 bit unique identifier.

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---

V4:
 - Remove changes to siphash.{ch}        
 - Do word size check, and return value cast, directly in ptr_to_id().
 - Use add_ready_random_callback() to guard call to get_random_bytes()

V3:
 - Use atomic_xchg() to guard setting [random] key.
 - Remove erroneous white space change.

V2:
 - Use SipHash to do the hashing.

The discussion related to this patch has been fragmented. There are
three threads associated with this patch. Email threads by subject:

[PATCH] printk: hash addresses printed with %p
[PATCH 0/3] add %pX specifier
[kernel-hardening] [RFC V2 0/6] add more kernel pointer filter options

 lib/vsprintf.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 3 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 86c3385b9eb3..4609738cd2cd 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -33,6 +33,8 @@
 #include <linux/uuid.h>
 #include <linux/of.h>
 #include <net/addrconf.h>
+#include <linux/siphash.h>
+#include <linux/spinlock.h>
 #ifdef CONFIG_BLOCK
 #include <linux/blkdev.h>
 #endif
@@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
 	return widen_string(buf, buf - buf_start, end, spec);
 }
 
+/* protects ptr_secret and have_key */
+DEFINE_SPINLOCK(key_lock);
+static siphash_key_t ptr_secret __read_mostly;
+static atomic_t have_key = ATOMIC_INIT(0);
+
+static int initialize_ptr_secret(void)
+{
+	spin_lock(&key_lock);
+	if (atomic_read(&have_key) == 1)
+		goto unlock;
+
+	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
+	atomic_set(&have_key, 1);
+
+unlock:
+	spin_unlock(&key_lock);
+	return 0;
+}
+
+static void schedule_async_key_init(struct random_ready_callback *rdy)
+{
+	initialize_ptr_secret();
+}
+
+/* Maps a pointer to a 32 bit unique identifier. */
+static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
+{
+	static struct random_ready_callback random_ready;
+	unsigned int hashval;
+	int err;
+
+	if (atomic_read(&have_key) == 0) {
+		random_ready.owner = NULL;
+		random_ready.func = schedule_async_key_init;
+
+		err = add_random_ready_callback(&random_ready);
+
+		switch (err) {
+		case 0:
+			return "(pointer value)";
+
+		case -EALREADY:
+			initialize_ptr_secret();
+			break;
+
+		default:
+			/* shouldn't get here */
+			return "(ptr_to_id() error)";
+		}
+	}
+
+#ifdef CONFIG_64BIT
+	hashval = (unsigned int)siphash_1u64((u64)ptr, &ptr_secret);
+#else
+	hashval = (unsigned int)siphash_1u32((u32)ptr, &ptr_secret);
+#endif
+
+	spec.field_width = 2 + 2 * sizeof(unsigned int); /* 0x + hex */
+	spec.flags = SPECIAL | SMALL | ZEROPAD;
+	spec.base = 16;
+
+	return number(buf, end, hashval, spec);
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -1703,6 +1769,9 @@ int kptr_restrict __read_mostly;
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
+ *
+ * Default behaviour (unadorned %p) is to hash the address, rendering it useful
+ * as a unique identifier.
  */
 static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
@@ -1858,14 +1927,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			return device_node_string(buf, end, ptr, spec, fmt + 1);
 		}
 	}
-	spec.flags |= SMALL;
+
 	if (spec.field_width == -1) {
 		spec.field_width = default_width;
 		spec.flags |= ZEROPAD;
 	}
-	spec.base = 16;
 
-	return number(buf, end, (unsigned long) ptr, spec);
+	return ptr_to_id(buf, end, ptr, spec);
 }
 
 /*
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [kernel-hardening] [PATCH v4] printk: hash addresses printed with %p
@ 2017-10-18  4:21 ` Tobin C. Harding
  0 siblings, 0 replies; 8+ messages in thread
From: Tobin C. Harding @ 2017-10-18  4:21 UTC (permalink / raw)
  To: kernel-hardening
  Cc: Tobin C. Harding, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

Currently there are many places in the kernel where addresses are being
printed using an unadorned %p. Kernel pointers should be printed using
%pK allowing some control via the kptr_restrict sysctl. Exposing addresses
gives attackers sensitive information about the kernel layout in memory.

We can reduce the attack surface by hashing all addresses printed with
%p. This will of course break some users, forcing code printing needed
addresses to be updated.

For what it's worth, usage of unadorned %p can be broken down as
follows (thanks to Joe Perches).

$ git grep -E '%p[^A-Za-z0-9]' | cut -f1 -d"/" | sort | uniq -c
   1084 arch
     20 block
     10 crypto
     32 Documentation
   8121 drivers
   1221 fs
    143 include
    101 kernel
     69 lib
    100 mm
   1510 net
     40 samples
      7 scripts
     11 security
    166 sound
    152 tools
      2 virt

Add function ptr_to_id() to map an address to a 32 bit unique identifier.

Signed-off-by: Tobin C. Harding <me@tobin.cc>
---

V4:
 - Remove changes to siphash.{ch}        
 - Do word size check, and return value cast, directly in ptr_to_id().
 - Use add_ready_random_callback() to guard call to get_random_bytes()

V3:
 - Use atomic_xchg() to guard setting [random] key.
 - Remove erroneous white space change.

V2:
 - Use SipHash to do the hashing.

The discussion related to this patch has been fragmented. There are
three threads associated with this patch. Email threads by subject:

[PATCH] printk: hash addresses printed with %p
[PATCH 0/3] add %pX specifier
[kernel-hardening] [RFC V2 0/6] add more kernel pointer filter options

 lib/vsprintf.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 3 deletions(-)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 86c3385b9eb3..4609738cd2cd 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -33,6 +33,8 @@
 #include <linux/uuid.h>
 #include <linux/of.h>
 #include <net/addrconf.h>
+#include <linux/siphash.h>
+#include <linux/spinlock.h>
 #ifdef CONFIG_BLOCK
 #include <linux/blkdev.h>
 #endif
@@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
 	return widen_string(buf, buf - buf_start, end, spec);
 }
 
+/* protects ptr_secret and have_key */
+DEFINE_SPINLOCK(key_lock);
+static siphash_key_t ptr_secret __read_mostly;
+static atomic_t have_key = ATOMIC_INIT(0);
+
+static int initialize_ptr_secret(void)
+{
+	spin_lock(&key_lock);
+	if (atomic_read(&have_key) == 1)
+		goto unlock;
+
+	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
+	atomic_set(&have_key, 1);
+
+unlock:
+	spin_unlock(&key_lock);
+	return 0;
+}
+
+static void schedule_async_key_init(struct random_ready_callback *rdy)
+{
+	initialize_ptr_secret();
+}
+
+/* Maps a pointer to a 32 bit unique identifier. */
+static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
+{
+	static struct random_ready_callback random_ready;
+	unsigned int hashval;
+	int err;
+
+	if (atomic_read(&have_key) == 0) {
+		random_ready.owner = NULL;
+		random_ready.func = schedule_async_key_init;
+
+		err = add_random_ready_callback(&random_ready);
+
+		switch (err) {
+		case 0:
+			return "(pointer value)";
+
+		case -EALREADY:
+			initialize_ptr_secret();
+			break;
+
+		default:
+			/* shouldn't get here */
+			return "(ptr_to_id() error)";
+		}
+	}
+
+#ifdef CONFIG_64BIT
+	hashval = (unsigned int)siphash_1u64((u64)ptr, &ptr_secret);
+#else
+	hashval = (unsigned int)siphash_1u32((u32)ptr, &ptr_secret);
+#endif
+
+	spec.field_width = 2 + 2 * sizeof(unsigned int); /* 0x + hex */
+	spec.flags = SPECIAL | SMALL | ZEROPAD;
+	spec.base = 16;
+
+	return number(buf, end, hashval, spec);
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -1703,6 +1769,9 @@ int kptr_restrict __read_mostly;
  * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
  * function pointers are really function descriptors, which contain a
  * pointer to the real address.
+ *
+ * Default behaviour (unadorned %p) is to hash the address, rendering it useful
+ * as a unique identifier.
  */
 static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
@@ -1858,14 +1927,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			return device_node_string(buf, end, ptr, spec, fmt + 1);
 		}
 	}
-	spec.flags |= SMALL;
+
 	if (spec.field_width == -1) {
 		spec.field_width = default_width;
 		spec.flags |= ZEROPAD;
 	}
-	spec.base = 16;
 
-	return number(buf, end, (unsigned long) ptr, spec);
+	return ptr_to_id(buf, end, ptr, spec);
 }
 
 /*
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4] printk: hash addresses printed with %p
  2017-10-18  4:21 ` [kernel-hardening] " Tobin C. Harding
@ 2017-10-18  5:44   ` Sergey Senozhatsky
  -1 siblings, 0 replies; 8+ messages in thread
From: Sergey Senozhatsky @ 2017-10-18  5:44 UTC (permalink / raw)
  To: Tobin C. Harding
  Cc: kernel-hardening, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On (10/18/17 15:21), Tobin C. Harding wrote:
[..]
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 86c3385b9eb3..4609738cd2cd 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -33,6 +33,8 @@
>  #include <linux/uuid.h>
>  #include <linux/of.h>
>  #include <net/addrconf.h>
> +#include <linux/siphash.h>
> +#include <linux/spinlock.h>
>  #ifdef CONFIG_BLOCK
>  #include <linux/blkdev.h>
>  #endif
> @@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
>  	return widen_string(buf, buf - buf_start, end, spec);
>  }
>  
> +/* protects ptr_secret and have_key */
> +DEFINE_SPINLOCK(key_lock);
> +static siphash_key_t ptr_secret __read_mostly;
> +static atomic_t have_key = ATOMIC_INIT(0);
> +
> +static int initialize_ptr_secret(void)
> +{
> +	spin_lock(&key_lock);
> +	if (atomic_read(&have_key) == 1)
> +		goto unlock;
> +
> +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> +	atomic_set(&have_key, 1);
> +
> +unlock:
> +	spin_unlock(&key_lock);
> +	return 0;
> +}

is this spinlock legal? what happens if we are getting interrupted by NMI?

printk()
 vprintk_emit()
  vscnprintf()
   pointer()
    ptr_to_id()
     initialize_ptr_secret()
      spin_lock(&key_lock)

----> NMI

      printk()
       printk_safe_log_store()
        vscnprintf()
         pointer()
          ptr_to_id()
           initialize_ptr_secret()
            spin_lock(&key_lock)   <<<<


or am I completely misreading the patch? sorry if so.

	-ss

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [kernel-hardening] Re: [PATCH v4] printk: hash addresses printed with %p
@ 2017-10-18  5:44   ` Sergey Senozhatsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sergey Senozhatsky @ 2017-10-18  5:44 UTC (permalink / raw)
  To: Tobin C. Harding
  Cc: kernel-hardening, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On (10/18/17 15:21), Tobin C. Harding wrote:
[..]
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index 86c3385b9eb3..4609738cd2cd 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -33,6 +33,8 @@
>  #include <linux/uuid.h>
>  #include <linux/of.h>
>  #include <net/addrconf.h>
> +#include <linux/siphash.h>
> +#include <linux/spinlock.h>
>  #ifdef CONFIG_BLOCK
>  #include <linux/blkdev.h>
>  #endif
> @@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
>  	return widen_string(buf, buf - buf_start, end, spec);
>  }
>  
> +/* protects ptr_secret and have_key */
> +DEFINE_SPINLOCK(key_lock);
> +static siphash_key_t ptr_secret __read_mostly;
> +static atomic_t have_key = ATOMIC_INIT(0);
> +
> +static int initialize_ptr_secret(void)
> +{
> +	spin_lock(&key_lock);
> +	if (atomic_read(&have_key) == 1)
> +		goto unlock;
> +
> +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> +	atomic_set(&have_key, 1);
> +
> +unlock:
> +	spin_unlock(&key_lock);
> +	return 0;
> +}

is this spinlock legal? what happens if we are getting interrupted by NMI?

printk()
 vprintk_emit()
  vscnprintf()
   pointer()
    ptr_to_id()
     initialize_ptr_secret()
      spin_lock(&key_lock)

----> NMI

      printk()
       printk_safe_log_store()
        vscnprintf()
         pointer()
          ptr_to_id()
           initialize_ptr_secret()
            spin_lock(&key_lock)   <<<<


or am I completely misreading the patch? sorry if so.

	-ss

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4] printk: hash addresses printed with %p
  2017-10-18  5:44   ` [kernel-hardening] " Sergey Senozhatsky
@ 2017-10-18  6:04     ` Tobin C. Harding
  -1 siblings, 0 replies; 8+ messages in thread
From: Tobin C. Harding @ 2017-10-18  6:04 UTC (permalink / raw)
  To: Sergey Senozhatsky
  Cc: kernel-hardening, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On Wed, Oct 18, 2017 at 02:44:31PM +0900, Sergey Senozhatsky wrote:
> On (10/18/17 15:21), Tobin C. Harding wrote:
> [..]
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 86c3385b9eb3..4609738cd2cd 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -33,6 +33,8 @@
> >  #include <linux/uuid.h>
> >  #include <linux/of.h>
> >  #include <net/addrconf.h>
> > +#include <linux/siphash.h>
> > +#include <linux/spinlock.h>
> >  #ifdef CONFIG_BLOCK
> >  #include <linux/blkdev.h>
> >  #endif
> > @@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
> >  	return widen_string(buf, buf - buf_start, end, spec);
> >  }
> >  
> > +/* protects ptr_secret and have_key */
> > +DEFINE_SPINLOCK(key_lock);
> > +static siphash_key_t ptr_secret __read_mostly;
> > +static atomic_t have_key = ATOMIC_INIT(0);
> > +
> > +static int initialize_ptr_secret(void)
> > +{
> > +	spin_lock(&key_lock);
> > +	if (atomic_read(&have_key) == 1)
> > +		goto unlock;
> > +
> > +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> > +	atomic_set(&have_key, 1);
> > +
> > +unlock:
> > +	spin_unlock(&key_lock);
> > +	return 0;
> > +}
> 
> is this spinlock legal? what happens if we are getting interrupted by NMI?

I think we can do without the spinlock. I think I was already told that when
I tried to put it [some where else] in v1.

It's fun failing in public ;)

> printk()
>  vprintk_emit()
>   vscnprintf()
>    pointer()
>     ptr_to_id()
>      initialize_ptr_secret()
>       spin_lock(&key_lock)
> 
> ----> NMI
> 
>       printk()
>        printk_safe_log_store()
>         vscnprintf()
>          pointer()
>           ptr_to_id()
>            initialize_ptr_secret()
>             spin_lock(&key_lock)   <<<<
> 
> 
> or am I completely misreading the patch? sorry if so.
> 
> 	-ss

thanks,
Tobin.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [kernel-hardening] Re: [PATCH v4] printk: hash addresses printed with %p
@ 2017-10-18  6:04     ` Tobin C. Harding
  0 siblings, 0 replies; 8+ messages in thread
From: Tobin C. Harding @ 2017-10-18  6:04 UTC (permalink / raw)
  To: Sergey Senozhatsky
  Cc: kernel-hardening, Linus Torvalds, Kees Cook, Paolo Bonzini,
	Tycho Andersen, Roberts, William C, Tejun Heo, Jordan Glover,
	Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On Wed, Oct 18, 2017 at 02:44:31PM +0900, Sergey Senozhatsky wrote:
> On (10/18/17 15:21), Tobin C. Harding wrote:
> [..]
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index 86c3385b9eb3..4609738cd2cd 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -33,6 +33,8 @@
> >  #include <linux/uuid.h>
> >  #include <linux/of.h>
> >  #include <net/addrconf.h>
> > +#include <linux/siphash.h>
> > +#include <linux/spinlock.h>
> >  #ifdef CONFIG_BLOCK
> >  #include <linux/blkdev.h>
> >  #endif
> > @@ -1591,6 +1593,70 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
> >  	return widen_string(buf, buf - buf_start, end, spec);
> >  }
> >  
> > +/* protects ptr_secret and have_key */
> > +DEFINE_SPINLOCK(key_lock);
> > +static siphash_key_t ptr_secret __read_mostly;
> > +static atomic_t have_key = ATOMIC_INIT(0);
> > +
> > +static int initialize_ptr_secret(void)
> > +{
> > +	spin_lock(&key_lock);
> > +	if (atomic_read(&have_key) == 1)
> > +		goto unlock;
> > +
> > +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> > +	atomic_set(&have_key, 1);
> > +
> > +unlock:
> > +	spin_unlock(&key_lock);
> > +	return 0;
> > +}
> 
> is this spinlock legal? what happens if we are getting interrupted by NMI?

I think we can do without the spinlock. I think I was already told that when
I tried to put it [some where else] in v1.

It's fun failing in public ;)

> printk()
>  vprintk_emit()
>   vscnprintf()
>    pointer()
>     ptr_to_id()
>      initialize_ptr_secret()
>       spin_lock(&key_lock)
> 
> ----> NMI
> 
>       printk()
>        printk_safe_log_store()
>         vscnprintf()
>          pointer()
>           ptr_to_id()
>            initialize_ptr_secret()
>             spin_lock(&key_lock)   <<<<
> 
> 
> or am I completely misreading the patch? sorry if so.
> 
> 	-ss

thanks,
Tobin.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4] printk: hash addresses printed with %p
  2017-10-18  6:04     ` [kernel-hardening] " Tobin C. Harding
@ 2017-10-19  0:00       ` Sergey Senozhatsky
  -1 siblings, 0 replies; 8+ messages in thread
From: Sergey Senozhatsky @ 2017-10-19  0:00 UTC (permalink / raw)
  To: Tobin C. Harding
  Cc: Sergey Senozhatsky, kernel-hardening, Linus Torvalds, Kees Cook,
	Paolo Bonzini, Tycho Andersen, Roberts, William C, Tejun Heo,
	Jordan Glover, Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On (10/18/17 17:04), Tobin C. Harding wrote:
[..]
> > > +/* protects ptr_secret and have_key */
> > > +DEFINE_SPINLOCK(key_lock);
> > > +static siphash_key_t ptr_secret __read_mostly;
> > > +static atomic_t have_key = ATOMIC_INIT(0);
> > > +
> > > +static int initialize_ptr_secret(void)
> > > +{
> > > +	spin_lock(&key_lock);
> > > +	if (atomic_read(&have_key) == 1)
> > > +		goto unlock;
> > > +
> > > +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> > > +	atomic_set(&have_key, 1);
> > > +
> > > +unlock:
> > > +	spin_unlock(&key_lock);
> > > +	return 0;
> > > +}
> > 
> > is this spinlock legal? what happens if we are getting interrupted by NMI?
> 
> I think we can do without the spinlock. I think I was already told that when
> I tried to put it [some where else] in v1.
> 
> It's fun failing in public ;)

another note is that printk()->vscnprintf()->get_random_bytes()->warn_unseeded_randomness()
causes a printk() recursion, but we should be fine now, we are in printk_safe
mode by the time we vscnprintf().

but a bigger problem might the following thing:

vscnprintf()
 pointer()
  ptr_to_id()
   initialize_ptr_secret()
    get_random_bytes()
     _get_random_bytes()
      extract_crng()
       _extract_crng()
        spin_lock_irqsave(&crng->lock, flags);   <<<<<


this, once again, can deadlock. can it? just like before:

> > printk()
> >  vprintk_emit()
> >   vscnprintf()
> >    pointer()
> >     ptr_to_id()
> >      initialize_ptr_secret()
> >       spin_lock(&key_lock)
> > 
> > ----> NMI
> > 
> >       printk()
> >        printk_safe_log_store()
> >         vscnprintf()
> >          pointer()
> >           ptr_to_id()
> >            initialize_ptr_secret()
> >             spin_lock(&key_lock)   <<<<

	-ss

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [kernel-hardening] Re: [PATCH v4] printk: hash addresses printed with %p
@ 2017-10-19  0:00       ` Sergey Senozhatsky
  0 siblings, 0 replies; 8+ messages in thread
From: Sergey Senozhatsky @ 2017-10-19  0:00 UTC (permalink / raw)
  To: Tobin C. Harding
  Cc: Sergey Senozhatsky, kernel-hardening, Linus Torvalds, Kees Cook,
	Paolo Bonzini, Tycho Andersen, Roberts, William C, Tejun Heo,
	Jordan Glover, Greg KH, Petr Mladek, Joe Perches, Ian Campbell,
	Sergey Senozhatsky, Catalin Marinas, Will Deacon, Steven Rostedt,
	Chris Fries, Dave Weinstein, Daniel Micay, Djalal Harouni,
	linux-kernel

On (10/18/17 17:04), Tobin C. Harding wrote:
[..]
> > > +/* protects ptr_secret and have_key */
> > > +DEFINE_SPINLOCK(key_lock);
> > > +static siphash_key_t ptr_secret __read_mostly;
> > > +static atomic_t have_key = ATOMIC_INIT(0);
> > > +
> > > +static int initialize_ptr_secret(void)
> > > +{
> > > +	spin_lock(&key_lock);
> > > +	if (atomic_read(&have_key) == 1)
> > > +		goto unlock;
> > > +
> > > +	get_random_bytes(&ptr_secret, sizeof(ptr_secret));
> > > +	atomic_set(&have_key, 1);
> > > +
> > > +unlock:
> > > +	spin_unlock(&key_lock);
> > > +	return 0;
> > > +}
> > 
> > is this spinlock legal? what happens if we are getting interrupted by NMI?
> 
> I think we can do without the spinlock. I think I was already told that when
> I tried to put it [some where else] in v1.
> 
> It's fun failing in public ;)

another note is that printk()->vscnprintf()->get_random_bytes()->warn_unseeded_randomness()
causes a printk() recursion, but we should be fine now, we are in printk_safe
mode by the time we vscnprintf().

but a bigger problem might the following thing:

vscnprintf()
 pointer()
  ptr_to_id()
   initialize_ptr_secret()
    get_random_bytes()
     _get_random_bytes()
      extract_crng()
       _extract_crng()
        spin_lock_irqsave(&crng->lock, flags);   <<<<<


this, once again, can deadlock. can it? just like before:

> > printk()
> >  vprintk_emit()
> >   vscnprintf()
> >    pointer()
> >     ptr_to_id()
> >      initialize_ptr_secret()
> >       spin_lock(&key_lock)
> > 
> > ----> NMI
> > 
> >       printk()
> >        printk_safe_log_store()
> >         vscnprintf()
> >          pointer()
> >           ptr_to_id()
> >            initialize_ptr_secret()
> >             spin_lock(&key_lock)   <<<<

	-ss

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-10-19  0:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-18  4:21 [PATCH v4] printk: hash addresses printed with %p Tobin C. Harding
2017-10-18  4:21 ` [kernel-hardening] " Tobin C. Harding
2017-10-18  5:44 ` Sergey Senozhatsky
2017-10-18  5:44   ` [kernel-hardening] " Sergey Senozhatsky
2017-10-18  6:04   ` Tobin C. Harding
2017-10-18  6:04     ` [kernel-hardening] " Tobin C. Harding
2017-10-19  0:00     ` Sergey Senozhatsky
2017-10-19  0:00       ` [kernel-hardening] " Sergey Senozhatsky

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.