[ANNOUNCE][CFP] Linux Security Summit Europe 2020

2020-05-07 Thread Elena Reshetova
==
   ANNOUNCEMENT AND CALL FOR PARTICIPATION

LINUX SECURITY SUMMIT EUROPE 2020

 29-30 OCTOBER
DUBLIN, IRELAND
==

DESCRIPTION

Linux Security Summit Europe (LSS-EU) is a technical forum for
collaboration between Linux developers, researchers, and end-users.  Its
primary aim is to foster community efforts in analyzing and solving Linux
security challenges.

 The program committee currently seeks proposals for:

   * Refereed Presentations:
 45 minutes in length.

   * Panel Discussion Topics:
 45 minutes in length.

   * Short Topics:
 30 minutes in total, including at least 10 minutes discussion.

   * Tutorials
 90 minutes in length.

Tutorial sessions should be focused on advanced Linux security defense
topics within areas such as the kernel, compiler, and security-related
libraries.  Priority will be given to tutorials created for this conference,
and those where the presenter a leading subject matter expert on the topic.

Topic areas include, but are not limited to:

   * Kernel self-protection
   * Access control
   * Cryptography and key management
   * Integrity policy and enforcement
   * Hardware Security
   * IoT and embedded security
   * Virtualization and containers
   * System-specific system hardening
   * Case studies
   * Security tools
   * Security UX
   * Emerging technologies, threats & techniques

  Proposals should be submitted via:

   https://events.linuxfoundation.org/linux-security-summit-europe/program/cfp/

DATES

  * CFP close:July 31
  * CFP notifications:August 10
  * Schedule announced:   September 1
  * Event:October 29-30

COVID-19 SITUATION

Currently LSS-EU is planned as in-person event, however this would be
re-evaluated closer to the event itself and if the situation in Europe does
not permit such events, it would be switched to a virtual event, similarly
as this year’s LSS-NA.

WHO SHOULD ATTEND

We're seeking a diverse range of attendees and welcome participation by
people involved in Linux security development, operations, and research.

LSS-EU is a unique global event that provides the opportunity to present and
discuss your work or research with key Linux security community members and
maintainers.  It’s also useful for those who wish to keep up with the latest
in Linux security development and to provide input to the development
process.

WEB SITE

https://events.linuxfoundation.org/linux-security-summit-europe/

TWITTER

  For event updates and announcements, follow:

https://twitter.com/LinuxSecSummit

#linuxsecuritysummit

PROGRAM COMMITTEE

  The program committee for LSS 2020 is:

* James Morris, Microsoft
* Serge Hallyn, Cisco
* Paul Moore, Cisco
* Stephen Smalley, NSA
    * Elena Reshetova, Intel
* John Johansen, Canonical
* Kees Cook, Google
* Casey Schaufler, Intel
* Mimi Zohar, IBM
* David A. Wheeler, Institute for Defense Analyses

  The program committee may be contacted as a group via email:
lss-pc () lists.linuxfoundation.org


[PATCH] x86/entry/64: randomize kernel stack offset upon syscall

2019-04-15 Thread Elena Reshetova
of the above two differences, the implementation
of RANDKSTACK and RANDOMIZE_KSTACK_OFFSET has nothing in common.

[4] https://www.openwall.com/lists/kernel-hardening/2019/02/08/6

Signed-off-by: Elena Reshetova 
---
 arch/Kconfig| 15 +++
 arch/x86/Kconfig|  1 +
 arch/x86/entry/common.c | 18 ++
 3 files changed, 34 insertions(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index 4cfb6de48f79..9a2557b0cfce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -808,6 +808,21 @@ config VMAP_STACK
  the stack to map directly to the KASAN shadow map using a formula
  that is incorrect if the stack is in vmalloc space.
 
+config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   def_bool n
+   help
+ An arch should select this symbol if it can support kernel stack
+ offset randomization.
+
+config RANDOMIZE_KSTACK_OFFSET
+   default n
+   bool "Randomize kernel stack offset on syscall entry"
+   depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   help
+ Enable this if you want the randomize kernel stack offset upon
+ each syscall entry. This causes kernel stack (after pt_regs) to
+ have a randomized offset upon executing each system call.
+
 config ARCH_OPTIONAL_KERNEL_RWX
def_bool n
 
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ade12ec4224b..87e5444cd366 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -131,6 +131,7 @@ config X86
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
select HAVE_ARCH_VMAP_STACK if X86_64
+   select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 7bc105f47d21..076085611e94 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -35,6 +35,20 @@
 #define CREATE_TRACE_POINTS
 #include 
 
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
+#include 
+
+void *__builtin_alloca(size_t size);
+
+#define add_random_stack_offset() do {   \
+   size_t offset = ((size_t)prandom_u32()) % 256;   \
+   char *ptr = __builtin_alloca(offset);\
+   asm volatile("":"=m"(*ptr)); \
+} while (0)
+#else
+#define add_random_stack_offset() do {} while (0)
+#endif
+
 #ifdef CONFIG_CONTEXT_TRACKING
 /* Called on entry from user mode with IRQs off. */
 __visible inline void enter_from_user_mode(void)
@@ -273,6 +287,7 @@ __visible void do_syscall_64(unsigned long nr, struct 
pt_regs *regs)
 {
struct thread_info *ti;
 
+   add_random_stack_offset();
enter_from_user_mode();
local_irq_enable();
ti = current_thread_info();
@@ -344,6 +359,7 @@ static __always_inline void do_syscall_32_irqs_on(struct 
pt_regs *regs)
 /* Handles int $0x80 */
 __visible void do_int80_syscall_32(struct pt_regs *regs)
 {
+   add_random_stack_offset();
enter_from_user_mode();
local_irq_enable();
do_syscall_32_irqs_on(regs);
@@ -360,6 +376,8 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
unsigned long landing_pad = (unsigned long)current->mm->context.vdso +
vdso_image_32.sym_int80_landing_pad;
 
+   add_random_stack_offset();
+
/*
 * SYSENTER loses EIP, and even SYSCALL32 needs us to skip forward
 * so that 'regs->ip -= 2' lands back on an int $0x80 instruction.
-- 
2.17.1



[PATCH 1/1] x86/entry/64: randomize kernel stack offset upon syscall

2019-04-10 Thread Elena Reshetova
 the exit, as with RANDKSTACK.

Also, as a result of the above two differences, the implementation
of RANDKSTACK and RANDOMIZE_KSTACK_OFFSET has nothing in common.

[4] https://www.openwall.com/lists/kernel-hardening/2019/02/08/6

Signed-off-by: Elena Reshetova 
---
 arch/Kconfig| 15 +++
 arch/x86/Kconfig|  1 +
 arch/x86/entry/common.c | 13 +
 3 files changed, 29 insertions(+)

diff --git a/arch/Kconfig b/arch/Kconfig
index 4cfb6de48f79..9a2557b0cfce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -808,6 +808,21 @@ config VMAP_STACK
  the stack to map directly to the KASAN shadow map using a formula
  that is incorrect if the stack is in vmalloc space.
 
+config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   def_bool n
+   help
+ An arch should select this symbol if it can support kernel stack
+ offset randomization.
+
+config RANDOMIZE_KSTACK_OFFSET
+   default n
+   bool "Randomize kernel stack offset on syscall entry"
+   depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   help
+ Enable this if you want the randomize kernel stack offset upon
+ each syscall entry. This causes kernel stack (after pt_regs) to
+ have a randomized offset upon executing each system call.
+
 config ARCH_OPTIONAL_KERNEL_RWX
def_bool n
 
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ade12ec4224b..5edcae945b73 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -131,6 +131,7 @@ config X86
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
select HAVE_ARCH_VMAP_STACK if X86_64
+   select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET  if X86_64
select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 7bc105f47d21..58fd17eaca1a 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -35,6 +35,12 @@
 #define CREATE_TRACE_POINTS
 #include 
 
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
+#include 
+
+void *__builtin_alloca(size_t size);
+#endif
+
 #ifdef CONFIG_CONTEXT_TRACKING
 /* Called on entry from user mode with IRQs off. */
 __visible inline void enter_from_user_mode(void)
@@ -273,6 +279,13 @@ __visible void do_syscall_64(unsigned long nr, struct 
pt_regs *regs)
 {
struct thread_info *ti;
 
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
+   size_t offset = ((size_t)prandom_u32()) % 256;
+   char *ptr = __builtin_alloca(offset);
+
+   asm volatile("":"=m"(*ptr));
+#endif
+
enter_from_user_mode();
local_irq_enable();
ti = current_thread_info();
-- 
2.17.1



[PATCH 0/1] v2, randomize stack offset upon syscall

2019-04-10 Thread Elena Reshetova
Resending the patch since the first attempt never made
it to lkml.

changes in v2:
 - alloca() is changed to __builtin_alloca() in order
   to be compatible with 32 bit versions

Elena Reshetova (1):
  x86/entry/64: randomize kernel stack offset upon syscall

 arch/Kconfig| 15 +++
 arch/x86/Kconfig|  1 +
 arch/x86/entry/common.c | 13 +
 3 files changed, 29 insertions(+)

-- 
2.17.1



[RFC PATCH] x86/entry/64: randomize kernel stack offset upon syscall

2019-03-18 Thread Elena Reshetova
is done upon
syscall entry and not the exit, as with RANDKSTACK.

Also, as a result of the above two differences, the implementation
of RANDKSTACK and RANDOMIZE_KSTACK_OFFSET has nothing in common.

[4] https://www.openwall.com/lists/kernel-hardening/2019/02/08/6

Signed-off-by: Elena Reshetova 
---
 arch/Kconfig   | 15 +++
 arch/x86/Kconfig   |  1 +
 arch/x86/entry/calling.h   | 14 ++
 arch/x86/entry/entry_64.S  |  6 ++
 arch/x86/include/asm/frame.h   |  3 +++
 arch/x86/kernel/dumpstack.c| 10 +-
 arch/x86/kernel/unwind_frame.c |  9 -
 7 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 4cfb6de48f79..9a2557b0cfce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -808,6 +808,21 @@ config VMAP_STACK
  the stack to map directly to the KASAN shadow map using a formula
  that is incorrect if the stack is in vmalloc space.
 
+config HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   def_bool n
+   help
+ An arch should select this symbol if it can support kernel stack
+ offset randomization.
+
+config RANDOMIZE_KSTACK_OFFSET
+   default n
+   bool "Randomize kernel stack offset on syscall entry"
+   depends on HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
+   help
+ Enable this if you want the randomize kernel stack offset upon
+ each syscall entry. This causes kernel stack (after pt_regs) to
+ have a randomized offset upon executing each system call.
+
 config ARCH_OPTIONAL_KERNEL_RWX
def_bool n
 
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ade12ec4224b..5edcae945b73 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -131,6 +131,7 @@ config X86
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
select HAVE_ARCH_VMAP_STACK if X86_64
+   select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET  if X86_64
select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index efb0d1b1f15f..68502645d812 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -345,6 +345,20 @@ For 32-bit we have the following conventions - kernel is 
built with
 #endif
 .endm
 
+.macro RANDOMIZE_KSTACK
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
+   /* prepare a random offset in rax */
+   pushq %rax
+   xorq  %rax, %rax
+   ALTERNATIVE "rdtsc", "rdrand %rax", X86_FEATURE_RDRAND
+   andq  $__MAX_STACK_RANDOM_OFFSET, %rax
+
+   /* store offset in r15 */
+   movq  %rax, %r15
+   popq  %rax
+#endif
+.endm
+
 /*
  * This does 'call enter_from_user_mode' unless we can avoid it based on
  * kernel config or using the static jump infrastructure.
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 1f0efdb7b629..0816ec680c21 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -167,13 +167,19 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
 
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
 
+   RANDOMIZE_KSTACK/* stores randomized offset in r15 */
+
TRACE_IRQS_OFF
 
/* IRQs are off. */
movq%rax, %rdi
movq%rsp, %rsi
+   sub %r15, %rsp  /* substitute random offset from rsp */
calldo_syscall_64   /* returns with IRQs disabled */
 
+   /* need to restore the gap */
+   add %r15, %rsp   /* add random offset back to rsp */
+
TRACE_IRQS_IRETQ/* we're about to change IF */
 
/*
diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h
index 5cbce6fbb534..e1bb91504f6e 100644
--- a/arch/x86/include/asm/frame.h
+++ b/arch/x86/include/asm/frame.h
@@ -4,6 +4,9 @@
 
 #include 
 
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
+#define __MAX_STACK_RANDOM_OFFSET 0xFF0
+#endif
 /*
  * These are stack frame creation macros.  They should be used by every
  * callable non-leaf asm function to make kernel stack traces more reliable.
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 2b5886401e5f..4146a4c3e9c6 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -192,7 +192,6 @@ void show_trace_log_lvl(struct task_struct *task, struct 
pt_regs *regs,
 */
for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
const char *stack_name;
-
if (get_stack_info(stack, task, _info, _mask)) {
/*
 * We weren't on a valid stack.  It's possible that
@@ -224,6 +223,9 @@ void show_trace_log_lvl(struct task_struct *task, struct 
pt_regs *regs,
 */
for (; stack < stack_info.end; stack++) {
unsigned long real_addr;
+#ifdef CONFIG_RANDOMIZE_KSTACK_OFF

[PATCH 2/3] groups: convert group_info.usage to refcount_t

2019-03-06 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 group_info.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the group_info.usage it might make a difference
in following places:
 - put_group_info(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/cred.h | 7 ---
 kernel/cred.c| 2 +-
 kernel/groups.c  | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index ddd45bb74887..cad4b415ae90 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,7 +28,7 @@ struct inode;
  * COW Supplementary groups list
  */
 struct group_info {
-   atomic_tusage;
+   refcount_t  usage;
int ngroups;
kgid_t  gid[0];
 } __randomize_layout;
@@ -43,7 +44,7 @@ struct group_info {
  */
 static inline struct group_info *get_group_info(struct group_info *gi)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return gi;
 }
 
@@ -53,7 +54,7 @@ static inline struct group_info *get_group_info(struct 
group_info *gi)
  */
 #define put_group_info(group_info) \
 do {   \
-   if (atomic_dec_and_test(&(group_info)->usage))  \
+   if (refcount_dec_and_test(&(group_info)->usage))\
groups_free(group_info);\
 } while (0)
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 45d77284aed0..49d23bd45a23 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -37,7 +37,7 @@ do {  
\
 static struct kmem_cache *cred_jar;
 
 /* init to 2 - one for init_task, one to ensure it is never freed */
-struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
+struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
 
 /*
  * The initial credentials for the initial task
diff --git a/kernel/groups.c b/kernel/groups.c
index daae2f2dc6d4..e8194bbf0dbe 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -24,7 +24,7 @@ struct group_info *groups_alloc(int gidsetsize)
if (!gi)
return NULL;
 
-   atomic_set(>usage, 1);
+   refcount_set(>usage, 1);
gi->ngroups = gidsetsize;
return gi;
 }
-- 
2.17.1



[PATCH 1/3] nsproxy: convert nsproxy.count to refcount_t

2019-03-06 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 nsproxy.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nsproxy.count it might make a difference
in following places:
 - put_nsproxy() and switch_task_namespaces(): decrement in
   refcount_dec_and_test() only provides RELEASE ordering
   and ACQUIRE ordering on success vs. fully ordered
   atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/nsproxy.h | 6 +++---
 kernel/nsproxy.c| 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 2ae1b1a4d84d..90f09ffca20f 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -29,7 +29,7 @@ struct fs_struct;
  * nsproxy is copied.
  */
 struct nsproxy {
-   atomic_t count;
+   refcount_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
@@ -75,14 +75,14 @@ int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
-   if (atomic_dec_and_test(>count)) {
+   if (refcount_dec_and_test(>count)) {
free_nsproxy(ns);
}
 }
 
 static inline void get_nsproxy(struct nsproxy *ns)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
 }
 
 #endif
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f6c5d330059a..5bfe69194621 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -31,7 +31,7 @@
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = {
-   .count  = ATOMIC_INIT(1),
+   .count  = REFCOUNT_INIT(1),
.uts_ns = _uts_ns,
 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
.ipc_ns = _ipc_ns,
@@ -52,7 +52,7 @@ static inline struct nsproxy *create_nsproxy(void)
 
nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
if (nsproxy)
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
return nsproxy;
 }
 
@@ -225,7 +225,7 @@ void switch_task_namespaces(struct task_struct *p, struct 
nsproxy *new)
p->nsproxy = new;
task_unlock(p);
 
-   if (ns && atomic_dec_and_test(>count))
+   if (ns && refcount_dec_and_test(>count))
free_nsproxy(ns);
 }
 
-- 
2.17.1



[PATCH 3/3] creds: convert cred.usage to refcount_t

2019-03-06 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 cred.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the cred.usage it might make a difference
in following places:
 - get_task_cred(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_cred(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/cred.h |  8 
 kernel/cred.c| 42 +-
 net/sunrpc/auth.c|  2 +-
 3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index cad4b415ae90..ee99a39e 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -114,7 +114,7 @@ static inline int groups_search(const struct group_info 
*group_info, kgid_t grp)
  * same context as task->real_cred.
  */
 struct cred {
-   atomic_tusage;
+   refcount_t  usage;
 #ifdef CONFIG_DEBUG_CREDENTIALS
atomic_tsubscribers;/* number of processes subscribed */
void*put_addr;
@@ -228,7 +228,7 @@ static inline bool cap_ambient_invariant_ok(const struct 
cred *cred)
  */
 static inline struct cred *get_new_cred(struct cred *cred)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return cred;
 }
 
@@ -259,7 +259,7 @@ static inline const struct cred *get_cred_rcu(const struct 
cred *cred)
struct cred *nonconst_cred = (struct cred *) cred;
if (!cred)
return NULL;
-   if (!atomic_inc_not_zero(_cred->usage))
+   if (!refcount_inc_not_zero(_cred->usage))
return NULL;
validate_creds(cred);
return cred;
@@ -282,7 +282,7 @@ static inline void put_cred(const struct cred *_cred)
 
if (cred) {
validate_creds(cred);
-   if (atomic_dec_and_test(&(cred)->usage))
+   if (refcount_dec_and_test(&(cred)->usage))
__put_cred(cred);
}
 }
diff --git a/kernel/cred.c b/kernel/cred.c
index 49d23bd45a23..ceb2f8a2399e 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -43,7 +43,7 @@ struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
  * The initial credentials for the initial task
  */
 struct cred init_cred = {
-   .usage  = ATOMIC_INIT(4),
+   .usage  = REFCOUNT_INIT(4),
 #ifdef CONFIG_DEBUG_CREDENTIALS
.subscribers= ATOMIC_INIT(2),
.magic  = CRED_MAGIC,
@@ -102,17 +102,17 @@ static void put_cred_rcu(struct rcu_head *rcu)
 
 #ifdef CONFIG_DEBUG_CREDENTIALS
if (cred->magic != CRED_MAGIC_DEAD ||
-   atomic_read(>usage) != 0 ||
+   refcount_read(>usage) != 0 ||
read_cred_subscribers(cred) != 0)
panic("CRED: put_cred_rcu() sees %p with"
  " mag %x, put %p, usage %d, subscr %d\n",
  cred, cred->magic, cred->put_addr,
- atomic_read(>usage),
+ refcount_read(>usage),
  read_cred_subscribers(cred));
 #else
-   if (atomic_read(>usage) != 0)
+   if (refcount_read(>usage) != 0)
panic("CRED: put_cred_rcu() sees %p with usage %d\n",
- cred, atomic_read(>usage));
+ cred, refcount_read(>usage));
 #endif
 
security_cred_free(cred);
@@ -136,10 +136,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 void __put_cred(struct cr

[PATCH 0/3] creds/cgroups/ns_proxy refcount_t conversions

2019-03-06 Thread Elena Reshetova
I would like to reopen ages-old discussion on these conversions now.
Eric had objections against them in past, namely on not providing enough
security for reference counters (but we still argue it is better
than overflowing atomic_t and resulting use-after-free).
However now, refcount_t has been successfully used in kernel in many places,
helped to detect bugs and mistakes in logic of refcounters.
We have converted most of core kernel reference counters by now and these
3 are pretty core ones, so it would be really great to have them covered
also.

The patches are fully independent and can be cherry-picked and
discussed separately. More information about each conversion in each patch
separately.

Elena Reshetova (3):
  nsproxy: convert nsproxy.count to refcount_t
  groups: convert group_info.usage to refcount_t
  creds: convert cred.usage to refcount_t

 include/linux/cred.h| 15 +++---
 include/linux/nsproxy.h |  6 +++---
 kernel/cred.c   | 44 -
 kernel/groups.c |  2 +-
 kernel/nsproxy.c|  6 +++---
 net/sunrpc/auth.c   |  2 +-
 6 files changed, 38 insertions(+), 37 deletions(-)

-- 
2.17.1



[tip:locking/core] futex: Convert futex_pi_state.refcount to refcount_t

2019-02-11 Thread tip-bot for Elena Reshetova
Commit-ID:  49262de2270e09882d7bd8866a691cdd69ab32f6
Gitweb: https://git.kernel.org/tip/49262de2270e09882d7bd8866a691cdd69ab32f6
Author: Elena Reshetova 
AuthorDate: Tue, 5 Feb 2019 14:24:27 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 11 Feb 2019 11:37:16 +0100

futex: Convert futex_pi_state.refcount to refcount_t

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 futex_pi_state.refcount is used as pure
reference counter. Convert it to refcount_t and fix up
the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the futex_pi_state.refcount it might make a difference
in following places:

 - get_pi_state() and exit_pi_state_list(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_pi_state(): decrement in refcount_dec_and_test() provides
   RELEASE ordering and ACQUIRE ordering on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Cc: Andrew Morton 
Cc: Linus Torvalds 
Cc: Paul E. McKenney 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: dvh...@infradead.org
Link: 
http://lkml.kernel.org/r/1549369467-3505-1-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 kernel/futex.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 2abe1a0b3062..113f1c042250 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -68,6 +68,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -212,7 +213,7 @@ struct futex_pi_state {
struct rt_mutex pi_mutex;
 
struct task_struct *owner;
-   atomic_t refcount;
+   refcount_t refcount;
 
union futex_key key;
 } __randomize_layout;
@@ -799,7 +800,7 @@ static int refill_pi_state_cache(void)
INIT_LIST_HEAD(_state->list);
/* pi_mutex gets initialized later */
pi_state->owner = NULL;
-   atomic_set(_state->refcount, 1);
+   refcount_set(_state->refcount, 1);
pi_state->key = FUTEX_KEY_INIT;
 
current->pi_state_cache = pi_state;
@@ -819,7 +820,7 @@ static struct futex_pi_state *alloc_pi_state(void)
 
 static void get_pi_state(struct futex_pi_state *pi_state)
 {
-   WARN_ON_ONCE(!atomic_inc_not_zero(_state->refcount));
+   WARN_ON_ONCE(!refcount_inc_not_zero(_state->refcount));
 }
 
 /*
@@ -831,7 +832,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
if (!pi_state)
return;
 
-   if (!atomic_dec_and_test(_state->refcount))
+   if (!refcount_dec_and_test(_state->refcount))
return;
 
/*
@@ -861,7 +862,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
 * refcount is at 0 - put it back to 1.
 */
pi_state->owner = NULL;
-   atomic_set(_state->refcount, 1);
+   refcount_set(_state->refcount, 1);
current->pi_state_cache = pi_state;
}
 }
@@ -904,7 +905,7 @@ void exit_pi_state_list(struct task_struct *curr)
 * In that case; drop the locks to let put_pi_state() make
 * progress and retry the loop.
 */
-   if (!atomic_inc_not_zero(_state->refcount)) {
+   if (!refcount_inc_not_zero(_state->refcount)) {
raw_spin_unlock_irq(>pi_lock);
cpu_relax();
raw_spin_lock_irq(>pi_lock);
@@ -1060,7 +1061,7 @@ static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
 * and futex_wait_requeue_pi() as it cannot go to 0 and consequently
 * free pi_state before we can take a reference ourselves.
 */
-   WARN_ON(!atomic_read(_state->refcount));
+   WARN_ON(!refc

[PATCH] futex: convert futex_pi_state.refcount to refcount_t

2019-02-05 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 futex_pi_state.refcount is used as pure
reference counter. Convert it to refcount_t and fix up
the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the futex_pi_state.refcount it might make a difference
in following places:
 - get_pi_state() and exit_pi_state_list(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_pi_state(): decrement in refcount_dec_and_test() provides
   RELEASE ordering and ACQUIRE ordering on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/futex.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/kernel/futex.c b/kernel/futex.c
index 873204a..2442136 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -68,6 +68,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -212,7 +213,7 @@ struct futex_pi_state {
struct rt_mutex pi_mutex;
 
struct task_struct *owner;
-   atomic_t refcount;
+   refcount_t refcount;
 
union futex_key key;
 } __randomize_layout;
@@ -799,7 +800,7 @@ static int refill_pi_state_cache(void)
INIT_LIST_HEAD(_state->list);
/* pi_mutex gets initialized later */
pi_state->owner = NULL;
-   atomic_set(_state->refcount, 1);
+   refcount_set(_state->refcount, 1);
pi_state->key = FUTEX_KEY_INIT;
 
current->pi_state_cache = pi_state;
@@ -819,7 +820,7 @@ static struct futex_pi_state *alloc_pi_state(void)
 
 static void get_pi_state(struct futex_pi_state *pi_state)
 {
-   WARN_ON_ONCE(!atomic_inc_not_zero(_state->refcount));
+   WARN_ON_ONCE(!refcount_inc_not_zero(_state->refcount));
 }
 
 /*
@@ -831,7 +832,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
if (!pi_state)
return;
 
-   if (!atomic_dec_and_test(_state->refcount))
+   if (!refcount_dec_and_test(_state->refcount))
return;
 
/*
@@ -861,7 +862,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
 * refcount is at 0 - put it back to 1.
 */
pi_state->owner = NULL;
-   atomic_set(_state->refcount, 1);
+   refcount_set(_state->refcount, 1);
current->pi_state_cache = pi_state;
}
 }
@@ -904,7 +905,7 @@ void exit_pi_state_list(struct task_struct *curr)
 * In that case; drop the locks to let put_pi_state() make
 * progress and retry the loop.
 */
-   if (!atomic_inc_not_zero(_state->refcount)) {
+   if (!refcount_inc_not_zero(_state->refcount)) {
raw_spin_unlock_irq(>pi_lock);
cpu_relax();
raw_spin_lock_irq(>pi_lock);
@@ -1060,7 +1061,7 @@ static int attach_to_pi_state(u32 __user *uaddr, u32 uval,
 * and futex_wait_requeue_pi() as it cannot go to 0 and consequently
 * free pi_state before we can take a reference ourselves.
 */
-   WARN_ON(!atomic_read(_state->refcount));
+   WARN_ON(!refcount_read(_state->refcount));
 
/*
 * Now that we have a pi_state, we can acquire wait_lock
-- 
2.7.4



[tip:locking/core] refcount_t: Add ACQUIRE ordering on success for dec(sub)_and_test() variants

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  47b8f3ab9c49daa824af848f9e02889662d8638f
Gitweb: https://git.kernel.org/tip/47b8f3ab9c49daa824af848f9e02889662d8638f
Author: Elena Reshetova 
AuthorDate: Wed, 30 Jan 2019 13:18:51 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 09:03:31 +0100

refcount_t: Add ACQUIRE ordering on success for dec(sub)_and_test() variants

This adds an smp_acquire__after_ctrl_dep() barrier on successful
decrease of refcounter value from 1 to 0 for refcount_dec(sub)_and_test
variants and therefore gives stronger memory ordering guarantees than
prior versions of these functions.

Co-developed-by: Peter Zijlstra (Intel) 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: Andrea Parri 
Cc: Andrew Morton 
Cc: Linus Torvalds 
Cc: Paul E. McKenney 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: Will Deacon 
Cc: dvyu...@google.com
Cc: keesc...@chromium.org
Cc: st...@rowland.harvard.edu
Link: 
https://lkml.kernel.org/r/1548847131-27854-2-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 Documentation/core-api/refcount-vs-atomic.rst | 24 +---
 arch/x86/include/asm/refcount.h   | 22 ++
 lib/refcount.c| 18 +-
 3 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
index 322851bada16..976e85adffe8 100644
--- a/Documentation/core-api/refcount-vs-atomic.rst
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -54,6 +54,13 @@ must propagate to all other CPUs before the release operation
 (A-cumulative property). This is implemented using
 :c:func:`smp_store_release`.
 
+An ACQUIRE memory ordering guarantees that all post loads and
+stores (all po-later instructions) on the same CPU are
+completed after the acquire operation. It also guarantees that all
+po-later stores on the same CPU must propagate to all other CPUs
+after the acquire operation executes. This is implemented using
+:c:func:`smp_acquire__after_ctrl_dep`.
+
 A control dependency (on success) for refcounters guarantees that
 if a reference for an object was successfully obtained (reference
 counter increment or addition happened, function returned true),
@@ -119,13 +126,24 @@ Memory ordering guarantees changes:
result of obtaining pointer to the object!
 
 
-case 5) - decrement-based RMW ops that return a value
--
+case 5) - generic dec/sub decrement-based RMW ops that return a value
+-
 
 Function changes:
 
  * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test`
  * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test`
+
+Memory ordering guarantees changes:
+
+ * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
+
+
+case 6) other decrement-based RMW ops that return a value
+-
+
+Function changes:
+
  * no atomic counterpart --> :c:func:`refcount_dec_if_one`
  * ``atomic_add_unless(, -1, 1)`` --> ``refcount_dec_not_one()``
 
@@ -136,7 +154,7 @@ Memory ordering guarantees changes:
 .. note:: :c:func:`atomic_add_unless` only provides full order on success.
 
 
-case 6) - lock-based RMW
+case 7) - lock-based RMW
 
 
 Function changes:
diff --git a/arch/x86/include/asm/refcount.h b/arch/x86/include/asm/refcount.h
index dbaed55c1c24..232f856e0db0 100644
--- a/arch/x86/include/asm/refcount.h
+++ b/arch/x86/include/asm/refcount.h
@@ -67,16 +67,30 @@ static __always_inline void refcount_dec(refcount_t *r)
 static __always_inline __must_check
 bool refcount_sub_and_test(unsigned int i, refcount_t *r)
 {
-   return GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
+   bool ret = GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
 REFCOUNT_CHECK_LT_ZERO,
 r->refs.counter, e, "er", i, "cx");
+
+   if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+   }
+
+   return false;
 }
 
 static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
 {
-   return GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
-   REFCOUNT_CHECK_LT_ZERO,
-   r->refs.counter, e, "cx");
+   bool ret = GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
+REFCOUNT_CHECK_LT_ZERO,
+r->refs.counter, e, "cx");
+
+   if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+   }
+
+   return false;
 }
 
 static __always_inline __must_check
diff --git a/lib/refco

[tip:sched/core] sched/core: Convert task_struct.stack_refcount to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  f0b89d3958d73cd0785ec381f0ddf8efb6f183d8
Gitweb: https://git.kernel.org/tip/f0b89d3958d73cd0785ec381f0ddf8efb6f183d8
Author: Elena Reshetova 
AuthorDate: Fri, 18 Jan 2019 14:27:30 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:53:56 +0100

sched/core: Convert task_struct.stack_refcount to refcount_t

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 task_struct.stack_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.

The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.

Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.stack_refcount it might make a difference
in following places:

 - try_get_task_stack(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_task_stack(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Reviewed-by: Andrea Parri 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@linux-foundation.org
Cc: v...@zeniv.linux.org.uk
Link: 
https://lkml.kernel.org/r/1547814450-18902-6-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 include/linux/init_task.h| 1 +
 include/linux/sched.h| 2 +-
 include/linux/sched/task_stack.h | 2 +-
 init/init_task.c | 2 +-
 kernel/fork.c| 6 +++---
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index a7083a45a26c..6049baa5b8bc 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9d14d6864ca6..628bf13cb5a5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1194,7 +1194,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
/* A live task holds one reference: */
-   atomic_tstack_refcount;
+   refcount_t  stack_refcount;
 #endif
 #ifdef CONFIG_LIVEPATCH
int patch_state;
diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h
index 6a841929073f..2413427e439c 100644
--- a/include/linux/sched/task_stack.h
+++ b/include/linux/sched/task_stack.h
@@ -61,7 +61,7 @@ static inline unsigned long *end_of_stack(struct task_struct 
*p)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline void *try_get_task_stack(struct task_struct *tsk)
 {
-   return atomic_inc_not_zero(>stack_refcount) ?
+   return refcount_inc_not_zero(>stack_refcount) ?
task_stack_page(tsk) : NULL;
 }
 
diff --git a/init/init_task.c b/init/init_task.c
index aca34c89529f..46dbf546264d 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -61,7 +61,7 @@ struct task_struct init_task
 = {
 #ifdef CONFIG_THREAD_INFO_IN_TASK
.thread_info= INIT_THREAD_INFO(init_task),
-   .stack_refcount = ATOMIC_INIT(1),
+   .stack_refcount = REFCOUNT_INIT(1),
 #endif
.state  = 0,
.stack  = init_stack,
diff --git a/kernel/fork.c b/kernel/fork.c
index 3f7e192e29f2..77059b211608 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -429,7 +429,7 @@ static void release_task_stack(struct task_struct *tsk)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 void put_task_stack(struct task_struct *tsk)
 {
-   if (atomic_dec_and_test(>stack_refcount))
+   if (refcount_dec_and_test(>stack_refcount))
release_task_stack(tsk);
 }
 #endif
@@ -447,7 +447,7 @@ void free_task(struct task

[tip:sched/core] sched/core: Convert task_struct.usage to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  ec1d281923cf81cc660343d0cb8ffc837ffb991d
Gitweb: https://git.kernel.org/tip/ec1d281923cf81cc660343d0cb8ffc837ffb991d
Author: Elena Reshetova 
AuthorDate: Fri, 18 Jan 2019 14:27:29 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:53:55 +0100

sched/core: Convert task_struct.usage to refcount_t

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 task_struct.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.

The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.

Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.usage it might make a difference
in following places:

 - put_task_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Reviewed-by: Andrea Parri 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@linux-foundation.org
Cc: v...@zeniv.linux.org.uk
Link: 
https://lkml.kernel.org/r/1547814450-18902-5-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 include/linux/sched.h  | 3 ++-
 include/linux/sched/task.h | 4 ++--
 init/init_task.c   | 2 +-
 kernel/fork.c  | 4 ++--
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index e2bba022827d..9d14d6864ca6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -607,7 +608,7 @@ struct task_struct {
randomized_struct_fields_start
 
void*stack;
-   atomic_tusage;
+   refcount_t  usage;
/* Per task flags (PF_*), defined further below: */
unsigned intflags;
unsigned intptrace;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 44c6f15800ff..2e97a2227045 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -88,13 +88,13 @@ extern void sched_exec(void);
 #define sched_exec()   {}
 #endif
 
-#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
-   if (atomic_dec_and_test(>usage))
+   if (refcount_dec_and_test(>usage))
__put_task_struct(t);
 }
 
diff --git a/init/init_task.c b/init/init_task.c
index 9aa3ebc74970..aca34c89529f 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -65,7 +65,7 @@ struct task_struct init_task
 #endif
.state  = 0,
.stack  = init_stack,
-   .usage  = ATOMIC_INIT(2),
+   .usage  = REFCOUNT_INIT(2),
.flags  = PF_KTHREAD,
.prio   = MAX_PRIO - 20,
.static_prio= MAX_PRIO - 20,
diff --git a/kernel/fork.c b/kernel/fork.c
index 935a42d5f8ff..3f7e192e29f2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -717,7 +717,7 @@ static inline void put_signal_struct(struct signal_struct 
*sig)
 void __put_task_struct(struct task_struct *tsk)
 {
WARN_ON(!tsk->exit_state);
-   WARN_ON(atomic_read(>usage));
+   WARN_ON(refcount_read(>usage));
WARN_ON(tsk == current);
 
cgroup_free(tsk);
@@ -896,7 +896,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
 * One for us, one for whoever does the "release_task()" (usually
 * parent)
 */
-   atomic_set(>

[tip:sched/core] sched/fair: Convert numa_group.refcount to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  c45a77952427b678aa9205e1b0ee3bcf9a2e
Gitweb: https://git.kernel.org/tip/c45a77952427b678aa9205e1b0ee3bcf9a2e
Author: Elena Reshetova 
AuthorDate: Fri, 18 Jan 2019 14:27:28 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:53:54 +0100

sched/fair: Convert numa_group.refcount to refcount_t

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 numa_group.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.

The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.

Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the numa_group.refcount it might make a difference
in following places:

 - get_numa_group(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_numa_group(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Reviewed-by: Andrea Parri 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@linux-foundation.org
Cc: v...@zeniv.linux.org.uk
Link: 
https://lkml.kernel.org/r/1547814450-18902-4-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 kernel/sched/fair.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e2ff4b69dcf6..5b2b919c7929 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1035,7 +1035,7 @@ unsigned int sysctl_numa_balancing_scan_size = 256;
 unsigned int sysctl_numa_balancing_scan_delay = 1000;
 
 struct numa_group {
-   atomic_t refcount;
+   refcount_t refcount;
 
spinlock_t lock; /* nr_tasks, tasks */
int nr_tasks;
@@ -1104,7 +1104,7 @@ static unsigned int task_scan_start(struct task_struct *p)
unsigned long shared = group_faults_shared(ng);
unsigned long private = group_faults_priv(ng);
 
-   period *= atomic_read(>refcount);
+   period *= refcount_read(>refcount);
period *= shared + 1;
period /= private + shared + 1;
}
@@ -1127,7 +1127,7 @@ static unsigned int task_scan_max(struct task_struct *p)
unsigned long private = group_faults_priv(ng);
unsigned long period = smax;
 
-   period *= atomic_read(>refcount);
+   period *= refcount_read(>refcount);
period *= shared + 1;
period /= private + shared + 1;
 
@@ -2203,12 +2203,12 @@ static void task_numa_placement(struct task_struct *p)
 
 static inline int get_numa_group(struct numa_group *grp)
 {
-   return atomic_inc_not_zero(>refcount);
+   return refcount_inc_not_zero(>refcount);
 }
 
 static inline void put_numa_group(struct numa_group *grp)
 {
-   if (atomic_dec_and_test(>refcount))
+   if (refcount_dec_and_test(>refcount))
kfree_rcu(grp, rcu);
 }
 
@@ -2229,7 +2229,7 @@ static void task_numa_group(struct task_struct *p, int 
cpupid, int flags,
if (!grp)
return;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
grp->active_nodes = 1;
grp->max_faults_cpu = 0;
spin_lock_init(>lock);


[tip:sched/core] sched/core: Convert signal_struct.sigcnt to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  60d4de3ff7f775509deba94b3db3c1abe55bf7a5
Gitweb: https://git.kernel.org/tip/60d4de3ff7f775509deba94b3db3c1abe55bf7a5
Author: Elena Reshetova 
AuthorDate: Fri, 18 Jan 2019 14:27:27 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:53:53 +0100

sched/core: Convert signal_struct.sigcnt to refcount_t

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 signal_struct.sigcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.

The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.

Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the signal_struct.sigcnt it might make a difference
in following places:

 - put_signal_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Reviewed-by: Andrea Parri 
Reviewed-by: Oleg Nesterov 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@linux-foundation.org
Cc: v...@zeniv.linux.org.uk
Link: 
https://lkml.kernel.org/r/1547814450-18902-3-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 include/linux/sched/signal.h | 2 +-
 init/init_task.c | 2 +-
 kernel/fork.c| 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 37eeb1a28eba..ae5655197698 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -83,7 +83,7 @@ struct multiprocess_signals {
  * the locking of signal_struct.
  */
 struct signal_struct {
-   atomic_tsigcnt;
+   refcount_t  sigcnt;
atomic_tlive;
int nr_threads;
struct list_headthread_head;
diff --git a/init/init_task.c b/init/init_task.c
index 5aebe3be4d7c..9aa3ebc74970 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -44,7 +44,7 @@ static struct signal_struct init_signals = {
 };
 
 static struct sighand_struct init_sighand = {
-   .count  = ATOMIC_INIT(1),
+   .count  = REFCOUNT_INIT(1),
.action = { { { .sa_handler = SIG_DFL, } }, },
.siglock= __SPIN_LOCK_UNLOCKED(init_sighand.siglock),
.signalfd_wqh   = 
__WAIT_QUEUE_HEAD_INITIALIZER(init_sighand.signalfd_wqh),
diff --git a/kernel/fork.c b/kernel/fork.c
index 370856d4c0b3..935a42d5f8ff 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -710,7 +710,7 @@ static inline void free_signal_struct(struct signal_struct 
*sig)
 
 static inline void put_signal_struct(struct signal_struct *sig)
 {
-   if (atomic_dec_and_test(>sigcnt))
+   if (refcount_dec_and_test(>sigcnt))
free_signal_struct(sig);
 }
 
@@ -1527,7 +1527,7 @@ static int copy_signal(unsigned long clone_flags, struct 
task_struct *tsk)
 
sig->nr_threads = 1;
atomic_set(>live, 1);
-   atomic_set(>sigcnt, 1);
+   refcount_set(>sigcnt, 1);
 
/* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
@@ -2082,7 +2082,7 @@ static __latent_entropy struct task_struct *copy_process(
} else {
current->signal->nr_threads++;
atomic_inc(>signal->live);
-   atomic_inc(>signal->sigcnt);
+   refcount_inc(>signal->sigcnt);
task_join_group_stop(p);
list_add_tail_rcu(>thread_group,
  >group_leader->thread_group);


[tip:sched/core] sched/core: Convert sighand_struct.count to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  d036bda7d0e7269c2982eb979acfef855f5d7977
Gitweb: https://git.kernel.org/tip/d036bda7d0e7269c2982eb979acfef855f5d7977
Author: Elena Reshetova 
AuthorDate: Fri, 18 Jan 2019 14:27:26 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:53:52 +0100

sched/core: Convert sighand_struct.count to refcount_t

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 sighand_struct.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.

The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.

Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the sighand_struct.count it might make a difference
in following places:

 - __cleanup_sighand: decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Reviewed-by: Andrea Parri 
Reviewed-by: Oleg Nesterov 
Cc: Linus Torvalds 
Cc: Mike Galbraith 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@linux-foundation.org
Cc: v...@zeniv.linux.org.uk
Link: 
https://lkml.kernel.org/r/1547814450-18902-2-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 fs/exec.c| 4 ++--
 fs/proc/task_nommu.c | 2 +-
 include/linux/sched/signal.h | 3 ++-
 kernel/fork.c| 8 
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index fb72d36f7823..966cd98a2ce2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1189,7 +1189,7 @@ no_thread_group:
flush_itimer_signals();
 #endif
 
-   if (atomic_read(>count) != 1) {
+   if (refcount_read(>count) != 1) {
struct sighand_struct *newsighand;
/*
 * This ->sighand is shared with the CLONE_SIGHAND
@@ -1199,7 +1199,7 @@ no_thread_group:
if (!newsighand)
return -ENOMEM;
 
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
memcpy(newsighand->action, oldsighand->action,
   sizeof(newsighand->action));
 
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 0b63d68dedb2..f912872fbf91 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -64,7 +64,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
else
bytes += kobjsize(current->files);
 
-   if (current->sighand && atomic_read(>sighand->count) > 1)
+   if (current->sighand && refcount_read(>sighand->count) > 1)
sbytes += kobjsize(current->sighand);
else
bytes += kobjsize(current->sighand);
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 13789d10a50e..37eeb1a28eba 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -8,13 +8,14 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Types defining task->signal and task->sighand and APIs using them:
  */
 
 struct sighand_struct {
-   atomic_tcount;
+   refcount_t  count;
struct k_sigaction  action[_NSIG];
spinlock_t  siglock;
wait_queue_head_t   signalfd_wqh;
diff --git a/kernel/fork.c b/kernel/fork.c
index b69248e6f0e0..370856d4c0b3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1463,7 +1463,7 @@ static int copy_sighand(unsigned long clone_flags, struct 
task_struct *tsk)
struct sighand_struct *sig;
 
if (clone_flags & CLONE_SIGHAND) {
-   atomic_inc(>sighand->count);
+   refcount_inc(>sighand->count);
return 0;
}
sig = kmem_cache_alloc(sighand_cache

[tip:perf/core] perf/ring_buffer: Convert ring_buffer.aux_refcount to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  ca3bb3d027f69ac3ab1dafb32bde2f5a3a44439c
Gitweb: https://git.kernel.org/tip/ca3bb3d027f69ac3ab1dafb32bde2f5a3a44439c
Author: Elena Reshetova 
AuthorDate: Mon, 28 Jan 2019 14:27:28 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:46:17 +0100

perf/ring_buffer: Convert ring_buffer.aux_refcount to refcount_t

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 ring_buffer.aux_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.aux_refcount it might make a difference
in following places:

 - perf_aux_output_begin(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - rb_free_aux(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering + control dependency
   on success vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Cc: Alexander Shishkin 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@kernel.org
Cc: namhy...@kernel.org
Link: 
https://lkml.kernel.org/r/1548678448-24458-4-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 kernel/events/core.c| 2 +-
 kernel/events/internal.h| 2 +-
 kernel/events/ring_buffer.c | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 284232edf9be..5aeb4c74fb99 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5468,7 +5468,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
/* this has to be the last one */
rb_free_aux(rb);
-   WARN_ON_ONCE(atomic_read(>aux_refcount));
+   WARN_ON_ONCE(refcount_read(>aux_refcount));
 
mutex_unlock(>mmap_mutex);
}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 4718de2a04e6..79c47076700a 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -49,7 +49,7 @@ struct ring_buffer {
atomic_taux_mmap_count;
unsigned long   aux_mmap_locked;
void(*free_aux)(void *);
-   atomic_taux_refcount;
+   refcount_t  aux_refcount;
void**aux_pages;
void*aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 0a71d16ca41b..805f0423ee0b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -357,7 +357,7 @@ void *perf_aux_output_begin(struct perf_output_handle 
*handle,
if (!atomic_read(>aux_mmap_count))
goto err;
 
-   if (!atomic_inc_not_zero(>aux_refcount))
+   if (!refcount_inc_not_zero(>aux_refcount))
goto err;
 
/*
@@ -670,7 +670,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 * we keep a refcount here to make sure either of the two can
 * reference them safely.
 */
-   atomic_set(>aux_refcount, 1);
+   refcount_set(>aux_refcount, 1);
 
rb->aux_overwrite = overwrite;
rb->aux_watermark = watermark;
@@ -689,7 +689,7 @@ out:
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-   if (atomic_dec_and_test(>aux_refcount))
+   if (refcount_dec_and_test(>aux_refcount))
__rb_free_aux(rb);
 }
 


[tip:perf/core] perf/ring_buffer: Convert ring_buffer.refcount to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  fecb8ed2ce7010db373f8517ee815380d8e3c0c4
Gitweb: https://git.kernel.org/tip/fecb8ed2ce7010db373f8517ee815380d8e3c0c4
Author: Elena Reshetova 
AuthorDate: Mon, 28 Jan 2019 14:27:27 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:46:16 +0100

perf/ring_buffer: Convert ring_buffer.refcount to refcount_t

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 ring_buffer.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.refcount it might make a difference
in following places:

 - ring_buffer_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - ring_buffer_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering + control dependency
   on success vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Cc: Alexander Shishkin 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@kernel.org
Cc: namhy...@kernel.org
Link: 
https://lkml.kernel.org/r/1548678448-24458-3-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 kernel/events/core.c| 4 ++--
 kernel/events/internal.h| 3 ++-
 kernel/events/ring_buffer.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 677164d54547..284232edf9be 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5393,7 +5393,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
rcu_read_lock();
rb = rcu_dereference(event->rb);
if (rb) {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
rb = NULL;
}
rcu_read_unlock();
@@ -5403,7 +5403,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-   if (!atomic_dec_and_test(>refcount))
+   if (!refcount_dec_and_test(>refcount))
return;
 
WARN_ON_ONCE(!list_empty(>event_list));
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 6dc725a7e7bc..4718de2a04e6 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -4,13 +4,14 @@
 
 #include 
 #include 
+#include 
 
 /* Buffer handling */
 
 #define RING_BUFFER_WRITABLE   0x01
 
 struct ring_buffer {
-   atomic_trefcount;
+   refcount_t  refcount;
struct rcu_head rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct  work;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index ed6409300ef5..0a71d16ca41b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -284,7 +284,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, 
int flags)
else
rb->overwrite = 1;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 
INIT_LIST_HEAD(>event_list);
spin_lock_init(>event_lock);


[tip:perf/core] perf: Convert perf_event_context.refcount to refcount_t

2019-02-04 Thread tip-bot for Elena Reshetova
Commit-ID:  8c94abbbe1ba24961278055434504b7dc3595415
Gitweb: https://git.kernel.org/tip/8c94abbbe1ba24961278055434504b7dc3595415
Author: Elena Reshetova 
AuthorDate: Mon, 28 Jan 2019 14:27:26 +0200
Committer:  Ingo Molnar 
CommitDate: Mon, 4 Feb 2019 08:46:15 +0100

perf: Convert perf_event_context.refcount to refcount_t

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 perf_event_context.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

** Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the perf_event_context.refcount it might make a difference
in following places:

 - get_ctx(), perf_event_ctx_lock_nested(), perf_lock_task_context()
   and __perf_event_ctx_lock_double(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_ctx(): decrement in refcount_dec_and_test() provides
   RELEASE ordering and ACQUIRE ordering + control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Signed-off-by: Elena Reshetova 
Signed-off-by: Peter Zijlstra (Intel) 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Cc: Alexander Shishkin 
Cc: Arnaldo Carvalho de Melo 
Cc: Jiri Olsa 
Cc: Linus Torvalds 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: a...@kernel.org
Cc: namhy...@kernel.org
Link: 
https://lkml.kernel.org/r/1548678448-24458-2-git-send-email-elena.reshet...@intel.com
Signed-off-by: Ingo Molnar 
---
 include/linux/perf_event.h |  3 ++-
 kernel/events/core.c   | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index a79e59fc3b7d..6cb5d483ab34 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -54,6 +54,7 @@ struct perf_guest_info_callbacks {
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct perf_callchain_entry {
@@ -737,7 +738,7 @@ struct perf_event_context {
int nr_stat;
int nr_freq;
int rotate_disable;
-   atomic_trefcount;
+   refcount_t  refcount;
struct task_struct  *task;
 
/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5b89de7918d0..677164d54547 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1172,7 +1172,7 @@ static void perf_event_ctx_deactivate(struct 
perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-   WARN_ON(!atomic_inc_not_zero(>refcount));
+   refcount_inc(>refcount);
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1186,7 +1186,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1268,7 +1268,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int 
nesting)
 again:
rcu_read_lock();
ctx = READ_ONCE(event->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
@@ -1401,7 +1401,7 @@ retry:
}
 
if (ctx->task == TASK_TOMBSTONE ||
-   !atomic_inc_not_zero(>refcount)) {
+   !refcount_inc_not_zero(>refcount)) {
raw_spin_unlock(>lock);
ctx = NULL;
} else {
@@ -4057,7 +4057,7 @@ static void __perf_event_init_context(struct 
perf_event_context *ctx)
INIT_LIST_HEA

[PATCH] refcount_t: add ACQUIRE ordering on success for dec(sub)_and_test variants

2019-01-30 Thread Elena Reshetova
This adds an smp_acquire__after_ctrl_dep() barrier on successful
decrease of refcounter value from 1 to 0 for refcount_dec(sub)_and_test
variants and therefore gives stronger memory ordering guarantees than
prior versions of these functions.

Co-developed-by: Peter Zijlstra (Intel) 
Signed-off-by: Elena Reshetova 
---
 Documentation/core-api/refcount-vs-atomic.rst | 24 +---
 arch/x86/include/asm/refcount.h   | 22 ++
 lib/refcount.c| 18 +-
 3 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
index 322851b..976e85a 100644
--- a/Documentation/core-api/refcount-vs-atomic.rst
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -54,6 +54,13 @@ must propagate to all other CPUs before the release operation
 (A-cumulative property). This is implemented using
 :c:func:`smp_store_release`.
 
+An ACQUIRE memory ordering guarantees that all post loads and
+stores (all po-later instructions) on the same CPU are
+completed after the acquire operation. It also guarantees that all
+po-later stores on the same CPU must propagate to all other CPUs
+after the acquire operation executes. This is implemented using
+:c:func:`smp_acquire__after_ctrl_dep`.
+
 A control dependency (on success) for refcounters guarantees that
 if a reference for an object was successfully obtained (reference
 counter increment or addition happened, function returned true),
@@ -119,13 +126,24 @@ Memory ordering guarantees changes:
result of obtaining pointer to the object!
 
 
-case 5) - decrement-based RMW ops that return a value
--
+case 5) - generic dec/sub decrement-based RMW ops that return a value
+-
 
 Function changes:
 
  * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test`
  * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test`
+
+Memory ordering guarantees changes:
+
+ * fully ordered --> RELEASE ordering + ACQUIRE ordering on success
+
+
+case 6) other decrement-based RMW ops that return a value
+-
+
+Function changes:
+
  * no atomic counterpart --> :c:func:`refcount_dec_if_one`
  * ``atomic_add_unless(, -1, 1)`` --> ``refcount_dec_not_one()``
 
@@ -136,7 +154,7 @@ Memory ordering guarantees changes:
 .. note:: :c:func:`atomic_add_unless` only provides full order on success.
 
 
-case 6) - lock-based RMW
+case 7) - lock-based RMW
 
 
 Function changes:
diff --git a/arch/x86/include/asm/refcount.h b/arch/x86/include/asm/refcount.h
index dbaed55..232f856 100644
--- a/arch/x86/include/asm/refcount.h
+++ b/arch/x86/include/asm/refcount.h
@@ -67,16 +67,30 @@ static __always_inline void refcount_dec(refcount_t *r)
 static __always_inline __must_check
 bool refcount_sub_and_test(unsigned int i, refcount_t *r)
 {
-   return GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
+   bool ret = GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
 REFCOUNT_CHECK_LT_ZERO,
 r->refs.counter, e, "er", i, "cx");
+
+   if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+   }
+
+   return false;
 }
 
 static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
 {
-   return GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
-   REFCOUNT_CHECK_LT_ZERO,
-   r->refs.counter, e, "cx");
+   bool ret = GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
+REFCOUNT_CHECK_LT_ZERO,
+r->refs.counter, e, "cx");
+
+   if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+   }
+
+   return false;
 }
 
 static __always_inline __must_check
diff --git a/lib/refcount.c b/lib/refcount.c
index ebcf8cd..6e904af 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -33,6 +33,9 @@
  * Note that the allocator is responsible for ordering things between free()
  * and alloc().
  *
+ * The decrements dec_and_test() and sub_and_test() also provide acquire
+ * ordering on success.
+ *
  */
 
 #include 
@@ -164,8 +167,8 @@ EXPORT_SYMBOL(refcount_inc_checked);
  * at UINT_MAX.
  *
  * Provides release memory ordering, such that prior loads and stores are done
- * before, and provides a control dependency such that free() must come after.
- * See the comment on top.
+ * before, and provides an acquire ordering on success such that free()
+ * must come after.
  *
  * Use of this function is not recommended

[PATCH v2] Adding smp_acquire__after_ctrl_dep barrier

2019-01-30 Thread Elena Reshetova
Changes in v2:
 - hopefully fixed all (at least to my eye and to checkpatch)
   errors on whitespacing, etc.
 - changed text on ACQUIRE guarantees pointed by Andrea and
   Dmitry
 - removed mentioning of control dependency on dec/sub_and_test
   variants

I also have to send it now with a cover letter, because I think
it is Intel mailer that malformed the patch last time for god knows
what reason...

Elena Reshetova (1):
  refcount_t: add ACQUIRE ordering on success for dec(sub)_and_test
variants

 Documentation/core-api/refcount-vs-atomic.rst | 24 +---
 arch/x86/include/asm/refcount.h   | 22 ++
 lib/refcount.c| 18 +-
 3 files changed, 52 insertions(+), 12 deletions(-)

-- 
2.7.4



[PATCH 1/3] perf: convert perf_event_context.refcount to refcount_t

2019-01-28 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 perf_event_context.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the perf_event_context.refcount it might make a difference
in following places:
 - get_ctx(), perf_event_ctx_lock_nested(), perf_lock_task_context()
   and __perf_event_ctx_lock_double(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_ctx(): decrement in refcount_dec_and_test() provides
   RELEASE ordering and ACQUIRE ordering + control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/perf_event.h |  3 ++-
 kernel/events/core.c   | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 1d5c551..6a94097 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -55,6 +55,7 @@ struct perf_guest_info_callbacks {
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct perf_callchain_entry {
@@ -737,7 +738,7 @@ struct perf_event_context {
int nr_stat;
int nr_freq;
int rotate_disable;
-   atomic_trefcount;
+   refcount_t  refcount;
struct task_struct  *task;
 
/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3cd13a3..a1e87d2 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1171,7 +1171,7 @@ static void perf_event_ctx_deactivate(struct 
perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-   WARN_ON(!atomic_inc_not_zero(>refcount));
+   WARN_ON(!refcount_inc_not_zero(>refcount));
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1185,7 +1185,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1267,7 +1267,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int 
nesting)
 again:
rcu_read_lock();
ctx = READ_ONCE(event->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
@@ -1400,7 +1400,7 @@ perf_lock_task_context(struct task_struct *task, int 
ctxn, unsigned long *flags)
}
 
if (ctx->task == TASK_TOMBSTONE ||
-   !atomic_inc_not_zero(>refcount)) {
+   !refcount_inc_not_zero(>refcount)) {
raw_spin_unlock(>lock);
ctx = NULL;
} else {
@@ -4056,7 +4056,7 @@ static void __perf_event_init_context(struct 
perf_event_context *ctx)
INIT_LIST_HEAD(>event_list);
INIT_LIST_HEAD(>pinned_active);
INIT_LIST_HEAD(>flexible_active);
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 }
 
 static struct perf_event_context *
@@ -10391,7 +10391,7 @@ __perf_event_ctx_lock_double(struct perf_event 
*group_leader,
 again:
rcu_read_lock();
gctx = READ_ONCE(group_leader->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
-- 
2.7.4



[PATCH 0/3] perf refcount_t conversions

2019-01-28 Thread Elena Reshetova
Another set of old patches, rebased and this time the commits
also updated since we merged the docs in past and also
refcount_dec_and_test() gets new acquire ordering on success
very soon, which is also reflected in commit messages.


Elena Reshetova (3):
  perf: convert perf_event_context.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t

 include/linux/perf_event.h  |  3 ++-
 kernel/events/core.c| 18 +-
 kernel/events/internal.h|  5 +++--
 kernel/events/ring_buffer.c |  8 
 4 files changed, 18 insertions(+), 16 deletions(-)

-- 
2.7.4



[PATCH 3/3] perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t

2019-01-28 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 ring_buffer.aux_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.aux_refcount it might make a difference
in following places:
 - perf_aux_output_begin(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - rb_free_aux(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering + control dependency
   on success vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/core.c| 2 +-
 kernel/events/internal.h| 2 +-
 kernel/events/ring_buffer.c | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 963cee0..31ab5d7 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5463,7 +5463,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
/* this has to be the last one */
rb_free_aux(rb);
-   WARN_ON_ONCE(atomic_read(>aux_refcount));
+   WARN_ON_ONCE(refcount_read(>aux_refcount));
 
mutex_unlock(>mmap_mutex);
}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 4718de2..79c4707 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -49,7 +49,7 @@ struct ring_buffer {
atomic_taux_mmap_count;
unsigned long   aux_mmap_locked;
void(*free_aux)(void *);
-   atomic_taux_refcount;
+   refcount_t  aux_refcount;
void**aux_pages;
void*aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index e841d48..0416f01 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -358,7 +358,7 @@ void *perf_aux_output_begin(struct perf_output_handle 
*handle,
if (!atomic_read(>aux_mmap_count))
goto err;
 
-   if (!atomic_inc_not_zero(>aux_refcount))
+   if (!refcount_inc_not_zero(>aux_refcount))
goto err;
 
/*
@@ -671,7 +671,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 * we keep a refcount here to make sure either of the two can
 * reference them safely.
 */
-   atomic_set(>aux_refcount, 1);
+   refcount_set(>aux_refcount, 1);
 
rb->aux_overwrite = overwrite;
rb->aux_watermark = watermark;
@@ -690,7 +690,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-   if (atomic_dec_and_test(>aux_refcount))
+   if (refcount_dec_and_test(>aux_refcount))
__rb_free_aux(rb);
 }
 
-- 
2.7.4



[PATCH 2/3] perf/ring_buffer: convert ring_buffer.refcount to refcount_t

2019-01-28 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 ring_buffer.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts. Please check Documentation/core-api/refcount-vs-atomic.rst
for more information.

Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.refcount it might make a difference
in following places:
 - ring_buffer_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - ring_buffer_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and ACQUIRE ordering + control dependency
   on success vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/core.c| 4 ++--
 kernel/events/internal.h| 3 ++-
 kernel/events/ring_buffer.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index a1e87d2..963cee0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5388,7 +5388,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
rcu_read_lock();
rb = rcu_dereference(event->rb);
if (rb) {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
rb = NULL;
}
rcu_read_unlock();
@@ -5398,7 +5398,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-   if (!atomic_dec_and_test(>refcount))
+   if (!refcount_dec_and_test(>refcount))
return;
 
WARN_ON_ONCE(!list_empty(>event_list));
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 6dc725a..4718de2 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -4,13 +4,14 @@
 
 #include 
 #include 
+#include 
 
 /* Buffer handling */
 
 #define RING_BUFFER_WRITABLE   0x01
 
 struct ring_buffer {
-   atomic_trefcount;
+   refcount_t  refcount;
struct rcu_head rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct  work;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 4a99370..e841d48 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -285,7 +285,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, 
int flags)
else
rb->overwrite = 1;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 
INIT_LIST_HEAD(>event_list);
spin_lock_init(>event_lock);
-- 
2.7.4



[PATCH] refcount_t: add ACQUIRE ordering on success for dec(sub)_and_test variants

2019-01-28 Thread Elena Reshetova
This adds an smp_acquire__after_ctrl_dep() barrier on successful
decrease of refcounter value from 1 to 0 for refcount_dec(sub)_and_test
variants and therefore gives stronger memory ordering guarantees than
prior versions of these functions.

Co-Developed-by: Peter Zijlstra (Intel) 
Signed-off-by: Elena Reshetova 
---
 Documentation/core-api/refcount-vs-atomic.rst | 28 +++
 arch/x86/include/asm/refcount.h   | 21 
 lib/refcount.c| 16 ++-
 3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
index 322851b..95d4b4e 100644
--- a/Documentation/core-api/refcount-vs-atomic.rst
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -54,6 +54,14 @@ must propagate to all other CPUs before the release operation
 (A-cumulative property). This is implemented using
 :c:func:`smp_store_release`.
 
+An ACQUIRE memory ordering guarantees that all post loads and
+stores (all po-later instructions) on the same CPU are
+completed after the acquire operation. It also guarantees that all
+po-later stores on the same CPU and all propagated stores from other CPUs
+must propagate to all other CPUs after the acquire operation
+(A-cumulative property). This is implemented using
+:c:func:`smp_acquire__after_ctrl_dep`.
+
 A control dependency (on success) for refcounters guarantees that
 if a reference for an object was successfully obtained (reference
 counter increment or addition happened, function returned true),
@@ -119,24 +127,36 @@ Memory ordering guarantees changes:
result of obtaining pointer to the object!
 
 
-case 5) - decrement-based RMW ops that return a value
--
+case 5) - generic dec/sub decrement-based RMW ops that return a value
+-
 
 Function changes:
 
  * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test`
  * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test`
+
+Memory ordering guarantees changes:
+
+ * fully ordered --> RELEASE ordering + ACQUIRE ordering and control dependency
+   on success.  
+
+
+case 6) other decrement-based RMW ops that return a value
+-
+
+Function changes:
+
  * no atomic counterpart --> :c:func:`refcount_dec_if_one`
  * ``atomic_add_unless(, -1, 1)`` --> ``refcount_dec_not_one()``
 
 Memory ordering guarantees changes:
 
- * fully ordered --> RELEASE ordering + control dependency
+ * fully ordered --> RELEASE ordering + control dependency 
 
 .. note:: :c:func:`atomic_add_unless` only provides full order on success.
 
 
-case 6) - lock-based RMW
+case 7) - lock-based RMW
 
 
 Function changes:
diff --git a/arch/x86/include/asm/refcount.h b/arch/x86/include/asm/refcount.h
index dbaed55..ab8f584 100644
--- a/arch/x86/include/asm/refcount.h
+++ b/arch/x86/include/asm/refcount.h
@@ -67,16 +67,29 @@ static __always_inline void refcount_dec(refcount_t *r)
 static __always_inline __must_check
 bool refcount_sub_and_test(unsigned int i, refcount_t *r)
 {
-   return GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
+   bool ret = GEN_BINARY_SUFFIXED_RMWcc(LOCK_PREFIX "subl",
 REFCOUNT_CHECK_LT_ZERO,
 r->refs.counter, e, "er", i, "cx");
+
+if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+}
+
+return false;
 }
 
 static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r)
 {
-   return GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
-   REFCOUNT_CHECK_LT_ZERO,
-   r->refs.counter, e, "cx");
+   bool ret = GEN_UNARY_SUFFIXED_RMWcc(LOCK_PREFIX "decl",
+   REFCOUNT_CHECK_LT_ZERO,
+   r->refs.counter, e, "cx");
+if (ret) {
+   smp_acquire__after_ctrl_dep();
+   return true;
+}
+
+return false;
 }
 
 static __always_inline __must_check
diff --git a/lib/refcount.c b/lib/refcount.c
index ebcf8cd..732feac 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -33,6 +33,9 @@
  * Note that the allocator is responsible for ordering things between free()
  * and alloc().
  *
+ * The decrements dec_and_test() and sub_and_test() also provide acquire
+ * ordering on success. 
+ *
  */
 
 #include 
@@ -164,8 +167,7 @@ EXPORT_SYMBOL(refcount_inc_checked);
  * at UINT_MAX.
  *
  * Provides release memory ordering, such that prior loads and stores are done
- * before, and provides a control dependency such that free() must come after.
- * See the comment on top.
+ * befor

[PATCH 3/5] sched: convert numa_group.refcount to refcount_t

2019-01-18 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 numa_group.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the numa_group.refcount it might make a difference
in following places:
 - get_numa_group(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_numa_group(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/sched/fair.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7303e0b..32a2382 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1035,7 +1035,7 @@ unsigned int sysctl_numa_balancing_scan_size = 256;
 unsigned int sysctl_numa_balancing_scan_delay = 1000;
 
 struct numa_group {
-   atomic_t refcount;
+   refcount_t refcount;
 
spinlock_t lock; /* nr_tasks, tasks */
int nr_tasks;
@@ -1104,7 +1104,7 @@ static unsigned int task_scan_start(struct task_struct *p)
unsigned long shared = group_faults_shared(ng);
unsigned long private = group_faults_priv(ng);
 
-   period *= atomic_read(>refcount);
+   period *= refcount_read(>refcount);
period *= shared + 1;
period /= private + shared + 1;
}
@@ -1127,7 +1127,7 @@ static unsigned int task_scan_max(struct task_struct *p)
unsigned long private = group_faults_priv(ng);
unsigned long period = smax;
 
-   period *= atomic_read(>refcount);
+   period *= refcount_read(>refcount);
period *= shared + 1;
period /= private + shared + 1;
 
@@ -2203,12 +2203,12 @@ static void task_numa_placement(struct task_struct *p)
 
 static inline int get_numa_group(struct numa_group *grp)
 {
-   return atomic_inc_not_zero(>refcount);
+   return refcount_inc_not_zero(>refcount);
 }
 
 static inline void put_numa_group(struct numa_group *grp)
 {
-   if (atomic_dec_and_test(>refcount))
+   if (refcount_dec_and_test(>refcount))
kfree_rcu(grp, rcu);
 }
 
@@ -2229,7 +2229,7 @@ static void task_numa_group(struct task_struct *p, int 
cpupid, int flags,
if (!grp)
return;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
grp->active_nodes = 1;
grp->max_faults_cpu = 0;
spin_lock_init(>lock);
-- 
2.7.4



[PATCH 4/5] sched/task_struct: convert task_struct.usage to refcount_t

2019-01-18 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 task_struct.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.usage it might make a difference
in following places:
 - put_task_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/sched.h  | 3 ++-
 include/linux/sched/task.h | 4 ++--
 init/init_task.c   | 2 +-
 kernel/fork.c  | 4 ++--
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5e66900..bead0c7 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -608,7 +609,7 @@ struct task_struct {
randomized_struct_fields_start
 
void*stack;
-   atomic_tusage;
+   refcount_t  usage;
/* Per task flags (PF_*), defined further below: */
unsigned intflags;
unsigned intptrace;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 44c6f15..2e97a22 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -88,13 +88,13 @@ extern void sched_exec(void);
 #define sched_exec()   {}
 #endif
 
-#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
-   if (atomic_dec_and_test(>usage))
+   if (refcount_dec_and_test(>usage))
__put_task_struct(t);
 }
 
diff --git a/init/init_task.c b/init/init_task.c
index 756be60..0ad9772 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -66,7 +66,7 @@ struct task_struct init_task
 #endif
.state  = 0,
.stack  = init_stack,
-   .usage  = ATOMIC_INIT(2),
+   .usage  = REFCOUNT_INIT(2),
.flags  = PF_KTHREAD,
.prio   = MAX_PRIO - 20,
.static_prio= MAX_PRIO - 20,
diff --git a/kernel/fork.c b/kernel/fork.c
index 504324c..a4ac220 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -716,7 +716,7 @@ static inline void put_signal_struct(struct signal_struct 
*sig)
 void __put_task_struct(struct task_struct *tsk)
 {
WARN_ON(!tsk->exit_state);
-   WARN_ON(atomic_read(>usage));
+   WARN_ON(refcount_read(>usage));
WARN_ON(tsk == current);
 
cgroup_free(tsk);
@@ -895,7 +895,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
 * One for us, one for whoever does the "release_task()" (usually
 * parent)
 */
-   atomic_set(>usage, 2);
+   refcount_set(>usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
tsk->btrace_seq = 0;
 #endif
-- 
2.7.4



[PATCH 5/5] sched/task_struct: convert task_struct.stack_refcount to refcount_t

2019-01-18 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 task_struct.stack_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.stack_refcount it might make a difference
in following places:
 - try_get_task_stack(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_task_stack(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/init_task.h| 1 +
 include/linux/sched.h| 2 +-
 include/linux/sched/task_stack.h | 2 +-
 init/init_task.c | 2 +-
 kernel/fork.c| 6 +++---
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index a7083a4..6049baa 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index bead0c7..439e34a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1201,7 +1201,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
/* A live task holds one reference: */
-   atomic_tstack_refcount;
+   refcount_t  stack_refcount;
 #endif
 #ifdef CONFIG_LIVEPATCH
int patch_state;
diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h
index 6a84192..2413427 100644
--- a/include/linux/sched/task_stack.h
+++ b/include/linux/sched/task_stack.h
@@ -61,7 +61,7 @@ static inline unsigned long *end_of_stack(struct task_struct 
*p)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline void *try_get_task_stack(struct task_struct *tsk)
 {
-   return atomic_inc_not_zero(>stack_refcount) ?
+   return refcount_inc_not_zero(>stack_refcount) ?
task_stack_page(tsk) : NULL;
 }
 
diff --git a/init/init_task.c b/init/init_task.c
index 0ad9772..df0257c 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -62,7 +62,7 @@ struct task_struct init_task
 = {
 #ifdef CONFIG_THREAD_INFO_IN_TASK
.thread_info= INIT_THREAD_INFO(init_task),
-   .stack_refcount = ATOMIC_INIT(1),
+   .stack_refcount = REFCOUNT_INIT(1),
 #endif
.state  = 0,
.stack  = init_stack,
diff --git a/kernel/fork.c b/kernel/fork.c
index a4ac220..73c2c9f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -428,7 +428,7 @@ static void release_task_stack(struct task_struct *tsk)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 void put_task_stack(struct task_struct *tsk)
 {
-   if (atomic_dec_and_test(>stack_refcount))
+   if (refcount_dec_and_test(>stack_refcount))
release_task_stack(tsk);
 }
 #endif
@@ -446,7 +446,7 @@ void free_task(struct task_struct *tsk)
 * If the task had a separate stack allocation, it should be gone
 * by now.
 */
-   WARN_ON_ONCE(atomic_read(>stack_refcount) != 0);
+   WARN_ON_ONCE(refcount_read(>stack_refcount) != 0);
 #endif
rt_mutex_debug_task_free(tsk);
ftrace_graph_exit_task(tsk);
@@ -866,7 +866,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
tsk->stack_vm_area = stack_vm_area;
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
-   atomic_set(>stack_refcount, 1);
+   refcount_set(>stack_refcount, 1);
 #endif
 
if (err)
-- 
2.7.4



[PATCH 2/5] sched: convert signal_struct.sigcnt to refcount_t

2019-01-18 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 signal_struct.sigcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the signal_struct.sigcnt it might make a difference
in following places:
 - put_signal_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/sched/signal.h | 2 +-
 init/init_task.c | 2 +-
 kernel/fork.c| 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 2a65721..38a0f07 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -83,7 +83,7 @@ struct multiprocess_signals {
  * the locking of signal_struct.
  */
 struct signal_struct {
-   atomic_tsigcnt;
+   refcount_t  sigcnt;
atomic_tlive;
int nr_threads;
struct list_headthread_head;
diff --git a/init/init_task.c b/init/init_task.c
index 26131e7..756be60 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -45,7 +45,7 @@ static struct signal_struct init_signals = {
 };
 
 static struct sighand_struct init_sighand = {
-   .count  = ATOMIC_INIT(1),
+   .count  = REFCOUNT_INIT(1),
.action = { { { .sa_handler = SIG_DFL, } }, },
.siglock= __SPIN_LOCK_UNLOCKED(init_sighand.siglock),
.signalfd_wqh   = 
__WAIT_QUEUE_HEAD_INITIALIZER(init_sighand.signalfd_wqh),
diff --git a/kernel/fork.c b/kernel/fork.c
index 71b4757..504324c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -709,7 +709,7 @@ static inline void free_signal_struct(struct signal_struct 
*sig)
 
 static inline void put_signal_struct(struct signal_struct *sig)
 {
-   if (atomic_dec_and_test(>sigcnt))
+   if (refcount_dec_and_test(>sigcnt))
free_signal_struct(sig);
 }
 
@@ -1527,7 +1527,7 @@ static int copy_signal(unsigned long clone_flags, struct 
task_struct *tsk)
 
sig->nr_threads = 1;
atomic_set(>live, 1);
-   atomic_set(>sigcnt, 1);
+   refcount_set(>sigcnt, 1);
 
/* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
@@ -2082,7 +2082,7 @@ static __latent_entropy struct task_struct *copy_process(
} else {
current->signal->nr_threads++;
atomic_inc(>signal->live);
-   atomic_inc(>signal->sigcnt);
+   refcount_inc(>signal->sigcnt);
task_join_group_stop(p);
list_add_tail_rcu(>thread_group,
  >group_leader->thread_group);
-- 
2.7.4



[PATCH 1/5] sched: convert sighand_struct.count to refcount_t

2019-01-18 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 sighand_struct.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the sighand_struct.count it might make a difference
in following places:
 - __cleanup_sighand: decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/exec.c| 4 ++--
 fs/proc/task_nommu.c | 2 +-
 include/linux/sched/signal.h | 3 ++-
 kernel/fork.c| 8 
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index fb72d36..966cd98 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1189,7 +1189,7 @@ static int de_thread(struct task_struct *tsk)
flush_itimer_signals();
 #endif
 
-   if (atomic_read(>count) != 1) {
+   if (refcount_read(>count) != 1) {
struct sighand_struct *newsighand;
/*
 * This ->sighand is shared with the CLONE_SIGHAND
@@ -1199,7 +1199,7 @@ static int de_thread(struct task_struct *tsk)
if (!newsighand)
return -ENOMEM;
 
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
memcpy(newsighand->action, oldsighand->action,
   sizeof(newsighand->action));
 
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 0b63d68..f912872 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -64,7 +64,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
else
bytes += kobjsize(current->files);
 
-   if (current->sighand && atomic_read(>sighand->count) > 1)
+   if (current->sighand && refcount_read(>sighand->count) > 1)
sbytes += kobjsize(current->sighand);
else
bytes += kobjsize(current->sighand);
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 0c3e396..2a65721 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -8,13 +8,14 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Types defining task->signal and task->sighand and APIs using them:
  */
 
 struct sighand_struct {
-   atomic_tcount;
+   refcount_t  count;
struct k_sigaction  action[_NSIG];
spinlock_t  siglock;
wait_queue_head_t   signalfd_wqh;
diff --git a/kernel/fork.c b/kernel/fork.c
index c48e9e2..71b4757 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1463,7 +1463,7 @@ static int copy_sighand(unsigned long clone_flags, struct 
task_struct *tsk)
struct sighand_struct *sig;
 
if (clone_flags & CLONE_SIGHAND) {
-   atomic_inc(>sighand->count);
+   refcount_inc(>sighand->count);
return 0;
}
sig = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
@@ -1471,7 +1471,7 @@ static int copy_sighand(unsigned long clone_flags, struct 
task_struct *tsk)
if (!sig)
return -ENOMEM;
 
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
spin_lock_irq(>sighand->siglock);
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
spin_unlock_irq(>sighand->siglock);
@@ -1480,7 +1480,7 @@ static int copy_sighand(unsigned long clone_flags, struct 
task_struct *tsk)
 
 void __cleanup_sighand(struct sighand_struct *sighand)
 {
-   if (atomic_dec_and_test(>count)) {
+   if (refcount_dec_and_test(>count)) {
   

[PATCH 0/5] sched refcount_t conversions

2019-01-18 Thread Elena Reshetova
I would really love finally to merge these old patches
(now rebased on top of linux-next/master as of last friday),
since as far as I remember none has raised any more concerns
on them.

refcount_t has been now successfully used in kernel in many places,
helped to detect bugs and mistakes in logic of refcounters.

This series, for scheduler and task struct specifically,
replaces atomic_t reference counters with the new refcount_t type
and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can lead to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
More information about each conversion in each patch separately.

Elena Reshetova (5):
  sched: convert sighand_struct.count to refcount_t
  sched: convert signal_struct.sigcnt to refcount_t
  sched: convert numa_group.refcount to refcount_t
  sched/task_struct: convert task_struct.usage to refcount_t
  sched/task_struct: convert task_struct.stack_refcount to refcount_t

 fs/exec.c|  4 ++--
 fs/proc/task_nommu.c |  2 +-
 include/linux/init_task.h|  1 +
 include/linux/sched.h|  5 +++--
 include/linux/sched/signal.h |  5 +++--
 include/linux/sched/task.h   |  4 ++--
 include/linux/sched/task_stack.h |  2 +-
 init/init_task.c |  6 +++---
 kernel/fork.c| 24 
 kernel/sched/fair.c  | 12 ++--
 10 files changed, 34 insertions(+), 31 deletions(-)

-- 
2.7.4



[PATCH] uprobes: convert uprobe.ref to refcount_t

2019-01-16 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 uprobe.ref is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the uprobe.ref it might make a difference
in following places:
 - put_uprobe(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/uprobes.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ad415f7..750aece 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -66,7 +66,7 @@ static struct percpu_rw_semaphore dup_mmap_sem;
 
 struct uprobe {
struct rb_node  rb_node;/* node in the rb tree */
-   atomic_tref;
+   refcount_t  ref;
struct rw_semaphore register_rwsem;
struct rw_semaphore consumer_rwsem;
struct list_headpending_list;
@@ -561,13 +561,13 @@ set_orig_insn(struct arch_uprobe *auprobe, struct 
mm_struct *mm, unsigned long v
 
 static struct uprobe *get_uprobe(struct uprobe *uprobe)
 {
-   atomic_inc(>ref);
+   refcount_inc(>ref);
return uprobe;
 }
 
 static void put_uprobe(struct uprobe *uprobe)
 {
-   if (atomic_dec_and_test(>ref)) {
+   if (refcount_dec_and_test(>ref)) {
/*
 * If application munmap(exec_vma) before uprobe_unregister()
 * gets called, we don't get a chance to remove uprobe from
@@ -658,7 +658,7 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, _tree);
/* get access + creation ref */
-   atomic_set(>ref, 2);
+   refcount_set(>ref, 2);
 
return u;
 }
-- 
2.7.4



[PATCH] kcov: convert kcov.refcount to refcount_t

2019-01-16 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 kcov.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the kcov.refcount it might make a difference
in following places:
 - kcov_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/kcov.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/kcov.c b/kernel/kcov.c
index c2277db..051e86e 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Number of 64-bit words written per one comparison: */
@@ -44,7 +45,7 @@ struct kcov {
 *  - opened file descriptor
 *  - task with enabled coverage (we can't unwire it from another task)
 */
-   atomic_trefcount;
+   refcount_t  refcount;
/* The lock protects mode, size, area and t. */
spinlock_t  lock;
enum kcov_mode  mode;
@@ -228,12 +229,12 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_switch);
 
 static void kcov_get(struct kcov *kcov)
 {
-   atomic_inc(>refcount);
+   refcount_inc(>refcount);
 }
 
 static void kcov_put(struct kcov *kcov)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
vfree(kcov->area);
kfree(kcov);
}
@@ -312,7 +313,7 @@ static int kcov_open(struct inode *inode, struct file 
*filep)
if (!kcov)
return -ENOMEM;
kcov->mode = KCOV_MODE_DISABLED;
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
spin_lock_init(>lock);
filep->private_data = kcov;
return nonseekable_open(inode, filep);
-- 
2.7.4



[PATCH] docs: refcount_t documentation

2017-12-05 Thread Elena Reshetova
Some functions from refcount_t API provide different
memory ordering guarantees that their atomic counterparts.
This adds a document outlining these differences (
Documentation/core-api/refcount-vs-atomic.rst) as well as
some other minor improvements.

Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
Signed-off-by: Kees Cook <keesc...@chromium.org>
---
 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 150 ++
 Documentation/driver-api/basics.rst   |  21 ++--
 include/linux/refcount.h  |   2 +-
 4 files changed, 167 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index d5bbe03..d4d54b0 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -14,6 +14,7 @@ Core utilities
kernel-api
assoc_array
atomic_ops
+   refcount-vs-atomic
cpu_hotplug
local_ops
workqueue
diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
new file mode 100644
index 000..83351c2
--- /dev/null
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -0,0 +1,150 @@
+===
+refcount_t API compared to atomic_t
+===
+
+.. contents:: :local:
+
+Introduction
+
+
+The goal of refcount_t API is to provide a minimal API for implementing
+an object's reference counters. While a generic architecture-independent
+implementation from lib/refcount.c uses atomic operations underneath,
+there are a number of differences between some of the ``refcount_*()`` and
+``atomic_*()`` functions with regards to the memory ordering guarantees.
+This document outlines the differences and provides respective examples
+in order to help maintainers validate their code against the change in
+these memory ordering guarantees.
+
+The terms used through this document try to follow the formal LKMM defined in
+github.com/aparri/memory-model/blob/master/Documentation/explanation.txt
+
+memory-barriers.txt and atomic_t.txt provide more background to the
+memory ordering in general and for atomic operations specifically.
+
+Relevant types of memory ordering
+=
+
+.. note:: The following section only covers some of the memory
+   ordering types that are relevant for the atomics and reference
+   counters and used through this document. For a much broader picture
+   please consult memory-barriers.txt document.
+
+In the absence of any memory ordering guarantees (i.e. fully unordered)
+atomics & refcounters only provide atomicity and
+program order (po) relation (on the same CPU). It guarantees that
+each ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
+are executed in program order on a single CPU.
+This is implemented using :c:func:`READ_ONCE`/:c:func:`WRITE_ONCE` and
+compare-and-swap primitives.
+
+A strong (full) memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before any po-later instruction is executed on the same CPU.
+It also guarantees that all po-earlier stores on the same CPU
+and all propagated stores from other CPUs must propagate to all
+other CPUs before any po-later instruction is executed on the original
+CPU (A-cumulative property). This is implemented using :c:func:`smp_mb`.
+
+A RELEASE memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before the operation. It also guarantees that all po-earlier
+stores on the same CPU and all propagated stores from other CPUs
+must propagate to all other CPUs before the release operation
+(A-cumulative property). This is implemented using
+:c:func:`smp_store_release`.
+
+A control dependency (on success) for refcounters guarantees that
+if a reference for an object was successfully obtained (reference
+counter increment or addition happened, function returned true),
+then further stores are ordered against this operation.
+Control dependency on stores are not implemented using any explicit
+barriers, but rely on CPU not to speculate on stores. This is only
+a single CPU relation and provides no guarantees for other CPUs.
+
+
+Comparison of functions
+===
+
+case 1) - non-"Read/Modify/Write" (RMW) ops
+---
+
+Function changes:
+
+ * :c:func:`atomic_set` --> :c:func:`refcount_set`
+ * :c:func:`atomic_read` --> :c:func:`refcount_read`
+
+Memory ordering guarantee changes:
+
+ * none (both fully unordered)
+
+
+case 2) - increment-based ops that return no value
+--
+
+Function changes:
+
+ * :c:func:`atomic_inc` --> :c:func:`refcount_inc`
+ * :c:func:`atomic_add` -

[PATCH] docs: refcount_t documentation

2017-12-05 Thread Elena Reshetova
Some functions from refcount_t API provide different
memory ordering guarantees that their atomic counterparts.
This adds a document outlining these differences (
Documentation/core-api/refcount-vs-atomic.rst) as well as
some other minor improvements.

Signed-off-by: Elena Reshetova 
Signed-off-by: Kees Cook 
---
 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 150 ++
 Documentation/driver-api/basics.rst   |  21 ++--
 include/linux/refcount.h  |   2 +-
 4 files changed, 167 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index d5bbe03..d4d54b0 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -14,6 +14,7 @@ Core utilities
kernel-api
assoc_array
atomic_ops
+   refcount-vs-atomic
cpu_hotplug
local_ops
workqueue
diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
new file mode 100644
index 000..83351c2
--- /dev/null
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -0,0 +1,150 @@
+===
+refcount_t API compared to atomic_t
+===
+
+.. contents:: :local:
+
+Introduction
+
+
+The goal of refcount_t API is to provide a minimal API for implementing
+an object's reference counters. While a generic architecture-independent
+implementation from lib/refcount.c uses atomic operations underneath,
+there are a number of differences between some of the ``refcount_*()`` and
+``atomic_*()`` functions with regards to the memory ordering guarantees.
+This document outlines the differences and provides respective examples
+in order to help maintainers validate their code against the change in
+these memory ordering guarantees.
+
+The terms used through this document try to follow the formal LKMM defined in
+github.com/aparri/memory-model/blob/master/Documentation/explanation.txt
+
+memory-barriers.txt and atomic_t.txt provide more background to the
+memory ordering in general and for atomic operations specifically.
+
+Relevant types of memory ordering
+=
+
+.. note:: The following section only covers some of the memory
+   ordering types that are relevant for the atomics and reference
+   counters and used through this document. For a much broader picture
+   please consult memory-barriers.txt document.
+
+In the absence of any memory ordering guarantees (i.e. fully unordered)
+atomics & refcounters only provide atomicity and
+program order (po) relation (on the same CPU). It guarantees that
+each ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
+are executed in program order on a single CPU.
+This is implemented using :c:func:`READ_ONCE`/:c:func:`WRITE_ONCE` and
+compare-and-swap primitives.
+
+A strong (full) memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before any po-later instruction is executed on the same CPU.
+It also guarantees that all po-earlier stores on the same CPU
+and all propagated stores from other CPUs must propagate to all
+other CPUs before any po-later instruction is executed on the original
+CPU (A-cumulative property). This is implemented using :c:func:`smp_mb`.
+
+A RELEASE memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before the operation. It also guarantees that all po-earlier
+stores on the same CPU and all propagated stores from other CPUs
+must propagate to all other CPUs before the release operation
+(A-cumulative property). This is implemented using
+:c:func:`smp_store_release`.
+
+A control dependency (on success) for refcounters guarantees that
+if a reference for an object was successfully obtained (reference
+counter increment or addition happened, function returned true),
+then further stores are ordered against this operation.
+Control dependency on stores are not implemented using any explicit
+barriers, but rely on CPU not to speculate on stores. This is only
+a single CPU relation and provides no guarantees for other CPUs.
+
+
+Comparison of functions
+===
+
+case 1) - non-"Read/Modify/Write" (RMW) ops
+---
+
+Function changes:
+
+ * :c:func:`atomic_set` --> :c:func:`refcount_set`
+ * :c:func:`atomic_read` --> :c:func:`refcount_read`
+
+Memory ordering guarantee changes:
+
+ * none (both fully unordered)
+
+
+case 2) - increment-based ops that return no value
+--
+
+Function changes:
+
+ * :c:func:`atomic_inc` --> :c:func:`refcount_inc`
+ * :c:func:`atomic_add` --> :c:func:`refcount_add`
+
+Memory ordering guarantee chang

[PATCH v3] refcount_t vs. atomic_t ordering differences

2017-11-29 Thread Elena Reshetova
Changes in v3:

 - fixes from Kees incorporated apart from concrete examples
   for practical cases.
 - document converted to rst and linked under core-api


Changes in v2:

 - typos and english are fixed based on Randy Dunlap's
   proof reading
 - structure of document improved: 
 * definitions now in the beginning
 * confusing examples removed
 * less redundancy overall and more up-to-the-point text
 - definitions try to follow LKMM defined in
   github.com/aparri/memory-model/blob/master/Documentation/explanation.txt


Elena Reshetova (1):
  refcount_t: documentation for memory ordering differences

 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 129 ++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

-- 
2.7.4



[PATCH v3] refcount_t vs. atomic_t ordering differences

2017-11-29 Thread Elena Reshetova
Changes in v3:

 - fixes from Kees incorporated apart from concrete examples
   for practical cases.
 - document converted to rst and linked under core-api


Changes in v2:

 - typos and english are fixed based on Randy Dunlap's
   proof reading
 - structure of document improved: 
 * definitions now in the beginning
 * confusing examples removed
 * less redundancy overall and more up-to-the-point text
 - definitions try to follow LKMM defined in
   github.com/aparri/memory-model/blob/master/Documentation/explanation.txt


Elena Reshetova (1):
  refcount_t: documentation for memory ordering differences

 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 129 ++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

-- 
2.7.4



[PATCH] refcount_t: documentation for memory ordering differences

2017-11-29 Thread Elena Reshetova
Some functions from refcount_t API provide different
memory ordering guarantees that their atomic counterparts.
This adds a document outlining these differences.

Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 129 ++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index d5bbe03..d4d54b0 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -14,6 +14,7 @@ Core utilities
kernel-api
assoc_array
atomic_ops
+   refcount-vs-atomic
cpu_hotplug
local_ops
workqueue
diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
new file mode 100644
index 000..5619d48
--- /dev/null
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -0,0 +1,129 @@
+===
+refcount_t API compared to atomic_t
+===
+
+The goal of refcount_t API is to provide a minimal API for implementing
+an object's reference counters. While a generic architecture-independent
+implementation from lib/refcount.c uses atomic operations underneath,
+there are a number of differences between some of the refcount_*() and
+atomic_*() functions with regards to the memory ordering guarantees.
+This document outlines the differences and provides respective examples
+in order to help maintainers validate their code against the change in
+these memory ordering guarantees.
+
+memory-barriers.txt and atomic_t.txt provide more background to the
+memory ordering in general and for atomic operations specifically.
+
+Relevant types of memory ordering
+=
+
+**Note**: the following section only covers some of the memory
+ordering types that are relevant for the atomics and reference
+counters and used through this document. For a much broader picture
+please consult memory-barriers.txt document.
+
+In the absence of any memory ordering guarantees (i.e. fully unordered)
+atomics & refcounters only provide atomicity and
+program order (po) relation (on the same CPU). It guarantees that
+each atomic_*() and refcount_*() operation is atomic and instructions
+are executed in program order on a single CPU.
+This is implemented using READ_ONCE()/WRITE_ONCE() and
+compare-and-swap primitives.
+
+A strong (full) memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before any po-later instruction is executed on the same CPU.
+It also guarantees that all po-earlier stores on the same CPU
+and all propagated stores from other CPUs must propagate to all
+other CPUs before any po-later instruction is executed on the original
+CPU (A-cumulative property). This is implemented using smp_mb().
+
+A RELEASE memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before the operation. It also guarantees that all po-earlier
+stores on the same CPU and all propagated stores from other CPUs
+must propagate to all other CPUs before the release operation
+(A-cumulative property). This is implemented using smp_store_release().
+
+A control dependency (on success) for refcounters guarantees that
+if a reference for an object was successfully obtained (reference
+counter increment or addition happened, function returned true),
+then further stores are ordered against this operation.
+Control dependency on stores are not implemented using any explicit
+barriers, but rely on CPU not to speculate on stores. This is only
+a single CPU relation and provides no guarantees for other CPUs.
+
+
+Comparison of functions
+===
+
+case 1) - non-"Read/Modify/Write" (RMW) ops
+---
+
+Function changes:
+atomic_set() --> refcount_set()
+atomic_read() --> refcount_read()
+
+Memory ordering guarantee changes:
+none (both fully unordered)
+
+case 2) - increment-based ops that return no value
+--
+
+Function changes:
+atomic_inc() --> refcount_inc()
+atomic_add() --> refcount_add()
+
+Memory ordering guarantee changes:
+none (both fully unordered)
+
+
+case 3) - decrement-based RMW ops that return no value
+--
+Function changes:
+atomic_dec() --> refcount_dec()
+
+Memory ordering guarantee changes:
+fully unordered --> RELEASE ordering
+
+
+case 4) - increment-based RMW ops that return a value
+-
+
+Function changes

[PATCH] refcount_t: documentation for memory ordering differences

2017-11-29 Thread Elena Reshetova
Some functions from refcount_t API provide different
memory ordering guarantees that their atomic counterparts.
This adds a document outlining these differences.

Signed-off-by: Elena Reshetova 
---
 Documentation/core-api/index.rst  |   1 +
 Documentation/core-api/refcount-vs-atomic.rst | 129 ++
 2 files changed, 130 insertions(+)
 create mode 100644 Documentation/core-api/refcount-vs-atomic.rst

diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst
index d5bbe03..d4d54b0 100644
--- a/Documentation/core-api/index.rst
+++ b/Documentation/core-api/index.rst
@@ -14,6 +14,7 @@ Core utilities
kernel-api
assoc_array
atomic_ops
+   refcount-vs-atomic
cpu_hotplug
local_ops
workqueue
diff --git a/Documentation/core-api/refcount-vs-atomic.rst 
b/Documentation/core-api/refcount-vs-atomic.rst
new file mode 100644
index 000..5619d48
--- /dev/null
+++ b/Documentation/core-api/refcount-vs-atomic.rst
@@ -0,0 +1,129 @@
+===
+refcount_t API compared to atomic_t
+===
+
+The goal of refcount_t API is to provide a minimal API for implementing
+an object's reference counters. While a generic architecture-independent
+implementation from lib/refcount.c uses atomic operations underneath,
+there are a number of differences between some of the refcount_*() and
+atomic_*() functions with regards to the memory ordering guarantees.
+This document outlines the differences and provides respective examples
+in order to help maintainers validate their code against the change in
+these memory ordering guarantees.
+
+memory-barriers.txt and atomic_t.txt provide more background to the
+memory ordering in general and for atomic operations specifically.
+
+Relevant types of memory ordering
+=
+
+**Note**: the following section only covers some of the memory
+ordering types that are relevant for the atomics and reference
+counters and used through this document. For a much broader picture
+please consult memory-barriers.txt document.
+
+In the absence of any memory ordering guarantees (i.e. fully unordered)
+atomics & refcounters only provide atomicity and
+program order (po) relation (on the same CPU). It guarantees that
+each atomic_*() and refcount_*() operation is atomic and instructions
+are executed in program order on a single CPU.
+This is implemented using READ_ONCE()/WRITE_ONCE() and
+compare-and-swap primitives.
+
+A strong (full) memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before any po-later instruction is executed on the same CPU.
+It also guarantees that all po-earlier stores on the same CPU
+and all propagated stores from other CPUs must propagate to all
+other CPUs before any po-later instruction is executed on the original
+CPU (A-cumulative property). This is implemented using smp_mb().
+
+A RELEASE memory ordering guarantees that all prior loads and
+stores (all po-earlier instructions) on the same CPU are completed
+before the operation. It also guarantees that all po-earlier
+stores on the same CPU and all propagated stores from other CPUs
+must propagate to all other CPUs before the release operation
+(A-cumulative property). This is implemented using smp_store_release().
+
+A control dependency (on success) for refcounters guarantees that
+if a reference for an object was successfully obtained (reference
+counter increment or addition happened, function returned true),
+then further stores are ordered against this operation.
+Control dependency on stores are not implemented using any explicit
+barriers, but rely on CPU not to speculate on stores. This is only
+a single CPU relation and provides no guarantees for other CPUs.
+
+
+Comparison of functions
+===
+
+case 1) - non-"Read/Modify/Write" (RMW) ops
+---
+
+Function changes:
+atomic_set() --> refcount_set()
+atomic_read() --> refcount_read()
+
+Memory ordering guarantee changes:
+none (both fully unordered)
+
+case 2) - increment-based ops that return no value
+--
+
+Function changes:
+atomic_inc() --> refcount_inc()
+atomic_add() --> refcount_add()
+
+Memory ordering guarantee changes:
+none (both fully unordered)
+
+
+case 3) - decrement-based RMW ops that return no value
+--
+Function changes:
+atomic_dec() --> refcount_dec()
+
+Memory ordering guarantee changes:
+fully unordered --> RELEASE ordering
+
+
+case 4) - increment-based RMW ops that return a value
+-
+
+Function changes:
+atomic_inc_not_

[PATCH 0/5] v2 xfs refcount conversions

2017-11-29 Thread Elena Reshetova
Hi Dave,

Following our previous conversation I have updated each
patch with a highlight of potential problematic places
with regards to the memory ordering guarantees, as well
as link to the document I am working on to clarify the
matter.

While I didn't see any issues with these 5 particular
conversions, of course I don't understand code anywhere
good enough to make the final claim that "everything is
100% ok".

Please let me know what kind of other clarification or
anything is needed that can help you to make the needed
verification.

Best Regards,
Elena.



Changes in v2:
  - each patch now has a clarification on potential
problematic places with regards to the memory ordering
guarantees as well as reference to a hopefully soon to be
merged more extensive documentation on the
differences between atomic_t and refcount_t on ordering.
  - Rebase on linux-next master.


This series, for xfs, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can lead to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
trees.

Elena Reshetova (5):
  fs, xfs: convert xfs_bui_log_item.bui_refcount from atomic_t to
refcount_t
  fs, xfs: convert xfs_efi_log_item.efi_refcount from atomic_t to
refcount_t
  fs, xfs: convert xlog_ticket.t_ref from atomic_t to refcount_t
  fs, xfs: convert xfs_cui_log_item.cui_refcount from atomic_t to
refcount_t
  fs, xfs: convert xfs_rui_log_item.rui_refcount from atomic_t to
refcount_t

 fs/xfs/xfs_bmap_item.c |  6 +++---
 fs/xfs/xfs_bmap_item.h |  2 +-
 fs/xfs/xfs_extfree_item.c  |  6 +++---
 fs/xfs/xfs_extfree_item.h  |  2 +-
 fs/xfs/xfs_linux.h |  1 +
 fs/xfs/xfs_log.c   | 10 +-
 fs/xfs/xfs_log_priv.h  |  2 +-
 fs/xfs/xfs_refcount_item.c |  6 +++---
 fs/xfs/xfs_refcount_item.h |  2 +-
 fs/xfs/xfs_rmap_item.c |  6 +++---
 fs/xfs/xfs_rmap_item.h |  2 +-
 11 files changed, 23 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH 0/5] v2 xfs refcount conversions

2017-11-29 Thread Elena Reshetova
Hi Dave,

Following our previous conversation I have updated each
patch with a highlight of potential problematic places
with regards to the memory ordering guarantees, as well
as link to the document I am working on to clarify the
matter.

While I didn't see any issues with these 5 particular
conversions, of course I don't understand code anywhere
good enough to make the final claim that "everything is
100% ok".

Please let me know what kind of other clarification or
anything is needed that can help you to make the needed
verification.

Best Regards,
Elena.



Changes in v2:
  - each patch now has a clarification on potential
problematic places with regards to the memory ordering
guarantees as well as reference to a hopefully soon to be
merged more extensive documentation on the
differences between atomic_t and refcount_t on ordering.
  - Rebase on linux-next master.


This series, for xfs, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can lead to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
trees.

Elena Reshetova (5):
  fs, xfs: convert xfs_bui_log_item.bui_refcount from atomic_t to
refcount_t
  fs, xfs: convert xfs_efi_log_item.efi_refcount from atomic_t to
refcount_t
  fs, xfs: convert xlog_ticket.t_ref from atomic_t to refcount_t
  fs, xfs: convert xfs_cui_log_item.cui_refcount from atomic_t to
refcount_t
  fs, xfs: convert xfs_rui_log_item.rui_refcount from atomic_t to
refcount_t

 fs/xfs/xfs_bmap_item.c |  6 +++---
 fs/xfs/xfs_bmap_item.h |  2 +-
 fs/xfs/xfs_extfree_item.c  |  6 +++---
 fs/xfs/xfs_extfree_item.h  |  2 +-
 fs/xfs/xfs_linux.h |  1 +
 fs/xfs/xfs_log.c   | 10 +-
 fs/xfs/xfs_log_priv.h  |  2 +-
 fs/xfs/xfs_refcount_item.c |  6 +++---
 fs/xfs/xfs_refcount_item.h |  2 +-
 fs/xfs/xfs_rmap_item.c |  6 +++---
 fs/xfs/xfs_rmap_item.h |  2 +-
 11 files changed, 23 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH 4/5] fs, xfs: convert xfs_cui_log_item.cui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_cui_log_item.cui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_cui_log_item.cui_refcount it might make a difference
in following places:
 - xfs_cui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/xfs/xfs_refcount_item.c | 6 +++---
 fs/xfs/xfs_refcount_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index 8f2e2fa..004d002 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -205,7 +205,7 @@ xfs_cui_init(
cuip->cui_format.cui_nextents = nextents;
cuip->cui_format.cui_id = (uintptr_t)(void *)cuip;
atomic_set(>cui_next_extent, 0);
-   atomic_set(>cui_refcount, 2);
+   refcount_set(>cui_refcount, 2);
 
return cuip;
 }
@@ -221,8 +221,8 @@ void
 xfs_cui_release(
struct xfs_cui_log_item *cuip)
 {
-   ASSERT(atomic_read(>cui_refcount) > 0);
-   if (atomic_dec_and_test(>cui_refcount)) {
+   ASSERT(refcount_read(>cui_refcount) > 0);
+   if (refcount_dec_and_test(>cui_refcount)) {
xfs_trans_ail_remove(>cui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_cui_item_free(cuip);
}
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index 5b74ddd..abc0377 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -63,7 +63,7 @@ struct kmem_zone;
  */
 struct xfs_cui_log_item {
struct xfs_log_item cui_item;
-   atomic_tcui_refcount;
+   refcount_t  cui_refcount;
atomic_tcui_next_extent;
unsigned long   cui_flags;  /* misc flags */
struct xfs_cui_log_format   cui_format;
-- 
2.7.4



[PATCH 4/5] fs, xfs: convert xfs_cui_log_item.cui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_cui_log_item.cui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_cui_log_item.cui_refcount it might make a difference
in following places:
 - xfs_cui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/xfs/xfs_refcount_item.c | 6 +++---
 fs/xfs/xfs_refcount_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index 8f2e2fa..004d002 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -205,7 +205,7 @@ xfs_cui_init(
cuip->cui_format.cui_nextents = nextents;
cuip->cui_format.cui_id = (uintptr_t)(void *)cuip;
atomic_set(>cui_next_extent, 0);
-   atomic_set(>cui_refcount, 2);
+   refcount_set(>cui_refcount, 2);
 
return cuip;
 }
@@ -221,8 +221,8 @@ void
 xfs_cui_release(
struct xfs_cui_log_item *cuip)
 {
-   ASSERT(atomic_read(>cui_refcount) > 0);
-   if (atomic_dec_and_test(>cui_refcount)) {
+   ASSERT(refcount_read(>cui_refcount) > 0);
+   if (refcount_dec_and_test(>cui_refcount)) {
xfs_trans_ail_remove(>cui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_cui_item_free(cuip);
}
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index 5b74ddd..abc0377 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -63,7 +63,7 @@ struct kmem_zone;
  */
 struct xfs_cui_log_item {
struct xfs_log_item cui_item;
-   atomic_tcui_refcount;
+   refcount_t  cui_refcount;
atomic_tcui_next_extent;
unsigned long   cui_flags;  /* misc flags */
struct xfs_cui_log_format   cui_format;
-- 
2.7.4



[PATCH 5/5] fs, xfs: convert xfs_rui_log_item.rui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_rui_log_item.rui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_rui_log_item.rui_refcount it might make a difference
in following places:
 - xfs_rui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/xfs/xfs_rmap_item.c | 6 +++---
 fs/xfs/xfs_rmap_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index f3b139c..f914829f 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -204,7 +204,7 @@ xfs_rui_init(
ruip->rui_format.rui_nextents = nextents;
ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
atomic_set(>rui_next_extent, 0);
-   atomic_set(>rui_refcount, 2);
+   refcount_set(>rui_refcount, 2);
 
return ruip;
 }
@@ -243,8 +243,8 @@ void
 xfs_rui_release(
struct xfs_rui_log_item *ruip)
 {
-   ASSERT(atomic_read(>rui_refcount) > 0);
-   if (atomic_dec_and_test(>rui_refcount)) {
+   ASSERT(refcount_read(>rui_refcount) > 0);
+   if (refcount_dec_and_test(>rui_refcount)) {
xfs_trans_ail_remove(>rui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_rui_item_free(ruip);
}
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
index 340c968..1e425a9 100644
--- a/fs/xfs/xfs_rmap_item.h
+++ b/fs/xfs/xfs_rmap_item.h
@@ -64,7 +64,7 @@ struct kmem_zone;
  */
 struct xfs_rui_log_item {
struct xfs_log_item rui_item;
-   atomic_trui_refcount;
+   refcount_t  rui_refcount;
atomic_trui_next_extent;
unsigned long   rui_flags;  /* misc flags */
struct xfs_rui_log_format   rui_format;
-- 
2.7.4



[PATCH 3/5] fs, xfs: convert xlog_ticket.t_ref from atomic_t to refcount_t

2017-11-29 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 xlog_ticket.t_ref is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xlog_ticket.t_ref it might make a difference
in following places:
 - xfs_log_ticket_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/xfs/xfs_log.c  | 10 +-
 fs/xfs/xfs_log_priv.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index a503af9..6e1528f 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3600,8 +3600,8 @@ void
 xfs_log_ticket_put(
xlog_ticket_t   *ticket)
 {
-   ASSERT(atomic_read(>t_ref) > 0);
-   if (atomic_dec_and_test(>t_ref))
+   ASSERT(refcount_read(>t_ref) > 0);
+   if (refcount_dec_and_test(>t_ref))
kmem_zone_free(xfs_log_ticket_zone, ticket);
 }
 
@@ -3609,8 +3609,8 @@ xlog_ticket_t *
 xfs_log_ticket_get(
xlog_ticket_t   *ticket)
 {
-   ASSERT(atomic_read(>t_ref) > 0);
-   atomic_inc(>t_ref);
+   ASSERT(refcount_read(>t_ref) > 0);
+   refcount_inc(>t_ref);
return ticket;
 }
 
@@ -3732,7 +3732,7 @@ xlog_ticket_alloc(
 
unit_res = xfs_log_calc_unit_res(log->l_mp, unit_bytes);
 
-   atomic_set(>t_ref, 1);
+   refcount_set(>t_ref, 1);
tic->t_task = current;
INIT_LIST_HEAD(>t_queue);
tic->t_unit_res = unit_res;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 1299759..7482145 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -168,7 +168,7 @@ typedef struct xlog_ticket {
struct list_head   t_queue;  /* reserve/write queue */
struct task_struct *t_task;  /* task that owns this ticket */
xlog_tid_t t_tid;/* transaction identifier   : 4  */
-   atomic_t   t_ref;/* ticket reference count   : 4  */
+   refcount_t t_ref;/* ticket reference count   : 4  */
intt_curr_res;   /* current reservation in bytes : 4  */
intt_unit_res;   /* unit reservation in bytes: 4  */
char   t_ocnt;   /* original count   : 1  */
-- 
2.7.4



[PATCH 5/5] fs, xfs: convert xfs_rui_log_item.rui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_rui_log_item.rui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_rui_log_item.rui_refcount it might make a difference
in following places:
 - xfs_rui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/xfs/xfs_rmap_item.c | 6 +++---
 fs/xfs/xfs_rmap_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index f3b139c..f914829f 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -204,7 +204,7 @@ xfs_rui_init(
ruip->rui_format.rui_nextents = nextents;
ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
atomic_set(>rui_next_extent, 0);
-   atomic_set(>rui_refcount, 2);
+   refcount_set(>rui_refcount, 2);
 
return ruip;
 }
@@ -243,8 +243,8 @@ void
 xfs_rui_release(
struct xfs_rui_log_item *ruip)
 {
-   ASSERT(atomic_read(>rui_refcount) > 0);
-   if (atomic_dec_and_test(>rui_refcount)) {
+   ASSERT(refcount_read(>rui_refcount) > 0);
+   if (refcount_dec_and_test(>rui_refcount)) {
xfs_trans_ail_remove(>rui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_rui_item_free(ruip);
}
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
index 340c968..1e425a9 100644
--- a/fs/xfs/xfs_rmap_item.h
+++ b/fs/xfs/xfs_rmap_item.h
@@ -64,7 +64,7 @@ struct kmem_zone;
  */
 struct xfs_rui_log_item {
struct xfs_log_item rui_item;
-   atomic_trui_refcount;
+   refcount_t  rui_refcount;
atomic_trui_next_extent;
unsigned long   rui_flags;  /* misc flags */
struct xfs_rui_log_format   rui_format;
-- 
2.7.4



[PATCH 3/5] fs, xfs: convert xlog_ticket.t_ref from atomic_t to refcount_t

2017-11-29 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 xlog_ticket.t_ref is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xlog_ticket.t_ref it might make a difference
in following places:
 - xfs_log_ticket_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/xfs/xfs_log.c  | 10 +-
 fs/xfs/xfs_log_priv.h |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index a503af9..6e1528f 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3600,8 +3600,8 @@ void
 xfs_log_ticket_put(
xlog_ticket_t   *ticket)
 {
-   ASSERT(atomic_read(>t_ref) > 0);
-   if (atomic_dec_and_test(>t_ref))
+   ASSERT(refcount_read(>t_ref) > 0);
+   if (refcount_dec_and_test(>t_ref))
kmem_zone_free(xfs_log_ticket_zone, ticket);
 }
 
@@ -3609,8 +3609,8 @@ xlog_ticket_t *
 xfs_log_ticket_get(
xlog_ticket_t   *ticket)
 {
-   ASSERT(atomic_read(>t_ref) > 0);
-   atomic_inc(>t_ref);
+   ASSERT(refcount_read(>t_ref) > 0);
+   refcount_inc(>t_ref);
return ticket;
 }
 
@@ -3732,7 +3732,7 @@ xlog_ticket_alloc(
 
unit_res = xfs_log_calc_unit_res(log->l_mp, unit_bytes);
 
-   atomic_set(>t_ref, 1);
+   refcount_set(>t_ref, 1);
tic->t_task = current;
INIT_LIST_HEAD(>t_queue);
tic->t_unit_res = unit_res;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 1299759..7482145 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -168,7 +168,7 @@ typedef struct xlog_ticket {
struct list_head   t_queue;  /* reserve/write queue */
struct task_struct *t_task;  /* task that owns this ticket */
xlog_tid_t t_tid;/* transaction identifier   : 4  */
-   atomic_t   t_ref;/* ticket reference count   : 4  */
+   refcount_t t_ref;/* ticket reference count   : 4  */
intt_curr_res;   /* current reservation in bytes : 4  */
intt_unit_res;   /* unit reservation in bytes: 4  */
char   t_ocnt;   /* original count   : 1  */
-- 
2.7.4



[PATCH 1/5] fs, xfs: convert xfs_bui_log_item.bui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_bui_log_item.bui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_bui_log_item.bui_refcount it might make a difference
in following places:
 - xfs_bui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/xfs/xfs_bmap_item.c | 6 +++---
 fs/xfs/xfs_bmap_item.h | 2 +-
 fs/xfs/xfs_linux.h | 1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index dd136f7..0f2e3d8 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -201,7 +201,7 @@ xfs_bui_init(
buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
buip->bui_format.bui_id = (uintptr_t)(void *)buip;
atomic_set(>bui_next_extent, 0);
-   atomic_set(>bui_refcount, 2);
+   refcount_set(>bui_refcount, 2);
 
return buip;
 }
@@ -217,8 +217,8 @@ void
 xfs_bui_release(
struct xfs_bui_log_item *buip)
 {
-   ASSERT(atomic_read(>bui_refcount) > 0);
-   if (atomic_dec_and_test(>bui_refcount)) {
+   ASSERT(refcount_read(>bui_refcount) > 0);
+   if (refcount_dec_and_test(>bui_refcount)) {
xfs_trans_ail_remove(>bui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_bui_item_free(buip);
}
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index c867daa..7048b14 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -61,7 +61,7 @@ struct kmem_zone;
  */
 struct xfs_bui_log_item {
struct xfs_log_item bui_item;
-   atomic_tbui_refcount;
+   refcount_t  bui_refcount;
atomic_tbui_next_extent;
unsigned long   bui_flags;  /* misc flags */
struct xfs_bui_log_format   bui_format;
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 99562ec..31658ac 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -20,6 +20,7 @@
 
 #include 
 #include 
+#include 
 
 /*
  * Kernel specific type declarations for XFS
-- 
2.7.4



[PATCH 1/5] fs, xfs: convert xfs_bui_log_item.bui_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_bui_log_item.bui_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_bui_log_item.bui_refcount it might make a difference
in following places:
 - xfs_bui_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/xfs/xfs_bmap_item.c | 6 +++---
 fs/xfs/xfs_bmap_item.h | 2 +-
 fs/xfs/xfs_linux.h | 1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index dd136f7..0f2e3d8 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -201,7 +201,7 @@ xfs_bui_init(
buip->bui_format.bui_nextents = XFS_BUI_MAX_FAST_EXTENTS;
buip->bui_format.bui_id = (uintptr_t)(void *)buip;
atomic_set(>bui_next_extent, 0);
-   atomic_set(>bui_refcount, 2);
+   refcount_set(>bui_refcount, 2);
 
return buip;
 }
@@ -217,8 +217,8 @@ void
 xfs_bui_release(
struct xfs_bui_log_item *buip)
 {
-   ASSERT(atomic_read(>bui_refcount) > 0);
-   if (atomic_dec_and_test(>bui_refcount)) {
+   ASSERT(refcount_read(>bui_refcount) > 0);
+   if (refcount_dec_and_test(>bui_refcount)) {
xfs_trans_ail_remove(>bui_item, SHUTDOWN_LOG_IO_ERROR);
xfs_bui_item_free(buip);
}
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index c867daa..7048b14 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -61,7 +61,7 @@ struct kmem_zone;
  */
 struct xfs_bui_log_item {
struct xfs_log_item bui_item;
-   atomic_tbui_refcount;
+   refcount_t  bui_refcount;
atomic_tbui_next_extent;
unsigned long   bui_flags;  /* misc flags */
struct xfs_bui_log_format   bui_format;
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 99562ec..31658ac 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -20,6 +20,7 @@
 
 #include 
 #include 
+#include 
 
 /*
  * Kernel specific type declarations for XFS
-- 
2.7.4



[PATCH 2/5] fs, xfs: convert xfs_efi_log_item.efi_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_efi_log_item.efi_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_efi_log_item.efi_refcount it might make a difference
in following places:
 - xfs_efi_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/xfs/xfs_extfree_item.c | 6 +++---
 fs/xfs/xfs_extfree_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 44f8c54..dfe2bcb 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -220,7 +220,7 @@ xfs_efi_init(
efip->efi_format.efi_nextents = nextents;
efip->efi_format.efi_id = (uintptr_t)(void *)efip;
atomic_set(>efi_next_extent, 0);
-   atomic_set(>efi_refcount, 2);
+   refcount_set(>efi_refcount, 2);
 
return efip;
 }
@@ -290,8 +290,8 @@ void
 xfs_efi_release(
struct xfs_efi_log_item *efip)
 {
-   ASSERT(atomic_read(>efi_refcount) > 0);
-   if (atomic_dec_and_test(>efi_refcount)) {
+   ASSERT(refcount_read(>efi_refcount) > 0);
+   if (refcount_dec_and_test(>efi_refcount)) {
xfs_trans_ail_remove(>efi_item, SHUTDOWN_LOG_IO_ERROR);
xfs_efi_item_free(efip);
}
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index a32c794..fadf736 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -64,7 +64,7 @@ struct kmem_zone;
  */
 typedef struct xfs_efi_log_item {
xfs_log_item_t  efi_item;
-   atomic_tefi_refcount;
+   refcount_t  efi_refcount;
atomic_tefi_next_extent;
unsigned long   efi_flags;  /* misc flags */
xfs_efi_log_format_tefi_format;
-- 
2.7.4



[PATCH 2/5] fs, xfs: convert xfs_efi_log_item.efi_refcount from atomic_t to refcount_t

2017-11-29 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 xfs_efi_log_item.efi_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the xfs_efi_log_item.efi_refcount it might make a difference
in following places:
 - xfs_efi_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/xfs/xfs_extfree_item.c | 6 +++---
 fs/xfs/xfs_extfree_item.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 44f8c54..dfe2bcb 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -220,7 +220,7 @@ xfs_efi_init(
efip->efi_format.efi_nextents = nextents;
efip->efi_format.efi_id = (uintptr_t)(void *)efip;
atomic_set(>efi_next_extent, 0);
-   atomic_set(>efi_refcount, 2);
+   refcount_set(>efi_refcount, 2);
 
return efip;
 }
@@ -290,8 +290,8 @@ void
 xfs_efi_release(
struct xfs_efi_log_item *efip)
 {
-   ASSERT(atomic_read(>efi_refcount) > 0);
-   if (atomic_dec_and_test(>efi_refcount)) {
+   ASSERT(refcount_read(>efi_refcount) > 0);
+   if (refcount_dec_and_test(>efi_refcount)) {
xfs_trans_ail_remove(>efi_item, SHUTDOWN_LOG_IO_ERROR);
xfs_efi_item_free(efip);
}
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index a32c794..fadf736 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -64,7 +64,7 @@ struct kmem_zone;
  */
 typedef struct xfs_efi_log_item {
xfs_log_item_t  efi_item;
-   atomic_tefi_refcount;
+   refcount_t  efi_refcount;
atomic_tefi_next_extent;
unsigned long   efi_flags;  /* misc flags */
xfs_efi_log_format_tefi_format;
-- 
2.7.4



[PATCH] mbcache: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t

2017-11-29 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 mb_cache_entry.e_refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the mb_cache_entry.e_refcnt it might make a difference
in following places:
 - mb_cache_destroy(), mb_cache_shrink() and mb_cache_entry_delete():
   decrement in refcount_dec() provides RELEASE ordering vs. fully
   unordered atomic counterpart. Since the change is for better, it
   should not matter for these cases.
 - mb_cache_entry_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/mbcache.c| 16 
 include/linux/mbcache.h |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/mbcache.c b/fs/mbcache.c
index d818fd2..8bdb52b 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -90,7 +90,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, 
u32 key,
 
INIT_LIST_HEAD(>e_list);
/* One ref for hash, one ref returned */
-   atomic_set(>e_refcnt, 1);
+   refcount_set(>e_refcnt, 1);
entry->e_key = key;
entry->e_value = value;
entry->e_reusable = reusable;
@@ -109,7 +109,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t 
mask, u32 key,
spin_lock(>c_list_lock);
list_add_tail(>e_list, >c_list);
/* Grab ref for LRU list */
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
cache->c_entry_count++;
spin_unlock(>c_list_lock);
 
@@ -141,7 +141,7 @@ static struct mb_cache_entry *__entry_find(struct mb_cache 
*cache,
entry = hlist_bl_entry(node, struct mb_cache_entry,
   e_hash_list);
if (entry->e_key == key && entry->e_reusable) {
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
goto out;
}
node = node->next;
@@ -204,7 +204,7 @@ struct mb_cache_entry *mb_cache_entry_get(struct mb_cache 
*cache, u32 key,
hlist_bl_lock(head);
hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
if (entry->e_key == key && entry->e_value == value) {
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
goto out;
}
}
@@ -239,7 +239,7 @@ void mb_cache_entry_delete(struct mb_cache *cache, u32 key, 
u64 value)
if (!list_empty(>e_list)) {
list_del_init(>e_list);
cache->c_entry_count--;
-   atomic_dec(>e_refcnt);
+   refcount_dec(>e_refcnt);
}
spin_unlock(>c_list_lock);
mb_cache_entry_put(cache, entry);
@@ -300,7 +300,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache,
hlist_bl_lock(head);
if (!hlist_bl_unhashed(>e_hash_list)) {
hlist_bl_del_init(>e_hash_list);
-   atomic_dec(>e_refcnt);
+   refcount_dec(>e_refcnt);
}
hlist_bl_unlock(head);
if (mb_cache_entry_put(cache, entry))
@@ -397,11 +397,11 @@ void mb_cache_destroy(stru

[PATCH] mbcache: convert mb_cache_entry.e_refcnt from atomic_t to refcount_t

2017-11-29 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 mb_cache_entry.e_refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the mb_cache_entry.e_refcnt it might make a difference
in following places:
 - mb_cache_destroy(), mb_cache_shrink() and mb_cache_entry_delete():
   decrement in refcount_dec() provides RELEASE ordering vs. fully
   unordered atomic counterpart. Since the change is for better, it
   should not matter for these cases.
 - mb_cache_entry_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/mbcache.c| 16 
 include/linux/mbcache.h |  6 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/fs/mbcache.c b/fs/mbcache.c
index d818fd2..8bdb52b 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -90,7 +90,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, 
u32 key,
 
INIT_LIST_HEAD(>e_list);
/* One ref for hash, one ref returned */
-   atomic_set(>e_refcnt, 1);
+   refcount_set(>e_refcnt, 1);
entry->e_key = key;
entry->e_value = value;
entry->e_reusable = reusable;
@@ -109,7 +109,7 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t 
mask, u32 key,
spin_lock(>c_list_lock);
list_add_tail(>e_list, >c_list);
/* Grab ref for LRU list */
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
cache->c_entry_count++;
spin_unlock(>c_list_lock);
 
@@ -141,7 +141,7 @@ static struct mb_cache_entry *__entry_find(struct mb_cache 
*cache,
entry = hlist_bl_entry(node, struct mb_cache_entry,
   e_hash_list);
if (entry->e_key == key && entry->e_reusable) {
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
goto out;
}
node = node->next;
@@ -204,7 +204,7 @@ struct mb_cache_entry *mb_cache_entry_get(struct mb_cache 
*cache, u32 key,
hlist_bl_lock(head);
hlist_bl_for_each_entry(entry, node, head, e_hash_list) {
if (entry->e_key == key && entry->e_value == value) {
-   atomic_inc(>e_refcnt);
+   refcount_inc(>e_refcnt);
goto out;
}
}
@@ -239,7 +239,7 @@ void mb_cache_entry_delete(struct mb_cache *cache, u32 key, 
u64 value)
if (!list_empty(>e_list)) {
list_del_init(>e_list);
cache->c_entry_count--;
-   atomic_dec(>e_refcnt);
+   refcount_dec(>e_refcnt);
}
spin_unlock(>c_list_lock);
mb_cache_entry_put(cache, entry);
@@ -300,7 +300,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache,
hlist_bl_lock(head);
if (!hlist_bl_unhashed(>e_hash_list)) {
hlist_bl_del_init(>e_hash_list);
-   atomic_dec(>e_refcnt);
+   refcount_dec(>e_refcnt);
}
hlist_bl_unlock(head);
if (mb_cache_entry_put(cache, entry))
@@ -397,11 +397,11 @@ void mb_cache_destroy(struct mb_cache *cache)
list_for_each_entry_safe(entry, next, >c_list, e_list) {
if (!hlist_bl_unhashed(>

[PATCH] posix_acl: convert posix_acl.a_refcount from atomic_t to refcount_t

2017-11-29 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 posix_acl.a_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the posix_acl.a_refcount it might make a difference
in following places:
 - get_cached_acl(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart. However this operation is performed under
   rcu_read_lock(), so this should be fine.
 - posix_acl_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/f2fs/acl.c | 2 +-
 fs/posix_acl.c| 6 +++---
 include/linux/posix_acl.h | 7 ---
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 2bb7c9f..1118241 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -270,7 +270,7 @@ static struct posix_acl *f2fs_acl_clone(const struct 
posix_acl *acl,
sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags);
if (clone)
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
}
return clone;
 }
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index eebf5f6..2fd0fde 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -43,7 +43,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int 
type)
rcu_read_lock();
acl = rcu_dereference(*p);
if (!acl || is_uncached_acl(acl) ||
-   atomic_inc_not_zero(>a_refcount))
+   refcount_inc_not_zero(>a_refcount))
break;
rcu_read_unlock();
cpu_relax();
@@ -164,7 +164,7 @@ EXPORT_SYMBOL(get_acl);
 void
 posix_acl_init(struct posix_acl *acl, int count)
 {
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
acl->a_count = count;
 }
 EXPORT_SYMBOL(posix_acl_init);
@@ -197,7 +197,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
   sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags);
if (clone)
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
}
return clone;
 }
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index b2b7255..540595a 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct posix_acl_entry {
@@ -24,7 +25,7 @@ struct posix_acl_entry {
 };
 
 struct posix_acl {
-   atomic_ta_refcount;
+   refcount_t  a_refcount;
struct rcu_head a_rcu;
unsigned inta_count;
struct posix_acl_entry  a_entries[0];
@@ -41,7 +42,7 @@ static inline struct posix_acl *
 posix_acl_dup(struct posix_acl *acl)
 {
if (acl)
-   atomic_inc(>a_refcount);
+   refcount_inc(>a_refcount);
return acl;
 }
 
@@ -51,7 +52,7 @@ posix_acl_dup(struct posix_acl *acl)
 static inline void
 posix_acl_release(struct posix_acl *acl)
 {
-   if (acl && atomic_dec_and_test(>a_refcount))
+   if (acl && refcount_dec_and_test(>a_refcount))
kfree_rcu(acl, a_rcu);
 }
 
-- 
2.7.4



[PATCH] posix_acl: convert posix_acl.a_refcount from atomic_t to refcount_t

2017-11-29 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 posix_acl.a_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the posix_acl.a_refcount it might make a difference
in following places:
 - get_cached_acl(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart. However this operation is performed under
   rcu_read_lock(), so this should be fine.
 - posix_acl_release(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/f2fs/acl.c | 2 +-
 fs/posix_acl.c| 6 +++---
 include/linux/posix_acl.h | 7 ---
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 2bb7c9f..1118241 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -270,7 +270,7 @@ static struct posix_acl *f2fs_acl_clone(const struct 
posix_acl *acl,
sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags);
if (clone)
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
}
return clone;
 }
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index eebf5f6..2fd0fde 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -43,7 +43,7 @@ struct posix_acl *get_cached_acl(struct inode *inode, int 
type)
rcu_read_lock();
acl = rcu_dereference(*p);
if (!acl || is_uncached_acl(acl) ||
-   atomic_inc_not_zero(>a_refcount))
+   refcount_inc_not_zero(>a_refcount))
break;
rcu_read_unlock();
cpu_relax();
@@ -164,7 +164,7 @@ EXPORT_SYMBOL(get_acl);
 void
 posix_acl_init(struct posix_acl *acl, int count)
 {
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
acl->a_count = count;
 }
 EXPORT_SYMBOL(posix_acl_init);
@@ -197,7 +197,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
   sizeof(struct posix_acl_entry);
clone = kmemdup(acl, size, flags);
if (clone)
-   atomic_set(>a_refcount, 1);
+   refcount_set(>a_refcount, 1);
}
return clone;
 }
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index b2b7255..540595a 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct posix_acl_entry {
@@ -24,7 +25,7 @@ struct posix_acl_entry {
 };
 
 struct posix_acl {
-   atomic_ta_refcount;
+   refcount_t  a_refcount;
struct rcu_head a_rcu;
unsigned inta_count;
struct posix_acl_entry  a_entries[0];
@@ -41,7 +42,7 @@ static inline struct posix_acl *
 posix_acl_dup(struct posix_acl *acl)
 {
if (acl)
-   atomic_inc(>a_refcount);
+   refcount_inc(>a_refcount);
return acl;
 }
 
@@ -51,7 +52,7 @@ posix_acl_dup(struct posix_acl *acl)
 static inline void
 posix_acl_release(struct posix_acl *acl)
 {
-   if (acl && atomic_dec_and_test(>a_refcount))
+   if (acl && refcount_dec_and_test(>a_refcount))
kfree_rcu(acl, a_rcu);
 }
 
-- 
2.7.4



[PATCH] mnt_namespace: convert mnt_namespace.count from atomic_t to refcount_t

2017-11-29 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 mnt_namespace.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the mnt_namespace.count it might make a difference
in following places:
 - put_mnt_ns(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/mount.h | 5 +++--
 fs/namespace.c | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/mount.h b/fs/mount.h
index f39bc9d..e28e76d 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -4,9 +4,10 @@
 #include 
 #include 
 #include 
+#include 
 
 struct mnt_namespace {
-   atomic_tcount;
+   refcount_t  count;
struct ns_commonns;
struct mount *  root;
struct list_headlist;
@@ -112,7 +113,7 @@ static inline void detach_mounts(struct dentry *dentry)
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
 }
 
 extern seqlock_t mount_lock;
diff --git a/fs/namespace.c b/fs/namespace.c
index 7c421e0..848e9b0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2895,7 +2895,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct 
user_namespace *user_ns)
}
new_ns->ns.ops = _operations;
new_ns->seq = atomic64_add_return(1, _ns_seq);
-   atomic_set(_ns->count, 1);
+   refcount_set(_ns->count, 1);
new_ns->root = NULL;
INIT_LIST_HEAD(_ns->list);
init_waitqueue_head(_ns->poll);
@@ -3279,7 +3279,7 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-   if (!atomic_dec_and_test(>count))
+   if (!refcount_dec_and_test(>count))
return;
drop_collected_mounts(>root->mnt);
free_mnt_ns(ns);
-- 
2.7.4



[PATCH] mnt_namespace: convert mnt_namespace.count from atomic_t to refcount_t

2017-11-29 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 mnt_namespace.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the mnt_namespace.count it might make a difference
in following places:
 - put_mnt_ns(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/mount.h | 5 +++--
 fs/namespace.c | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/mount.h b/fs/mount.h
index f39bc9d..e28e76d 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -4,9 +4,10 @@
 #include 
 #include 
 #include 
+#include 
 
 struct mnt_namespace {
-   atomic_tcount;
+   refcount_t  count;
struct ns_commonns;
struct mount *  root;
struct list_headlist;
@@ -112,7 +113,7 @@ static inline void detach_mounts(struct dentry *dentry)
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
 }
 
 extern seqlock_t mount_lock;
diff --git a/fs/namespace.c b/fs/namespace.c
index 7c421e0..848e9b0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2895,7 +2895,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct 
user_namespace *user_ns)
}
new_ns->ns.ops = _operations;
new_ns->seq = atomic64_add_return(1, _ns_seq);
-   atomic_set(_ns->count, 1);
+   refcount_set(_ns->count, 1);
new_ns->root = NULL;
INIT_LIST_HEAD(_ns->list);
init_waitqueue_head(_ns->poll);
@@ -3279,7 +3279,7 @@ void __init mnt_init(void)
 
 void put_mnt_ns(struct mnt_namespace *ns)
 {
-   if (!atomic_dec_and_test(>count))
+   if (!refcount_dec_and_test(>count))
return;
drop_collected_mounts(>root->mnt);
free_mnt_ns(ns);
-- 
2.7.4



[PATCH] fs: convert super_block.s_active from atomic_t to refcount_t

2017-11-29 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 super_block.s_active is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the super_block.s_active it might make a difference
in following places:
 - kernfs_pin_sb(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart. However the operation is perfomed under
   mutex_lock(), so this case should be ok.
 - proc_sys_prune_dcache(): increment in refcount_inc_not_zero()
   only guarantees control dependency on success vs. fully ordered
   atomic counterpart. However the operation is perfomed under
   rcu_read_lock(), so this case should be ok.
 - nfs_sb_active() and grab_super(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart.
 - deactivate_locked_super(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart
 - nfs_sb_active() and deactivate_locked_super(): decrement in
   refcount_dec() only provides RELEASE ordering vs. fully unordered
   atomic counterpart. Since the change is for better, it should not
   matter for these cases.
 - deactivate_super(): decrement in refcount_dec_not_one() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered on success atomic atomic_add_unless(, -1, 1).

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +-
 fs/cifs/cifsfs.c|  2 +-
 fs/devpts/inode.c   |  2 +-
 fs/gfs2/super.c |  2 +-
 fs/kernfs/mount.c   |  2 +-
 fs/namespace.c  |  4 ++--
 fs/nfs/super.c  |  4 ++--
 fs/proc/proc_sysctl.c   |  2 +-
 fs/super.c  | 10 +-
 include/linux/fs.h  |  3 ++-
 10 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c 
b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 8666f1e..6cc1526 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -1991,7 +1991,7 @@ void ll_umount_begin(struct super_block *sb)
struct l_wait_info lwi;
 
CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb,
-  sb->s_count, atomic_read(>s_active));
+  sb->s_count, refcount_read(>s_active));
 
obd = class_exp2obd(sbi->ll_md_exp);
if (!obd) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 2cbd0c9..95d965e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -101,7 +101,7 @@ cifs_sb_active(struct super_block *sb)
struct cifs_sb_info *server = CIFS_SB(sb);
 
if (atomic_inc_return(>active) == 1)
-   atomic_inc(>s_active);
+   refcount_inc(>s_active);
 }
 
 void
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 7eae33f..2544e2c 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -197,7 +197,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
 * pty code needs to hold extra references in case of last /dev/tty 
close
 */
sb = path.mnt->mnt_sb;
-   atomic_inc(>s_active);
+   refcount_inc(>s_active);
result = DEVPTS_SB(sb);
 
 out:
diff --git a/fs/gfs2/super.c b/fs/gfs

[PATCH] fs: convert super_block.s_active from atomic_t to refcount_t

2017-11-29 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 super_block.s_active is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the super_block.s_active it might make a difference
in following places:
 - kernfs_pin_sb(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart. However the operation is perfomed under
   mutex_lock(), so this case should be ok.
 - proc_sys_prune_dcache(): increment in refcount_inc_not_zero()
   only guarantees control dependency on success vs. fully ordered
   atomic counterpart. However the operation is perfomed under
   rcu_read_lock(), so this case should be ok.
 - nfs_sb_active() and grab_super(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart.
 - deactivate_locked_super(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart
 - nfs_sb_active() and deactivate_locked_super(): decrement in
   refcount_dec() only provides RELEASE ordering vs. fully unordered
   atomic counterpart. Since the change is for better, it should not
   matter for these cases.
 - deactivate_super(): decrement in refcount_dec_not_one() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered on success atomic atomic_add_unless(, -1, 1).

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 drivers/staging/lustre/lustre/llite/llite_lib.c |  2 +-
 fs/cifs/cifsfs.c|  2 +-
 fs/devpts/inode.c   |  2 +-
 fs/gfs2/super.c |  2 +-
 fs/kernfs/mount.c   |  2 +-
 fs/namespace.c  |  4 ++--
 fs/nfs/super.c  |  4 ++--
 fs/proc/proc_sysctl.c   |  2 +-
 fs/super.c  | 10 +-
 include/linux/fs.h  |  3 ++-
 10 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c 
b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 8666f1e..6cc1526 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -1991,7 +1991,7 @@ void ll_umount_begin(struct super_block *sb)
struct l_wait_info lwi;
 
CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb,
-  sb->s_count, atomic_read(>s_active));
+  sb->s_count, refcount_read(>s_active));
 
obd = class_exp2obd(sbi->ll_md_exp);
if (!obd) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 2cbd0c9..95d965e 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -101,7 +101,7 @@ cifs_sb_active(struct super_block *sb)
struct cifs_sb_info *server = CIFS_SB(sb);
 
if (atomic_inc_return(>active) == 1)
-   atomic_inc(>s_active);
+   refcount_inc(>s_active);
 }
 
 void
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 7eae33f..2544e2c 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -197,7 +197,7 @@ struct pts_fs_info *devpts_acquire(struct file *filp)
 * pty code needs to hold extra references in case of last /dev/tty 
close
 */
sb = path.mnt->mnt_sb;
-   atomic_inc(>s_active);
+   refcount_inc(>s_active);
result = DEVPTS_SB(sb);
 
 out:
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index d81d46e..cf29290 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -957,7 +957,7 @@ voi

[PATCH] userfaultfd: convert userfaultfd_ctx.refcount from atomic_t to refcount_t

2017-11-29 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 userfaultfd_ctx.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the userfaultfd_ctx.refcount it might make a difference
in following places:
 - userfaultfd_ctx_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - userfaultfd_ctx_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/userfaultfd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index ac9a4e6..b63ebcac 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
@@ -53,7 +54,7 @@ struct userfaultfd_ctx {
/* a refile sequence protected by fault_pending_wqh lock */
struct seqcount refile_seq;
/* pseudo fd refcounting */
-   atomic_t refcount;
+   refcount_t refcount;
/* userfaultfd syscall flags */
unsigned int flags;
/* features requested from the userspace */
@@ -138,7 +139,7 @@ static int userfaultfd_wake_function(wait_queue_entry_t 
*wq, unsigned mode,
  */
 static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
 {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
BUG();
 }
 
@@ -152,7 +153,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
  */
 static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
VM_BUG_ON(spin_is_locked(>fault_pending_wqh.lock));
VM_BUG_ON(waitqueue_active(>fault_pending_wqh));
VM_BUG_ON(spin_is_locked(>fault_wqh.lock));
@@ -662,7 +663,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct 
list_head *fcs)
return -ENOMEM;
}
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
ctx->flags = octx->flags;
ctx->state = UFFD_STATE_RUNNING;
ctx->features = octx->features;
@@ -1902,7 +1903,7 @@ static struct file *userfaultfd_file_create(int flags)
if (!ctx)
goto out;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
ctx->flags = flags;
ctx->features = 0;
ctx->state = UFFD_STATE_WAIT_API;
-- 
2.7.4



[PATCH] userfaultfd: convert userfaultfd_ctx.refcount from atomic_t to refcount_t

2017-11-29 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 userfaultfd_ctx.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the userfaultfd_ctx.refcount it might make a difference
in following places:
 - userfaultfd_ctx_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - userfaultfd_ctx_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/userfaultfd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index ac9a4e6..b63ebcac 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
 
@@ -53,7 +54,7 @@ struct userfaultfd_ctx {
/* a refile sequence protected by fault_pending_wqh lock */
struct seqcount refile_seq;
/* pseudo fd refcounting */
-   atomic_t refcount;
+   refcount_t refcount;
/* userfaultfd syscall flags */
unsigned int flags;
/* features requested from the userspace */
@@ -138,7 +139,7 @@ static int userfaultfd_wake_function(wait_queue_entry_t 
*wq, unsigned mode,
  */
 static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
 {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
BUG();
 }
 
@@ -152,7 +153,7 @@ static void userfaultfd_ctx_get(struct userfaultfd_ctx *ctx)
  */
 static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
VM_BUG_ON(spin_is_locked(>fault_pending_wqh.lock));
VM_BUG_ON(waitqueue_active(>fault_pending_wqh));
VM_BUG_ON(spin_is_locked(>fault_wqh.lock));
@@ -662,7 +663,7 @@ int dup_userfaultfd(struct vm_area_struct *vma, struct 
list_head *fcs)
return -ENOMEM;
}
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
ctx->flags = octx->flags;
ctx->state = UFFD_STATE_RUNNING;
ctx->features = octx->features;
@@ -1902,7 +1903,7 @@ static struct file *userfaultfd_file_create(int flags)
if (!ctx)
goto out;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
ctx->flags = flags;
ctx->features = 0;
ctx->state = UFFD_STATE_WAIT_API;
-- 
2.7.4



[PATCH 3/4] lockd: convert nlm_lockowner.count from atomic_t to refcount_t

2017-11-29 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 nlm_lockowner.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_lockowner.count it might make a difference
in following places:
 - nlm_put_lockowner(): decrement in refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success and
   holds a spin lock on success vs. fully ordered atomic counterpart.
   No changes in spin lock guarantees.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/lockd/clntproc.c | 6 +++---
 include/linux/lockd/lockd.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 066ac31..112173d 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -48,13 +48,13 @@ void nlmclnt_next_cookie(struct nlm_cookie *c)
 
 static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
return lockowner;
 }
 
 static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
 {
-   if (!atomic_dec_and_lock(>count, >host->h_lock))
+   if (!refcount_dec_and_lock(>count, >host->h_lock))
return;
list_del(>list);
spin_unlock(>host->h_lock);
@@ -105,7 +105,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct 
nlm_host *host, fl_owner_
res = __nlm_find_lockowner(host, owner);
if (res == NULL && new != NULL) {
res = new;
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
new->owner = owner;
new->pid = __nlm_alloc_pid(host);
new->host = nlm_get_host(host);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index cded0ad..86d012a 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -123,7 +123,7 @@ static inline struct sockaddr *nlm_srcaddr(const struct 
nlm_host *host)
  */
 struct nlm_lockowner {
struct list_head list;
-   atomic_t count;
+   refcount_t count;
 
struct nlm_host *host;
fl_owner_t owner;
-- 
2.7.4



[PATCH 3/4] lockd: convert nlm_lockowner.count from atomic_t to refcount_t

2017-11-29 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 nlm_lockowner.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_lockowner.count it might make a difference
in following places:
 - nlm_put_lockowner(): decrement in refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success and
   holds a spin lock on success vs. fully ordered atomic counterpart.
   No changes in spin lock guarantees.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/lockd/clntproc.c | 6 +++---
 include/linux/lockd/lockd.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 066ac31..112173d 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -48,13 +48,13 @@ void nlmclnt_next_cookie(struct nlm_cookie *c)
 
 static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
return lockowner;
 }
 
 static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
 {
-   if (!atomic_dec_and_lock(>count, >host->h_lock))
+   if (!refcount_dec_and_lock(>count, >host->h_lock))
return;
list_del(>list);
spin_unlock(>host->h_lock);
@@ -105,7 +105,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct 
nlm_host *host, fl_owner_
res = __nlm_find_lockowner(host, owner);
if (res == NULL && new != NULL) {
res = new;
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
new->owner = owner;
new->pid = __nlm_alloc_pid(host);
new->host = nlm_get_host(host);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index cded0ad..86d012a 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -123,7 +123,7 @@ static inline struct sockaddr *nlm_srcaddr(const struct 
nlm_host *host)
  */
 struct nlm_lockowner {
struct list_head list;
-   atomic_t count;
+   refcount_t count;
 
struct nlm_host *host;
fl_owner_t owner;
-- 
2.7.4



[PATCH 2/4] lockd: convert nsm_handle.sm_count from atomic_t to refcount_t

2017-11-29 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 nsm_handle.sm_count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nsm_handle.sm_count it might make a difference
in following places:
 - nsm_release(): decrement in refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success
   and holds a spin lock on success vs. fully ordered atomic
   counterpart. No change for the spin lock guarantees.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/lockd/host.c |  2 +-
 fs/lockd/mon.c  | 14 +++---
 include/linux/lockd/lockd.h |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 11b6832..7d6ab72 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -114,7 +114,7 @@ static struct nlm_host *nlm_alloc_host(struct 
nlm_lookup_host_info *ni,
unsigned long now = jiffies;
 
if (nsm != NULL)
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
else {
host = NULL;
nsm = nsm_get_handle(ni->net, ni->sap, ni->salen,
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 96cfb29..654594e 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -191,7 +191,7 @@ void nsm_unmonitor(const struct nlm_host *host)
struct nsm_res  res;
int status;
 
-   if (atomic_read(>sm_count) == 1
+   if (refcount_read(>sm_count) == 1
 && nsm->sm_monitored && !nsm->sm_sticky) {
dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
 
@@ -279,7 +279,7 @@ static struct nsm_handle *nsm_create_handle(const struct 
sockaddr *sap,
if (unlikely(new == NULL))
return NULL;
 
-   atomic_set(>sm_count, 1);
+   refcount_set(>sm_count, 1);
new->sm_name = (char *)(new + 1);
memcpy(nsm_addr(new), sap, salen);
new->sm_addrlen = salen;
@@ -337,13 +337,13 @@ struct nsm_handle *nsm_get_handle(const struct net *net,
cached = nsm_lookup_addr(>nsm_handles, sap);
 
if (cached != NULL) {
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
spin_unlock(_lock);
kfree(new);
dprintk("lockd: found nsm_handle for %s (%s), "
"cnt %d\n", cached->sm_name,
cached->sm_addrbuf,
-   atomic_read(>sm_count));
+   refcount_read(>sm_count));
return cached;
}
 
@@ -388,12 +388,12 @@ struct nsm_handle *nsm_reboot_lookup(const struct net 
*net,
return cached;
}
 
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
spin_unlock(_lock);
 
dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
cached->sm_name, cached->sm_addrbuf,
-   atomic_read(>sm_count));
+   refcount_read(>sm_count));
return cached;
 }
 
@@ -404,7 +404,7 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net,
  */
 void nsm_release(struct nsm_handle *nsm)
 {
-   if (atomic_dec_and_lock(>sm_count, _lock)) {
+   if (refcount_dec_and_lock(>sm_count, _lock)) {
list_del(>sm_link);
spin_unlock(_lock);
dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
diff --git a/include/linux/lockd/l

[PATCH 2/4] lockd: convert nsm_handle.sm_count from atomic_t to refcount_t

2017-11-29 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 nsm_handle.sm_count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nsm_handle.sm_count it might make a difference
in following places:
 - nsm_release(): decrement in refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success
   and holds a spin lock on success vs. fully ordered atomic
   counterpart. No change for the spin lock guarantees.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/lockd/host.c |  2 +-
 fs/lockd/mon.c  | 14 +++---
 include/linux/lockd/lockd.h |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 11b6832..7d6ab72 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -114,7 +114,7 @@ static struct nlm_host *nlm_alloc_host(struct 
nlm_lookup_host_info *ni,
unsigned long now = jiffies;
 
if (nsm != NULL)
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
else {
host = NULL;
nsm = nsm_get_handle(ni->net, ni->sap, ni->salen,
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 96cfb29..654594e 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -191,7 +191,7 @@ void nsm_unmonitor(const struct nlm_host *host)
struct nsm_res  res;
int status;
 
-   if (atomic_read(>sm_count) == 1
+   if (refcount_read(>sm_count) == 1
 && nsm->sm_monitored && !nsm->sm_sticky) {
dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name);
 
@@ -279,7 +279,7 @@ static struct nsm_handle *nsm_create_handle(const struct 
sockaddr *sap,
if (unlikely(new == NULL))
return NULL;
 
-   atomic_set(>sm_count, 1);
+   refcount_set(>sm_count, 1);
new->sm_name = (char *)(new + 1);
memcpy(nsm_addr(new), sap, salen);
new->sm_addrlen = salen;
@@ -337,13 +337,13 @@ struct nsm_handle *nsm_get_handle(const struct net *net,
cached = nsm_lookup_addr(>nsm_handles, sap);
 
if (cached != NULL) {
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
spin_unlock(_lock);
kfree(new);
dprintk("lockd: found nsm_handle for %s (%s), "
"cnt %d\n", cached->sm_name,
cached->sm_addrbuf,
-   atomic_read(>sm_count));
+   refcount_read(>sm_count));
return cached;
}
 
@@ -388,12 +388,12 @@ struct nsm_handle *nsm_reboot_lookup(const struct net 
*net,
return cached;
}
 
-   atomic_inc(>sm_count);
+   refcount_inc(>sm_count);
spin_unlock(_lock);
 
dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
cached->sm_name, cached->sm_addrbuf,
-   atomic_read(>sm_count));
+   refcount_read(>sm_count));
return cached;
 }
 
@@ -404,7 +404,7 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net,
  */
 void nsm_release(struct nsm_handle *nsm)
 {
-   if (atomic_dec_and_lock(>sm_count, _lock)) {
+   if (refcount_dec_and_lock(>sm_count, _lock)) {
list_del(>sm_link);
spin_unlock(_lock);
dprintk("lockd: destroyed nsm_handle for %s (%s)\n",
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 39dfeea..cded0ad 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linu

[PATCH 1/4] lockd: convert nlm_host.h_count from atomic_t to refcount_t

2017-11-29 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 nlm_host.h_count  is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_host.h_count it might make a difference
in following places:
 - nlmsvc_release_host(): decrement in refcount_dec()
   provides RELEASE ordering, while original atomic_dec()
   was fully unordered. Since the change is for better, it
   should not matter.
 - nlmclnt_release_host(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart. It doesn't seem to
   matter in this case since object freeing happens under mutex
   lock anyway.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/lockd/host.c | 14 +++---
 include/linux/lockd/lockd.h |  3 ++-
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 826a891..11b6832 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -151,7 +151,7 @@ static struct nlm_host *nlm_alloc_host(struct 
nlm_lookup_host_info *ni,
host->h_state  = 0;
host->h_nsmstate   = 0;
host->h_pidcount   = 0;
-   atomic_set(>h_count, 1);
+   refcount_set(>h_count, 1);
mutex_init(>h_mutex);
host->h_nextrebind = now + NLM_HOST_REBIND;
host->h_expires= now + NLM_HOST_EXPIRE;
@@ -290,7 +290,7 @@ void nlmclnt_release_host(struct nlm_host *host)
 
WARN_ON_ONCE(host->h_server);
 
-   if (atomic_dec_and_test(>h_count)) {
+   if (refcount_dec_and_test(>h_count)) {
WARN_ON_ONCE(!list_empty(>h_lockowners));
WARN_ON_ONCE(!list_empty(>h_granted));
WARN_ON_ONCE(!list_empty(>h_reclaim));
@@ -410,7 +410,7 @@ void nlmsvc_release_host(struct nlm_host *host)
dprintk("lockd: release server host %s\n", host->h_name);
 
WARN_ON_ONCE(!host->h_server);
-   atomic_dec(>h_count);
+   refcount_dec(>h_count);
 }
 
 /*
@@ -504,7 +504,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
 {
if (host) {
dprintk("lockd: get host %s\n", host->h_name);
-   atomic_inc(>h_count);
+   refcount_inc(>h_count);
host->h_expires = jiffies + NLM_HOST_EXPIRE;
}
return host;
@@ -593,7 +593,7 @@ static void nlm_complain_hosts(struct net *net)
if (net && host->net != net)
continue;
dprintk("   %s (cnt %d use %d exp %ld net %x)\n",
-   host->h_name, atomic_read(>h_count),
+   host->h_name, refcount_read(>h_count),
host->h_inuse, host->h_expires, host->net->ns.inum);
}
 }
@@ -662,11 +662,11 @@ nlm_gc_hosts(struct net *net)
for_each_host_safe(host, next, chain, nlm_server_hosts) {
if (net && host->net != net)
continue;
-   if (atomic_read(>h_count) || host->h_inuse
+   if (refcount_read(>h_count) || host->h_inuse
 || time_before(jiffies, host->h_expires)) {
dprintk("nlm_gc_hosts skipping %s "
"(cnt %d use %d exp %ld net %x)\n",
-   host->h_name, atomic_read(>h_count),
+   host->h_name, refcount_read(>h_count),
host-&

[PATCH 1/4] lockd: convert nlm_host.h_count from atomic_t to refcount_t

2017-11-29 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 nlm_host.h_count  is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_host.h_count it might make a difference
in following places:
 - nlmsvc_release_host(): decrement in refcount_dec()
   provides RELEASE ordering, while original atomic_dec()
   was fully unordered. Since the change is for better, it
   should not matter.
 - nlmclnt_release_host(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart. It doesn't seem to
   matter in this case since object freeing happens under mutex
   lock anyway.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/lockd/host.c | 14 +++---
 include/linux/lockd/lockd.h |  3 ++-
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 826a891..11b6832 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -151,7 +151,7 @@ static struct nlm_host *nlm_alloc_host(struct 
nlm_lookup_host_info *ni,
host->h_state  = 0;
host->h_nsmstate   = 0;
host->h_pidcount   = 0;
-   atomic_set(>h_count, 1);
+   refcount_set(>h_count, 1);
mutex_init(>h_mutex);
host->h_nextrebind = now + NLM_HOST_REBIND;
host->h_expires= now + NLM_HOST_EXPIRE;
@@ -290,7 +290,7 @@ void nlmclnt_release_host(struct nlm_host *host)
 
WARN_ON_ONCE(host->h_server);
 
-   if (atomic_dec_and_test(>h_count)) {
+   if (refcount_dec_and_test(>h_count)) {
WARN_ON_ONCE(!list_empty(>h_lockowners));
WARN_ON_ONCE(!list_empty(>h_granted));
WARN_ON_ONCE(!list_empty(>h_reclaim));
@@ -410,7 +410,7 @@ void nlmsvc_release_host(struct nlm_host *host)
dprintk("lockd: release server host %s\n", host->h_name);
 
WARN_ON_ONCE(!host->h_server);
-   atomic_dec(>h_count);
+   refcount_dec(>h_count);
 }
 
 /*
@@ -504,7 +504,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
 {
if (host) {
dprintk("lockd: get host %s\n", host->h_name);
-   atomic_inc(>h_count);
+   refcount_inc(>h_count);
host->h_expires = jiffies + NLM_HOST_EXPIRE;
}
return host;
@@ -593,7 +593,7 @@ static void nlm_complain_hosts(struct net *net)
if (net && host->net != net)
continue;
dprintk("   %s (cnt %d use %d exp %ld net %x)\n",
-   host->h_name, atomic_read(>h_count),
+   host->h_name, refcount_read(>h_count),
host->h_inuse, host->h_expires, host->net->ns.inum);
}
 }
@@ -662,11 +662,11 @@ nlm_gc_hosts(struct net *net)
for_each_host_safe(host, next, chain, nlm_server_hosts) {
if (net && host->net != net)
continue;
-   if (atomic_read(>h_count) || host->h_inuse
+   if (refcount_read(>h_count) || host->h_inuse
 || time_before(jiffies, host->h_expires)) {
dprintk("nlm_gc_hosts skipping %s "
"(cnt %d use %d exp %ld net %x)\n",
-   host->h_name, atomic_read(>h_count),
+   host->h_name, refcount_read(>h_count),
host->h_inuse, host->h_expires,
host->net->ns.inum);

[PATCH 4/4] lockd: convert nlm_rqst.a_count from atomic_t to refcount_t

2017-11-29 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 nlm_rqst.a_count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_rqst.a_count it might make a difference
in following places:
 - nlmclnt_release_call() and nlmsvc_release_call(): decrement
   in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 fs/lockd/clntproc.c | 8 
 fs/lockd/svcproc.c  | 2 +-
 include/linux/lockd/lockd.h | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 112173d..a2c0dfc 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -204,7 +204,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
for(;;) {
call = kzalloc(sizeof(*call), GFP_KERNEL);
if (call != NULL) {
-   atomic_set(>a_count, 1);
+   refcount_set(>a_count, 1);
locks_init_lock(>a_args.lock.fl);
locks_init_lock(>a_res.lock.fl);
call->a_host = nlm_get_host(host);
@@ -222,7 +222,7 @@ void nlmclnt_release_call(struct nlm_rqst *call)
 {
const struct nlmclnt_operations *nlmclnt_ops = 
call->a_host->h_nlmclnt_ops;
 
-   if (!atomic_dec_and_test(>a_count))
+   if (!refcount_dec_and_test(>a_count))
return;
if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call)
nlmclnt_ops->nlmclnt_release_call(call->a_callback_data);
@@ -678,7 +678,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
goto out;
}
 
-   atomic_inc(>a_count);
+   refcount_inc(>a_count);
status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
NLMPROC_UNLOCK, _unlock_ops);
if (status < 0)
@@ -769,7 +769,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, 
struct file_lock *fl
nlmclnt_setlockargs(req, fl);
req->a_args.block = block;
 
-   atomic_inc(>a_count);
+   refcount_inc(>a_count);
status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
NLMPROC_CANCEL, _cancel_ops);
if (status == 0 && req->a_res.status == nlm_lck_denied)
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 0d670c5..ea77c66 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -295,7 +295,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, 
void *data)
 
 void nlmsvc_release_call(struct nlm_rqst *call)
 {
-   if (!atomic_dec_and_test(>a_count))
+   if (!refcount_dec_and_test(>a_count))
return;
nlmsvc_release_host(call->a_host);
kfree(call);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 86d012a..4fd95db 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -137,7 +137,7 @@ struct nlm_wait;
  */
 #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
-   atomic_ta_count;
+   refcount_t  a_count;
unsigned inta_flags;/* initial RPC task flags */
struct nlm_host *   a_host; /* host handle */
struct nlm_args a_args; /* arguments */
-- 
2.7.4



[PATCH 4/4] lockd: convert nlm_rqst.a_count from atomic_t to refcount_t

2017-11-29 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 nlm_rqst.a_count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nlm_rqst.a_count it might make a difference
in following places:
 - nlmclnt_release_call() and nlmsvc_release_call(): decrement
   in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 fs/lockd/clntproc.c | 8 
 fs/lockd/svcproc.c  | 2 +-
 include/linux/lockd/lockd.h | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 112173d..a2c0dfc 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -204,7 +204,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
for(;;) {
call = kzalloc(sizeof(*call), GFP_KERNEL);
if (call != NULL) {
-   atomic_set(>a_count, 1);
+   refcount_set(>a_count, 1);
locks_init_lock(>a_args.lock.fl);
locks_init_lock(>a_res.lock.fl);
call->a_host = nlm_get_host(host);
@@ -222,7 +222,7 @@ void nlmclnt_release_call(struct nlm_rqst *call)
 {
const struct nlmclnt_operations *nlmclnt_ops = 
call->a_host->h_nlmclnt_ops;
 
-   if (!atomic_dec_and_test(>a_count))
+   if (!refcount_dec_and_test(>a_count))
return;
if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call)
nlmclnt_ops->nlmclnt_release_call(call->a_callback_data);
@@ -678,7 +678,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
goto out;
}
 
-   atomic_inc(>a_count);
+   refcount_inc(>a_count);
status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
NLMPROC_UNLOCK, _unlock_ops);
if (status < 0)
@@ -769,7 +769,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, 
struct file_lock *fl
nlmclnt_setlockargs(req, fl);
req->a_args.block = block;
 
-   atomic_inc(>a_count);
+   refcount_inc(>a_count);
status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req,
NLMPROC_CANCEL, _cancel_ops);
if (status == 0 && req->a_res.status == nlm_lck_denied)
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 0d670c5..ea77c66 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -295,7 +295,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, 
void *data)
 
 void nlmsvc_release_call(struct nlm_rqst *call)
 {
-   if (!atomic_dec_and_test(>a_count))
+   if (!refcount_dec_and_test(>a_count))
return;
nlmsvc_release_host(call->a_host);
kfree(call);
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 86d012a..4fd95db 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -137,7 +137,7 @@ struct nlm_wait;
  */
 #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u)
 struct nlm_rqst {
-   atomic_ta_count;
+   refcount_t  a_count;
unsigned inta_flags;/* initial RPC task flags */
struct nlm_host *   a_host; /* host handle */
struct nlm_args a_args; /* arguments */
-- 
2.7.4



[PATCH 0/4] lockd refcount conversions

2017-11-29 Thread Elena Reshetova
This series, for lockd component, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
tree.

Elena Reshetova (4):
  lockd: convert nlm_host.h_count from atomic_t to refcount_t
  lockd: convert nsm_handle.sm_count from atomic_t to refcount_t
  lockd: convert nlm_lockowner.count from atomic_t to refcount_t
  lockd: convert nlm_rqst.a_count from atomic_t to refcount_t

 fs/lockd/clntproc.c | 14 +++---
 fs/lockd/host.c | 16 
 fs/lockd/mon.c  | 14 +++---
 fs/lockd/svcproc.c  |  2 +-
 include/linux/lockd/lockd.h |  9 +
 5 files changed, 28 insertions(+), 27 deletions(-)

-- 
2.7.4



[PATCH 0/4] lockd refcount conversions

2017-11-29 Thread Elena Reshetova
This series, for lockd component, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
tree.

Elena Reshetova (4):
  lockd: convert nlm_host.h_count from atomic_t to refcount_t
  lockd: convert nsm_handle.sm_count from atomic_t to refcount_t
  lockd: convert nlm_lockowner.count from atomic_t to refcount_t
  lockd: convert nlm_rqst.a_count from atomic_t to refcount_t

 fs/lockd/clntproc.c | 14 +++---
 fs/lockd/host.c | 16 
 fs/lockd/mon.c  | 14 +++---
 fs/lockd/svcproc.c  |  2 +-
 include/linux/lockd/lockd.h |  9 +
 5 files changed, 28 insertions(+), 27 deletions(-)

-- 
2.7.4



[PATCH 12/16] nsproxy: convert nsproxy.count to refcount_t

2017-11-16 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 nsproxy.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nsproxy.count it might make a difference
in following places:
 - put_nsproxy() and switch_task_namespaces(): decrement in
   refcount_dec_and_test() only provides RELEASE ordering
   and control dependency on success vs. fully ordered
   atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/nsproxy.h | 6 +++---
 kernel/nsproxy.c| 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 2ae1b1a..90f09ff 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -29,7 +29,7 @@ struct fs_struct;
  * nsproxy is copied.
  */
 struct nsproxy {
-   atomic_t count;
+   refcount_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
@@ -75,14 +75,14 @@ int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
-   if (atomic_dec_and_test(>count)) {
+   if (refcount_dec_and_test(>count)) {
free_nsproxy(ns);
}
 }
 
 static inline void get_nsproxy(struct nsproxy *ns)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
 }
 
 #endif
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f6c5d33..5bfe691 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -31,7 +31,7 @@
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = {
-   .count  = ATOMIC_INIT(1),
+   .count  = REFCOUNT_INIT(1),
.uts_ns = _uts_ns,
 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
.ipc_ns = _ipc_ns,
@@ -52,7 +52,7 @@ static inline struct nsproxy *create_nsproxy(void)
 
nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
if (nsproxy)
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
return nsproxy;
 }
 
@@ -225,7 +225,7 @@ void switch_task_namespaces(struct task_struct *p, struct 
nsproxy *new)
p->nsproxy = new;
task_unlock(p);
 
-   if (ns && atomic_dec_and_test(>count))
+   if (ns && refcount_dec_and_test(>count))
free_nsproxy(ns);
 }
 
-- 
2.7.4



[PATCH 12/16] nsproxy: convert nsproxy.count to refcount_t

2017-11-16 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 nsproxy.count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the nsproxy.count it might make a difference
in following places:
 - put_nsproxy() and switch_task_namespaces(): decrement in
   refcount_dec_and_test() only provides RELEASE ordering
   and control dependency on success vs. fully ordered
   atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/nsproxy.h | 6 +++---
 kernel/nsproxy.c| 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 2ae1b1a..90f09ff 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -29,7 +29,7 @@ struct fs_struct;
  * nsproxy is copied.
  */
 struct nsproxy {
-   atomic_t count;
+   refcount_t count;
struct uts_namespace *uts_ns;
struct ipc_namespace *ipc_ns;
struct mnt_namespace *mnt_ns;
@@ -75,14 +75,14 @@ int __init nsproxy_cache_init(void);
 
 static inline void put_nsproxy(struct nsproxy *ns)
 {
-   if (atomic_dec_and_test(>count)) {
+   if (refcount_dec_and_test(>count)) {
free_nsproxy(ns);
}
 }
 
 static inline void get_nsproxy(struct nsproxy *ns)
 {
-   atomic_inc(>count);
+   refcount_inc(>count);
 }
 
 #endif
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index f6c5d33..5bfe691 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -31,7 +31,7 @@
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = {
-   .count  = ATOMIC_INIT(1),
+   .count  = REFCOUNT_INIT(1),
.uts_ns = _uts_ns,
 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
.ipc_ns = _ipc_ns,
@@ -52,7 +52,7 @@ static inline struct nsproxy *create_nsproxy(void)
 
nsproxy = kmem_cache_alloc(nsproxy_cachep, GFP_KERNEL);
if (nsproxy)
-   atomic_set(>count, 1);
+   refcount_set(>count, 1);
return nsproxy;
 }
 
@@ -225,7 +225,7 @@ void switch_task_namespaces(struct task_struct *p, struct 
nsproxy *new)
p->nsproxy = new;
task_unlock(p);
 
-   if (ns && atomic_dec_and_test(>count))
+   if (ns && refcount_dec_and_test(>count))
free_nsproxy(ns);
 }
 
-- 
2.7.4



[PATCH 00/16] v6 kernel core pieces refcount conversions

2017-11-16 Thread Elena Reshetova
Changes in v6:
 * memory ordering differences are outlined in each patch
   together with potential problematic areas.
  Note: I didn't include any statements in individual patches
  on why I think the memory ordering changes do not matter
  in that particular case since ultimately these are only
  known by maintainers (unless explicitly documented) and
  very hard to figure out reliably from the code.
  Therefore maintainers are expected to double check the
  specific pointed functions and make the end decision.
 * rebase on top of today's linux-next/master  
 

Changes in v5:
 * Kees catched that the following changes in
   perf_event_context.refcount and futex_pi_state.refcount
   are not correct now when ARCH_HAS_REFCOUNT is enabled:
-   WARN_ON(!atomic_inc_not_zero(refcount));
+   refcount_inc(refcount);
   So they are now changed back to using refcount_inc_not_zero. 

Changes in v4:
 * just rebase and corrections on linux-next/master

Changes in v3:
 * SoB chain corrected
 * minor corrections based on v2 feedback
 * rebase on linux-next/master as of today

Changes in v2:
 * dropped already merged patches
 * rebase on top of linux-next/master
 * Now by default refcount_t = atomic_t (*) and uses all atomic
   standard operations unless CONFIG_REFCOUNT_FULL is enabled.
   This is a compromise for the systems that are critical on
   performance (such as net) and cannot accept even slight delay
   on the refcounter operations.

This series, for core kernel components, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
trees.


Elena Reshetova (16):
  futex: convert futex_pi_state.refcount to refcount_t
  sched: convert sighand_struct.count to refcount_t
  sched: convert signal_struct.sigcnt to refcount_t
  sched: convert user_struct.__count to refcount_t
  sched: convert numa_group.refcount to refcount_t
  sched/task_struct: convert task_struct.usage to refcount_t
  sched/task_struct: convert task_struct.stack_refcount to refcount_t
  perf: convert perf_event_context.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t
  uprobes: convert uprobe.ref to refcount_t
  nsproxy: convert nsproxy.count to refcount_t
  groups: convert group_info.usage to refcount_t
  creds: convert cred.usage to refcount_t
  kcov: convert kcov.refcount to refcount_t
  bdi: convert bdi_writeback_congested.refcnt from atomic_t to
refcount_t

 fs/exec.c|  4 ++--
 fs/proc/task_nommu.c |  2 +-
 include/linux/backing-dev-defs.h |  3 ++-
 include/linux/backing-dev.h  |  4 ++--
 include/linux/cred.h | 13 ++--
 include/linux/init_task.h|  7 +++---
 include/linux/nsproxy.h  |  6 +++---
 include/linux/perf_event.h   |  3 ++-
 include/linux/sched.h|  5 +++--
 include/linux/sched/signal.h |  5 +++--
 include/linux/sched/task.h   |  4 ++--
 include/linux/sched/task_stack.h |  2 +-
 include/linux/sched/user.h   |  5 +++--
 kernel/cred.c| 46 
 kernel/events/core.c | 18 
 kernel/events/internal.h |  5 +++--
 kernel/events/ring_buffer.c  |  8 +++
 kernel/events/uprobes.c  |  8 +++
 kernel/fork.c| 24 ++---
 kernel/futex.c   | 15 +++--
 kernel/groups.c  |  2 +-
 kernel/kcov.c|  9 
 kernel/nsproxy.c |  6 +++---
 kernel/sched/fair.c  | 12 +--
 kernel/user.c|  8 +++
 mm/backing-dev.c | 14 ++--
 26 files changed, 125 insertions(+), 113 deletions(-)

-- 
2.7.4



[PATCH 00/16] v6 kernel core pieces refcount conversions

2017-11-16 Thread Elena Reshetova
Changes in v6:
 * memory ordering differences are outlined in each patch
   together with potential problematic areas.
  Note: I didn't include any statements in individual patches
  on why I think the memory ordering changes do not matter
  in that particular case since ultimately these are only
  known by maintainers (unless explicitly documented) and
  very hard to figure out reliably from the code.
  Therefore maintainers are expected to double check the
  specific pointed functions and make the end decision.
 * rebase on top of today's linux-next/master  
 

Changes in v5:
 * Kees catched that the following changes in
   perf_event_context.refcount and futex_pi_state.refcount
   are not correct now when ARCH_HAS_REFCOUNT is enabled:
-   WARN_ON(!atomic_inc_not_zero(refcount));
+   refcount_inc(refcount);
   So they are now changed back to using refcount_inc_not_zero. 

Changes in v4:
 * just rebase and corrections on linux-next/master

Changes in v3:
 * SoB chain corrected
 * minor corrections based on v2 feedback
 * rebase on linux-next/master as of today

Changes in v2:
 * dropped already merged patches
 * rebase on top of linux-next/master
 * Now by default refcount_t = atomic_t (*) and uses all atomic
   standard operations unless CONFIG_REFCOUNT_FULL is enabled.
   This is a compromise for the systems that are critical on
   performance (such as net) and cannot accept even slight delay
   on the refcounter operations.

This series, for core kernel components, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
If there are no objections to the patches, please merge them via respective 
trees.


Elena Reshetova (16):
  futex: convert futex_pi_state.refcount to refcount_t
  sched: convert sighand_struct.count to refcount_t
  sched: convert signal_struct.sigcnt to refcount_t
  sched: convert user_struct.__count to refcount_t
  sched: convert numa_group.refcount to refcount_t
  sched/task_struct: convert task_struct.usage to refcount_t
  sched/task_struct: convert task_struct.stack_refcount to refcount_t
  perf: convert perf_event_context.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.refcount to refcount_t
  perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t
  uprobes: convert uprobe.ref to refcount_t
  nsproxy: convert nsproxy.count to refcount_t
  groups: convert group_info.usage to refcount_t
  creds: convert cred.usage to refcount_t
  kcov: convert kcov.refcount to refcount_t
  bdi: convert bdi_writeback_congested.refcnt from atomic_t to
refcount_t

 fs/exec.c|  4 ++--
 fs/proc/task_nommu.c |  2 +-
 include/linux/backing-dev-defs.h |  3 ++-
 include/linux/backing-dev.h  |  4 ++--
 include/linux/cred.h | 13 ++--
 include/linux/init_task.h|  7 +++---
 include/linux/nsproxy.h  |  6 +++---
 include/linux/perf_event.h   |  3 ++-
 include/linux/sched.h|  5 +++--
 include/linux/sched/signal.h |  5 +++--
 include/linux/sched/task.h   |  4 ++--
 include/linux/sched/task_stack.h |  2 +-
 include/linux/sched/user.h   |  5 +++--
 kernel/cred.c| 46 
 kernel/events/core.c | 18 
 kernel/events/internal.h |  5 +++--
 kernel/events/ring_buffer.c  |  8 +++
 kernel/events/uprobes.c  |  8 +++
 kernel/fork.c| 24 ++---
 kernel/futex.c   | 15 +++--
 kernel/groups.c  |  2 +-
 kernel/kcov.c|  9 
 kernel/nsproxy.c |  6 +++---
 kernel/sched/fair.c  | 12 +--
 kernel/user.c|  8 +++
 mm/backing-dev.c | 14 ++--
 26 files changed, 125 insertions(+), 113 deletions(-)

-- 
2.7.4



[PATCH 11/16] uprobes: convert uprobe.ref to refcount_t

2017-11-16 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 uprobe.ref is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the uprobe.ref it might make a difference
in following places:
 - put_uprobe(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 kernel/events/uprobes.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8d42d8f..3514b42 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -66,7 +66,7 @@ static struct percpu_rw_semaphore dup_mmap_sem;
 
 struct uprobe {
struct rb_node  rb_node;/* node in the rb tree */
-   atomic_tref;
+   refcount_t  ref;
struct rw_semaphore register_rwsem;
struct rw_semaphore consumer_rwsem;
struct list_headpending_list;
@@ -371,13 +371,13 @@ set_orig_insn(struct arch_uprobe *auprobe, struct 
mm_struct *mm, unsigned long v
 
 static struct uprobe *get_uprobe(struct uprobe *uprobe)
 {
-   atomic_inc(>ref);
+   refcount_inc(>ref);
return uprobe;
 }
 
 static void put_uprobe(struct uprobe *uprobe)
 {
-   if (atomic_dec_and_test(>ref))
+   if (refcount_dec_and_test(>ref))
kfree(uprobe);
 }
 
@@ -459,7 +459,7 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, _tree);
/* get access + creation ref */
-   atomic_set(>ref, 2);
+   refcount_set(>ref, 2);
 
return u;
 }
-- 
2.7.4



[PATCH 11/16] uprobes: convert uprobe.ref to refcount_t

2017-11-16 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 uprobe.ref is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the uprobe.ref it might make a difference
in following places:
 - put_uprobe(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/uprobes.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8d42d8f..3514b42 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -66,7 +66,7 @@ static struct percpu_rw_semaphore dup_mmap_sem;
 
 struct uprobe {
struct rb_node  rb_node;/* node in the rb tree */
-   atomic_tref;
+   refcount_t  ref;
struct rw_semaphore register_rwsem;
struct rw_semaphore consumer_rwsem;
struct list_headpending_list;
@@ -371,13 +371,13 @@ set_orig_insn(struct arch_uprobe *auprobe, struct 
mm_struct *mm, unsigned long v
 
 static struct uprobe *get_uprobe(struct uprobe *uprobe)
 {
-   atomic_inc(>ref);
+   refcount_inc(>ref);
return uprobe;
 }
 
 static void put_uprobe(struct uprobe *uprobe)
 {
-   if (atomic_dec_and_test(>ref))
+   if (refcount_dec_and_test(>ref))
kfree(uprobe);
 }
 
@@ -459,7 +459,7 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
rb_link_node(>rb_node, parent, p);
rb_insert_color(>rb_node, _tree);
/* get access + creation ref */
-   atomic_set(>ref, 2);
+   refcount_set(>ref, 2);
 
return u;
 }
-- 
2.7.4



[PATCH 06/16] sched/task_struct: convert task_struct.usage to refcount_t

2017-11-15 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 task_struct.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.usage it might make a difference
in following places:
 - put_task_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/init_task.h  | 2 +-
 include/linux/sched.h  | 3 ++-
 include/linux/sched/task.h | 4 ++--
 kernel/fork.c  | 4 ++--
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 9eb2ce8..1e35fce 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -227,7 +227,7 @@ extern struct cred init_cred;
INIT_TASK_TI(tsk)   \
.state  = 0,\
.stack  = init_stack,   \
-   .usage  = ATOMIC_INIT(2),   \
+   .usage  = REFCOUNT_INIT(2), \
.flags  = PF_KTHREAD,   \
.prio   = MAX_PRIO-20,  \
.static_prio= MAX_PRIO-20,  \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 44f9df5..924a812 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -536,7 +537,7 @@ struct task_struct {
randomized_struct_fields_start
 
void*stack;
-   atomic_tusage;
+   refcount_t  usage;
/* Per task flags (PF_*), defined further below: */
unsigned intflags;
unsigned intptrace;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 5be31eb..dae8d04 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -86,13 +86,13 @@ extern void sched_exec(void);
 #define sched_exec()   {}
 #endif
 
-#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
-   if (atomic_dec_and_test(>usage))
+   if (refcount_dec_and_test(>usage))
__put_task_struct(t);
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index a65ec7d..16df4f5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -649,7 +649,7 @@ static inline void put_signal_struct(struct signal_struct 
*sig)
 void __put_task_struct(struct task_struct *tsk)
 {
WARN_ON(!tsk->exit_state);
-   WARN_ON(atomic_read(>usage));
+   WARN_ON(refcount_read(>usage));
WARN_ON(tsk == current);
 
cgroup_free(tsk);
@@ -824,7 +824,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
 * One for us, one for whoever does the "release_task()" (usually
 * parent)
 */
-   atomic_set(>usage, 2);
+   refcount_set(>usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
tsk->btrace_seq = 0;
 #endif
-- 
2.7.4



[PATCH 06/16] sched/task_struct: convert task_struct.usage to refcount_t

2017-11-15 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 task_struct.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.usage it might make a difference
in following places:
 - put_task_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/init_task.h  | 2 +-
 include/linux/sched.h  | 3 ++-
 include/linux/sched/task.h | 4 ++--
 kernel/fork.c  | 4 ++--
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 9eb2ce8..1e35fce 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -227,7 +227,7 @@ extern struct cred init_cred;
INIT_TASK_TI(tsk)   \
.state  = 0,\
.stack  = init_stack,   \
-   .usage  = ATOMIC_INIT(2),   \
+   .usage  = REFCOUNT_INIT(2), \
.flags  = PF_KTHREAD,   \
.prio   = MAX_PRIO-20,  \
.static_prio= MAX_PRIO-20,  \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 44f9df5..924a812 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -536,7 +537,7 @@ struct task_struct {
randomized_struct_fields_start
 
void*stack;
-   atomic_tusage;
+   refcount_t  usage;
/* Per task flags (PF_*), defined further below: */
unsigned intflags;
unsigned intptrace;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 5be31eb..dae8d04 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -86,13 +86,13 @@ extern void sched_exec(void);
 #define sched_exec()   {}
 #endif
 
-#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
+#define get_task_struct(tsk) do { refcount_inc(&(tsk)->usage); } while(0)
 
 extern void __put_task_struct(struct task_struct *t);
 
 static inline void put_task_struct(struct task_struct *t)
 {
-   if (atomic_dec_and_test(>usage))
+   if (refcount_dec_and_test(>usage))
__put_task_struct(t);
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index a65ec7d..16df4f5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -649,7 +649,7 @@ static inline void put_signal_struct(struct signal_struct 
*sig)
 void __put_task_struct(struct task_struct *tsk)
 {
WARN_ON(!tsk->exit_state);
-   WARN_ON(atomic_read(>usage));
+   WARN_ON(refcount_read(>usage));
WARN_ON(tsk == current);
 
cgroup_free(tsk);
@@ -824,7 +824,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
 * One for us, one for whoever does the "release_task()" (usually
 * parent)
 */
-   atomic_set(>usage, 2);
+   refcount_set(>usage, 2);
 #ifdef CONFIG_BLK_DEV_IO_TRACE
tsk->btrace_seq = 0;
 #endif
-- 
2.7.4



[PATCH 07/16] sched/task_struct: convert task_struct.stack_refcount to refcount_t

2017-11-15 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 task_struct.stack_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.stack_refcount it might make a difference
in following places:
 - try_get_task_stack(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_task_stack(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/init_task.h| 3 ++-
 include/linux/sched.h| 2 +-
 include/linux/sched/task_stack.h | 2 +-
 kernel/fork.c| 6 +++---
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 1e35fce..6a87579 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -207,7 +208,7 @@ extern struct cred init_cred;
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 # define INIT_TASK_TI(tsk) \
.thread_info = INIT_THREAD_INFO(tsk),   \
-   .stack_refcount = ATOMIC_INIT(1),
+   .stack_refcount = REFCOUNT_INIT(1),
 #else
 # define INIT_TASK_TI(tsk)
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 924a812..c8c6d17 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1098,7 +1098,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
/* A live task holds one reference: */
-   atomic_tstack_refcount;
+   refcount_t  stack_refcount;
 #endif
 #ifdef CONFIG_LIVEPATCH
int patch_state;
diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h
index cb4828a..4559316 100644
--- a/include/linux/sched/task_stack.h
+++ b/include/linux/sched/task_stack.h
@@ -61,7 +61,7 @@ static inline unsigned long *end_of_stack(struct task_struct 
*p)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline void *try_get_task_stack(struct task_struct *tsk)
 {
-   return atomic_inc_not_zero(>stack_refcount) ?
+   return refcount_inc_not_zero(>stack_refcount) ?
task_stack_page(tsk) : NULL;
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 16df4f5..822efa2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -362,7 +362,7 @@ static void release_task_stack(struct task_struct *tsk)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 void put_task_stack(struct task_struct *tsk)
 {
-   if (atomic_dec_and_test(>stack_refcount))
+   if (refcount_dec_and_test(>stack_refcount))
release_task_stack(tsk);
 }
 #endif
@@ -380,7 +380,7 @@ void free_task(struct task_struct *tsk)
 * If the task had a separate stack allocation, it should be gone
 * by now.
 */
-   WARN_ON_ONCE(atomic_read(>stack_refcount) != 0);
+   WARN_ON_ONCE(refcount_read(>stack_refcount) != 0);
 #endif
rt_mutex_debug_task_free(tsk);
ftrace_graph_exit_task(tsk);
@@ -795,7 +795,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
tsk->stack_vm_area = stack_vm_area;
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
-   atomic_set(>stack_refcount, 1);
+   refcount_set(>stack_refcount, 1);
 #endif
 
if (err)
-- 
2.7.4



[PATCH 07/16] sched/task_struct: convert task_struct.stack_refcount to refcount_t

2017-11-15 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 task_struct.stack_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the task_struct.stack_refcount it might make a difference
in following places:
 - try_get_task_stack(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_task_stack(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/init_task.h| 3 ++-
 include/linux/sched.h| 2 +-
 include/linux/sched/task_stack.h | 2 +-
 kernel/fork.c| 6 +++---
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 1e35fce..6a87579 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -207,7 +208,7 @@ extern struct cred init_cred;
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 # define INIT_TASK_TI(tsk) \
.thread_info = INIT_THREAD_INFO(tsk),   \
-   .stack_refcount = ATOMIC_INIT(1),
+   .stack_refcount = REFCOUNT_INIT(1),
 #else
 # define INIT_TASK_TI(tsk)
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 924a812..c8c6d17 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1098,7 +1098,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
/* A live task holds one reference: */
-   atomic_tstack_refcount;
+   refcount_t  stack_refcount;
 #endif
 #ifdef CONFIG_LIVEPATCH
int patch_state;
diff --git a/include/linux/sched/task_stack.h b/include/linux/sched/task_stack.h
index cb4828a..4559316 100644
--- a/include/linux/sched/task_stack.h
+++ b/include/linux/sched/task_stack.h
@@ -61,7 +61,7 @@ static inline unsigned long *end_of_stack(struct task_struct 
*p)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline void *try_get_task_stack(struct task_struct *tsk)
 {
-   return atomic_inc_not_zero(>stack_refcount) ?
+   return refcount_inc_not_zero(>stack_refcount) ?
task_stack_page(tsk) : NULL;
 }
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 16df4f5..822efa2 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -362,7 +362,7 @@ static void release_task_stack(struct task_struct *tsk)
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 void put_task_stack(struct task_struct *tsk)
 {
-   if (atomic_dec_and_test(>stack_refcount))
+   if (refcount_dec_and_test(>stack_refcount))
release_task_stack(tsk);
 }
 #endif
@@ -380,7 +380,7 @@ void free_task(struct task_struct *tsk)
 * If the task had a separate stack allocation, it should be gone
 * by now.
 */
-   WARN_ON_ONCE(atomic_read(>stack_refcount) != 0);
+   WARN_ON_ONCE(refcount_read(>stack_refcount) != 0);
 #endif
rt_mutex_debug_task_free(tsk);
ftrace_graph_exit_task(tsk);
@@ -795,7 +795,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig, int node)
tsk->stack_vm_area = stack_vm_area;
 #endif
 #ifdef CONFIG_THREAD_INFO_IN_TASK
-   atomic_set(>stack_refcount, 1);
+   refcount_set(>stack_refcount, 1);
 #endif
 
if (err)
-- 
2.7.4



[PATCH 08/16] perf: convert perf_event_context.refcount to refcount_t

2017-11-15 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 perf_event_context.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the perf_event_context.refcount it might make a difference
in following places:
 - get_ctx(), perf_event_ctx_lock_nested(), perf_lock_task_context()
   and __perf_event_ctx_lock_double(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_ctx(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/perf_event.h |  3 ++-
 kernel/events/core.c   | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 2c9c87d..6a78705 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -54,6 +54,7 @@ struct perf_guest_info_callbacks {
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct perf_callchain_entry {
@@ -718,7 +719,7 @@ struct perf_event_context {
int nr_stat;
int nr_freq;
int rotate_disable;
-   atomic_trefcount;
+   refcount_t  refcount;
struct task_struct  *task;
 
/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d084a97..29c381f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1148,7 +1148,7 @@ static void perf_event_ctx_deactivate(struct 
perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-   WARN_ON(!atomic_inc_not_zero(>refcount));
+   WARN_ON(!refcount_inc_not_zero(>refcount));
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1162,7 +1162,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1240,7 +1240,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int 
nesting)
 again:
rcu_read_lock();
ctx = READ_ONCE(event->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
@@ -1373,7 +1373,7 @@ perf_lock_task_context(struct task_struct *task, int 
ctxn, unsigned long *flags)
}
 
if (ctx->task == TASK_TOMBSTONE ||
-   !atomic_inc_not_zero(>refcount)) {
+   !refcount_inc_not_zero(>refcount)) {
raw_spin_unlock(>lock);
ctx = NULL;
} else {
@@ -3715,7 +3715,7 @@ static void __perf_event_init_context(struct 
perf_event_context *ctx)
INIT_LIST_HEAD(>pinned_groups);
INIT_LIST_HEAD(>flexible_groups);
INIT_LIST_HEAD(>event_list);
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 }
 
 static struct perf_event_context *
@@ -9793,7 +9793,7 @@ __perf_event_ctx_lock_double(struct perf_event 
*group_leader,
 again:
rcu_read_lock();
gctx = READ_ONCE(group_leader->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+ 

[PATCH 08/16] perf: convert perf_event_context.refcount to refcount_t

2017-11-15 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 perf_event_context.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the perf_event_context.refcount it might make a difference
in following places:
 - get_ctx(), perf_event_ctx_lock_nested(), perf_lock_task_context()
   and __perf_event_ctx_lock_double(): increment in
   refcount_inc_not_zero() only guarantees control dependency
   on success vs. fully ordered atomic counterpart
 - put_ctx(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/perf_event.h |  3 ++-
 kernel/events/core.c   | 12 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 2c9c87d..6a78705 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -54,6 +54,7 @@ struct perf_guest_info_callbacks {
 #include 
 #include 
 #include 
+#include 
 #include 
 
 struct perf_callchain_entry {
@@ -718,7 +719,7 @@ struct perf_event_context {
int nr_stat;
int nr_freq;
int rotate_disable;
-   atomic_trefcount;
+   refcount_t  refcount;
struct task_struct  *task;
 
/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d084a97..29c381f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1148,7 +1148,7 @@ static void perf_event_ctx_deactivate(struct 
perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-   WARN_ON(!atomic_inc_not_zero(>refcount));
+   WARN_ON(!refcount_inc_not_zero(>refcount));
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1162,7 +1162,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1240,7 +1240,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int 
nesting)
 again:
rcu_read_lock();
ctx = READ_ONCE(event->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
@@ -1373,7 +1373,7 @@ perf_lock_task_context(struct task_struct *task, int 
ctxn, unsigned long *flags)
}
 
if (ctx->task == TASK_TOMBSTONE ||
-   !atomic_inc_not_zero(>refcount)) {
+   !refcount_inc_not_zero(>refcount)) {
raw_spin_unlock(>lock);
ctx = NULL;
} else {
@@ -3715,7 +3715,7 @@ static void __perf_event_init_context(struct 
perf_event_context *ctx)
INIT_LIST_HEAD(>pinned_groups);
INIT_LIST_HEAD(>flexible_groups);
INIT_LIST_HEAD(>event_list);
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 }
 
 static struct perf_event_context *
@@ -9793,7 +9793,7 @@ __perf_event_ctx_lock_double(struct perf_event 
*group_leader,
 again:
rcu_read_lock();
gctx = READ_ONCE(group_leader->ctx);
-   if (!atomic_inc_not_zero(>refcount)) {
+   if (!refcount_inc_not_zero(>refcount)) {
rcu_read_unlock();
goto again;
}
-- 
2.7.4



[PATCH 14/16] creds: convert cred.usage to refcount_t

2017-11-15 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 cred.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the cred.usage it might make a difference
in following places:
 - get_task_cred(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_cred(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/cred.h |  6 +++---
 kernel/cred.c| 44 ++--
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index 00948dd..a9f217b 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -109,7 +109,7 @@ extern bool may_setgroups(void);
  * same context as task->real_cred.
  */
 struct cred {
-   atomic_tusage;
+   refcount_t  usage;
 #ifdef CONFIG_DEBUG_CREDENTIALS
atomic_tsubscribers;/* number of processes subscribed */
void*put_addr;
@@ -222,7 +222,7 @@ static inline bool cap_ambient_invariant_ok(const struct 
cred *cred)
  */
 static inline struct cred *get_new_cred(struct cred *cred)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return cred;
 }
 
@@ -262,7 +262,7 @@ static inline void put_cred(const struct cred *_cred)
struct cred *cred = (struct cred *) _cred;
 
validate_creds(cred);
-   if (atomic_dec_and_test(&(cred)->usage))
+   if (refcount_dec_and_test(&(cred)->usage))
__put_cred(cred);
 }
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 9604c1a..86c039a 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -42,7 +42,7 @@ struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
  * The initial credentials for the initial task
  */
 struct cred init_cred = {
-   .usage  = ATOMIC_INIT(4),
+   .usage  = REFCOUNT_INIT(4),
 #ifdef CONFIG_DEBUG_CREDENTIALS
.subscribers= ATOMIC_INIT(2),
.magic  = CRED_MAGIC,
@@ -101,17 +101,17 @@ static void put_cred_rcu(struct rcu_head *rcu)
 
 #ifdef CONFIG_DEBUG_CREDENTIALS
if (cred->magic != CRED_MAGIC_DEAD ||
-   atomic_read(>usage) != 0 ||
+   refcount_read(>usage) != 0 ||
read_cred_subscribers(cred) != 0)
panic("CRED: put_cred_rcu() sees %p with"
  " mag %x, put %p, usage %d, subscr %d\n",
  cred, cred->magic, cred->put_addr,
- atomic_read(>usage),
+ refcount_read(>usage),
  read_cred_subscribers(cred));
 #else
-   if (atomic_read(>usage) != 0)
+   if (refcount_read(>usage) != 0)
panic("CRED: put_cred_rcu() sees %p with usage %d\n",
- cred, atomic_read(>usage));
+ cred, refcount_read(>usage));
 #endif
 
security_cred_free(cred);
@@ -135,10 +135,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 void __put_cred(struct cred *cred)
 {
kdebug("__put_cred(%p{%d,%d})", cred,
-  atomic_read(>usage),
+  refcount_read(>usage),
   read_cred_subscribers(cred));
 
-   BUG_ON(atomic_read(>usage) != 0);
+   BUG_ON(refcount_read(>usage) != 0);
 #ifdef CONFIG_DEBUG_CREDENTIALS
BUG

[PATCH 14/16] creds: convert cred.usage to refcount_t

2017-11-15 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 cred.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the cred.usage it might make a difference
in following places:
 - get_task_cred(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - put_cred(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/cred.h |  6 +++---
 kernel/cred.c| 44 ++--
 2 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index 00948dd..a9f217b 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -109,7 +109,7 @@ extern bool may_setgroups(void);
  * same context as task->real_cred.
  */
 struct cred {
-   atomic_tusage;
+   refcount_t  usage;
 #ifdef CONFIG_DEBUG_CREDENTIALS
atomic_tsubscribers;/* number of processes subscribed */
void*put_addr;
@@ -222,7 +222,7 @@ static inline bool cap_ambient_invariant_ok(const struct 
cred *cred)
  */
 static inline struct cred *get_new_cred(struct cred *cred)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return cred;
 }
 
@@ -262,7 +262,7 @@ static inline void put_cred(const struct cred *_cred)
struct cred *cred = (struct cred *) _cred;
 
validate_creds(cred);
-   if (atomic_dec_and_test(&(cred)->usage))
+   if (refcount_dec_and_test(&(cred)->usage))
__put_cred(cred);
 }
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 9604c1a..86c039a 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -42,7 +42,7 @@ struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
  * The initial credentials for the initial task
  */
 struct cred init_cred = {
-   .usage  = ATOMIC_INIT(4),
+   .usage  = REFCOUNT_INIT(4),
 #ifdef CONFIG_DEBUG_CREDENTIALS
.subscribers= ATOMIC_INIT(2),
.magic  = CRED_MAGIC,
@@ -101,17 +101,17 @@ static void put_cred_rcu(struct rcu_head *rcu)
 
 #ifdef CONFIG_DEBUG_CREDENTIALS
if (cred->magic != CRED_MAGIC_DEAD ||
-   atomic_read(>usage) != 0 ||
+   refcount_read(>usage) != 0 ||
read_cred_subscribers(cred) != 0)
panic("CRED: put_cred_rcu() sees %p with"
  " mag %x, put %p, usage %d, subscr %d\n",
  cred, cred->magic, cred->put_addr,
- atomic_read(>usage),
+ refcount_read(>usage),
  read_cred_subscribers(cred));
 #else
-   if (atomic_read(>usage) != 0)
+   if (refcount_read(>usage) != 0)
panic("CRED: put_cred_rcu() sees %p with usage %d\n",
- cred, atomic_read(>usage));
+ cred, refcount_read(>usage));
 #endif
 
security_cred_free(cred);
@@ -135,10 +135,10 @@ static void put_cred_rcu(struct rcu_head *rcu)
 void __put_cred(struct cred *cred)
 {
kdebug("__put_cred(%p{%d,%d})", cred,
-  atomic_read(>usage),
+  refcount_read(>usage),
   read_cred_subscribers(cred));
 
-   BUG_ON(atomic_read(>usage) != 0);
+   BUG_ON(refcount_read(>usage) != 0);
 #ifdef CONFIG_DEBUG_CREDENTIALS
BUG_ON(read_cred_subscribers(cred) != 0);
cred->magic = CRED_MAGIC_DEAD;
@@ -159,7 +159,7 @@ void exit_cred

[PATCH 16/16] bdi: convert bdi_writeback_congested.refcnt from atomic_t to refcount_t

2017-11-15 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 bdi_writeback_congested.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the bdi_writeback_congested.refcnt it might make a difference
in following places:
 - wb_congested_put() in include/linux/backing-dev.h:
   decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart
 - wb_congested_put() in mm/backing-dev.c: decrement in
   refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success
   and hold spin_lock() on success vs. fully ordered atomic
   counterpart. Note, there is no difference in spin lock
   locking.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/backing-dev-defs.h |  3 ++-
 include/linux/backing-dev.h  |  4 ++--
 mm/backing-dev.c | 14 --
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index bfe86b5..0b1bcce 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -76,7 +77,7 @@ enum wb_reason {
  */
 struct bdi_writeback_congested {
unsigned long state;/* WB_[a]sync_congested flags */
-   atomic_t refcnt;/* nr of attached wb's and blkg */
+   refcount_t refcnt;  /* nr of attached wb's and blkg */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
struct backing_dev_info *__bdi; /* the associated bdi, set to NULL
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index e54e7e0..d6bac2e 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -402,13 +402,13 @@ static inline bool inode_cgwb_enabled(struct inode *inode)
 static inline struct bdi_writeback_congested *
 wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 {
-   atomic_inc(>wb_congested->refcnt);
+   refcount_inc(>wb_congested->refcnt);
return bdi->wb_congested;
 }
 
 static inline void wb_congested_put(struct bdi_writeback_congested *congested)
 {
-   if (atomic_dec_and_test(>refcnt))
+   if (refcount_dec_and_test(>refcnt))
kfree(congested);
 }
 
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 74b52df..e92a20f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -440,14 +440,17 @@ wb_congested_get_create(struct backing_dev_info *bdi, int 
blkcg_id, gfp_t gfp)
node = >rb_left;
else if (congested->blkcg_id > blkcg_id)
node = >rb_right;
-   else
-   goto found;
+   else {
+   refcount_inc(>refcnt);
+   goto found;
+   }
}
 
if (new_congested) {
/* !found and storage for new one already allocated, insert */
congested = new_congested;
new_congested = NULL;
+   refcount_set(>refcnt, 1);
rb_link_node(>rb_node, parent, node);
rb_insert_color(>rb_node, >cgwb_congested_tree);
goto found;
@@ -460,13 +463,12 @@ wb_congested_get_create(struct backing_dev_info *bdi, int 
blkcg_id, gfp_t gfp)
if (!new_congested)
return NULL;
 
-   atomic_set(_congested->refcnt, 0);
+   refcount_set(_congested->refcnt, 0);
new_congeste

[PATCH 16/16] bdi: convert bdi_writeback_congested.refcnt from atomic_t to refcount_t

2017-11-15 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 bdi_writeback_congested.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the bdi_writeback_congested.refcnt it might make a difference
in following places:
 - wb_congested_put() in include/linux/backing-dev.h:
   decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart
 - wb_congested_put() in mm/backing-dev.c: decrement in
   refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success
   and hold spin_lock() on success vs. fully ordered atomic
   counterpart. Note, there is no difference in spin lock
   locking.

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/backing-dev-defs.h |  3 ++-
 include/linux/backing-dev.h  |  4 ++--
 mm/backing-dev.c | 14 --
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index bfe86b5..0b1bcce 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -76,7 +77,7 @@ enum wb_reason {
  */
 struct bdi_writeback_congested {
unsigned long state;/* WB_[a]sync_congested flags */
-   atomic_t refcnt;/* nr of attached wb's and blkg */
+   refcount_t refcnt;  /* nr of attached wb's and blkg */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
struct backing_dev_info *__bdi; /* the associated bdi, set to NULL
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index e54e7e0..d6bac2e 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -402,13 +402,13 @@ static inline bool inode_cgwb_enabled(struct inode *inode)
 static inline struct bdi_writeback_congested *
 wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 {
-   atomic_inc(>wb_congested->refcnt);
+   refcount_inc(>wb_congested->refcnt);
return bdi->wb_congested;
 }
 
 static inline void wb_congested_put(struct bdi_writeback_congested *congested)
 {
-   if (atomic_dec_and_test(>refcnt))
+   if (refcount_dec_and_test(>refcnt))
kfree(congested);
 }
 
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 74b52df..e92a20f 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -440,14 +440,17 @@ wb_congested_get_create(struct backing_dev_info *bdi, int 
blkcg_id, gfp_t gfp)
node = >rb_left;
else if (congested->blkcg_id > blkcg_id)
node = >rb_right;
-   else
-   goto found;
+   else {
+   refcount_inc(>refcnt);
+   goto found;
+   }
}
 
if (new_congested) {
/* !found and storage for new one already allocated, insert */
congested = new_congested;
new_congested = NULL;
+   refcount_set(>refcnt, 1);
rb_link_node(>rb_node, parent, node);
rb_insert_color(>rb_node, >cgwb_congested_tree);
goto found;
@@ -460,13 +463,12 @@ wb_congested_get_create(struct backing_dev_info *bdi, int 
blkcg_id, gfp_t gfp)
if (!new_congested)
return NULL;
 
-   atomic_set(_congested->refcnt, 0);
+   refcount_set(_congested->refcnt, 0);
new_congested->__bdi = bdi;
new_congested->blkcg_id = blkcg_id;
goto retry;
 
 found:
-   atom

[PATCH 15/16] kcov: convert kcov.refcount to refcount_t

2017-11-15 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 kcov.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the kcov.refcount it might make a difference
in following places:
 - kcov_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 kernel/kcov.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/kcov.c b/kernel/kcov.c
index 15f33fa..343288c 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Number of 64-bit words written per one comparison: */
@@ -44,7 +45,7 @@ struct kcov {
 *  - opened file descriptor
 *  - task with enabled coverage (we can't unwire it from another task)
 */
-   atomic_trefcount;
+   refcount_t  refcount;
/* The lock protects mode, size, area and t. */
spinlock_t  lock;
enum kcov_mode  mode;
@@ -228,12 +229,12 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_switch);
 
 static void kcov_get(struct kcov *kcov)
 {
-   atomic_inc(>refcount);
+   refcount_inc(>refcount);
 }
 
 static void kcov_put(struct kcov *kcov)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
vfree(kcov->area);
kfree(kcov);
}
@@ -311,7 +312,7 @@ static int kcov_open(struct inode *inode, struct file 
*filep)
if (!kcov)
return -ENOMEM;
kcov->mode = KCOV_MODE_DISABLED;
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
spin_lock_init(>lock);
filep->private_data = kcov;
return nonseekable_open(inode, filep);
-- 
2.7.4



[PATCH 15/16] kcov: convert kcov.refcount to refcount_t

2017-11-15 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 kcov.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the kcov.refcount it might make a difference
in following places:
 - kcov_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/kcov.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/kcov.c b/kernel/kcov.c
index 15f33fa..343288c 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /* Number of 64-bit words written per one comparison: */
@@ -44,7 +45,7 @@ struct kcov {
 *  - opened file descriptor
 *  - task with enabled coverage (we can't unwire it from another task)
 */
-   atomic_trefcount;
+   refcount_t  refcount;
/* The lock protects mode, size, area and t. */
spinlock_t  lock;
enum kcov_mode  mode;
@@ -228,12 +229,12 @@ EXPORT_SYMBOL(__sanitizer_cov_trace_switch);
 
 static void kcov_get(struct kcov *kcov)
 {
-   atomic_inc(>refcount);
+   refcount_inc(>refcount);
 }
 
 static void kcov_put(struct kcov *kcov)
 {
-   if (atomic_dec_and_test(>refcount)) {
+   if (refcount_dec_and_test(>refcount)) {
vfree(kcov->area);
kfree(kcov);
}
@@ -311,7 +312,7 @@ static int kcov_open(struct inode *inode, struct file 
*filep)
if (!kcov)
return -ENOMEM;
kcov->mode = KCOV_MODE_DISABLED;
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
spin_lock_init(>lock);
filep->private_data = kcov;
return nonseekable_open(inode, filep);
-- 
2.7.4



[PATCH 13/16] groups: convert group_info.usage to refcount_t

2017-11-15 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 group_info.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the group_info.usage it might make a difference
in following places:
 - put_group_info(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/cred.h | 7 ---
 kernel/cred.c| 2 +-
 kernel/groups.c  | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index 099058e..00948dd 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -28,7 +29,7 @@ struct inode;
  * COW Supplementary groups list
  */
 struct group_info {
-   atomic_tusage;
+   refcount_t  usage;
int ngroups;
kgid_t  gid[0];
 } __randomize_layout;
@@ -44,7 +45,7 @@ struct group_info {
  */
 static inline struct group_info *get_group_info(struct group_info *gi)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return gi;
 }
 
@@ -54,7 +55,7 @@ static inline struct group_info *get_group_info(struct 
group_info *gi)
  */
 #define put_group_info(group_info) \
 do {   \
-   if (atomic_dec_and_test(&(group_info)->usage))  \
+   if (refcount_dec_and_test(&(group_info)->usage))\
groups_free(group_info);\
 } while (0)
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 0192a94..9604c1a 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -36,7 +36,7 @@ do {  
\
 static struct kmem_cache *cred_jar;
 
 /* init to 2 - one for init_task, one to ensure it is never freed */
-struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
+struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
 
 /*
  * The initial credentials for the initial task
diff --git a/kernel/groups.c b/kernel/groups.c
index e357bc8..2ab0e56 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -24,7 +24,7 @@ struct group_info *groups_alloc(int gidsetsize)
if (!gi)
return NULL;
 
-   atomic_set(>usage, 1);
+   refcount_set(>usage, 1);
gi->ngroups = gidsetsize;
return gi;
 }
-- 
2.7.4



[PATCH 13/16] groups: convert group_info.usage to refcount_t

2017-11-15 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 group_info.usage is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the group_info.usage it might make a difference
in following places:
 - put_group_info(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/cred.h | 7 ---
 kernel/cred.c| 2 +-
 kernel/groups.c  | 2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/linux/cred.h b/include/linux/cred.h
index 099058e..00948dd 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -28,7 +29,7 @@ struct inode;
  * COW Supplementary groups list
  */
 struct group_info {
-   atomic_tusage;
+   refcount_t  usage;
int ngroups;
kgid_t  gid[0];
 } __randomize_layout;
@@ -44,7 +45,7 @@ struct group_info {
  */
 static inline struct group_info *get_group_info(struct group_info *gi)
 {
-   atomic_inc(>usage);
+   refcount_inc(>usage);
return gi;
 }
 
@@ -54,7 +55,7 @@ static inline struct group_info *get_group_info(struct 
group_info *gi)
  */
 #define put_group_info(group_info) \
 do {   \
-   if (atomic_dec_and_test(&(group_info)->usage))  \
+   if (refcount_dec_and_test(&(group_info)->usage))\
groups_free(group_info);\
 } while (0)
 
diff --git a/kernel/cred.c b/kernel/cred.c
index 0192a94..9604c1a 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -36,7 +36,7 @@ do {  
\
 static struct kmem_cache *cred_jar;
 
 /* init to 2 - one for init_task, one to ensure it is never freed */
-struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
+struct group_info init_groups = { .usage = REFCOUNT_INIT(2) };
 
 /*
  * The initial credentials for the initial task
diff --git a/kernel/groups.c b/kernel/groups.c
index e357bc8..2ab0e56 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -24,7 +24,7 @@ struct group_info *groups_alloc(int gidsetsize)
if (!gi)
return NULL;
 
-   atomic_set(>usage, 1);
+   refcount_set(>usage, 1);
gi->ngroups = gidsetsize;
return gi;
 }
-- 
2.7.4



[PATCH 09/16] perf/ring_buffer: convert ring_buffer.refcount to refcount_t

2017-11-15 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 ring_buffer.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.refcount it might make a difference
in following places:
 - ring_buffer_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - ring_buffer_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 kernel/events/core.c| 4 ++--
 kernel/events/internal.h| 3 ++-
 kernel/events/ring_buffer.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 29c381f..3497c6a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5020,7 +5020,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
rcu_read_lock();
rb = rcu_dereference(event->rb);
if (rb) {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
rb = NULL;
}
rcu_read_unlock();
@@ -5030,7 +5030,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-   if (!atomic_dec_and_test(>refcount))
+   if (!refcount_dec_and_test(>refcount))
return;
 
WARN_ON_ONCE(!list_empty(>event_list));
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 09b1537..86c5c7f 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -4,13 +4,14 @@
 
 #include 
 #include 
+#include 
 
 /* Buffer handling */
 
 #define RING_BUFFER_WRITABLE   0x01
 
 struct ring_buffer {
-   atomic_trefcount;
+   refcount_t  refcount;
struct rcu_head rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct  work;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 141aa2c..de12d36 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -284,7 +284,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, 
int flags)
else
rb->overwrite = 1;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 
INIT_LIST_HEAD(>event_list);
spin_lock_init(>event_lock);
-- 
2.7.4



[PATCH 09/16] perf/ring_buffer: convert ring_buffer.refcount to refcount_t

2017-11-15 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 ring_buffer.refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.refcount it might make a difference
in following places:
 - ring_buffer_get(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - ring_buffer_put(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/core.c| 4 ++--
 kernel/events/internal.h| 3 ++-
 kernel/events/ring_buffer.c | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 29c381f..3497c6a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5020,7 +5020,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
rcu_read_lock();
rb = rcu_dereference(event->rb);
if (rb) {
-   if (!atomic_inc_not_zero(>refcount))
+   if (!refcount_inc_not_zero(>refcount))
rb = NULL;
}
rcu_read_unlock();
@@ -5030,7 +5030,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event 
*event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-   if (!atomic_dec_and_test(>refcount))
+   if (!refcount_dec_and_test(>refcount))
return;
 
WARN_ON_ONCE(!list_empty(>event_list));
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 09b1537..86c5c7f 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -4,13 +4,14 @@
 
 #include 
 #include 
+#include 
 
 /* Buffer handling */
 
 #define RING_BUFFER_WRITABLE   0x01
 
 struct ring_buffer {
-   atomic_trefcount;
+   refcount_t  refcount;
struct rcu_head rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct  work;
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 141aa2c..de12d36 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -284,7 +284,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, 
int flags)
else
rb->overwrite = 1;
 
-   atomic_set(>refcount, 1);
+   refcount_set(>refcount, 1);
 
INIT_LIST_HEAD(>event_list);
spin_lock_init(>event_lock);
-- 
2.7.4



[PATCH 03/16] sched: convert signal_struct.sigcnt to refcount_t

2017-11-15 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 signal_struct.sigcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the signal_struct.sigcnt it might make a difference
in following places:
 - put_signal_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/sched/signal.h | 2 +-
 kernel/fork.c| 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 4a0e2d8..14e3a0c 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -78,7 +78,7 @@ struct thread_group_cputimer {
  * the locking of signal_struct.
  */
 struct signal_struct {
-   atomic_tsigcnt;
+   refcount_t  sigcnt;
atomic_tlive;
int nr_threads;
struct list_headthread_head;
diff --git a/kernel/fork.c b/kernel/fork.c
index be451af..a65ec7d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -642,7 +642,7 @@ static inline void free_signal_struct(struct signal_struct 
*sig)
 
 static inline void put_signal_struct(struct signal_struct *sig)
 {
-   if (atomic_dec_and_test(>sigcnt))
+   if (refcount_dec_and_test(>sigcnt))
free_signal_struct(sig);
 }
 
@@ -1443,7 +1443,7 @@ static int copy_signal(unsigned long clone_flags, struct 
task_struct *tsk)
 
sig->nr_threads = 1;
atomic_set(>live, 1);
-   atomic_set(>sigcnt, 1);
+   refcount_set(>sigcnt, 1);
 
/* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
@@ -1952,7 +1952,7 @@ static __latent_entropy struct task_struct *copy_process(
} else {
current->signal->nr_threads++;
atomic_inc(>signal->live);
-   atomic_inc(>signal->sigcnt);
+   refcount_inc(>signal->sigcnt);
list_add_tail_rcu(>thread_group,
  >group_leader->thread_group);
list_add_tail_rcu(>thread_node,
-- 
2.7.4



[PATCH 03/16] sched: convert signal_struct.sigcnt to refcount_t

2017-11-15 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 signal_struct.sigcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the signal_struct.sigcnt it might make a difference
in following places:
 - put_signal_struct(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 include/linux/sched/signal.h | 2 +-
 kernel/fork.c| 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 4a0e2d8..14e3a0c 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -78,7 +78,7 @@ struct thread_group_cputimer {
  * the locking of signal_struct.
  */
 struct signal_struct {
-   atomic_tsigcnt;
+   refcount_t  sigcnt;
atomic_tlive;
int nr_threads;
struct list_headthread_head;
diff --git a/kernel/fork.c b/kernel/fork.c
index be451af..a65ec7d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -642,7 +642,7 @@ static inline void free_signal_struct(struct signal_struct 
*sig)
 
 static inline void put_signal_struct(struct signal_struct *sig)
 {
-   if (atomic_dec_and_test(>sigcnt))
+   if (refcount_dec_and_test(>sigcnt))
free_signal_struct(sig);
 }
 
@@ -1443,7 +1443,7 @@ static int copy_signal(unsigned long clone_flags, struct 
task_struct *tsk)
 
sig->nr_threads = 1;
atomic_set(>live, 1);
-   atomic_set(>sigcnt, 1);
+   refcount_set(>sigcnt, 1);
 
/* list_add(thread_node, thread_head) without INIT_LIST_HEAD() */
sig->thread_head = (struct list_head)LIST_HEAD_INIT(tsk->thread_node);
@@ -1952,7 +1952,7 @@ static __latent_entropy struct task_struct *copy_process(
} else {
current->signal->nr_threads++;
atomic_inc(>signal->live);
-   atomic_inc(>signal->sigcnt);
+   refcount_inc(>signal->sigcnt);
list_add_tail_rcu(>thread_group,
  >group_leader->thread_group);
list_add_tail_rcu(>thread_node,
-- 
2.7.4



[PATCH 10/16] perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t

2017-11-15 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 ring_buffer.aux_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.aux_refcount it might make a difference
in following places:
 - perf_aux_output_begin(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - rb_free_aux(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 kernel/events/core.c| 2 +-
 kernel/events/internal.h| 2 +-
 kernel/events/ring_buffer.c | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3497c6a..5f087f4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5095,7 +5095,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
/* this has to be the last one */
rb_free_aux(rb);
-   WARN_ON_ONCE(atomic_read(>aux_refcount));
+   WARN_ON_ONCE(refcount_read(>aux_refcount));
 
mutex_unlock(>mmap_mutex);
}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 86c5c7f..50ecf00 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -49,7 +49,7 @@ struct ring_buffer {
atomic_taux_mmap_count;
unsigned long   aux_mmap_locked;
void(*free_aux)(void *);
-   atomic_taux_refcount;
+   refcount_t  aux_refcount;
void**aux_pages;
void*aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index de12d36..b29d6ce 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -357,7 +357,7 @@ void *perf_aux_output_begin(struct perf_output_handle 
*handle,
if (!atomic_read(>aux_mmap_count))
goto err;
 
-   if (!atomic_inc_not_zero(>aux_refcount))
+   if (!refcount_inc_not_zero(>aux_refcount))
goto err;
 
/*
@@ -659,7 +659,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 * we keep a refcount here to make sure either of the two can
 * reference them safely.
 */
-   atomic_set(>aux_refcount, 1);
+   refcount_set(>aux_refcount, 1);
 
rb->aux_overwrite = overwrite;
rb->aux_watermark = watermark;
@@ -678,7 +678,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-   if (atomic_dec_and_test(>aux_refcount))
+   if (refcount_dec_and_test(>aux_refcount))
__rb_free_aux(rb);
 }
 
-- 
2.7.4



[PATCH 10/16] perf/ring_buffer: convert ring_buffer.aux_refcount to refcount_t

2017-11-15 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 ring_buffer.aux_refcount is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the ring_buffer.aux_refcount it might make a difference
in following places:
 - perf_aux_output_begin(): increment in refcount_inc_not_zero() only
   guarantees control dependency on success vs. fully ordered
   atomic counterpart
 - rb_free_aux(): decrement in refcount_dec_and_test() only
   provides RELEASE ordering and control dependency on success
   vs. fully ordered atomic counterpart

Suggested-by: Kees Cook 
Reviewed-by: David Windsor 
Reviewed-by: Hans Liljestrand 
Signed-off-by: Elena Reshetova 
---
 kernel/events/core.c| 2 +-
 kernel/events/internal.h| 2 +-
 kernel/events/ring_buffer.c | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3497c6a..5f087f4 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5095,7 +5095,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
/* this has to be the last one */
rb_free_aux(rb);
-   WARN_ON_ONCE(atomic_read(>aux_refcount));
+   WARN_ON_ONCE(refcount_read(>aux_refcount));
 
mutex_unlock(>mmap_mutex);
}
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 86c5c7f..50ecf00 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -49,7 +49,7 @@ struct ring_buffer {
atomic_taux_mmap_count;
unsigned long   aux_mmap_locked;
void(*free_aux)(void *);
-   atomic_taux_refcount;
+   refcount_t  aux_refcount;
void**aux_pages;
void*aux_priv;
 
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index de12d36..b29d6ce 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -357,7 +357,7 @@ void *perf_aux_output_begin(struct perf_output_handle 
*handle,
if (!atomic_read(>aux_mmap_count))
goto err;
 
-   if (!atomic_inc_not_zero(>aux_refcount))
+   if (!refcount_inc_not_zero(>aux_refcount))
goto err;
 
/*
@@ -659,7 +659,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 * we keep a refcount here to make sure either of the two can
 * reference them safely.
 */
-   atomic_set(>aux_refcount, 1);
+   refcount_set(>aux_refcount, 1);
 
rb->aux_overwrite = overwrite;
rb->aux_watermark = watermark;
@@ -678,7 +678,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event 
*event,
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-   if (atomic_dec_and_test(>aux_refcount))
+   if (refcount_dec_and_test(>aux_refcount))
__rb_free_aux(rb);
 }
 
-- 
2.7.4



[PATCH 04/16] sched: convert user_struct.__count to refcount_t

2017-11-15 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 user_struct.__count is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

**Important note for maintainers:

Some functions from refcount_t API defined in lib/refcount.c
have different memory ordering guarantees than their atomic
counterparts.
The full comparison can be seen in
https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon
in state to be merged to the documentation tree.
Normally the differences should not matter since refcount_t provides
enough guarantees to satisfy the refcounting use cases, but in
some rare cases it might matter.
Please double check that you don't have some undocumented
memory guarantees for this variable usage.

For the user_struct.__count it might make a difference
in following places:
 - free_uid(): decrement in refcount_dec_and_lock() only
   provides RELEASE ordering, control dependency on success
   and will hold a spin lock on success vs. fully ordered
   atomic counterpart. Note there is no changes in spin lock
   locking here.

Suggested-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: David Windsor <dwind...@gmail.com>
Reviewed-by: Hans Liljestrand <ishkam...@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshet...@intel.com>
---
 include/linux/sched/user.h | 5 +++--
 kernel/user.c  | 8 
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/linux/sched/user.h b/include/linux/sched/user.h
index 0dcf4e4..2ca7cf4 100644
--- a/include/linux/sched/user.h
+++ b/include/linux/sched/user.h
@@ -4,6 +4,7 @@
 
 #include 
 #include 
+#include 
 
 struct key;
 
@@ -11,7 +12,7 @@ struct key;
  * Some day this will be a full-fledged user tracking system..
  */
 struct user_struct {
-   atomic_t __count;   /* reference count */
+   refcount_t __count; /* reference count */
atomic_t processes; /* How many processes does this user have? */
atomic_t sigpending;/* How many pending signals does this user 
have? */
 #ifdef CONFIG_FANOTIFY
@@ -55,7 +56,7 @@ extern struct user_struct root_user;
 extern struct user_struct * alloc_uid(kuid_t);
 static inline struct user_struct *get_uid(struct user_struct *u)
 {
-   atomic_inc(>__count);
+   refcount_inc(>__count);
return u;
 }
 extern void free_uid(struct user_struct *);
diff --git a/kernel/user.c b/kernel/user.c
index 9a20acc..f104474 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -96,7 +96,7 @@ static DEFINE_SPINLOCK(uidhash_lock);
 
 /* root_user.__count is 1, for init task cred */
 struct user_struct root_user = {
-   .__count= ATOMIC_INIT(1),
+   .__count= REFCOUNT_INIT(1),
.processes  = ATOMIC_INIT(1),
.sigpending = ATOMIC_INIT(0),
.locked_shm = 0,
@@ -122,7 +122,7 @@ static struct user_struct *uid_hash_find(kuid_t uid, struct 
hlist_head *hashent)
 
hlist_for_each_entry(user, hashent, uidhash_node) {
if (uid_eq(user->uid, uid)) {
-   atomic_inc(>__count);
+   refcount_inc(>__count);
return user;
}
}
@@ -169,7 +169,7 @@ void free_uid(struct user_struct *up)
return;
 
local_irq_save(flags);
-   if (atomic_dec_and_lock(>__count, _lock))
+   if (refcount_dec_and_lock(>__count, _lock))
free_user(up, flags);
else
local_irq_restore(flags);
@@ -190,7 +190,7 @@ struct user_struct *alloc_uid(kuid_t uid)
goto out_unlock;
 
new->uid = uid;
-   atomic_set(>__count, 1);
+   refcount_set(>__count, 1);
 
/*
 * Before adding this, check whether we raced
-- 
2.7.4



  1   2   3   4   5   6   7   8   9   10   >