Home Home > GIT Browse > SLE12-SP5-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Henriques <lhenriques@suse.com>2019-08-27 11:51:08 +0100
committerLuis Henriques <lhenriques@suse.com>2019-09-05 10:08:47 +0100
commit0277eb4e40f0e4a9e0f60d977e7aedf577fc3c95 (patch)
treef6d5da21e709e7e23db5a358f415e2527e116a71
parent8543f4877d019ec90c1a185083dcbfc02a1a6264 (diff)
ceph: fix buffer free while holding i_ceph_lock in
__ceph_setxattr() (bsc#1148133).
-rw-r--r--patches.suse/ceph-fix-buffer-free-while-holding-i_ceph_lock-in-_ceph_setxattr.patch88
-rw-r--r--series.conf1
2 files changed, 89 insertions, 0 deletions
diff --git a/patches.suse/ceph-fix-buffer-free-while-holding-i_ceph_lock-in-_ceph_setxattr.patch b/patches.suse/ceph-fix-buffer-free-while-holding-i_ceph_lock-in-_ceph_setxattr.patch
new file mode 100644
index 0000000000..ce9b3ed848
--- /dev/null
+++ b/patches.suse/ceph-fix-buffer-free-while-holding-i_ceph_lock-in-_ceph_setxattr.patch
@@ -0,0 +1,88 @@
+From: Luis Henriques <lhenriques@suse.com>
+Date: Fri, 19 Jul 2019 15:32:20 +0100
+Subject: ceph: fix buffer free while holding i_ceph_lock in __ceph_setxattr()
+Git-commit: 86968ef21596515958d5f0a40233d02be78ecec0
+Patch-mainline: v5.3-rc6
+References: bsc#1148133
+
+Calling ceph_buffer_put() in __ceph_setxattr() may end up freeing the
+i_xattrs.prealloc_blob buffer while holding the i_ceph_lock. This can be
+fixed by postponing the call until later, when the lock is released.
+
+The following backtrace was triggered by fstests generic/117.
+
+ BUG: sleeping function called from invalid context at mm/vmalloc.c:2283
+ in_atomic(): 1, irqs_disabled(): 0, pid: 650, name: fsstress
+ 3 locks held by fsstress/650:
+ #0: 00000000870a0fe8 (sb_writers#8){.+.+}, at: mnt_want_write+0x20/0x50
+ #1: 00000000ba0c4c74 (&type->i_mutex_dir_key#6){++++}, at: vfs_setxattr+0x55/0xa0
+ #2: 000000008dfbb3f2 (&(&ci->i_ceph_lock)->rlock){+.+.}, at: __ceph_setxattr+0x297/0x810
+ CPU: 1 PID: 650 Comm: fsstress Not tainted 5.2.0+ #437
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58-prebuilt.qemu.org 04/01/2014
+ Call Trace:
+ dump_stack+0x67/0x90
+ ___might_sleep.cold+0x9f/0xb1
+ vfree+0x4b/0x60
+ ceph_buffer_release+0x1b/0x60
+ __ceph_setxattr+0x2b4/0x810
+ __vfs_setxattr+0x66/0x80
+ __vfs_setxattr_noperm+0x59/0xf0
+ vfs_setxattr+0x81/0xa0
+ setxattr+0x115/0x230
+ ? filename_lookup+0xc9/0x140
+ ? rcu_read_lock_sched_held+0x74/0x80
+ ? rcu_sync_lockdep_assert+0x2e/0x60
+ ? __sb_start_write+0x142/0x1a0
+ ? mnt_want_write+0x20/0x50
+ path_setxattr+0xba/0xd0
+ __x64_sys_lsetxattr+0x24/0x30
+ do_syscall_64+0x50/0x1c0
+ entry_SYSCALL_64_after_hwframe+0x49/0xbe
+ RIP: 0033:0x7ff23514359a
+
+Signed-off-by: Luis Henriques <lhenriques@suse.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+---
+ fs/ceph/xattr.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
+index 37b458a9af3a..c083557b3657 100644
+--- a/fs/ceph/xattr.c
++++ b/fs/ceph/xattr.c
+@@ -1036,6 +1036,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
+ struct ceph_inode_info *ci = ceph_inode(inode);
+ struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_cap_flush *prealloc_cf = NULL;
++ struct ceph_buffer *old_blob = NULL;
+ int issued;
+ int err;
+ int dirty = 0;
+@@ -1109,13 +1110,15 @@ int __ceph_setxattr(struct inode *inode, const char *name,
+ struct ceph_buffer *blob;
+
+ spin_unlock(&ci->i_ceph_lock);
+- dout(" preaallocating new blob size=%d\n", required_blob_size);
++ ceph_buffer_put(old_blob); /* Shouldn't be required */
++ dout(" pre-allocating new blob size=%d\n", required_blob_size);
+ blob = ceph_buffer_new(required_blob_size, GFP_NOFS);
+ if (!blob)
+ goto do_sync_unlocked;
+ spin_lock(&ci->i_ceph_lock);
++ /* prealloc_blob can't be released while holding i_ceph_lock */
+ if (ci->i_xattrs.prealloc_blob)
+- ceph_buffer_put(ci->i_xattrs.prealloc_blob);
++ old_blob = ci->i_xattrs.prealloc_blob;
+ ci->i_xattrs.prealloc_blob = blob;
+ goto retry;
+ }
+@@ -1131,6 +1134,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
+ }
+
+ spin_unlock(&ci->i_ceph_lock);
++ ceph_buffer_put(old_blob);
+ if (lock_snap_rwsem)
+ up_read(&mdsc->snap_rwsem);
+ if (dirty)
+
diff --git a/series.conf b/series.conf
index a0a7d57b80..7da3c785a6 100644
--- a/series.conf
+++ b/series.conf
@@ -24127,6 +24127,7 @@
patches.suse/drm-mediatek-use-correct-device-to-import-PRIME-buff.patch
patches.suse/drm-mediatek-mtk_drm_drv.c-Add-of_node_put-before-go.patch
patches.suse/libceph-allow-ceph_buffer_put-to-receive-a-null-ceph_buffer.patch
+ patches.suse/ceph-fix-buffer-free-while-holding-i_ceph_lock-in-_ceph_setxattr.patch
patches.suse/vfs-fix-page-locking-deadlocks-when-deduping-files.patch
patches.suse/fs-xfs-Fix-return-code-of-xfs_break_leased_layouts.patch
patches.suse/Revert-dm-bufio-fix-deadlock-with-loop-device.patch