<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/fs/pipe.c, branch v3.13</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>vfs: fix subtle use-after-free of pipe_inode_info</title>
<updated>2013-12-02T17:44:51+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2013-12-02T17:44:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=b0d8d2292160bb63de1972361ebed100c64b5b37'/>
<id>b0d8d2292160bb63de1972361ebed100c64b5b37</id>
<content type='text'>
The pipe code was trying (and failing) to be very careful about freeing
the pipe info only after the last access, with a pattern like:

        spin_lock(&amp;inode-&gt;i_lock);
        if (!--pipe-&gt;files) {
                inode-&gt;i_pipe = NULL;
                kill = 1;
        }
        spin_unlock(&amp;inode-&gt;i_lock);
        __pipe_unlock(pipe);
        if (kill)
                free_pipe_info(pipe);

where the final freeing is done last.

HOWEVER.  The above is actually broken, because while the freeing is
done at the end, if we have two racing processes releasing the pipe
inode info, the one that *doesn't* free it will decrement the -&gt;files
count, and unlock the inode i_lock, but then still use the
"pipe_inode_info" afterwards when it does the "__pipe_unlock(pipe)".

This is *very* hard to trigger in practice, since the race window is
very small, and adding debug options seems to just hide it by slowing
things down.

Simon originally reported this way back in July as an Oops in
kmem_cache_allocate due to a single bit corruption (due to the final
"spin_unlock(pipe-&gt;mutex.wait_lock)" incrementing a field in a different
allocation that had re-used the free'd pipe-info), it's taken this long
to figure out.

Since the 'pipe-&gt;files' accesses aren't even protected by the pipe lock
(we very much use the inode lock for that), the simple solution is to
just drop the pipe lock early.  And since there were two users of this
pattern, create a helper function for it.

Introduced commit ba5bb147330a ("pipe: take allocation and freeing of
pipe_inode_info out of -&gt;i_mutex").

Reported-by: Simon Kirby &lt;sim@hostway.ca&gt;
Reported-by: Ian Applegate &lt;ia@cloudflare.com&gt;
Acked-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Cc: stable@kernel.org   # v3.10+
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The pipe code was trying (and failing) to be very careful about freeing
the pipe info only after the last access, with a pattern like:

        spin_lock(&amp;inode-&gt;i_lock);
        if (!--pipe-&gt;files) {
                inode-&gt;i_pipe = NULL;
                kill = 1;
        }
        spin_unlock(&amp;inode-&gt;i_lock);
        __pipe_unlock(pipe);
        if (kill)
                free_pipe_info(pipe);

where the final freeing is done last.

HOWEVER.  The above is actually broken, because while the freeing is
done at the end, if we have two racing processes releasing the pipe
inode info, the one that *doesn't* free it will decrement the -&gt;files
count, and unlock the inode i_lock, but then still use the
"pipe_inode_info" afterwards when it does the "__pipe_unlock(pipe)".

This is *very* hard to trigger in practice, since the race window is
very small, and adding debug options seems to just hide it by slowing
things down.

Simon originally reported this way back in July as an Oops in
kmem_cache_allocate due to a single bit corruption (due to the final
"spin_unlock(pipe-&gt;mutex.wait_lock)" incrementing a field in a different
allocation that had re-used the free'd pipe-info), it's taken this long
to figure out.

Since the 'pipe-&gt;files' accesses aren't even protected by the pipe lock
(we very much use the inode lock for that), the simple solution is to
just drop the pipe lock early.  And since there were two users of this
pattern, create a helper function for it.

Introduced commit ba5bb147330a ("pipe: take allocation and freeing of
pipe_inode_info out of -&gt;i_mutex").

Reported-by: Simon Kirby &lt;sim@hostway.ca&gt;
Reported-by: Ian Applegate &lt;ia@cloudflare.com&gt;
Acked-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Cc: stable@kernel.org   # v3.10+
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>aio: don't include aio.h in sched.h</title>
<updated>2013-05-08T03:16:25+00:00</updated>
<author>
<name>Kent Overstreet</name>
<email>koverstreet@google.com</email>
</author>
<published>2013-05-07T23:19:08+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=a27bb332c04cec8c4afd7912df0dc7890db27560'/>
<id>a27bb332c04cec8c4afd7912df0dc7890db27560</id>
<content type='text'>
Faster kernel compiles by way of fewer unnecessary includes.

[akpm@linux-foundation.org: fix fallout]
[akpm@linux-foundation.org: fix build]
Signed-off-by: Kent Overstreet &lt;koverstreet@google.com&gt;
Cc: Zach Brown &lt;zab@redhat.com&gt;
Cc: Felipe Balbi &lt;balbi@ti.com&gt;
Cc: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.com&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Rusty Russell &lt;rusty@rustcorp.com.au&gt;
Cc: Jens Axboe &lt;axboe@kernel.dk&gt;
Cc: Asai Thambi S P &lt;asamymuthupa@micron.com&gt;
Cc: Selvan Mani &lt;smani@micron.com&gt;
Cc: Sam Bradshaw &lt;sbradshaw@micron.com&gt;
Cc: Jeff Moyer &lt;jmoyer@redhat.com&gt;
Cc: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Cc: Benjamin LaHaise &lt;bcrl@kvack.org&gt;
Reviewed-by: "Theodore Ts'o" &lt;tytso@mit.edu&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Faster kernel compiles by way of fewer unnecessary includes.

[akpm@linux-foundation.org: fix fallout]
[akpm@linux-foundation.org: fix build]
Signed-off-by: Kent Overstreet &lt;koverstreet@google.com&gt;
Cc: Zach Brown &lt;zab@redhat.com&gt;
Cc: Felipe Balbi &lt;balbi@ti.com&gt;
Cc: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.com&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Rusty Russell &lt;rusty@rustcorp.com.au&gt;
Cc: Jens Axboe &lt;axboe@kernel.dk&gt;
Cc: Asai Thambi S P &lt;asamymuthupa@micron.com&gt;
Cc: Selvan Mani &lt;smani@micron.com&gt;
Cc: Sam Bradshaw &lt;sbradshaw@micron.com&gt;
Cc: Jeff Moyer &lt;jmoyer@redhat.com&gt;
Cc: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Cc: Benjamin LaHaise &lt;bcrl@kvack.org&gt;
Reviewed-by: "Theodore Ts'o" &lt;tytso@mit.edu&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>get rid of the last free_pipe_info() callers</title>
<updated>2013-04-09T18:13:02+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T15:06:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=4b8a8f1e4f94fd87747e6e3acef74cf0b4dc0dae'/>
<id>4b8a8f1e4f94fd87747e6e3acef74cf0b4dc0dae</id>
<content type='text'>
and rename __free_pipe_info() to free_pipe_info()

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
and rename __free_pipe_info() to free_pipe_info()

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>get rid of alloc_pipe_info() argument</title>
<updated>2013-04-09T18:13:01+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T15:04:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=7bee130e222dfb3a7a70c0404dc09f104cddd7d6'/>
<id>7bee130e222dfb3a7a70c0404dc09f104cddd7d6</id>
<content type='text'>
not used anymore

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
not used anymore

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>get rid of pipe-&gt;inode</title>
<updated>2013-04-09T18:13:01+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T15:01:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=6447a3cf19da8c4653283d1c491e2e775633f348'/>
<id>6447a3cf19da8c4653283d1c491e2e775633f348</id>
<content type='text'>
it's used only as a flag to distinguish normal pipes/FIFOs from the
internal per-task one used by file-to-file splice.  And pipe-&gt;files
would work just as well for that purpose...

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
it's used only as a flag to distinguish normal pipes/FIFOs from the
internal per-task one used by file-to-file splice.  And pipe-&gt;files
would work just as well for that purpose...

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>introduce variants of pipe_lock/pipe_unlock for real pipes/FIFOs</title>
<updated>2013-04-09T18:13:01+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T16:24:01+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=ebec73f4752b777b79b384bd52e5240203cb9b00'/>
<id>ebec73f4752b777b79b384bd52e5240203cb9b00</id>
<content type='text'>
fs/pipe.c file_operations methods *know* that pipe is not an internal one;
no need to check pipe-&gt;inode for those callers.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
fs/pipe.c file_operations methods *know* that pipe is not an internal one;
no need to check pipe-&gt;inode for those callers.

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pipe: set file-&gt;private_data to -&gt;i_pipe</title>
<updated>2013-04-09T18:13:00+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T15:16:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=de32ec4cfeb3b3afd2abf5116068deace10e420f'/>
<id>de32ec4cfeb3b3afd2abf5116068deace10e420f</id>
<content type='text'>
simplify get_pipe_info(), while we are at it

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
simplify get_pipe_info(), while we are at it

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pipe: don't use -&gt;i_mutex</title>
<updated>2013-04-09T18:13:00+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T06:32:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=72b0d9aacb89f3759931ec440e1b535671145bb4'/>
<id>72b0d9aacb89f3759931ec440e1b535671145bb4</id>
<content type='text'>
now it can be done - put mutex into pipe_inode_info, use it instead
of -&gt;i_mutex

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
now it can be done - put mutex into pipe_inode_info, use it instead
of -&gt;i_mutex

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pipe: take allocation and freeing of pipe_inode_info out of -&gt;i_mutex</title>
<updated>2013-04-09T18:12:59+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T06:21:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=ba5bb147330a8737b6b5a812cc774c79c070704b'/>
<id>ba5bb147330a8737b6b5a812cc774c79c070704b</id>
<content type='text'>
* new field - pipe-&gt;files; number of struct file over that pipe (all
  sharing the same inode, of course); protected by inode-&gt;i_lock.
* pipe_release() decrements pipe-&gt;files, clears inode-&gt;i_pipe when
  if the counter has reached 0 (all under -&gt;i_lock) and, in that case,
  frees pipe after having done pipe_unlock()
* fifo_open() starts with grabbing -&gt;i_lock, and either bumps pipe-&gt;files
  if -&gt;i_pipe was non-NULL or allocates a new pipe (dropping and regaining
  -&gt;i_lock) and rechecks -&gt;i_pipe; if it's still NULL, inserts new pipe
  there, otherwise bumps -&gt;i_pipe-&gt;files and frees the one we'd allocated.
  At that point we know that -&gt;i_pipe is non-NULL and won't go away, so
  we can do pipe_lock() on it and proceed as we used to.  If we end up
  failing, decrement pipe-&gt;files and if it reaches 0 clear -&gt;i_pipe and
  free the sucker after pipe_unlock().

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* new field - pipe-&gt;files; number of struct file over that pipe (all
  sharing the same inode, of course); protected by inode-&gt;i_lock.
* pipe_release() decrements pipe-&gt;files, clears inode-&gt;i_pipe when
  if the counter has reached 0 (all under -&gt;i_lock) and, in that case,
  frees pipe after having done pipe_unlock()
* fifo_open() starts with grabbing -&gt;i_lock, and either bumps pipe-&gt;files
  if -&gt;i_pipe was non-NULL or allocates a new pipe (dropping and regaining
  -&gt;i_lock) and rechecks -&gt;i_pipe; if it's still NULL, inserts new pipe
  there, otherwise bumps -&gt;i_pipe-&gt;files and frees the one we'd allocated.
  At that point we know that -&gt;i_pipe is non-NULL and won't go away, so
  we can do pipe_lock() on it and proceed as we used to.  If we end up
  failing, decrement pipe-&gt;files and if it reaches 0 clear -&gt;i_pipe and
  free the sucker after pipe_unlock().

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>pipe: preparation to new locking rules</title>
<updated>2013-04-09T18:12:59+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2013-03-21T06:16:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=18c03cfd403b88852f75f200206983ee6df28423'/>
<id>18c03cfd403b88852f75f200206983ee6df28423</id>
<content type='text'>
* use the fact that file_inode(file)-&gt;i_pipe doesn't change
  while the file is opened - no locks needed to access that.
* switch to pipe_lock/pipe_unlock where it's easy to do

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* use the fact that file_inode(file)-&gt;i_pipe doesn't change
  while the file is opened - no locks needed to access that.
* switch to pipe_lock/pipe_unlock where it's easy to do

Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
</pre>
</div>
</content>
</entry>
</feed>
