Re: fs: NULL deref in atime_needs_update

From: David Howells
Date: Mon Feb 29 2016 - 08:44:05 EST


Al Viro <viro@xxxxxxxxxxxxxxxxxx> wrote:

> David, Linus, do you see any problems with that? To me it looks saner
> that way and as cheap as the current code, but I might be missing something
> here...

You're effectively converting to this:

read d_seq.sequence
smp_rmb()
read d_inode, d_flags
smp_rmb()
check d_seq.sequence

in the read path and this:

write d_seq.sequence
smp_wmb()
write d_inode, d_flags
smp_wmb()
write d_seq.sequence

This should work - especially if we're wangling these sequence points anyway,
and so have to pay the barrier penalties whatever. In fact, you actually take
a barrier out, I think.

I have had a problem with getting the ordering of d_inode and d_flags right
because of __d_clear_type_and_inode() where we're required to unset a dentry
so that it can be repurposed[*] as a negative dentry rather than replacing it.

This is something we for performance sake - and it's something we can only do
if the dentry isn't referenced, whereas if we properly followed the RCU model,
we would have to wait a grace period after delisting an unlinked dentry before
we could repurpose it - but that significantly slows down rename, unlink and
rmdir.

[*] Al and I disagree on whether this is a reuse or merely a change of state.

David