Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-11-14 Thread David Miller
From: Elena Reshetova 
Date: Fri, 20 Oct 2017 10:57:57 +0300

> atomic_t variables are currently used to implement reference
> counters with the following properties:
>  - counter is initialized to 1 using atomic_set()
>  - a resource is freed upon counter reaching zero
>  - once counter reaches zero, its further
>increments aren't allowed
>  - counter schema uses basic atomic operations
>(set, inc, inc_not_zero, dec_and_test, etc.)
> 
> Such atomic variables should be converted to a newly provided
> refcount_t type and API that prevents accidental counter overflows
> and underflows. This is important since overflows and underflows
> can lead to use-after-free situation and be exploitable.
> 
> The variable mdesc_handle.refcnt is used as pure reference counter.
> Convert it to refcount_t and fix up the operations.
> 
> Suggested-by: Kees Cook 
> Reviewed-by: David Windsor 
> Reviewed-by: Hans Liljestrand 
> Signed-off-by: Elena Reshetova 

Applied.


Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-11-14 Thread David Miller
From: Elena Reshetova 
Date: Fri, 20 Oct 2017 10:57:57 +0300

> atomic_t variables are currently used to implement reference
> counters with the following properties:
>  - counter is initialized to 1 using atomic_set()
>  - a resource is freed upon counter reaching zero
>  - once counter reaches zero, its further
>increments aren't allowed
>  - counter schema uses basic atomic operations
>(set, inc, inc_not_zero, dec_and_test, etc.)
> 
> Such atomic variables should be converted to a newly provided
> refcount_t type and API that prevents accidental counter overflows
> and underflows. This is important since overflows and underflows
> can lead to use-after-free situation and be exploitable.
> 
> The variable mdesc_handle.refcnt is used as pure reference counter.
> Convert it to refcount_t and fix up the operations.
> 
> Suggested-by: Kees Cook 
> Reviewed-by: David Windsor 
> Reviewed-by: Hans Liljestrand 
> Signed-off-by: Elena Reshetova 

Applied.


Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-23 Thread Shannon Nelson

On 10/23/2017 12:10 AM, Reshetova, Elena wrote:

On 10/20/2017 12:57 AM, Elena Reshetova wrote:

atomic_t variables are currently used to implement reference
counters with the following properties:
   - counter is initialized to 1 using atomic_set()
   - a resource is freed upon counter reaching zero
   - once counter reaches zero, its further
 increments aren't allowed
   - counter schema uses basic atomic operations
 (set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 


Acked-by: Shannon Nelson 


Thank you Shannon! Would you be able to take this patch into the respective tree
to propagate normally from there?

Best Regards,
Elena.


Hi Elena,

Dave Miller takes good care of the sparclinux tree, I'm sure this is on 
his ToDo list already.


sln



Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-23 Thread Shannon Nelson

On 10/23/2017 12:10 AM, Reshetova, Elena wrote:

On 10/20/2017 12:57 AM, Elena Reshetova wrote:

atomic_t variables are currently used to implement reference
counters with the following properties:
   - counter is initialized to 1 using atomic_set()
   - a resource is freed upon counter reaching zero
   - once counter reaches zero, its further
 increments aren't allowed
   - counter schema uses basic atomic operations
 (set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 


Acked-by: Shannon Nelson 


Thank you Shannon! Would you be able to take this patch into the respective tree
to propagate normally from there?

Best Regards,
Elena.


Hi Elena,

Dave Miller takes good care of the sparclinux tree, I'm sure this is on 
his ToDo list already.


sln



RE: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-23 Thread Reshetova, Elena
> On 10/20/2017 12:57 AM, Elena Reshetova wrote:
> > atomic_t variables are currently used to implement reference
> > counters with the following properties:
> >   - counter is initialized to 1 using atomic_set()
> >   - a resource is freed upon counter reaching zero
> >   - once counter reaches zero, its further
> > increments aren't allowed
> >   - counter schema uses basic atomic operations
> > (set, inc, inc_not_zero, dec_and_test, etc.)
> >
> > Such atomic variables should be converted to a newly provided
> > refcount_t type and API that prevents accidental counter overflows
> > and underflows. This is important since overflows and underflows
> > can lead to use-after-free situation and be exploitable.
> >
> > The variable mdesc_handle.refcnt is used as pure reference counter.
> > Convert it to refcount_t and fix up the operations.
> >
> > Suggested-by: Kees Cook 
> > Reviewed-by: David Windsor 
> > Reviewed-by: Hans Liljestrand 
> > Signed-off-by: Elena Reshetova 
> 
> Acked-by: Shannon Nelson 

Thank you Shannon! Would you be able to take this patch into the respective tree
to propagate normally from there?

Best Regards,
Elena.
> 
> > ---
> >   arch/sparc/kernel/mdesc.c | 17 +
> >   1 file changed, 9 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
> > index fa466ce..821a724 100644
> > --- a/arch/sparc/kernel/mdesc.c
> > +++ b/arch/sparc/kernel/mdesc.c
> > @@ -12,6 +12,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >
> >   #include 
> >   #include 
> > @@ -70,7 +71,7 @@ struct mdesc_handle {
> > struct list_headlist;
> > struct mdesc_mem_ops*mops;
> > void*self_base;
> > -   atomic_trefcnt;
> > +   refcount_t  refcnt;
> > unsigned inthandle_size;
> > struct mdesc_hdrmdesc;
> >   };
> > @@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
> > memset(hp, 0, handle_size);
> > INIT_LIST_HEAD(>list);
> > hp->self_base = base;
> > -   atomic_set(>refcnt, 1);
> > +   refcount_set(>refcnt, 1);
> > hp->handle_size = handle_size;
> >   }
> >
> > @@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct
> mdesc_handle *hp)
> > unsigned int alloc_size;
> > unsigned long start;
> >
> > -   BUG_ON(atomic_read(>refcnt) != 0);
> > +   BUG_ON(refcount_read(>refcnt) != 0);
> > BUG_ON(!list_empty(>list));
> >
> > alloc_size = PAGE_ALIGN(hp->handle_size);
> > @@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int
> mdesc_size)
> >
> >   static void mdesc_kfree(struct mdesc_handle *hp)
> >   {
> > -   BUG_ON(atomic_read(>refcnt) != 0);
> > +   BUG_ON(refcount_read(>refcnt) != 0);
> > BUG_ON(!list_empty(>list));
> >
> > kfree(hp->self_base);
> > @@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
> > spin_lock_irqsave(_lock, flags);
> > hp = cur_mdesc;
> > if (hp)
> > -   atomic_inc(>refcnt);
> > +   refcount_inc(>refcnt);
> > spin_unlock_irqrestore(_lock, flags);
> >
> > return hp;
> > @@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
> > unsigned long flags;
> >
> > spin_lock_irqsave(_lock, flags);
> > -   if (atomic_dec_and_test(>refcnt)) {
> > +   if (refcount_dec_and_test(>refcnt)) {
> > list_del_init(>list);
> > hp->mops->free(hp);
> > }
> > @@ -513,7 +514,7 @@ void mdesc_update(void)
> > if (status != HV_EOK || real_len > len) {
> > printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
> >status);
> > -   atomic_dec(>refcnt);
> > +   refcount_dec(>refcnt);
> > mdesc_free(hp);
> > goto out;
> > }
> > @@ -526,7 +527,7 @@ void mdesc_update(void)
> > mdesc_notify_clients(orig_hp, hp);
> >
> > spin_lock_irqsave(_lock, flags);
> > -   if (atomic_dec_and_test(_hp->refcnt))
> > +   if (refcount_dec_and_test(_hp->refcnt))
> > mdesc_free(orig_hp);
> > else
> > list_add(_hp->list, _zombie_list);
> >


RE: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-23 Thread Reshetova, Elena
> On 10/20/2017 12:57 AM, Elena Reshetova wrote:
> > atomic_t variables are currently used to implement reference
> > counters with the following properties:
> >   - counter is initialized to 1 using atomic_set()
> >   - a resource is freed upon counter reaching zero
> >   - once counter reaches zero, its further
> > increments aren't allowed
> >   - counter schema uses basic atomic operations
> > (set, inc, inc_not_zero, dec_and_test, etc.)
> >
> > Such atomic variables should be converted to a newly provided
> > refcount_t type and API that prevents accidental counter overflows
> > and underflows. This is important since overflows and underflows
> > can lead to use-after-free situation and be exploitable.
> >
> > The variable mdesc_handle.refcnt is used as pure reference counter.
> > Convert it to refcount_t and fix up the operations.
> >
> > Suggested-by: Kees Cook 
> > Reviewed-by: David Windsor 
> > Reviewed-by: Hans Liljestrand 
> > Signed-off-by: Elena Reshetova 
> 
> Acked-by: Shannon Nelson 

Thank you Shannon! Would you be able to take this patch into the respective tree
to propagate normally from there?

Best Regards,
Elena.
> 
> > ---
> >   arch/sparc/kernel/mdesc.c | 17 +
> >   1 file changed, 9 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
> > index fa466ce..821a724 100644
> > --- a/arch/sparc/kernel/mdesc.c
> > +++ b/arch/sparc/kernel/mdesc.c
> > @@ -12,6 +12,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >
> >   #include 
> >   #include 
> > @@ -70,7 +71,7 @@ struct mdesc_handle {
> > struct list_headlist;
> > struct mdesc_mem_ops*mops;
> > void*self_base;
> > -   atomic_trefcnt;
> > +   refcount_t  refcnt;
> > unsigned inthandle_size;
> > struct mdesc_hdrmdesc;
> >   };
> > @@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
> > memset(hp, 0, handle_size);
> > INIT_LIST_HEAD(>list);
> > hp->self_base = base;
> > -   atomic_set(>refcnt, 1);
> > +   refcount_set(>refcnt, 1);
> > hp->handle_size = handle_size;
> >   }
> >
> > @@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct
> mdesc_handle *hp)
> > unsigned int alloc_size;
> > unsigned long start;
> >
> > -   BUG_ON(atomic_read(>refcnt) != 0);
> > +   BUG_ON(refcount_read(>refcnt) != 0);
> > BUG_ON(!list_empty(>list));
> >
> > alloc_size = PAGE_ALIGN(hp->handle_size);
> > @@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int
> mdesc_size)
> >
> >   static void mdesc_kfree(struct mdesc_handle *hp)
> >   {
> > -   BUG_ON(atomic_read(>refcnt) != 0);
> > +   BUG_ON(refcount_read(>refcnt) != 0);
> > BUG_ON(!list_empty(>list));
> >
> > kfree(hp->self_base);
> > @@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
> > spin_lock_irqsave(_lock, flags);
> > hp = cur_mdesc;
> > if (hp)
> > -   atomic_inc(>refcnt);
> > +   refcount_inc(>refcnt);
> > spin_unlock_irqrestore(_lock, flags);
> >
> > return hp;
> > @@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
> > unsigned long flags;
> >
> > spin_lock_irqsave(_lock, flags);
> > -   if (atomic_dec_and_test(>refcnt)) {
> > +   if (refcount_dec_and_test(>refcnt)) {
> > list_del_init(>list);
> > hp->mops->free(hp);
> > }
> > @@ -513,7 +514,7 @@ void mdesc_update(void)
> > if (status != HV_EOK || real_len > len) {
> > printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
> >status);
> > -   atomic_dec(>refcnt);
> > +   refcount_dec(>refcnt);
> > mdesc_free(hp);
> > goto out;
> > }
> > @@ -526,7 +527,7 @@ void mdesc_update(void)
> > mdesc_notify_clients(orig_hp, hp);
> >
> > spin_lock_irqsave(_lock, flags);
> > -   if (atomic_dec_and_test(_hp->refcnt))
> > +   if (refcount_dec_and_test(_hp->refcnt))
> > mdesc_free(orig_hp);
> > else
> > list_add(_hp->list, _zombie_list);
> >


Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-20 Thread Shannon Nelson

On 10/20/2017 12:57 AM, Elena Reshetova wrote:

atomic_t variables are currently used to implement reference
counters with the following properties:
  - counter is initialized to 1 using atomic_set()
  - a resource is freed upon counter reaching zero
  - once counter reaches zero, its further
increments aren't allowed
  - counter schema uses basic atomic operations
(set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 


Acked-by: Shannon Nelson 


---
  arch/sparc/kernel/mdesc.c | 17 +
  1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index fa466ce..821a724 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -12,6 +12,7 @@
  #include 
  #include 
  #include 
+#include 
  
  #include 

  #include 
@@ -70,7 +71,7 @@ struct mdesc_handle {
struct list_headlist;
struct mdesc_mem_ops*mops;
void*self_base;
-   atomic_trefcnt;
+   refcount_t  refcnt;
unsigned inthandle_size;
struct mdesc_hdrmdesc;
  };
@@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
memset(hp, 0, handle_size);
INIT_LIST_HEAD(>list);
hp->self_base = base;
-   atomic_set(>refcnt, 1);
+   refcount_set(>refcnt, 1);
hp->handle_size = handle_size;
  }
  
@@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct mdesc_handle *hp)

unsigned int alloc_size;
unsigned long start;
  
-	BUG_ON(atomic_read(>refcnt) != 0);

+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
  
  	alloc_size = PAGE_ALIGN(hp->handle_size);

@@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int 
mdesc_size)
  
  static void mdesc_kfree(struct mdesc_handle *hp)

  {
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
  
  	kfree(hp->self_base);

@@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
spin_lock_irqsave(_lock, flags);
hp = cur_mdesc;
if (hp)
-   atomic_inc(>refcnt);
+   refcount_inc(>refcnt);
spin_unlock_irqrestore(_lock, flags);
  
  	return hp;

@@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
unsigned long flags;
  
  	spin_lock_irqsave(_lock, flags);

-   if (atomic_dec_and_test(>refcnt)) {
+   if (refcount_dec_and_test(>refcnt)) {
list_del_init(>list);
hp->mops->free(hp);
}
@@ -513,7 +514,7 @@ void mdesc_update(void)
if (status != HV_EOK || real_len > len) {
printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
   status);
-   atomic_dec(>refcnt);
+   refcount_dec(>refcnt);
mdesc_free(hp);
goto out;
}
@@ -526,7 +527,7 @@ void mdesc_update(void)
mdesc_notify_clients(orig_hp, hp);
  
  	spin_lock_irqsave(_lock, flags);

-   if (atomic_dec_and_test(_hp->refcnt))
+   if (refcount_dec_and_test(_hp->refcnt))
mdesc_free(orig_hp);
else
list_add(_hp->list, _zombie_list);



Re: [PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-20 Thread Shannon Nelson

On 10/20/2017 12:57 AM, Elena Reshetova wrote:

atomic_t variables are currently used to implement reference
counters with the following properties:
  - counter is initialized to 1 using atomic_set()
  - a resource is freed upon counter reaching zero
  - once counter reaches zero, its further
increments aren't allowed
  - counter schema uses basic atomic operations
(set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 


Acked-by: Shannon Nelson 


---
  arch/sparc/kernel/mdesc.c | 17 +
  1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index fa466ce..821a724 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -12,6 +12,7 @@
  #include 
  #include 
  #include 
+#include 
  
  #include 

  #include 
@@ -70,7 +71,7 @@ struct mdesc_handle {
struct list_headlist;
struct mdesc_mem_ops*mops;
void*self_base;
-   atomic_trefcnt;
+   refcount_t  refcnt;
unsigned inthandle_size;
struct mdesc_hdrmdesc;
  };
@@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
memset(hp, 0, handle_size);
INIT_LIST_HEAD(>list);
hp->self_base = base;
-   atomic_set(>refcnt, 1);
+   refcount_set(>refcnt, 1);
hp->handle_size = handle_size;
  }
  
@@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct mdesc_handle *hp)

unsigned int alloc_size;
unsigned long start;
  
-	BUG_ON(atomic_read(>refcnt) != 0);

+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
  
  	alloc_size = PAGE_ALIGN(hp->handle_size);

@@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int 
mdesc_size)
  
  static void mdesc_kfree(struct mdesc_handle *hp)

  {
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
  
  	kfree(hp->self_base);

@@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
spin_lock_irqsave(_lock, flags);
hp = cur_mdesc;
if (hp)
-   atomic_inc(>refcnt);
+   refcount_inc(>refcnt);
spin_unlock_irqrestore(_lock, flags);
  
  	return hp;

@@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
unsigned long flags;
  
  	spin_lock_irqsave(_lock, flags);

-   if (atomic_dec_and_test(>refcnt)) {
+   if (refcount_dec_and_test(>refcnt)) {
list_del_init(>list);
hp->mops->free(hp);
}
@@ -513,7 +514,7 @@ void mdesc_update(void)
if (status != HV_EOK || real_len > len) {
printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
   status);
-   atomic_dec(>refcnt);
+   refcount_dec(>refcnt);
mdesc_free(hp);
goto out;
}
@@ -526,7 +527,7 @@ void mdesc_update(void)
mdesc_notify_clients(orig_hp, hp);
  
  	spin_lock_irqsave(_lock, flags);

-   if (atomic_dec_and_test(_hp->refcnt))
+   if (refcount_dec_and_test(_hp->refcnt))
mdesc_free(orig_hp);
else
list_add(_hp->list, _zombie_list);



[PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-20 Thread Elena Reshetova
atomic_t variables are currently used to implement reference
counters with the following properties:
 - counter is initialized to 1 using atomic_set()
 - a resource is freed upon counter reaching zero
 - once counter reaches zero, its further
   increments aren't allowed
 - counter schema uses basic atomic operations
   (set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 arch/sparc/kernel/mdesc.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index fa466ce..821a724 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -70,7 +71,7 @@ struct mdesc_handle {
struct list_headlist;
struct mdesc_mem_ops*mops;
void*self_base;
-   atomic_trefcnt;
+   refcount_t  refcnt;
unsigned inthandle_size;
struct mdesc_hdrmdesc;
 };
@@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
memset(hp, 0, handle_size);
INIT_LIST_HEAD(>list);
hp->self_base = base;
-   atomic_set(>refcnt, 1);
+   refcount_set(>refcnt, 1);
hp->handle_size = handle_size;
 }
 
@@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct mdesc_handle 
*hp)
unsigned int alloc_size;
unsigned long start;
 
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
 
alloc_size = PAGE_ALIGN(hp->handle_size);
@@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int 
mdesc_size)
 
 static void mdesc_kfree(struct mdesc_handle *hp)
 {
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
 
kfree(hp->self_base);
@@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
spin_lock_irqsave(_lock, flags);
hp = cur_mdesc;
if (hp)
-   atomic_inc(>refcnt);
+   refcount_inc(>refcnt);
spin_unlock_irqrestore(_lock, flags);
 
return hp;
@@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
unsigned long flags;
 
spin_lock_irqsave(_lock, flags);
-   if (atomic_dec_and_test(>refcnt)) {
+   if (refcount_dec_and_test(>refcnt)) {
list_del_init(>list);
hp->mops->free(hp);
}
@@ -513,7 +514,7 @@ void mdesc_update(void)
if (status != HV_EOK || real_len > len) {
printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
   status);
-   atomic_dec(>refcnt);
+   refcount_dec(>refcnt);
mdesc_free(hp);
goto out;
}
@@ -526,7 +527,7 @@ void mdesc_update(void)
mdesc_notify_clients(orig_hp, hp);
 
spin_lock_irqsave(_lock, flags);
-   if (atomic_dec_and_test(_hp->refcnt))
+   if (refcount_dec_and_test(_hp->refcnt))
mdesc_free(orig_hp);
else
list_add(_hp->list, _zombie_list);
-- 
2.7.4



[PATCH] sparc64: convert mdesc_handle.refcnt from atomic_t to refcount_t

2017-10-20 Thread Elena Reshetova
atomic_t variables are currently used to implement reference
counters with the following properties:
 - counter is initialized to 1 using atomic_set()
 - a resource is freed upon counter reaching zero
 - once counter reaches zero, its further
   increments aren't allowed
 - counter schema uses basic atomic operations
   (set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable mdesc_handle.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 arch/sparc/kernel/mdesc.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index fa466ce..821a724 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -70,7 +71,7 @@ struct mdesc_handle {
struct list_headlist;
struct mdesc_mem_ops*mops;
void*self_base;
-   atomic_trefcnt;
+   refcount_t  refcnt;
unsigned inthandle_size;
struct mdesc_hdrmdesc;
 };
@@ -152,7 +153,7 @@ static void mdesc_handle_init(struct mdesc_handle *hp,
memset(hp, 0, handle_size);
INIT_LIST_HEAD(>list);
hp->self_base = base;
-   atomic_set(>refcnt, 1);
+   refcount_set(>refcnt, 1);
hp->handle_size = handle_size;
 }
 
@@ -182,7 +183,7 @@ static void __init mdesc_memblock_free(struct mdesc_handle 
*hp)
unsigned int alloc_size;
unsigned long start;
 
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
 
alloc_size = PAGE_ALIGN(hp->handle_size);
@@ -220,7 +221,7 @@ static struct mdesc_handle *mdesc_kmalloc(unsigned int 
mdesc_size)
 
 static void mdesc_kfree(struct mdesc_handle *hp)
 {
-   BUG_ON(atomic_read(>refcnt) != 0);
+   BUG_ON(refcount_read(>refcnt) != 0);
BUG_ON(!list_empty(>list));
 
kfree(hp->self_base);
@@ -259,7 +260,7 @@ struct mdesc_handle *mdesc_grab(void)
spin_lock_irqsave(_lock, flags);
hp = cur_mdesc;
if (hp)
-   atomic_inc(>refcnt);
+   refcount_inc(>refcnt);
spin_unlock_irqrestore(_lock, flags);
 
return hp;
@@ -271,7 +272,7 @@ void mdesc_release(struct mdesc_handle *hp)
unsigned long flags;
 
spin_lock_irqsave(_lock, flags);
-   if (atomic_dec_and_test(>refcnt)) {
+   if (refcount_dec_and_test(>refcnt)) {
list_del_init(>list);
hp->mops->free(hp);
}
@@ -513,7 +514,7 @@ void mdesc_update(void)
if (status != HV_EOK || real_len > len) {
printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
   status);
-   atomic_dec(>refcnt);
+   refcount_dec(>refcnt);
mdesc_free(hp);
goto out;
}
@@ -526,7 +527,7 @@ void mdesc_update(void)
mdesc_notify_clients(orig_hp, hp);
 
spin_lock_irqsave(_lock, flags);
-   if (atomic_dec_and_test(_hp->refcnt))
+   if (refcount_dec_and_test(_hp->refcnt))
mdesc_free(orig_hp);
else
list_add(_hp->list, _zombie_list);
-- 
2.7.4