Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1723259 > unrolled thread
| Started by | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| First post | 2017-08-30 14:30 +0200 |
| Last post | 2017-09-01 19:10 +0200 |
| Articles | 20 on this page of 23 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH 00/15] v5 kernel core pieces refcount conversions Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
[PATCH 05/15] sched/task_struct: convert task_struct.usage to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
[PATCH 10/15] uprobes: convert uprobe.ref to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
[PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Thomas Gleixner <tglx@linutronix.de> - 2017-09-01 09:50 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Peter Zijlstra <peterz@infradead.org> - 2017-09-01 11:40 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Thomas Gleixner <tglx@linutronix.de> - 2017-09-01 11:50 +0200
RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-01 13:00 +0200
RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-01 13:10 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Peter Zijlstra <peterz@infradead.org> - 2017-09-01 14:40 +0200
RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-01 15:30 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Peter Zijlstra <peterz@infradead.org> - 2017-09-01 15:40 +0200
RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-01 19:10 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Peter Zijlstra <peterz@infradead.org> - 2017-09-01 21:20 +0200
RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-04 12:40 +0200
Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t Peter Zijlstra <peterz@infradead.org> - 2017-09-04 14:10 +0200
[PATCH 07/15] perf: convert perf_event_context.refcount to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
[PATCH 03/15] sched: convert user_struct.__count to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
[PATCH 11/15] nsproxy: convert nsproxy.count to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-08-30 14:30 +0200
Re: [PATCH 00/15] v5 kernel core pieces refcount conversions Kees Cook <keescook@chromium.org> - 2017-09-01 01:50 +0200
Re: [PATCH 00/15] v5 kernel core pieces refcount conversions Peter Zijlstra <peterz@infradead.org> - 2017-09-01 11:50 +0200
Re: [PATCH 00/15] v5 kernel core pieces refcount conversions Kees Cook <keescook@chromium.org> - 2017-09-01 19:00 +0200
RE: [PATCH 00/15] v5 kernel core pieces refcount conversions "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-09-01 19:10 +0200
Page 1 of 2 [1] 2 Next page →
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 00/15] v5 kernel core pieces refcount conversions |
| Message-ID | <ukai5-8hx-3@gated-at.bofh.it> |
Now we have at least x86 support for ARCH_HAS_REFCOUNT merged and
arm and others on their way.
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 (15):
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
futex: convert futex_pi_state.refcount to refcount_t
kcov: convert kcov.refcount to refcount_t
fs/exec.c | 4 ++--
fs/proc/task_nommu.c | 2 +-
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 | 13 ++++++------
kernel/groups.c | 2 +-
kernel/kcov.c | 9 ++++----
kernel/nsproxy.c | 6 +++---
kernel/sched/fair.c | 12 +++++------
kernel/user.c | 8 +++----
23 files changed, 112 insertions(+), 103 deletions(-)
--
2.7.4
[toc] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 05/15] sched/task_struct: convert task_struct.usage to refcount_t |
| Message-ID | <ukai6-8hx-39@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@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 6c6f520..d312376 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 6110471..1eeb300 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -20,6 +20,7 @@
#include <linux/seccomp.h>
#include <linux/nodemask.h>
#include <linux/rcupdate.h>
+#include <linux/refcount.h>
#include <linux/resource.h>
#include <linux/latencytop.h>
#include <linux/sched/prio.h>
@@ -534,7 +535,7 @@ struct task_struct {
randomized_struct_fields_start
void *stack;
- atomic_t usage;
+ refcount_t usage;
/* Per task flags (PF_*), defined further below: */
unsigned int flags;
unsigned int ptrace;
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 79a2a74..2ddc9b0 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -85,13 +85,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(&t->usage))
+ if (refcount_dec_and_test(&t->usage))
__put_task_struct(t);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index d2e2eb0..1e54683 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -407,7 +407,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(&tsk->usage));
+ WARN_ON(refcount_read(&tsk->usage));
WARN_ON(tsk == current);
cgroup_free(tsk);
@@ -564,7 +564,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(&tsk->usage, 2);
+ refcount_set(&tsk->usage, 2);
#ifdef CONFIG_BLK_DEV_IO_TRACE
tsk->btrace_seq = 0;
#endif
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 10/15] uprobes: convert uprobe.ref to refcount_t |
| Message-ID | <ukai7-8hx-43@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@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 456596d..ca093957 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_t ref;
+ refcount_t ref;
struct rw_semaphore register_rwsem;
struct rw_semaphore consumer_rwsem;
struct list_head pending_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(&uprobe->ref);
+ refcount_inc(&uprobe->ref);
return uprobe;
}
static void put_uprobe(struct uprobe *uprobe)
{
- if (atomic_dec_and_test(&uprobe->ref))
+ if (refcount_dec_and_test(&uprobe->ref))
kfree(uprobe);
}
@@ -459,7 +459,7 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
rb_link_node(&uprobe->rb_node, parent, p);
rb_insert_color(&uprobe->rb_node, &uprobes_tree);
/* get access + creation ref */
- atomic_set(&uprobe->ref, 2);
+ refcount_set(&uprobe->ref, 2);
return u;
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukai7-8hx-49@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
---
kernel/futex.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index 0939255..65460b4 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -67,6 +67,7 @@
#include <linux/freezer.h>
#include <linux/bootmem.h>
#include <linux/fault-inject.h>
+#include <linux/refcount.h>
#include <asm/futex.h>
@@ -209,7 +210,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;
@@ -795,7 +796,7 @@ static int refill_pi_state_cache(void)
INIT_LIST_HEAD(&pi_state->list);
/* pi_mutex gets initialized later */
pi_state->owner = NULL;
- atomic_set(&pi_state->refcount, 1);
+ refcount_set(&pi_state->refcount, 1);
pi_state->key = FUTEX_KEY_INIT;
current->pi_state_cache = pi_state;
@@ -815,7 +816,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(&pi_state->refcount));
+ WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount));
}
/*
@@ -829,7 +830,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
if (!pi_state)
return;
- if (!atomic_dec_and_test(&pi_state->refcount))
+ if (!refcount_dec_and_test(&pi_state->refcount))
return;
/*
@@ -853,7 +854,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(&pi_state->refcount, 1);
+ refcount_set(&pi_state->refcount, 1);
current->pi_state_cache = pi_state;
}
}
@@ -1051,7 +1052,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(&pi_state->refcount));
+ WARN_ON(!refcount_read(&pi_state->refcount));
/*
* Now that we have a pi_state, we can acquire wait_lock
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-09-01 09:50 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukOSd-Pw-5@gated-at.bofh.it> |
| In reply to | #1723262 |
On Wed, 30 Aug 2017, Elena Reshetova wrote: > atomic_t variables are currently used to implement reference > counters with the following properties: > - counter is initialized to 1 using atomic_set() > - a resource is freed upon counter reaching zero > - once counter reaches zero, its further > increments aren't allowed > - counter schema uses basic atomic operations > (set, inc, inc_not_zero, dec_and_test, etc.) > > Such atomic variables should be converted to a newly provided > refcount_t type and API that prevents accidental counter overflows > and underflows. This is important since overflows and underflows > can lead to use-after-free situation and be exploitable. > > The variable futex_pi_state.refcount is used as pure > reference counter. Convert it to refcount_t and fix up > the operations. > > Suggested-by: Kees Cook <keescook@chromium.org> > Reviewed-by: David Windsor <dwindsor@gmail.com> > Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> > Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-09-01 11:40 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukQAG-21R-21@gated-at.bofh.it> |
| In reply to | #1724842 |
On Fri, Sep 01, 2017 at 09:39:50AM +0200, Thomas Gleixner wrote: > On Wed, 30 Aug 2017, Elena Reshetova wrote: > > atomic_t variables are currently used to implement reference > > counters with the following properties: > > - counter is initialized to 1 using atomic_set() > > - a resource is freed upon counter reaching zero > > - once counter reaches zero, its further > > increments aren't allowed > > - counter schema uses basic atomic operations > > (set, inc, inc_not_zero, dec_and_test, etc.) > > > > Such atomic variables should be converted to a newly provided > > refcount_t type and API that prevents accidental counter overflows > > and underflows. This is important since overflows and underflows > > can lead to use-after-free situation and be exploitable. > > > > The variable futex_pi_state.refcount is used as pure > > reference counter. Convert it to refcount_t and fix up > > the operations. > > > > Suggested-by: Kees Cook <keescook@chromium.org> > > Reviewed-by: David Windsor <dwindsor@gmail.com> > > Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> > > Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> > > Reviewed-by: Thomas Gleixner <tglx@linutronix.de> So the thing to be careful with for things like futex and some of the other core kernel code is the memory ordering. atomic_dec_and_test() provides a full smp_mb() before and after, refcount_dec_and_test() only provides release semantics. This is typically sufficient, and I would argue that if we rely on more than that, there _should_ be a comment, however reality isn't always as nice. That said, I think this conversion is OK, pi_state->refcount isn't relied upon to provide additional memory ordering above and beyond what refcounting requires.
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-09-01 11:50 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukQKl-25K-1@gated-at.bofh.it> |
| In reply to | #1724913 |
On Fri, 1 Sep 2017, Peter Zijlstra wrote: > On Fri, Sep 01, 2017 at 09:39:50AM +0200, Thomas Gleixner wrote: > > On Wed, 30 Aug 2017, Elena Reshetova wrote: > > > atomic_t variables are currently used to implement reference > > > counters with the following properties: > > > - counter is initialized to 1 using atomic_set() > > > - a resource is freed upon counter reaching zero > > > - once counter reaches zero, its further > > > increments aren't allowed > > > - counter schema uses basic atomic operations > > > (set, inc, inc_not_zero, dec_and_test, etc.) > > > > > > Such atomic variables should be converted to a newly provided > > > refcount_t type and API that prevents accidental counter overflows > > > and underflows. This is important since overflows and underflows > > > can lead to use-after-free situation and be exploitable. > > > > > > The variable futex_pi_state.refcount is used as pure > > > reference counter. Convert it to refcount_t and fix up > > > the operations. > > > > > > Suggested-by: Kees Cook <keescook@chromium.org> > > > Reviewed-by: David Windsor <dwindsor@gmail.com> > > > Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> > > > Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> > > > > Reviewed-by: Thomas Gleixner <tglx@linutronix.de> > > So the thing to be careful with for things like futex and some of the > other core kernel code is the memory ordering. > > atomic_dec_and_test() provides a full smp_mb() before and after, > refcount_dec_and_test() only provides release semantics. > > This is typically sufficient, and I would argue that if we rely on more > than that, there _should_ be a comment, however reality isn't always as > nice. > > That said, I think this conversion is OK, pi_state->refcount isn't > relied upon to provide additional memory ordering above and beyond what > refcounting requires. So the changelogs should reflect that. The current one suggests that this is a one to one replacement for atomic_t just with the extra sanity checks added. Thanks, tglx
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-09-01 13:00 +0200 |
| Subject | RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukRQ6-2Wd-9@gated-at.bofh.it> |
| In reply to | #1724917 |
> On Fri, 1 Sep 2017, Peter Zijlstra wrote: > > On Fri, Sep 01, 2017 at 09:39:50AM +0200, Thomas Gleixner wrote: > > > On Wed, 30 Aug 2017, Elena Reshetova wrote: > > > > atomic_t variables are currently used to implement reference > > > > counters with the following properties: > > > > - counter is initialized to 1 using atomic_set() > > > > - a resource is freed upon counter reaching zero > > > > - once counter reaches zero, its further > > > > increments aren't allowed > > > > - counter schema uses basic atomic operations > > > > (set, inc, inc_not_zero, dec_and_test, etc.) > > > > > > > > Such atomic variables should be converted to a newly provided > > > > refcount_t type and API that prevents accidental counter overflows > > > > and underflows. This is important since overflows and underflows > > > > can lead to use-after-free situation and be exploitable. > > > > > > > > The variable futex_pi_state.refcount is used as pure > > > > reference counter. Convert it to refcount_t and fix up > > > > the operations. > > > > > > > > Suggested-by: Kees Cook <keescook@chromium.org> > > > > Reviewed-by: David Windsor <dwindsor@gmail.com> > > > > Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> > > > > Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> > > > > > > Reviewed-by: Thomas Gleixner <tglx@linutronix.de> > > > > So the thing to be careful with for things like futex and some of the > > other core kernel code is the memory ordering. > > > > atomic_dec_and_test() provides a full smp_mb() before and after, > > refcount_dec_and_test() only provides release semantics. > > > > This is typically sufficient, and I would argue that if we rely on more > > than that, there _should_ be a comment, however reality isn't always as > > nice. > > > > That said, I think this conversion is OK, pi_state->refcount isn't > > relied upon to provide additional memory ordering above and beyond what > > refcounting requires. > > So the changelogs should reflect that. The current one suggests that this > is a one to one replacement for atomic_t just with the extra sanity checks > added. I will update the commit texts accordingly and resend the whole series since this should be then mentioned in every commit to make sure it is not missed. Best Regards, Elena. > > Thanks, > > tglx
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-09-01 13:10 +0200 |
| Subject | RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukRZL-3id-7@gated-at.bofh.it> |
| In reply to | #1724917 |
> On Fri, 1 Sep 2017, Peter Zijlstra wrote: > > > On Fri, Sep 01, 2017 at 09:39:50AM +0200, Thomas Gleixner wrote: > > > > On Wed, 30 Aug 2017, Elena Reshetova wrote: > > > > > atomic_t variables are currently used to implement reference > > > > > counters with the following properties: > > > > > - counter is initialized to 1 using atomic_set() > > > > > - a resource is freed upon counter reaching zero > > > > > - once counter reaches zero, its further > > > > > increments aren't allowed > > > > > - counter schema uses basic atomic operations > > > > > (set, inc, inc_not_zero, dec_and_test, etc.) > > > > > > > > > > Such atomic variables should be converted to a newly provided > > > > > refcount_t type and API that prevents accidental counter overflows > > > > > and underflows. This is important since overflows and underflows > > > > > can lead to use-after-free situation and be exploitable. > > > > > > > > > > The variable futex_pi_state.refcount is used as pure > > > > > reference counter. Convert it to refcount_t and fix up > > > > > the operations. > > > > > > > > > > Suggested-by: Kees Cook <keescook@chromium.org> > > > > > Reviewed-by: David Windsor <dwindsor@gmail.com> > > > > > Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com> > > > > > Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> > > > > > > > > Reviewed-by: Thomas Gleixner <tglx@linutronix.de> > > > > > > So the thing to be careful with for things like futex and some of the > > > other core kernel code is the memory ordering. > > > > > > atomic_dec_and_test() provides a full smp_mb() before and after, > > > refcount_dec_and_test() only provides release semantics. > > > > > > This is typically sufficient, and I would argue that if we rely on more > > > than that, there _should_ be a comment, however reality isn't always as > > > nice. > > > > > > That said, I think this conversion is OK, pi_state->refcount isn't > > > relied upon to provide additional memory ordering above and beyond what > > > refcounting requires. > > > > So the changelogs should reflect that. The current one suggests that this > > is a one to one replacement for atomic_t just with the extra sanity checks > > added. > > I will update the commit texts accordingly and resend the whole series since > this should be then mentioned in every commit to make sure it is not missed. Actually on the second thought: does the above memory ordering differences really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way how it is currently implemented for x86 is the same way as it is for atomic cases. > > Best Regards, > Elena. > > > > > Thanks, > > > > tglx
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-09-01 14:40 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukToS-4zk-3@gated-at.bofh.it> |
| In reply to | #1724971 |
On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > Actually on the second thought: does the above memory ordering differences > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way > how it is currently implemented for x86 is the same way as it is for atomic cases. Never look to x86 for memory ordering, its boring. And yes, for the ARM implementation it can certainly make a difference.
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-09-01 15:30 +0200 |
| Subject | RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukUbg-5pL-47@gated-at.bofh.it> |
| In reply to | #1725016 |
> On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > > Actually on the second thought: does the above memory ordering differences > > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way > > how it is currently implemented for x86 is the same way as it is for atomic cases. > > Never look to x86 for memory ordering, its boring. > > And yes, for the ARM implementation it can certainly make a difference. So, yes, what I am trying to say is that it can really depend if you have ARCH_HAS_REFCOUNT enabled or not and then also based on architecture. Thus I believe is also true for atomic: there might be differences when you use arch. dependent version of function or not. So, I guess if I rewrite the commits, I should only include the statement on relaxed memory order for REFCOUNT_FULL and tell that arch. specific implementations may vary on their properties (as they do now).
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-09-01 15:40 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukUkX-5wR-53@gated-at.bofh.it> |
| In reply to | #1725054 |
On Fri, Sep 01, 2017 at 01:24:16PM +0000, Reshetova, Elena wrote: > > > On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > > > Actually on the second thought: does the above memory ordering differences > > > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way > > > how it is currently implemented for x86 is the same way as it is for atomic cases. > > > > Never look to x86 for memory ordering, its boring. > > > > And yes, for the ARM implementation it can certainly make a difference. > > So, yes, what I am trying to say is that it can really depend if you have ARCH_HAS_REFCOUNT > enabled or not and then also based on architecture. Thus I believe is also true for atomic: there > might be differences when you use arch. dependent version of function or not. So the generic one in lib/refcount.c is already weaker on ARM, they don't need to do a ARCH specific 'fast' implementation for the difference to show up.
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-09-01 19:10 +0200 |
| Subject | RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukXCa-81A-13@gated-at.bofh.it> |
| In reply to | #1725089 |
> On Fri, Sep 01, 2017 at 01:24:16PM +0000, Reshetova, Elena wrote: > > > > > On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > > > > Actually on the second thought: does the above memory ordering differences > > > > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way > > > > how it is currently implemented for x86 is the same way as it is for atomic > cases. > > > > > > Never look to x86 for memory ordering, its boring. > > > > > > And yes, for the ARM implementation it can certainly make a difference. > > > > So, yes, what I am trying to say is that it can really depend if you have > ARCH_HAS_REFCOUNT > > enabled or not and then also based on architecture. Thus I believe is also true for > atomic: there > > might be differences when you use arch. dependent version of function or not. > > So the generic one in lib/refcount.c is already weaker on ARM, they > don't need to do a ARCH specific 'fast' implementation for the > difference to show up. But can they make "fast" implementation on ARM that would give stronger memory guarantees?
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-09-01 21:20 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ukZDX-RU-3@gated-at.bofh.it> |
| In reply to | #1725239 |
On Fri, Sep 01, 2017 at 05:03:55PM +0000, Reshetova, Elena wrote: > > On Fri, Sep 01, 2017 at 01:24:16PM +0000, Reshetova, Elena wrote: > > > > > > > On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > > > > > Actually on the second thought: does the above memory ordering differences > > > > > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the way > > > > > how it is currently implemented for x86 is the same way as it is for atomic > > cases. > > > > > > > > Never look to x86 for memory ordering, its boring. > > > > > > > > And yes, for the ARM implementation it can certainly make a difference. > > > > > > So, yes, what I am trying to say is that it can really depend if you have > > ARCH_HAS_REFCOUNT > > > enabled or not and then also based on architecture. Thus I believe is also true for > > atomic: there > > > might be differences when you use arch. dependent version of function or not. > > > > So the generic one in lib/refcount.c is already weaker on ARM, they > > don't need to do a ARCH specific 'fast' implementation for the > > difference to show up. > > But can they make "fast" implementation on ARM that would give stronger memory guarantees? Whatever for?
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-09-04 12:40 +0200 |
| Subject | RE: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ulWXo-4m6-7@gated-at.bofh.it> |
| In reply to | #1725299 |
> -----Original Message----- > From: Peter Zijlstra [mailto:peterz@infradead.org] > Sent: Friday, September 1, 2017 10:13 PM > To: Reshetova, Elena <elena.reshetova@intel.com> > Cc: Thomas Gleixner <tglx@linutronix.de>; linux-kernel@vger.kernel.org; linux- > fsdevel@vger.kernel.org; gregkh@linuxfoundation.org; viro@zeniv.linux.org.uk; > tj@kernel.org; mingo@redhat.com; hannes@cmpxchg.org; lizefan@huawei.com; > acme@kernel.org; alexander.shishkin@linux.intel.com; eparis@redhat.com; > akpm@linux-foundation.org; arnd@arndb.de; luto@kernel.org; > keescook@chromium.org; dvhart@infradead.org; ebiederm@xmission.com > Subject: Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t > > On Fri, Sep 01, 2017 at 05:03:55PM +0000, Reshetova, Elena wrote: > > > On Fri, Sep 01, 2017 at 01:24:16PM +0000, Reshetova, Elena wrote: > > > > > > > > > On Fri, Sep 01, 2017 at 11:05:33AM +0000, Reshetova, Elena wrote: > > > > > > Actually on the second thought: does the above memory ordering > differences > > > > > > really apply when we have ARCH_HAS_REFCOUNT? To me it looks like the > way > > > > > > how it is currently implemented for x86 is the same way as it is for atomic > > > cases. > > > > > > > > > > Never look to x86 for memory ordering, its boring. > > > > > > > > > > And yes, for the ARM implementation it can certainly make a difference. > > > > > > > > So, yes, what I am trying to say is that it can really depend if you have > > > ARCH_HAS_REFCOUNT > > > > enabled or not and then also based on architecture. Thus I believe is also true > for > > > atomic: there > > > > might be differences when you use arch. dependent version of function or not. > > > > > > So the generic one in lib/refcount.c is already weaker on ARM, they > > > don't need to do a ARCH specific 'fast' implementation for the > > > difference to show up. > > > > But can they make "fast" implementation on ARM that would give stronger > memory guarantees? > > Whatever for? Well, maybe just by default when arch.-specific implementation is done. But I was just trying to speculate to understand. I will resend this one with new comment added. Still not sure if I need to resend the whole series with updated commits or break this up by individual patches further for the separate merges.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-09-04 14:10 +0200 |
| Subject | Re: [PATCH 14/15] futex: convert futex_pi_state.refcount to refcount_t |
| Message-ID | <ulYmu-5lg-13@gated-at.bofh.it> |
| In reply to | #1725986 |
On Mon, Sep 04, 2017 at 10:31:54AM +0000, Reshetova, Elena wrote:
> > > But can they make "fast" implementation on ARM that would give stronger
> > > memory guarantees?
> >
> > Whatever for?
>
> Well, maybe just by default when arch.-specific implementation is
> done. But I was just trying to speculate to understand. I will resend
> this one with new comment added.
So the generic lib/refcount.c already has weak ordering. It doesn't make
sense for an arch specific implementation (on a weakly ordered machine)
to provide stronger guarantees (it would make things slower).
The weaker ordering of the refcount_t primitives is sufficient if we're
talking pure refcounts. If for some reason code relies on stronger
ordering there _SHOULD_ be a comment with describing the additional
ordering requirements.
But that's a fairly big 'should'. I can well imagine the comment not
being there. In fact, see below.
> Still not sure if I need to resend the whole series with updated
> commits or break this up by individual patches further for the
> separate merges.
I've yet to look at the ones targeted at subsystems I do, I'm forever
and terminally behind on review :/
I called out the issue on futex in particular because it is fairly
tricky code that.
Now Thomas would like you to mention the fact that refcount_t doesn't
provide the exact same ordering as the atomic_t usages it replaces and
I think it would be good if you could hand-wave an argument on why the
futex code doesn't care.
Now, suppose we were to convert i_count to refcount_t (yes, I know, my
initial conversion wasn't well received), then we need to add
futex_get_inode() similar to futex_get_mm().
That is, smp_mb__{before,after}_atomic() works as expected and can be
used to fortify the implied barriers by refcount_t.
---
Subject: fs,inode: Add comment explaining additional ordering
Add a note to ihold() to document the ordering futex relies upon.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
fs/inode.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/inode.c b/fs/inode.c
index 50370599e371..17192ba92fef 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -395,6 +395,10 @@ void __iget(struct inode *inode)
*/
void ihold(struct inode *inode)
{
+ /*
+ * Note: futex.c:get_futex_key_refs() relies on this function
+ * implying an smp_mb().
+ */
WARN_ON(atomic_inc_return(&inode->i_count) < 2);
}
EXPORT_SYMBOL(ihold);
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 07/15] perf: convert perf_event_context.refcount to refcount_t |
| Message-ID | <ukai7-8hx-51@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@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 9bac4bf..75c11181 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -54,6 +54,7 @@ struct perf_guest_info_callbacks {
#include <linux/perf_regs.h>
#include <linux/workqueue.h>
#include <linux/cgroup.h>
+#include <linux/refcount.h>
#include <asm/local.h>
struct perf_callchain_entry {
@@ -737,7 +738,7 @@ struct perf_event_context {
int nr_stat;
int nr_freq;
int rotate_disable;
- atomic_t refcount;
+ refcount_t refcount;
struct task_struct *task;
/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 852768d..57ef7ce 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1109,7 +1109,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(&ctx->refcount));
+ WARN_ON(!refcount_inc_not_zero(&ctx->refcount));
}
static void free_ctx(struct rcu_head *head)
@@ -1123,7 +1123,7 @@ static void free_ctx(struct rcu_head *head)
static void put_ctx(struct perf_event_context *ctx)
{
- if (atomic_dec_and_test(&ctx->refcount)) {
+ if (refcount_dec_and_test(&ctx->refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1201,7 +1201,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int nesting)
again:
rcu_read_lock();
ctx = ACCESS_ONCE(event->ctx);
- if (!atomic_inc_not_zero(&ctx->refcount)) {
+ if (!refcount_inc_not_zero(&ctx->refcount)) {
rcu_read_unlock();
goto again;
}
@@ -1329,7 +1329,7 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags)
}
if (ctx->task == TASK_TOMBSTONE ||
- !atomic_inc_not_zero(&ctx->refcount)) {
+ !refcount_inc_not_zero(&ctx->refcount)) {
raw_spin_unlock(&ctx->lock);
ctx = NULL;
} else {
@@ -3795,7 +3795,7 @@ static void __perf_event_init_context(struct perf_event_context *ctx)
INIT_LIST_HEAD(&ctx->pinned_groups);
INIT_LIST_HEAD(&ctx->flexible_groups);
INIT_LIST_HEAD(&ctx->event_list);
- atomic_set(&ctx->refcount, 1);
+ refcount_set(&ctx->refcount, 1);
}
static struct perf_event_context *
@@ -9812,7 +9812,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(&gctx->refcount)) {
+ if (!refcount_inc_not_zero(&gctx->refcount)) {
rcu_read_unlock();
goto again;
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 03/15] sched: convert user_struct.__count to refcount_t |
| Message-ID | <ukai7-8hx-47@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@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 3c07e41..afcbf19 100644
--- a/include/linux/sched/user.h
+++ b/include/linux/sched/user.h
@@ -3,6 +3,7 @@
#include <linux/uidgid.h>
#include <linux/atomic.h>
+#include <linux/refcount.h>
struct key;
@@ -10,7 +11,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
@@ -54,7 +55,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(&u->__count);
+ refcount_inc(&u->__count);
return u;
}
extern void free_uid(struct user_struct *);
diff --git a/kernel/user.c b/kernel/user.c
index 00281ad..c072348 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -90,7 +90,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,
@@ -116,7 +116,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(&user->__count);
+ refcount_inc(&user->__count);
return user;
}
}
@@ -163,7 +163,7 @@ void free_uid(struct user_struct *up)
return;
local_irq_save(flags);
- if (atomic_dec_and_lock(&up->__count, &uidhash_lock))
+ if (refcount_dec_and_lock(&up->__count, &uidhash_lock))
free_user(up, flags);
else
local_irq_restore(flags);
@@ -184,7 +184,7 @@ struct user_struct *alloc_uid(kuid_t uid)
goto out_unlock;
new->uid = uid;
- atomic_set(&new->__count, 1);
+ refcount_set(&new->__count, 1);
/*
* Before adding this, check whether we raced
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-08-30 14:30 +0200 |
| Subject | [PATCH 11/15] nsproxy: convert nsproxy.count to refcount_t |
| Message-ID | <ukai7-8hx-55@gated-at.bofh.it> |
| In reply to | #1723259 |
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.
Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@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 ac0d65b..f862ba8 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -28,7 +28,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;
@@ -74,14 +74,14 @@ int __init nsproxy_cache_init(void);
static inline void put_nsproxy(struct nsproxy *ns)
{
- if (atomic_dec_and_test(&ns->count)) {
+ if (refcount_dec_and_test(&ns->count)) {
free_nsproxy(ns);
}
}
static inline void get_nsproxy(struct nsproxy *ns)
{
- atomic_inc(&ns->count);
+ refcount_inc(&ns->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 = &init_uts_ns,
#if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC)
.ipc_ns = &init_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(&nsproxy->count, 1);
+ refcount_set(&nsproxy->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(&ns->count))
+ if (ns && refcount_dec_and_test(&ns->count))
free_nsproxy(ns);
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2017-09-01 01:50 +0200 |
| Message-ID | <ukHnI-41L-27@gated-at.bofh.it> |
| In reply to | #1723259 |
On Wed, Aug 30, 2017 at 5:22 AM, Elena Reshetova <elena.reshetova@intel.com> wrote: > Now we have at least x86 support for ARCH_HAS_REFCOUNT merged and > arm and others on their way. > > 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. Thanks! Reviewed-by: Kees Cook <keescook@chromium.org> Andrew, are you able to carry these patches in -mm, since they span a bunch of core kernel areas? -Kees > > 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 (15): > 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 > futex: convert futex_pi_state.refcount to refcount_t > kcov: convert kcov.refcount to refcount_t > > fs/exec.c | 4 ++-- > fs/proc/task_nommu.c | 2 +- > 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 | 13 ++++++------ > kernel/groups.c | 2 +- > kernel/kcov.c | 9 ++++---- > kernel/nsproxy.c | 6 +++--- > kernel/sched/fair.c | 12 +++++------ > kernel/user.c | 8 +++---- > 23 files changed, 112 insertions(+), 103 deletions(-) > > -- > 2.7.4 > -- Kees Cook Pixel Security
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web