<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-stable.git/fs, branch v3.18.34</title>
<subtitle>Linux kernel stable tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/'/>
<entry>
<title>ocfs2: fix posix_acl_create deadlock</title>
<updated>2016-05-18T02:25:41+00:00</updated>
<author>
<name>Junxiao Bi</name>
<email>junxiao.bi@oracle.com</email>
</author>
<published>2016-05-12T22:42:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=b0efc68c6f9cb2fd22ab77f841883e7f3f9562be'/>
<id>b0efc68c6f9cb2fd22ab77f841883e7f3f9562be</id>
<content type='text'>
[ Upstream commit c25a1e0671fbca7b2c0d0757d533bd2650d6dc0c ]

Commit 702e5bc68ad2 ("ocfs2: use generic posix ACL infrastructure")
refactored code to use posix_acl_create.  The problem with this function
is that it is not mindful of the cluster wide inode lock making it
unsuitable for use with ocfs2 inode creation with ACLs.  For example,
when used in ocfs2_mknod, this function can cause deadlock as follows.
The parent dir inode lock is taken when calling posix_acl_create -&gt;
get_acl -&gt; ocfs2_iop_get_acl which takes the inode lock again.  This can
cause deadlock if there is a blocked remote lock request waiting for the
lock to be downconverted.  And same deadlock happened in ocfs2_reflink.
This fix is to revert back using ocfs2_init_acl.

Fixes: 702e5bc68ad2 ("ocfs2: use generic posix ACL infrastructure")
Signed-off-by: Tariq Saeed &lt;tariq.x.saeed@oracle.com&gt;
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Joseph Qi &lt;joseph.qi@huawei.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit c25a1e0671fbca7b2c0d0757d533bd2650d6dc0c ]

Commit 702e5bc68ad2 ("ocfs2: use generic posix ACL infrastructure")
refactored code to use posix_acl_create.  The problem with this function
is that it is not mindful of the cluster wide inode lock making it
unsuitable for use with ocfs2 inode creation with ACLs.  For example,
when used in ocfs2_mknod, this function can cause deadlock as follows.
The parent dir inode lock is taken when calling posix_acl_create -&gt;
get_acl -&gt; ocfs2_iop_get_acl which takes the inode lock again.  This can
cause deadlock if there is a blocked remote lock request waiting for the
lock to be downconverted.  And same deadlock happened in ocfs2_reflink.
This fix is to revert back using ocfs2_init_acl.

Fixes: 702e5bc68ad2 ("ocfs2: use generic posix ACL infrastructure")
Signed-off-by: Tariq Saeed &lt;tariq.x.saeed@oracle.com&gt;
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Joseph Qi &lt;joseph.qi@huawei.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ocfs2: revert using ocfs2_acl_chmod to avoid inode cluster lock hang</title>
<updated>2016-05-18T02:25:33+00:00</updated>
<author>
<name>Junxiao Bi</name>
<email>junxiao.bi@oracle.com</email>
</author>
<published>2016-05-12T22:42:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=7879a58a1c6c13501c79418b82053007ebf04f88'/>
<id>7879a58a1c6c13501c79418b82053007ebf04f88</id>
<content type='text'>
[ Upstream commit 5ee0fbd50fdf1c1329de8bee35ea9d7c6a81a2e0 ]

Commit 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()")
introduced this issue.  ocfs2_setattr called by chmod command holds
cluster wide inode lock when calling posix_acl_chmod.  This latter
function in turn calls ocfs2_iop_get_acl and ocfs2_iop_set_acl.  These
two are also called directly from vfs layer for getfacl/setfacl commands
and therefore acquire the cluster wide inode lock.  If a remote
conversion request comes after the first inode lock in ocfs2_setattr,
OCFS2_LOCK_BLOCKED will be set.  And this will cause the second call to
inode lock from the ocfs2_iop_get_acl() to block indefinetly.

The deleted version of ocfs2_acl_chmod() calls __posix_acl_chmod() which
does not call back into the filesystem.  Therefore, we restore
ocfs2_acl_chmod(), modify it slightly for locking as needed, and use that
instead.

Fixes: 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()")
Signed-off-by: Tariq Saeed &lt;tariq.x.saeed@oracle.com&gt;
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Joseph Qi &lt;joseph.qi@huawei.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 5ee0fbd50fdf1c1329de8bee35ea9d7c6a81a2e0 ]

Commit 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()")
introduced this issue.  ocfs2_setattr called by chmod command holds
cluster wide inode lock when calling posix_acl_chmod.  This latter
function in turn calls ocfs2_iop_get_acl and ocfs2_iop_set_acl.  These
two are also called directly from vfs layer for getfacl/setfacl commands
and therefore acquire the cluster wide inode lock.  If a remote
conversion request comes after the first inode lock in ocfs2_setattr,
OCFS2_LOCK_BLOCKED will be set.  And this will cause the second call to
inode lock from the ocfs2_iop_get_acl() to block indefinetly.

The deleted version of ocfs2_acl_chmod() calls __posix_acl_chmod() which
does not call back into the filesystem.  Therefore, we restore
ocfs2_acl_chmod(), modify it slightly for locking as needed, and use that
instead.

Fixes: 743b5f1434f5 ("ocfs2: take inode lock in ocfs2_iop_set/get_acl()")
Signed-off-by: Tariq Saeed &lt;tariq.x.saeed@oracle.com&gt;
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Cc: Joseph Qi &lt;joseph.qi@huawei.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ocfs2: dereferencing freed pointers in ocfs2_reflink()</title>
<updated>2016-05-18T02:25:26+00:00</updated>
<author>
<name>Dan Carpenter</name>
<email>dan.carpenter@oracle.com</email>
</author>
<published>2015-04-14T22:43:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=c0ce2224531ad6c19a62db19c0ec7575af1cfb10'/>
<id>c0ce2224531ad6c19a62db19c0ec7575af1cfb10</id>
<content type='text'>
[ Upstream commit e073fc58dfe6a4c9b614320c1d56bb71cb213ec4 ]

The code at the "out" label assumes that "default_acl" and "acl" are NULL,
but actually the pointers can be NULL, unitialized, or freed.

Signed-off-by: Dan Carpenter &lt;dan.carpenter@oracle.com&gt;
Reviewed-by: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit e073fc58dfe6a4c9b614320c1d56bb71cb213ec4 ]

The code at the "out" label assumes that "default_acl" and "acl" are NULL,
but actually the pointers can be NULL, unitialized, or freed.

Signed-off-by: Dan Carpenter &lt;dan.carpenter@oracle.com&gt;
Reviewed-by: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>ocfs2: fix SGID not inherited issue</title>
<updated>2016-05-18T02:23:18+00:00</updated>
<author>
<name>Junxiao Bi</name>
<email>junxiao.bi@oracle.com</email>
</author>
<published>2015-12-11T21:41:03+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=dd76ad6b17f4ef69e0522b625070c4efbcf8183c'/>
<id>dd76ad6b17f4ef69e0522b625070c4efbcf8183c</id>
<content type='text'>
[ Upstream commit 854ee2e944b4daf795e32562a7d2f9e90ab5a6a8 ]

Commit 8f1eb48758aa ("ocfs2: fix umask ignored issue") introduced an
issue, SGID of sub dir was not inherited from its parents dir.  It is
because SGID is set into "inode-&gt;i_mode" in ocfs2_get_init_inode(), but
is overwritten by "mode" which don't have SGID set later.

Fixes: 8f1eb48758aa ("ocfs2: fix umask ignored issue")
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Acked-by: Srinivas Eeda &lt;srinivas.eeda@oracle.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 854ee2e944b4daf795e32562a7d2f9e90ab5a6a8 ]

Commit 8f1eb48758aa ("ocfs2: fix umask ignored issue") introduced an
issue, SGID of sub dir was not inherited from its parents dir.  It is
because SGID is set into "inode-&gt;i_mode" in ocfs2_get_init_inode(), but
is overwritten by "mode" which don't have SGID set later.

Fixes: 8f1eb48758aa ("ocfs2: fix umask ignored issue")
Signed-off-by: Junxiao Bi &lt;junxiao.bi@oracle.com&gt;
Cc: Mark Fasheh &lt;mfasheh@suse.de&gt;
Cc: Joel Becker &lt;jlbec@evilplan.org&gt;
Acked-by: Srinivas Eeda &lt;srinivas.eeda@oracle.com&gt;
Cc: &lt;stable@vger.kernel.org&gt;
Signed-off-by: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>get_rock_ridge_filename(): handle malformed NM entries</title>
<updated>2016-05-18T01:48:14+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2016-05-05T20:25:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=b8500fc5acce9976a6de1c60daa09f40d148f11d'/>
<id>b8500fc5acce9976a6de1c60daa09f40d148f11d</id>
<content type='text'>
[ Upstream commit 99d825822eade8d827a1817357cbf3f889a552d6 ]

Payloads of NM entries are not supposed to contain NUL.  When we run
into such, only the part prior to the first NUL goes into the
concatenation (i.e. the directory entry name being encoded by a bunch
of NM entries).  We do stop when the amount collected so far + the
claimed amount in the current NM entry exceed 254.  So far, so good,
but what we return as the total length is the sum of *claimed*
sizes, not the actual amount collected.  And that can grow pretty
large - not unlimited, since you'd need to put CE entries in
between to be able to get more than the maximum that could be
contained in one isofs directory entry / continuation chunk and
we are stop once we'd encountered 32 CEs, but you can get about 8Kb
easily.  And that's what will be passed to readdir callback as the
name length.  8Kb __copy_to_user() from a buffer allocated by
__get_free_page()

Cc: stable@vger.kernel.org # 0.98pl6+ (yes, really)
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 99d825822eade8d827a1817357cbf3f889a552d6 ]

Payloads of NM entries are not supposed to contain NUL.  When we run
into such, only the part prior to the first NUL goes into the
concatenation (i.e. the directory entry name being encoded by a bunch
of NM entries).  We do stop when the amount collected so far + the
claimed amount in the current NM entry exceed 254.  So far, so good,
but what we return as the total length is the sum of *claimed*
sizes, not the actual amount collected.  And that can grow pretty
large - not unlimited, since you'd need to put CE entries in
between to be able to get more than the maximum that could be
contained in one isofs directory entry / continuation chunk and
we are stop once we'd encountered 32 CEs, but you can get about 8Kb
easily.  And that's what will be passed to readdir callback as the
name length.  8Kb __copy_to_user() from a buffer allocated by
__get_free_page()

Cc: stable@vger.kernel.org # 0.98pl6+ (yes, really)
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>propogate_mnt: Handle the first propogated copy being a slave</title>
<updated>2016-05-17T21:41:47+00:00</updated>
<author>
<name>Eric W. Biederman</name>
<email>ebiederm@xmission.com</email>
</author>
<published>2016-05-05T14:29:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=b688848a01ce5e9ce2a3d62af6e66b09dcd6f78d'/>
<id>b688848a01ce5e9ce2a3d62af6e66b09dcd6f78d</id>
<content type='text'>
[ Upstream commit 5ec0811d30378ae104f250bfc9b3640242d81e3f ]

When the first propgated copy was a slave the following oops would result:
&gt; BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
&gt; IP: [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt; PGD bacd4067 PUD bac66067 PMD 0
&gt; Oops: 0000 [#1] SMP
&gt; Modules linked in:
&gt; CPU: 1 PID: 824 Comm: mount Not tainted 4.6.0-rc5userns+ #1523
&gt; Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
&gt; task: ffff8800bb0a8000 ti: ffff8800bac3c000 task.ti: ffff8800bac3c000
&gt; RIP: 0010:[&lt;ffffffff811fba4e&gt;]  [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt; RSP: 0018:ffff8800bac3fd38  EFLAGS: 00010283
&gt; RAX: 0000000000000000 RBX: ffff8800bb77ec00 RCX: 0000000000000010
&gt; RDX: 0000000000000000 RSI: ffff8800bb58c000 RDI: ffff8800bb58c480
&gt; RBP: ffff8800bac3fd48 R08: 0000000000000001 R09: 0000000000000000
&gt; R10: 0000000000001ca1 R11: 0000000000001c9d R12: 0000000000000000
&gt; R13: ffff8800ba713800 R14: ffff8800bac3fda0 R15: ffff8800bb77ec00
&gt; FS:  00007f3c0cd9b7e0(0000) GS:ffff8800bfb00000(0000) knlGS:0000000000000000
&gt; CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
&gt; CR2: 0000000000000010 CR3: 00000000bb79d000 CR4: 00000000000006e0
&gt; Stack:
&gt;  ffff8800bb77ec00 0000000000000000 ffff8800bac3fd88 ffffffff811fbf85
&gt;  ffff8800bac3fd98 ffff8800bb77f080 ffff8800ba713800 ffff8800bb262b40
&gt;  0000000000000000 0000000000000000 ffff8800bac3fdd8 ffffffff811f1da0
&gt; Call Trace:
&gt;  [&lt;ffffffff811fbf85&gt;] propagate_mnt+0x105/0x140
&gt;  [&lt;ffffffff811f1da0&gt;] attach_recursive_mnt+0x120/0x1e0
&gt;  [&lt;ffffffff811f1ec3&gt;] graft_tree+0x63/0x70
&gt;  [&lt;ffffffff811f1f6b&gt;] do_add_mount+0x9b/0x100
&gt;  [&lt;ffffffff811f2c1a&gt;] do_mount+0x2aa/0xdf0
&gt;  [&lt;ffffffff8117efbe&gt;] ? strndup_user+0x4e/0x70
&gt;  [&lt;ffffffff811f3a45&gt;] SyS_mount+0x75/0xc0
&gt;  [&lt;ffffffff8100242b&gt;] do_syscall_64+0x4b/0xa0
&gt;  [&lt;ffffffff81988f3c&gt;] entry_SYSCALL64_slow_path+0x25/0x25
&gt; Code: 00 00 75 ec 48 89 0d 02 22 22 01 8b 89 10 01 00 00 48 89 05 fd 21 22 01 39 8e 10 01 00 00 0f 84 e0 00 00 00 48 8b 80 d8 00 00 00 &lt;48&gt; 8b 50 10 48 89 05 df 21 22 01 48 89 15 d0 21 22 01 8b 53 30
&gt; RIP  [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt;  RSP &lt;ffff8800bac3fd38&gt;
&gt; CR2: 0000000000000010
&gt; ---[ end trace 2725ecd95164f217 ]---

This oops happens with the namespace_sem held and can be triggered by
non-root users.  An all around not pleasant experience.

To avoid this scenario when finding the appropriate source mount to
copy stop the walk up the mnt_master chain when the first source mount
is encountered.

Further rewrite the walk up the last_source mnt_master chain so that
it is clear what is going on.

The reason why the first source mount is special is that it it's
mnt_parent is not a mount in the dest_mnt propagation tree, and as
such termination conditions based up on the dest_mnt mount propgation
tree do not make sense.

To avoid other kinds of confusion last_dest is not changed when
computing last_source.  last_dest is only used once in propagate_one
and that is above the point of the code being modified, so changing
the global variable is meaningless and confusing.

Cc: stable@vger.kernel.org
fixes: f2ebb3a921c1ca1e2ddd9242e95a1989a50c4c68 ("smarter propagate_mnt()")
Reported-by: Tycho Andersen &lt;tycho.andersen@canonical.com&gt;
Reviewed-by: Seth Forshee &lt;seth.forshee@canonical.com&gt;
Tested-by: Seth Forshee &lt;seth.forshee@canonical.com&gt;
Signed-off-by: "Eric W. Biederman" &lt;ebiederm@xmission.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 5ec0811d30378ae104f250bfc9b3640242d81e3f ]

When the first propgated copy was a slave the following oops would result:
&gt; BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
&gt; IP: [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt; PGD bacd4067 PUD bac66067 PMD 0
&gt; Oops: 0000 [#1] SMP
&gt; Modules linked in:
&gt; CPU: 1 PID: 824 Comm: mount Not tainted 4.6.0-rc5userns+ #1523
&gt; Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007
&gt; task: ffff8800bb0a8000 ti: ffff8800bac3c000 task.ti: ffff8800bac3c000
&gt; RIP: 0010:[&lt;ffffffff811fba4e&gt;]  [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt; RSP: 0018:ffff8800bac3fd38  EFLAGS: 00010283
&gt; RAX: 0000000000000000 RBX: ffff8800bb77ec00 RCX: 0000000000000010
&gt; RDX: 0000000000000000 RSI: ffff8800bb58c000 RDI: ffff8800bb58c480
&gt; RBP: ffff8800bac3fd48 R08: 0000000000000001 R09: 0000000000000000
&gt; R10: 0000000000001ca1 R11: 0000000000001c9d R12: 0000000000000000
&gt; R13: ffff8800ba713800 R14: ffff8800bac3fda0 R15: ffff8800bb77ec00
&gt; FS:  00007f3c0cd9b7e0(0000) GS:ffff8800bfb00000(0000) knlGS:0000000000000000
&gt; CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
&gt; CR2: 0000000000000010 CR3: 00000000bb79d000 CR4: 00000000000006e0
&gt; Stack:
&gt;  ffff8800bb77ec00 0000000000000000 ffff8800bac3fd88 ffffffff811fbf85
&gt;  ffff8800bac3fd98 ffff8800bb77f080 ffff8800ba713800 ffff8800bb262b40
&gt;  0000000000000000 0000000000000000 ffff8800bac3fdd8 ffffffff811f1da0
&gt; Call Trace:
&gt;  [&lt;ffffffff811fbf85&gt;] propagate_mnt+0x105/0x140
&gt;  [&lt;ffffffff811f1da0&gt;] attach_recursive_mnt+0x120/0x1e0
&gt;  [&lt;ffffffff811f1ec3&gt;] graft_tree+0x63/0x70
&gt;  [&lt;ffffffff811f1f6b&gt;] do_add_mount+0x9b/0x100
&gt;  [&lt;ffffffff811f2c1a&gt;] do_mount+0x2aa/0xdf0
&gt;  [&lt;ffffffff8117efbe&gt;] ? strndup_user+0x4e/0x70
&gt;  [&lt;ffffffff811f3a45&gt;] SyS_mount+0x75/0xc0
&gt;  [&lt;ffffffff8100242b&gt;] do_syscall_64+0x4b/0xa0
&gt;  [&lt;ffffffff81988f3c&gt;] entry_SYSCALL64_slow_path+0x25/0x25
&gt; Code: 00 00 75 ec 48 89 0d 02 22 22 01 8b 89 10 01 00 00 48 89 05 fd 21 22 01 39 8e 10 01 00 00 0f 84 e0 00 00 00 48 8b 80 d8 00 00 00 &lt;48&gt; 8b 50 10 48 89 05 df 21 22 01 48 89 15 d0 21 22 01 8b 53 30
&gt; RIP  [&lt;ffffffff811fba4e&gt;] propagate_one+0xbe/0x1c0
&gt;  RSP &lt;ffff8800bac3fd38&gt;
&gt; CR2: 0000000000000010
&gt; ---[ end trace 2725ecd95164f217 ]---

This oops happens with the namespace_sem held and can be triggered by
non-root users.  An all around not pleasant experience.

To avoid this scenario when finding the appropriate source mount to
copy stop the walk up the mnt_master chain when the first source mount
is encountered.

Further rewrite the walk up the last_source mnt_master chain so that
it is clear what is going on.

The reason why the first source mount is special is that it it's
mnt_parent is not a mount in the dest_mnt propagation tree, and as
such termination conditions based up on the dest_mnt mount propgation
tree do not make sense.

To avoid other kinds of confusion last_dest is not changed when
computing last_source.  last_dest is only used once in propagate_one
and that is above the point of the code being modified, so changing
the global variable is meaningless and confusing.

Cc: stable@vger.kernel.org
fixes: f2ebb3a921c1ca1e2ddd9242e95a1989a50c4c68 ("smarter propagate_mnt()")
Reported-by: Tycho Andersen &lt;tycho.andersen@canonical.com&gt;
Reviewed-by: Seth Forshee &lt;seth.forshee@canonical.com&gt;
Tested-by: Seth Forshee &lt;seth.forshee@canonical.com&gt;
Signed-off-by: "Eric W. Biederman" &lt;ebiederm@xmission.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>fs/pnode.c: treat zero mnt_group_id-s as unequal</title>
<updated>2016-05-17T21:41:38+00:00</updated>
<author>
<name>Maxim Patlasov</name>
<email>mpatlasov@virtuozzo.com</email>
</author>
<published>2016-02-16T19:45:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=66f0487aecd2515b550abc31ede08215cc3279e8'/>
<id>66f0487aecd2515b550abc31ede08215cc3279e8</id>
<content type='text'>
[ Upstream commit 7ae8fd0351f912b075149a1e03a017be8b903b9a ]

propagate_one(m) calculates "type" argument for copy_tree() like this:

&gt;    if (m-&gt;mnt_group_id == last_dest-&gt;mnt_group_id) {
&gt;        type = CL_MAKE_SHARED;
&gt;    } else {
&gt;        type = CL_SLAVE;
&gt;        if (IS_MNT_SHARED(m))
&gt;           type |= CL_MAKE_SHARED;
&gt;   }

The "type" argument then governs clone_mnt() behavior with respect to flags
and mnt_master of new mount. When we iterate through a slave group, it is
possible that both current "m" and "last_dest" are not shared (although,
both are slaves, i.e. have non-NULL mnt_master-s). Then the comparison
above erroneously makes new mount shared and sets its mnt_master to
last_source-&gt;mnt_master. The patch fixes the problem by handling zero
mnt_group_id-s as though they are unequal.

The similar problem exists in the implementation of "else" clause above
when we have to ascend upward in the master/slave tree by calling:

&gt;    last_source = last_source-&gt;mnt_master;
&gt;    last_dest = last_source-&gt;mnt_parent;

proper number of times. The last step is governed by
"n-&gt;mnt_group_id != last_dest-&gt;mnt_group_id" condition that may lie if
both are zero. The patch fixes this case in the same way as the former one.

[AV: don't open-code an obvious helper...]

Signed-off-by: Maxim Patlasov &lt;mpatlasov@virtuozzo.com&gt;
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 7ae8fd0351f912b075149a1e03a017be8b903b9a ]

propagate_one(m) calculates "type" argument for copy_tree() like this:

&gt;    if (m-&gt;mnt_group_id == last_dest-&gt;mnt_group_id) {
&gt;        type = CL_MAKE_SHARED;
&gt;    } else {
&gt;        type = CL_SLAVE;
&gt;        if (IS_MNT_SHARED(m))
&gt;           type |= CL_MAKE_SHARED;
&gt;   }

The "type" argument then governs clone_mnt() behavior with respect to flags
and mnt_master of new mount. When we iterate through a slave group, it is
possible that both current "m" and "last_dest" are not shared (although,
both are slaves, i.e. have non-NULL mnt_master-s). Then the comparison
above erroneously makes new mount shared and sets its mnt_master to
last_source-&gt;mnt_master. The patch fixes the problem by handling zero
mnt_group_id-s as though they are unequal.

The similar problem exists in the implementation of "else" clause above
when we have to ascend upward in the master/slave tree by calling:

&gt;    last_source = last_source-&gt;mnt_master;
&gt;    last_dest = last_source-&gt;mnt_parent;

proper number of times. The last step is governed by
"n-&gt;mnt_group_id != last_dest-&gt;mnt_group_id" condition that may lie if
both are zero. The patch fixes this case in the same way as the former one.

[AV: don't open-code an obvious helper...]

Signed-off-by: Maxim Patlasov &lt;mpatlasov@virtuozzo.com&gt;
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>atomic_open(): fix the handling of create_error</title>
<updated>2016-05-17T20:31:08+00:00</updated>
<author>
<name>Al Viro</name>
<email>viro@zeniv.linux.org.uk</email>
</author>
<published>2016-04-27T05:11:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=d6c198421db212898a96a3e34d7e526abca67a3a'/>
<id>d6c198421db212898a96a3e34d7e526abca67a3a</id>
<content type='text'>
[ Upstream commit 10c64cea04d3c75c306b3f990586ffb343b63287 ]

* if we have a hashed negative dentry and either CREAT|EXCL on
r/o filesystem, or CREAT|TRUNC on r/o filesystem, or CREAT|EXCL
with failing may_o_create(), we should fail with EROFS or the
error may_o_create() has returned, but not ENOENT.  Which is what
the current code ends up returning.

* if we have CREAT|TRUNC hitting a regular file on a read-only
filesystem, we can't fail with EROFS here.  At the very least,
not until we'd done follow_managed() - we might have a writable
file (or a device, for that matter) bound on top of that one.
Moreover, the code downstream will see that O_TRUNC and attempt
to grab the write access (*after* following possible mount), so
if we really should fail with EROFS, it will happen.  No need
to do that inside atomic_open().

The real logics is much simpler than what the current code is
trying to do - if we decided to go for simple lookup, ended
up with a negative dentry *and* had create_error set, fail with
create_error.  No matter whether we'd got that negative dentry
from lookup_real() or had found it in dcache.

Cc: stable@vger.kernel.org # v3.6+
Acked-by: Miklos Szeredi &lt;mszeredi@redhat.com&gt;
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 10c64cea04d3c75c306b3f990586ffb343b63287 ]

* if we have a hashed negative dentry and either CREAT|EXCL on
r/o filesystem, or CREAT|TRUNC on r/o filesystem, or CREAT|EXCL
with failing may_o_create(), we should fail with EROFS or the
error may_o_create() has returned, but not ENOENT.  Which is what
the current code ends up returning.

* if we have CREAT|TRUNC hitting a regular file on a read-only
filesystem, we can't fail with EROFS here.  At the very least,
not until we'd done follow_managed() - we might have a writable
file (or a device, for that matter) bound on top of that one.
Moreover, the code downstream will see that O_TRUNC and attempt
to grab the write access (*after* following possible mount), so
if we really should fail with EROFS, it will happen.  No need
to do that inside atomic_open().

The real logics is much simpler than what the current code is
trying to do - if we decided to go for simple lookup, ended
up with a negative dentry *and* had create_error set, fail with
create_error.  No matter whether we'd got that negative dentry
from lookup_real() or had found it in dcache.

Cc: stable@vger.kernel.org # v3.6+
Acked-by: Miklos Szeredi &lt;mszeredi@redhat.com&gt;
Signed-off-by: Al Viro &lt;viro@zeniv.linux.org.uk&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix list transaction-&gt;pending_ordered corruption</title>
<updated>2016-04-23T00:38:30+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-07-03T19:30:34+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=5d6226fe6abbaf576328d6cbc8c5473f32428d68'/>
<id>5d6226fe6abbaf576328d6cbc8c5473f32428d68</id>
<content type='text'>
[ Upstream commit d3efe08400317888f559bbedf0e42cd31575d0ef ]

When we call btrfs_commit_transaction(), we splice the list "ordered"
of our transaction handle into the transaction's "pending_ordered"
list, but we don't re-initialize the "ordered" list of our transaction
handle, this means it still points to the same elements it used to
before the splice. Then we check if the current transaction's state is
&gt;= TRANS_STATE_COMMIT_START and if it is we end up calling
btrfs_end_transaction() which simply splices again the "ordered" list
of our handle into the transaction's "pending_ordered" list, leaving
multiple pointers to the same ordered extents which results in list
corruption when we are iterating, removing and freeing ordered extents
at btrfs_wait_pending_ordered(), resulting in access to dangling
pointers / use-after-free issues.
Similarly, btrfs_end_transaction() can end up in some cases calling
btrfs_commit_transaction(), and both did a list splice of the transaction
handle's "ordered" list into the transaction's "pending_ordered" without
re-initializing the handle's "ordered" list, resulting in exactly the
same problem.

This produces the following warning on a kernel with linked list
debugging enabled:

[109749.265416] ------------[ cut here ]------------
[109749.266410] WARNING: CPU: 7 PID: 324 at lib/list_debug.c:59 __list_del_entry+0x5a/0x98()
[109749.267969] list_del corruption. prev-&gt;next should be ffff8800ba087e20, but was fffffff8c1f7c35d
(...)
[109749.287505] Call Trace:
[109749.288135]  [&lt;ffffffff8145f077&gt;] dump_stack+0x4f/0x7b
[109749.298080]  [&lt;ffffffff81095de5&gt;] ? console_unlock+0x356/0x3a2
[109749.331605]  [&lt;ffffffff8104b3b0&gt;] warn_slowpath_common+0xa1/0xbb
[109749.334849]  [&lt;ffffffff81260642&gt;] ? __list_del_entry+0x5a/0x98
[109749.337093]  [&lt;ffffffff8104b410&gt;] warn_slowpath_fmt+0x46/0x48
[109749.337847]  [&lt;ffffffff81260642&gt;] __list_del_entry+0x5a/0x98
[109749.338678]  [&lt;ffffffffa053e8bf&gt;] btrfs_wait_pending_ordered+0x46/0xdb [btrfs]
[109749.340145]  [&lt;ffffffffa058a65f&gt;] ? __btrfs_run_delayed_items+0x149/0x163 [btrfs]
[109749.348313]  [&lt;ffffffffa054077d&gt;] btrfs_commit_transaction+0x36b/0xa10 [btrfs]
[109749.349745]  [&lt;ffffffff81087310&gt;] ? trace_hardirqs_on+0xd/0xf
[109749.350819]  [&lt;ffffffffa055370d&gt;] btrfs_sync_file+0x36f/0x3fc [btrfs]
[109749.351976]  [&lt;ffffffff8118ec98&gt;] vfs_fsync_range+0x8f/0x9e
[109749.360341]  [&lt;ffffffff8118ecc3&gt;] vfs_fsync+0x1c/0x1e
[109749.368828]  [&lt;ffffffff8118ee1d&gt;] do_fsync+0x34/0x4e
[109749.369790]  [&lt;ffffffff8118f045&gt;] SyS_fsync+0x10/0x14
[109749.370925]  [&lt;ffffffff81465197&gt;] system_call_fastpath+0x12/0x6f
[109749.382274] ---[ end trace 48e0d07f7c03d95a ]---

On a non-debug kernel this leads to invalid memory accesses, causing a
crash. Fix this by using list_splice_init() instead of list_splice() in
btrfs_commit_transaction() and btrfs_end_transaction().

Cc: stable@vger.kernel.org
Fixes: 50d9aa99bd35 ("Btrfs: make sure logged extents complete in the current transaction V3"
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit d3efe08400317888f559bbedf0e42cd31575d0ef ]

When we call btrfs_commit_transaction(), we splice the list "ordered"
of our transaction handle into the transaction's "pending_ordered"
list, but we don't re-initialize the "ordered" list of our transaction
handle, this means it still points to the same elements it used to
before the splice. Then we check if the current transaction's state is
&gt;= TRANS_STATE_COMMIT_START and if it is we end up calling
btrfs_end_transaction() which simply splices again the "ordered" list
of our handle into the transaction's "pending_ordered" list, leaving
multiple pointers to the same ordered extents which results in list
corruption when we are iterating, removing and freeing ordered extents
at btrfs_wait_pending_ordered(), resulting in access to dangling
pointers / use-after-free issues.
Similarly, btrfs_end_transaction() can end up in some cases calling
btrfs_commit_transaction(), and both did a list splice of the transaction
handle's "ordered" list into the transaction's "pending_ordered" without
re-initializing the handle's "ordered" list, resulting in exactly the
same problem.

This produces the following warning on a kernel with linked list
debugging enabled:

[109749.265416] ------------[ cut here ]------------
[109749.266410] WARNING: CPU: 7 PID: 324 at lib/list_debug.c:59 __list_del_entry+0x5a/0x98()
[109749.267969] list_del corruption. prev-&gt;next should be ffff8800ba087e20, but was fffffff8c1f7c35d
(...)
[109749.287505] Call Trace:
[109749.288135]  [&lt;ffffffff8145f077&gt;] dump_stack+0x4f/0x7b
[109749.298080]  [&lt;ffffffff81095de5&gt;] ? console_unlock+0x356/0x3a2
[109749.331605]  [&lt;ffffffff8104b3b0&gt;] warn_slowpath_common+0xa1/0xbb
[109749.334849]  [&lt;ffffffff81260642&gt;] ? __list_del_entry+0x5a/0x98
[109749.337093]  [&lt;ffffffff8104b410&gt;] warn_slowpath_fmt+0x46/0x48
[109749.337847]  [&lt;ffffffff81260642&gt;] __list_del_entry+0x5a/0x98
[109749.338678]  [&lt;ffffffffa053e8bf&gt;] btrfs_wait_pending_ordered+0x46/0xdb [btrfs]
[109749.340145]  [&lt;ffffffffa058a65f&gt;] ? __btrfs_run_delayed_items+0x149/0x163 [btrfs]
[109749.348313]  [&lt;ffffffffa054077d&gt;] btrfs_commit_transaction+0x36b/0xa10 [btrfs]
[109749.349745]  [&lt;ffffffff81087310&gt;] ? trace_hardirqs_on+0xd/0xf
[109749.350819]  [&lt;ffffffffa055370d&gt;] btrfs_sync_file+0x36f/0x3fc [btrfs]
[109749.351976]  [&lt;ffffffff8118ec98&gt;] vfs_fsync_range+0x8f/0x9e
[109749.360341]  [&lt;ffffffff8118ecc3&gt;] vfs_fsync+0x1c/0x1e
[109749.368828]  [&lt;ffffffff8118ee1d&gt;] do_fsync+0x34/0x4e
[109749.369790]  [&lt;ffffffff8118f045&gt;] SyS_fsync+0x10/0x14
[109749.370925]  [&lt;ffffffff81465197&gt;] system_call_fastpath+0x12/0x6f
[109749.382274] ---[ end trace 48e0d07f7c03d95a ]---

On a non-debug kernel this leads to invalid memory accesses, causing a
crash. Fix this by using list_splice_init() instead of list_splice() in
btrfs_commit_transaction() and btrfs_end_transaction().

Cc: stable@vger.kernel.org
Fixes: 50d9aa99bd35 ("Btrfs: make sure logged extents complete in the current transaction V3"
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix file/data loss caused by fsync after rename and new inode</title>
<updated>2016-04-20T13:40:55+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2016-03-30T22:37:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=048605483fbdd1e77ead32a7cd7b95cc17eaaf0e'/>
<id>048605483fbdd1e77ead32a7cd7b95cc17eaaf0e</id>
<content type='text'>
[ Upstream commit 56f23fdbb600e6087db7b009775b95ce07cc3195 ]

If we rename an inode A (be it a file or a directory), create a new
inode B with the old name of inode A and under the same parent directory,
fsync inode B and then power fail, at log tree replay time we end up
removing inode A completely. If inode A is a directory then all its files
are gone too.

Example scenarios where this happens:
This is reproducible with the following steps, taken from a couple of
test cases written for fstests which are going to be submitted upstream
soon:

   # Scenario 1

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir -p /mnt/a/x
   echo "hello" &gt; /mnt/a/x/foo
   echo "world" &gt; /mnt/a/x/bar
   sync
   mv /mnt/a/x /mnt/a/y
   mkdir /mnt/a/x
   xfs_io -c fsync /mnt/a/x
   &lt;power failure happens&gt;

   The next time the fs is mounted, log tree replay happens and
   the directory "y" does not exist nor do the files "foo" and
   "bar" exist anywhere (neither in "y" nor in "x", nor the root
   nor anywhere).

   # Scenario 2

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir /mnt/a
   echo "hello" &gt; /mnt/a/foo
   sync
   mv /mnt/a/foo /mnt/a/bar
   echo "world" &gt; /mnt/a/foo
   xfs_io -c fsync /mnt/a/foo
   &lt;power failure happens&gt;

   The next time the fs is mounted, log tree replay happens and the
   file "bar" does not exists anymore. A file with the name "foo"
   exists and it matches the second file we created.

Another related problem that does not involve file/data loss is when a
new inode is created with the name of a deleted snapshot and we fsync it:

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir /mnt/testdir
   btrfs subvolume snapshot /mnt /mnt/testdir/snap
   btrfs subvolume delete /mnt/testdir/snap
   rmdir /mnt/testdir
   mkdir /mnt/testdir
   xfs_io -c fsync /mnt/testdir # or fsync some file inside /mnt/testdir
   &lt;power failure&gt;

   The next time the fs is mounted the log replay procedure fails because
   it attempts to delete the snapshot entry (which has dir item key type
   of BTRFS_ROOT_ITEM_KEY) as if it were a regular (non-root) entry,
   resulting in the following error that causes mount to fail:

   [52174.510532] BTRFS info (device dm-0): failed to delete reference to snap, inode 257 parent 257
   [52174.512570] ------------[ cut here ]------------
   [52174.513278] WARNING: CPU: 12 PID: 28024 at fs/btrfs/inode.c:3986 __btrfs_unlink_inode+0x178/0x351 [btrfs]()
   [52174.514681] BTRFS: Transaction aborted (error -2)
   [52174.515630] Modules linked in: btrfs dm_flakey dm_mod overlay crc32c_generic ppdev xor raid6_pq acpi_cpufreq parport_pc tpm_tis sg parport tpm evdev i2c_piix4 proc
   [52174.521568] CPU: 12 PID: 28024 Comm: mount Tainted: G        W       4.5.0-rc6-btrfs-next-27+ #1
   [52174.522805] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014
   [52174.524053]  0000000000000000 ffff8801df2a7710 ffffffff81264e93 ffff8801df2a7758
   [52174.524053]  0000000000000009 ffff8801df2a7748 ffffffff81051618 ffffffffa03591cd
   [52174.524053]  00000000fffffffe ffff88015e6e5000 ffff88016dbc3c88 ffff88016dbc3c88
   [52174.524053] Call Trace:
   [52174.524053]  [&lt;ffffffff81264e93&gt;] dump_stack+0x67/0x90
   [52174.524053]  [&lt;ffffffff81051618&gt;] warn_slowpath_common+0x99/0xb2
   [52174.524053]  [&lt;ffffffffa03591cd&gt;] ? __btrfs_unlink_inode+0x178/0x351 [btrfs]
   [52174.524053]  [&lt;ffffffff81051679&gt;] warn_slowpath_fmt+0x48/0x50
   [52174.524053]  [&lt;ffffffffa03591cd&gt;] __btrfs_unlink_inode+0x178/0x351 [btrfs]
   [52174.524053]  [&lt;ffffffff8118f5e9&gt;] ? iput+0xb0/0x284
   [52174.524053]  [&lt;ffffffffa0359fe8&gt;] btrfs_unlink_inode+0x1c/0x3d [btrfs]
   [52174.524053]  [&lt;ffffffffa038631e&gt;] check_item_in_log+0x1fe/0x29b [btrfs]
   [52174.524053]  [&lt;ffffffffa0386522&gt;] replay_dir_deletes+0x167/0x1cf [btrfs]
   [52174.524053]  [&lt;ffffffffa038739e&gt;] fixup_inode_link_count+0x289/0x2aa [btrfs]
   [52174.524053]  [&lt;ffffffffa038748a&gt;] fixup_inode_link_counts+0xcb/0x105 [btrfs]
   [52174.524053]  [&lt;ffffffffa038a5ec&gt;] btrfs_recover_log_trees+0x258/0x32c [btrfs]
   [52174.524053]  [&lt;ffffffffa03885b2&gt;] ? replay_one_extent+0x511/0x511 [btrfs]
   [52174.524053]  [&lt;ffffffffa034f288&gt;] open_ctree+0x1dd4/0x21b9 [btrfs]
   [52174.524053]  [&lt;ffffffffa032b753&gt;] btrfs_mount+0x97e/0xaed [btrfs]
   [52174.524053]  [&lt;ffffffff8108e1b7&gt;] ? trace_hardirqs_on+0xd/0xf
   [52174.524053]  [&lt;ffffffff8117bafa&gt;] mount_fs+0x67/0x131
   [52174.524053]  [&lt;ffffffff81193003&gt;] vfs_kern_mount+0x6c/0xde
   [52174.524053]  [&lt;ffffffffa032af81&gt;] btrfs_mount+0x1ac/0xaed [btrfs]
   [52174.524053]  [&lt;ffffffff8108e1b7&gt;] ? trace_hardirqs_on+0xd/0xf
   [52174.524053]  [&lt;ffffffff8108c262&gt;] ? lockdep_init_map+0xb9/0x1b3
   [52174.524053]  [&lt;ffffffff8117bafa&gt;] mount_fs+0x67/0x131
   [52174.524053]  [&lt;ffffffff81193003&gt;] vfs_kern_mount+0x6c/0xde
   [52174.524053]  [&lt;ffffffff8119590f&gt;] do_mount+0x8a6/0x9e8
   [52174.524053]  [&lt;ffffffff811358dd&gt;] ? strndup_user+0x3f/0x59
   [52174.524053]  [&lt;ffffffff81195c65&gt;] SyS_mount+0x77/0x9f
   [52174.524053]  [&lt;ffffffff814935d7&gt;] entry_SYSCALL_64_fastpath+0x12/0x6b
   [52174.561288] ---[ end trace 6b53049efb1a3ea6 ]---

Fix this by forcing a transaction commit when such cases happen.
This means we check in the commit root of the subvolume tree if there
was any other inode with the same reference when the inode we are
fsync'ing is a new inode (created in the current transaction).

Test cases for fstests, covering all the scenarios given above, were
submitted upstream for fstests:

  * fstests: generic test for fsync after renaming directory
    https://patchwork.kernel.org/patch/8694281/

  * fstests: generic test for fsync after renaming file
    https://patchwork.kernel.org/patch/8694301/

  * fstests: add btrfs test for fsync after snapshot deletion
    https://patchwork.kernel.org/patch/8670671/

Cc: stable@vger.kernel.org
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[ Upstream commit 56f23fdbb600e6087db7b009775b95ce07cc3195 ]

If we rename an inode A (be it a file or a directory), create a new
inode B with the old name of inode A and under the same parent directory,
fsync inode B and then power fail, at log tree replay time we end up
removing inode A completely. If inode A is a directory then all its files
are gone too.

Example scenarios where this happens:
This is reproducible with the following steps, taken from a couple of
test cases written for fstests which are going to be submitted upstream
soon:

   # Scenario 1

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir -p /mnt/a/x
   echo "hello" &gt; /mnt/a/x/foo
   echo "world" &gt; /mnt/a/x/bar
   sync
   mv /mnt/a/x /mnt/a/y
   mkdir /mnt/a/x
   xfs_io -c fsync /mnt/a/x
   &lt;power failure happens&gt;

   The next time the fs is mounted, log tree replay happens and
   the directory "y" does not exist nor do the files "foo" and
   "bar" exist anywhere (neither in "y" nor in "x", nor the root
   nor anywhere).

   # Scenario 2

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir /mnt/a
   echo "hello" &gt; /mnt/a/foo
   sync
   mv /mnt/a/foo /mnt/a/bar
   echo "world" &gt; /mnt/a/foo
   xfs_io -c fsync /mnt/a/foo
   &lt;power failure happens&gt;

   The next time the fs is mounted, log tree replay happens and the
   file "bar" does not exists anymore. A file with the name "foo"
   exists and it matches the second file we created.

Another related problem that does not involve file/data loss is when a
new inode is created with the name of a deleted snapshot and we fsync it:

   mkfs.btrfs -f /dev/sdc
   mount /dev/sdc /mnt
   mkdir /mnt/testdir
   btrfs subvolume snapshot /mnt /mnt/testdir/snap
   btrfs subvolume delete /mnt/testdir/snap
   rmdir /mnt/testdir
   mkdir /mnt/testdir
   xfs_io -c fsync /mnt/testdir # or fsync some file inside /mnt/testdir
   &lt;power failure&gt;

   The next time the fs is mounted the log replay procedure fails because
   it attempts to delete the snapshot entry (which has dir item key type
   of BTRFS_ROOT_ITEM_KEY) as if it were a regular (non-root) entry,
   resulting in the following error that causes mount to fail:

   [52174.510532] BTRFS info (device dm-0): failed to delete reference to snap, inode 257 parent 257
   [52174.512570] ------------[ cut here ]------------
   [52174.513278] WARNING: CPU: 12 PID: 28024 at fs/btrfs/inode.c:3986 __btrfs_unlink_inode+0x178/0x351 [btrfs]()
   [52174.514681] BTRFS: Transaction aborted (error -2)
   [52174.515630] Modules linked in: btrfs dm_flakey dm_mod overlay crc32c_generic ppdev xor raid6_pq acpi_cpufreq parport_pc tpm_tis sg parport tpm evdev i2c_piix4 proc
   [52174.521568] CPU: 12 PID: 28024 Comm: mount Tainted: G        W       4.5.0-rc6-btrfs-next-27+ #1
   [52174.522805] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014
   [52174.524053]  0000000000000000 ffff8801df2a7710 ffffffff81264e93 ffff8801df2a7758
   [52174.524053]  0000000000000009 ffff8801df2a7748 ffffffff81051618 ffffffffa03591cd
   [52174.524053]  00000000fffffffe ffff88015e6e5000 ffff88016dbc3c88 ffff88016dbc3c88
   [52174.524053] Call Trace:
   [52174.524053]  [&lt;ffffffff81264e93&gt;] dump_stack+0x67/0x90
   [52174.524053]  [&lt;ffffffff81051618&gt;] warn_slowpath_common+0x99/0xb2
   [52174.524053]  [&lt;ffffffffa03591cd&gt;] ? __btrfs_unlink_inode+0x178/0x351 [btrfs]
   [52174.524053]  [&lt;ffffffff81051679&gt;] warn_slowpath_fmt+0x48/0x50
   [52174.524053]  [&lt;ffffffffa03591cd&gt;] __btrfs_unlink_inode+0x178/0x351 [btrfs]
   [52174.524053]  [&lt;ffffffff8118f5e9&gt;] ? iput+0xb0/0x284
   [52174.524053]  [&lt;ffffffffa0359fe8&gt;] btrfs_unlink_inode+0x1c/0x3d [btrfs]
   [52174.524053]  [&lt;ffffffffa038631e&gt;] check_item_in_log+0x1fe/0x29b [btrfs]
   [52174.524053]  [&lt;ffffffffa0386522&gt;] replay_dir_deletes+0x167/0x1cf [btrfs]
   [52174.524053]  [&lt;ffffffffa038739e&gt;] fixup_inode_link_count+0x289/0x2aa [btrfs]
   [52174.524053]  [&lt;ffffffffa038748a&gt;] fixup_inode_link_counts+0xcb/0x105 [btrfs]
   [52174.524053]  [&lt;ffffffffa038a5ec&gt;] btrfs_recover_log_trees+0x258/0x32c [btrfs]
   [52174.524053]  [&lt;ffffffffa03885b2&gt;] ? replay_one_extent+0x511/0x511 [btrfs]
   [52174.524053]  [&lt;ffffffffa034f288&gt;] open_ctree+0x1dd4/0x21b9 [btrfs]
   [52174.524053]  [&lt;ffffffffa032b753&gt;] btrfs_mount+0x97e/0xaed [btrfs]
   [52174.524053]  [&lt;ffffffff8108e1b7&gt;] ? trace_hardirqs_on+0xd/0xf
   [52174.524053]  [&lt;ffffffff8117bafa&gt;] mount_fs+0x67/0x131
   [52174.524053]  [&lt;ffffffff81193003&gt;] vfs_kern_mount+0x6c/0xde
   [52174.524053]  [&lt;ffffffffa032af81&gt;] btrfs_mount+0x1ac/0xaed [btrfs]
   [52174.524053]  [&lt;ffffffff8108e1b7&gt;] ? trace_hardirqs_on+0xd/0xf
   [52174.524053]  [&lt;ffffffff8108c262&gt;] ? lockdep_init_map+0xb9/0x1b3
   [52174.524053]  [&lt;ffffffff8117bafa&gt;] mount_fs+0x67/0x131
   [52174.524053]  [&lt;ffffffff81193003&gt;] vfs_kern_mount+0x6c/0xde
   [52174.524053]  [&lt;ffffffff8119590f&gt;] do_mount+0x8a6/0x9e8
   [52174.524053]  [&lt;ffffffff811358dd&gt;] ? strndup_user+0x3f/0x59
   [52174.524053]  [&lt;ffffffff81195c65&gt;] SyS_mount+0x77/0x9f
   [52174.524053]  [&lt;ffffffff814935d7&gt;] entry_SYSCALL_64_fastpath+0x12/0x6b
   [52174.561288] ---[ end trace 6b53049efb1a3ea6 ]---

Fix this by forcing a transaction commit when such cases happen.
This means we check in the commit root of the subvolume tree if there
was any other inode with the same reference when the inode we are
fsync'ing is a new inode (created in the current transaction).

Test cases for fstests, covering all the scenarios given above, were
submitted upstream for fstests:

  * fstests: generic test for fsync after renaming directory
    https://patchwork.kernel.org/patch/8694281/

  * fstests: generic test for fsync after renaming file
    https://patchwork.kernel.org/patch/8694301/

  * fstests: add btrfs test for fsync after snapshot deletion
    https://patchwork.kernel.org/patch/8670671/

Cc: stable@vger.kernel.org
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
Signed-off-by: Sasha Levin &lt;sasha.levin@oracle.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
