Home Home > GIT Browse > openSUSE-15.1
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Tesarik <ptesarik@suse.cz>2019-05-16 08:52:12 +0200
committerPetr Tesarik <ptesarik@suse.cz>2019-05-16 08:52:12 +0200
commite0071c0721d159e65b5797e47becffb79445c8ab (patch)
tree02d6d3f5cd2d2d3ac956a8e5b6b9af95a987b51f
parentebb85b1bae224db837fa80b5da8a68dd1e7aedeb (diff)
parent74ce2cea0a4a2538826753adceca5c66feda9bac (diff)
Merge branch 'users/lhenriques/SLE15-SP1-UPDATE/for-next' into SLE15-SP1-UPDATE
Pull ceph fixes from Luis Henriques
-rw-r--r--patches.fixes/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch42
-rw-r--r--patches.fixes/ceph-fix-ci-i_head_snapc-leak.patch56
-rw-r--r--patches.fixes/ceph-fix-use-after-free-on-symlink-traversal.patch38
-rw-r--r--patches.fixes/ceph-only-use-d_name-directly-when-parent-is-locked.patch163
-rw-r--r--series.conf4
5 files changed, 303 insertions, 0 deletions
diff --git a/patches.fixes/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch b/patches.fixes/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch
new file mode 100644
index 0000000000..2d0b2b3956
--- /dev/null
+++ b/patches.fixes/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch
@@ -0,0 +1,42 @@
+From: Jeff Layton <jlayton@kernel.org>
+Date: Wed, 17 Apr 2019 12:58:28 -0400
+Subject: ceph: ensure d_name stability in ceph_dentry_hash()
+Git-commit: 76a495d666e5043ffc315695f8241f5e94a98849
+Patch-mainline: v5.1-rc7
+References: bsc#1134461
+
+Take the d_lock here to ensure that d_name doesn't change.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Acked-by: Luis Henriques <lhenriques@suse.com>
+---
+ fs/ceph/dir.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/ceph/dir.c
++++ b/fs/ceph/dir.c
+@@ -1466,6 +1466,7 @@ void ceph_dentry_lru_del(struct dentry *
+ unsigned ceph_dentry_hash(struct inode *dir, struct dentry *dn)
+ {
+ struct ceph_inode_info *dci = ceph_inode(dir);
++ unsigned hash;
+
+ switch (dci->i_dir_layout.dl_dir_hash) {
+ case 0: /* for backward compat */
+@@ -1473,8 +1474,11 @@ unsigned ceph_dentry_hash(struct inode *
+ return dn->d_name.hash;
+
+ default:
+- return ceph_str_hash(dci->i_dir_layout.dl_dir_hash,
++ spin_lock(&dn->d_lock);
++ hash = ceph_str_hash(dci->i_dir_layout.dl_dir_hash,
+ dn->d_name.name, dn->d_name.len);
++ spin_unlock(&dn->d_lock);
++ return hash;
+ }
+ }
+
+
diff --git a/patches.fixes/ceph-fix-ci-i_head_snapc-leak.patch b/patches.fixes/ceph-fix-ci-i_head_snapc-leak.patch
new file mode 100644
index 0000000000..00e3b4cca6
--- /dev/null
+++ b/patches.fixes/ceph-fix-ci-i_head_snapc-leak.patch
@@ -0,0 +1,56 @@
+From: "Yan, Zheng" <zyan@redhat.com>
+Date: Thu, 18 Apr 2019 11:24:57 +0800
+Subject: ceph: fix ci->i_head_snapc leak
+Git-commit: 37659182bff1eeaaeadcfc8f853c6d2b6dbc3f47
+Patch-mainline: v5.1-rc7
+References: bsc#1122776
+
+We missed two places that i_wrbuffer_ref_head, i_wr_ref, i_dirty_caps
+and i_flushing_caps may change. When they are all zeros, we should free
+i_head_snapc.
+
+Cc: stable@vger.kernel.org
+Link: https://tracker.ceph.com/issues/38224
+Reported-and-tested-by: Luis Henriques <lhenriques@suse.com>
+Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Acked-by: Luis Henriques <lhenriques@suse.com>
+---
+ fs/ceph/mds_client.c | 9 +++++++++
+ fs/ceph/snap.c | 7 ++++++-
+ 2 files changed, 15 insertions(+), 1 deletion(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -1259,6 +1259,15 @@ static int remove_session_caps_cb(struct
+ list_add(&ci->i_prealloc_cap_flush->i_list, &to_remove);
+ ci->i_prealloc_cap_flush = NULL;
+ }
++
++ if (drop &&
++ ci->i_wrbuffer_ref_head == 0 &&
++ ci->i_wr_ref == 0 &&
++ ci->i_dirty_caps == 0 &&
++ ci->i_flushing_caps == 0) {
++ ceph_put_snap_context(ci->i_head_snapc);
++ ci->i_head_snapc = NULL;
++ }
+ }
+ spin_unlock(&ci->i_ceph_lock);
+ while (!list_empty(&to_remove)) {
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -567,7 +567,12 @@ void ceph_queue_cap_snap(struct ceph_ino
+ old_snapc = NULL;
+
+ update_snapc:
+- if (ci->i_head_snapc) {
++ if (ci->i_wrbuffer_ref_head == 0 &&
++ ci->i_wr_ref == 0 &&
++ ci->i_dirty_caps == 0 &&
++ ci->i_flushing_caps == 0) {
++ ci->i_head_snapc = NULL;
++ } else {
+ ci->i_head_snapc = ceph_get_snap_context(new_snapc);
+ dout(" new snapc is %p\n", new_snapc);
+ }
diff --git a/patches.fixes/ceph-fix-use-after-free-on-symlink-traversal.patch b/patches.fixes/ceph-fix-use-after-free-on-symlink-traversal.patch
new file mode 100644
index 0000000000..5741476ec1
--- /dev/null
+++ b/patches.fixes/ceph-fix-use-after-free-on-symlink-traversal.patch
@@ -0,0 +1,38 @@
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 26 Mar 2019 01:38:58 +0000
+Subject: ceph: fix use-after-free on symlink traversal
+Git-commit: daf5cc27eed99afdea8d96e71b89ba41f5406ef6
+Patch-mainline: v5.1-rc3
+References: bsc#1134459
+
+free the symlink body after the same RCU delay we have for freeing the
+struct inode itself, so that traversal during RCU pathwalk wouldn't step
+into freed memory.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Acked-by: Luis Henriques <lhenriques@suse.com>
+---
+ fs/ceph/inode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ceph/inode.c
++++ b/fs/ceph/inode.c
+@@ -523,6 +523,7 @@ static void ceph_i_callback(struct rcu_h
+ struct inode *inode = container_of(head, struct inode, i_rcu);
+ struct ceph_inode_info *ci = ceph_inode(inode);
+
++ kfree(ci->i_symlink);
+ kmem_cache_free(ceph_inode_cachep, ci);
+ }
+
+@@ -560,7 +561,6 @@ void ceph_destroy_inode(struct inode *in
+ ceph_put_snap_realm(mdsc, realm);
+ }
+
+- kfree(ci->i_symlink);
+ while ((n = rb_first(&ci->i_fragtree)) != NULL) {
+ frag = rb_entry(n, struct ceph_inode_frag, node);
+ rb_erase(n, &ci->i_fragtree);
+
diff --git a/patches.fixes/ceph-only-use-d_name-directly-when-parent-is-locked.patch b/patches.fixes/ceph-only-use-d_name-directly-when-parent-is-locked.patch
new file mode 100644
index 0000000000..3e5ee57a77
--- /dev/null
+++ b/patches.fixes/ceph-only-use-d_name-directly-when-parent-is-locked.patch
@@ -0,0 +1,163 @@
+From: Jeff Layton <jlayton@kernel.org>
+Date: Mon, 15 Apr 2019 12:00:42 -0400
+Subject: ceph: only use d_name directly when parent is locked
+Git-commit: 1bcb344086f3ecf8d6705f6d708441baa823beb3
+Patch-mainline: v5.1-rc7
+References: bsc#1134460
+
+Ben reported tripping the BUG_ON in create_request_message during some
+performance testing. Analysis of the vmcore showed that the length of
+the r_dentry->d_name string changed after we allocated the buffer, but
+before we encoded it.
+
+build_dentry_path returns pointers to d_name in the common case of
+non-snapped dentries, but this optimization isn't safe unless the parent
+directory is locked. When it isn't, have the code make a copy of the
+d_name while holding the d_lock.
+
+Cc: stable@vger.kernel.org
+Reported-by: Ben England <bengland@redhat.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Acked-by: Luis Henriques <lhenriques@suse.com>
+---
+ fs/ceph/mds_client.c | 61 +++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 50 insertions(+), 11 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -1912,10 +1912,39 @@ retry:
+ return path;
+ }
+
++/* Duplicate the dentry->d_name.name safely */
++static int clone_dentry_name(struct dentry *dentry, const char **ppath,
++ int *ppathlen)
++{
++ u32 len;
++ char *name;
++
++retry:
++ len = READ_ONCE(dentry->d_name.len);
++ name = kmalloc(len + 1, GFP_NOFS);
++ if (!name)
++ return -ENOMEM;
++
++ spin_lock(&dentry->d_lock);
++ if (dentry->d_name.len != len) {
++ spin_unlock(&dentry->d_lock);
++ kfree(name);
++ goto retry;
++ }
++ memcpy(name, dentry->d_name.name, len);
++ spin_unlock(&dentry->d_lock);
++
++ name[len] = '\0';
++ *ppath = name;
++ *ppathlen = len;
++ return 0;
++}
++
+ static int build_dentry_path(struct dentry *dentry, struct inode *dir,
+ const char **ppath, int *ppathlen, u64 *pino,
+- int *pfreepath)
++ bool *pfreepath, bool parent_locked)
+ {
++ int ret;
+ char *path;
+
+ rcu_read_lock();
+@@ -1924,8 +1953,15 @@ static int build_dentry_path(struct dent
+ if (dir && ceph_snap(dir) == CEPH_NOSNAP) {
+ *pino = ceph_ino(dir);
+ rcu_read_unlock();
+- *ppath = dentry->d_name.name;
+- *ppathlen = dentry->d_name.len;
++ if (parent_locked) {
++ *ppath = dentry->d_name.name;
++ *ppathlen = dentry->d_name.len;
++ } else {
++ ret = clone_dentry_name(dentry, ppath, ppathlen);
++ if (ret)
++ return ret;
++ *pfreepath = true;
++ }
+ return 0;
+ }
+ rcu_read_unlock();
+@@ -1933,13 +1969,13 @@ static int build_dentry_path(struct dent
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ *ppath = path;
+- *pfreepath = 1;
++ *pfreepath = true;
+ return 0;
+ }
+
+ static int build_inode_path(struct inode *inode,
+ const char **ppath, int *ppathlen, u64 *pino,
+- int *pfreepath)
++ bool *pfreepath)
+ {
+ struct dentry *dentry;
+ char *path;
+@@ -1955,7 +1991,7 @@ static int build_inode_path(struct inode
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ *ppath = path;
+- *pfreepath = 1;
++ *pfreepath = true;
+ return 0;
+ }
+
+@@ -1966,7 +2002,7 @@ static int build_inode_path(struct inode
+ static int set_request_path_attr(struct inode *rinode, struct dentry *rdentry,
+ struct inode *rdiri, const char *rpath,
+ u64 rino, const char **ppath, int *pathlen,
+- u64 *ino, int *freepath)
++ u64 *ino, bool *freepath, bool parent_locked)
+ {
+ int r = 0;
+
+@@ -1976,7 +2012,7 @@ static int set_request_path_attr(struct
+ ceph_snap(rinode));
+ } else if (rdentry) {
+ r = build_dentry_path(rdentry, rdiri, ppath, pathlen, ino,
+- freepath);
++ freepath, parent_locked);
+ dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen,
+ *ppath);
+ } else if (rpath || rino) {
+@@ -2002,7 +2038,7 @@ static struct ceph_msg *create_request_m
+ const char *path2 = NULL;
+ u64 ino1 = 0, ino2 = 0;
+ int pathlen1 = 0, pathlen2 = 0;
+- int freepath1 = 0, freepath2 = 0;
++ bool freepath1 = false, freepath2 = false;
+ int len;
+ u16 releases;
+ void *p, *end;
+@@ -2010,16 +2046,19 @@ static struct ceph_msg *create_request_m
+
+ ret = set_request_path_attr(req->r_inode, req->r_dentry,
+ req->r_parent, req->r_path1, req->r_ino1.ino,
+- &path1, &pathlen1, &ino1, &freepath1);
++ &path1, &pathlen1, &ino1, &freepath1,
++ test_bit(CEPH_MDS_R_PARENT_LOCKED,
++ &req->r_req_flags));
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out;
+ }
+
++ /* If r_old_dentry is set, then assume that its parent is locked */
+ ret = set_request_path_attr(NULL, req->r_old_dentry,
+ req->r_old_dentry_dir,
+ req->r_path2, req->r_ino2.ino,
+- &path2, &pathlen2, &ino2, &freepath2);
++ &path2, &pathlen2, &ino2, &freepath2, true);
+ if (ret < 0) {
+ msg = ERR_PTR(ret);
+ goto out_free1;
+
diff --git a/series.conf b/series.conf
index a64ca9105e..1689e81d55 100644
--- a/series.conf
+++ b/series.conf
@@ -45437,6 +45437,7 @@
patches.drm/0001-drm-i915-gvt-Don-t-submit-request-for-error-workload.patch
patches.drm/drm-i915-selftests-Fix-an-IS_ERR-vs-NULL-check.patch
patches.drm/drm-i915-icl-Fix-VEBOX-mismatch-BUG_ON.patch
+ patches.fixes/ceph-fix-use-after-free-on-symlink-traversal.patch
patches.drivers/libata-fix-using-DMA-buffers-on-stack.patch
patches.fixes/nvmet-fix-building-bvec-from-sg-list.patch
patches.arch/kbuild-strip-whitespace-in-cmd_record_mcount-findstr.patch
@@ -45596,6 +45597,9 @@
patches.drivers/ALSA-info-Fix-racy-addition-deletion-of-nodes.patch
patches.drivers/ALSA-core-Fix-card-races-between-register-and-discon.patch
patches.drivers/ALSA-hda-realtek-add-two-more-pin-configuration-sets.patch
+ patches.fixes/ceph-only-use-d_name-directly-when-parent-is-locked.patch
+ patches.fixes/ceph-ensure-d_name-stability-in-ceph_dentry_hash.patch
+ patches.fixes/ceph-fix-ci-i_head_snapc-leak.patch
patches.drm/0001-drm-bridge-dw-hdmi-Fix-overflow-workaround-for-Rockc.patch
patches.drm/0002-drm-sun4i-Add-missing-drm_atomic_helper_shutdown-at-.patch
patches.drm/0003-drm-sun4i-Set-device-driver-data-at-bind-time-for-us.patch