All of lore.kernel.org
 help / color / mirror / Atom feed
* [kernel-hardening] Conversion from atomic_t to refcount_t: summary of issues
@ 2016-11-28 11:56 Reshetova, Elena
  2016-11-28 12:13 ` [kernel-hardening] " Peter Zijlstra
  0 siblings, 1 reply; 48+ messages in thread
From: Reshetova, Elena @ 2016-11-28 11:56 UTC (permalink / raw)
  To: Peter Zijlstra, kernel-hardening, Greg KH, Kees Cook,
	will.deacon, Boqun Feng
  Cc: Hans Liljestrand, David Windsor

Hi,

Now when we are almost over the huge set of conversions, I would like to make a summary of issues that we see to be very common.
So, that we can then decide how to address them.

First, about the types. 
We do have a number of instances of atomic_long_t used as refcounters, see below:

linux/perf_event.h:
struct perf_event {
...
 atomic_long_t refcount;
 ...
}

kernel/audit_tree.c:
struct audit_chunk {
...
    atomic_long_t refs;
..
}

kernel/acct.c:
struct bsd_acct_struct {
...
    atomic_long_t       count;
...
};

linux/fs.h:
struct file {
    ...
    atomic_long_t       f_count;
    ...
}

block/blk-ioc.c:
struct io_context {
    atomic_long_t refcount;
    ...
}

There might be more since we are not 100% finished, but at least struct file is pretty important one that we should be covering. 

And yes, we *do* have at least one instance (again not 100% finished, more might show up) of atomic64_t used as refcounter:

arch/powerpc/mm/mmu_context_iommu.c:
struct mm_iommu_table_group_mem_t {
...
    atomic64_t mapped;
...
}

Next with regards to API. Networking code surely wins the competitions of giving the most trouble.
The biggest overall issue seem to be in fact that freeing the object happens not when refcount is zero, but when it is -1,
which is obviously impossible to implement with current API that only returns unsigned int. 

Most common constructions that are hard to fit into current API are:

-    if (atomic_cmpxchg(&cur->refcnt, 1, 0) == 1) {...} (typical for networking code)
-    if (atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {..} (typical for networking code)
-    if (atomic_add_unless(&inode->i_count, -1, 1)) (typical for fs and other code)

Also, refcount_add() seems to be needed in number of places since it looks like refcounts in some cases are increased by two or by some constant. 
Luckily we haven't seen a need a sub().

The following functions are also needed quite commonly:
refcount_inc_return()
refcount_dec_return()

There is also a need for smth like refcount_dec_if_one(), i.e. decrement only if counter equals one and then do some housekeeping. 

I also saw one use of this from net/ipv4/udp.c:
    if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2))

Lastly as I mentioned previously, almost half of invocations of dec() in the code is plain atomic_dec() without any if statements and any checks on what happens as a result of dec(). 
Peter previously suggested to turn them into WARN_ON(refcount_dec_and_test()), but looking in the code, it is not really clear what would this help to achieve? 
It is clear that in that places the caller explicitly doesn't care about how the dec() goes and what is the end result....

Best Regards,
Elena.

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

end of thread, other threads:[~2017-01-10 14:58 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-28 11:56 [kernel-hardening] Conversion from atomic_t to refcount_t: summary of issues Reshetova, Elena
2016-11-28 12:13 ` [kernel-hardening] " Peter Zijlstra
2016-11-28 12:44   ` Peter Zijlstra
2016-11-28 12:48   ` Peter Zijlstra
2016-11-28 14:12   ` [kernel-hardening] " Reshetova, Elena
2016-11-29  3:19   ` [kernel-hardening] " Alexey Kardashevskiy
2016-11-29  9:31     ` Peter Zijlstra
2016-11-30  0:23       ` Alexey Kardashevskiy
2016-11-29 15:35   ` [kernel-hardening] " Reshetova, Elena
2016-11-29 15:47     ` Peter Zijlstra
2016-12-01 19:15     ` [kernel-hardening] " Peter Zijlstra
2016-12-01 21:31       ` David Windsor
2016-12-01 23:03         ` Peter Zijlstra
2016-12-01 23:20           ` Kees Cook
2016-12-01 23:29             ` David Windsor
2016-12-02  1:17             ` Boqun Feng
2016-12-02 20:25               ` David Windsor
2016-12-07 13:24                 ` Peter Zijlstra
2016-12-07 19:03                   ` David Windsor
2016-12-09 14:48                     ` David Windsor
2016-12-07 13:36             ` Peter Zijlstra
2016-12-01 23:20           ` David Windsor
2016-12-07 13:21             ` Peter Zijlstra
2016-12-02 15:44       ` Liljestrand Hans
2016-12-02 16:14         ` Greg KH
2016-12-07 13:52         ` Peter Zijlstra
2016-12-07 15:59           ` David Windsor
2016-12-07 16:26             ` Peter Zijlstra
2016-12-07 16:31               ` David Windsor
2016-12-16 12:10           ` [kernel-hardening] " Reshetova, Elena
2016-12-16 14:01             ` [kernel-hardening] " Peter Zijlstra
2016-12-19  7:55               ` [kernel-hardening] " Reshetova, Elena
2016-12-19 10:12                 ` [kernel-hardening] " Peter Zijlstra
2016-12-20  9:13                   ` [kernel-hardening] " Reshetova, Elena
2016-12-20  9:30                     ` [kernel-hardening] " Greg KH
2016-12-20  9:40                       ` [kernel-hardening] " Reshetova, Elena
2016-12-20  9:51                         ` [kernel-hardening] " Greg KH
2016-12-20  9:55                           ` [kernel-hardening] " Reshetova, Elena
2016-12-20 10:26                             ` [kernel-hardening] " Greg KH
2016-12-20  9:41                     ` Peter Zijlstra
2016-12-20  9:58                       ` [kernel-hardening] " Reshetova, Elena
2016-12-20 10:55                       ` [kernel-hardening] " Liljestrand Hans
2016-12-20 13:13                         ` Peter Zijlstra
2016-12-20 13:35                           ` Reshetova, Elena
2016-12-20 15:20                           ` Liljestrand Hans
2016-12-20 15:52                             ` Peter Zijlstra
2017-01-10 14:58                             ` Peter Zijlstra
2016-12-07 14:13     ` Peter Zijlstra

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