|
Message-ID: <20161128121347.GY3092@twins.programming.kicks-ass.net> Date: Mon, 28 Nov 2016 13:13:47 +0100 From: Peter Zijlstra <peterz@...radead.org> To: "Reshetova, Elena" <elena.reshetova@...el.com> Cc: "kernel-hardening@...ts.openwall.com" <kernel-hardening@...ts.openwall.com>, Greg KH <gregkh@...uxfoundation.org>, Kees Cook <keescook@...omium.org>, "will.deacon@....com" <will.deacon@....com>, Boqun Feng <boqun.feng@...il.com>, Hans Liljestrand <ishkamiel@...il.com>, David Windsor <dwindsor@...il.com>, aik@...abs.ru, david@...son.dropbear.id.au Subject: Re: Conversion from atomic_t to refcount_t: summary of issues On Mon, Nov 28, 2016 at 11:56:17AM +0000, Reshetova, Elena wrote: > First, about the types. > We do have a number of instances of atomic_long_t used as refcounters, see below: Right, those were expected. We could do long_refcount_t I suppose. > 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; > ... > } *urgh*, Alexey does that really need to be atomic64_t ? Wouldn't atomic_long_t work for you? > 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) Right, we spoke about this before, and the dec_if_one() you mentioned below could replace that. > - if (atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {..} (typical for networking code) That's really weird, a refcount of -1 doesn't really make sense. > - if (atomic_add_unless(&inode->i_count, -1, 1)) (typical for fs and other code) And that's dec_not_one(), really weird that, why do they need that? > 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(). There is sub_and_test() usage in for example memcontrol.c. > The following functions are also needed quite commonly: > refcount_inc_return() > refcount_dec_return() What for? They don't typicaly make sense for refcounting? Other than the trivial pattern of dec_return() == 0, which is already well covered. > I also saw one use of this from net/ipv4/udp.c: > if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2)) Yes, that one is quite unfortunate, we can trivially support that ofcourse, but it does make a bit of a mess of things. > 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? Well, it clearly marks where refcounting goes bad and we leak crap. A regular decrement should _never_ hit 0. > It is clear that in that places the caller explicitly > doesn't care about how the dec() goes and what is the end result.... No, the typical usage would be you _know_ it will not hit 0. Any other usage is broken and bad.
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.