]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Sun, 23 Jun 2019 02:02:50 +0000 (22:02 -0400)
committerSasha Levin <sashal@kernel.org>
Sun, 23 Jun 2019 02:02:50 +0000 (22:02 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/ovl-detect-overlapping-layers.patch [new file with mode: 0644]
queue-4.19/ovl-don-t-fail-with-disconnected-lower-nfs.patch [new file with mode: 0644]
queue-4.19/ovl-fix-bogus-wmaybe-unitialized-warning.patch [new file with mode: 0644]
queue-4.19/ovl-fix-wrong-flags-check-in-fs_ioc_fs-sg-etxattr-io.patch [new file with mode: 0644]
queue-4.19/ovl-make-i_ino-consistent-with-st_ino-in-more-cases.patch [new file with mode: 0644]
queue-4.19/ovl-support-the-fs_ioc_fs-sg-etxattr-ioctls.patch [new file with mode: 0644]
queue-4.19/s390-ap-rework-assembler-functions-to-use-unions-for.patch [new file with mode: 0644]
queue-4.19/s390-jump_label-use-jdd-constraint-on-gcc9.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/ovl-detect-overlapping-layers.patch b/queue-4.19/ovl-detect-overlapping-layers.patch
new file mode 100644 (file)
index 0000000..bbefa14
--- /dev/null
@@ -0,0 +1,573 @@
+From 0102ec399b0008a2bad0238c0bafd0ca06e55e0a Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Thu, 18 Apr 2019 17:42:08 +0300
+Subject: ovl: detect overlapping layers
+
+[ Upstream commit 146d62e5a5867fbf84490d82455718bfb10fe824 ]
+
+Overlapping overlay layers are not supported and can cause unexpected
+behavior, but overlayfs does not currently check or warn about these
+configurations.
+
+User is not supposed to specify the same directory for upper and
+lower dirs or for different lower layers and user is not supposed to
+specify directories that are descendants of each other for overlay
+layers, but that is exactly what this zysbot repro did:
+
+    https://syzkaller.appspot.com/x/repro.syz?x=12c7a94f400000
+
+Moving layer root directories into other layers while overlayfs
+is mounted could also result in unexpected behavior.
+
+This commit places "traps" in the overlay inode hash table.
+Those traps are dummy overlay inodes that are hashed by the layers
+root inodes.
+
+On mount, the hash table trap entries are used to verify that overlay
+layers are not overlapping.  While at it, we also verify that overlay
+layers are not overlapping with directories "in-use" by other overlay
+instances as upperdir/workdir.
+
+On lookup, the trap entries are used to verify that overlay layers
+root inodes have not been moved into other layers after mount.
+
+Some examples:
+
+$ ./run --ov --samefs -s
+...
+( mkdir -p base/upper/0/u base/upper/0/w base/lower lower upper mnt
+  mount -o bind base/lower lower
+  mount -o bind base/upper upper
+  mount -t overlay none mnt ...
+        -o lowerdir=lower,upperdir=upper/0/u,workdir=upper/0/w)
+
+$ umount mnt
+$ mount -t overlay none mnt ...
+        -o lowerdir=base,upperdir=upper/0/u,workdir=upper/0/w
+
+  [   94.434900] overlayfs: overlapping upperdir path
+  mount: mount overlay on mnt failed: Too many levels of symbolic links
+
+$ mount -t overlay none mnt ...
+        -o lowerdir=upper/0/u,upperdir=upper/0/u,workdir=upper/0/w
+
+  [  151.350132] overlayfs: conflicting lowerdir path
+  mount: none is already mounted or mnt busy
+
+$ mount -t overlay none mnt ...
+        -o lowerdir=lower:lower/a,upperdir=upper/0/u,workdir=upper/0/w
+
+  [  201.205045] overlayfs: overlapping lowerdir path
+  mount: mount overlay on mnt failed: Too many levels of symbolic links
+
+$ mount -t overlay none mnt ...
+        -o lowerdir=lower,upperdir=upper/0/u,workdir=upper/0/w
+$ mv base/upper/0/ base/lower/
+$ find mnt/0
+  mnt/0
+  mnt/0/w
+  find: 'mnt/0/w/work': Too many levels of symbolic links
+  find: 'mnt/0/u': Too many levels of symbolic links
+
+Reported-by: syzbot+9c69c282adc4edd2b540@syzkaller.appspotmail.com
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/inode.c     |  48 +++++++++++
+ fs/overlayfs/namei.c     |   8 ++
+ fs/overlayfs/overlayfs.h |   3 +
+ fs/overlayfs/ovl_entry.h |   6 ++
+ fs/overlayfs/super.c     | 169 +++++++++++++++++++++++++++++++++++----
+ fs/overlayfs/util.c      |  12 +++
+ 6 files changed, 229 insertions(+), 17 deletions(-)
+
+diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
+index 373ccff9880c..f0389849fd80 100644
+--- a/fs/overlayfs/inode.c
++++ b/fs/overlayfs/inode.c
+@@ -777,6 +777,54 @@ struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
+       return inode;
+ }
++bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir)
++{
++      struct inode *key = d_inode(dir);
++      struct inode *trap;
++      bool res;
++
++      trap = ilookup5(sb, (unsigned long) key, ovl_inode_test, key);
++      if (!trap)
++              return false;
++
++      res = IS_DEADDIR(trap) && !ovl_inode_upper(trap) &&
++                                !ovl_inode_lower(trap);
++
++      iput(trap);
++      return res;
++}
++
++/*
++ * Create an inode cache entry for layer root dir, that will intentionally
++ * fail ovl_verify_inode(), so any lookup that will find some layer root
++ * will fail.
++ */
++struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir)
++{
++      struct inode *key = d_inode(dir);
++      struct inode *trap;
++
++      if (!d_is_dir(dir))
++              return ERR_PTR(-ENOTDIR);
++
++      trap = iget5_locked(sb, (unsigned long) key, ovl_inode_test,
++                          ovl_inode_set, key);
++      if (!trap)
++              return ERR_PTR(-ENOMEM);
++
++      if (!(trap->i_state & I_NEW)) {
++              /* Conflicting layer roots? */
++              iput(trap);
++              return ERR_PTR(-ELOOP);
++      }
++
++      trap->i_mode = S_IFDIR;
++      trap->i_flags = S_DEAD;
++      unlock_new_inode(trap);
++
++      return trap;
++}
++
+ /*
+  * Does overlay inode need to be hashed by lower inode?
+  */
+diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
+index efd372312ef1..badf039267a2 100644
+--- a/fs/overlayfs/namei.c
++++ b/fs/overlayfs/namei.c
+@@ -18,6 +18,7 @@
+ #include "overlayfs.h"
+ struct ovl_lookup_data {
++      struct super_block *sb;
+       struct qstr name;
+       bool is_dir;
+       bool opaque;
+@@ -244,6 +245,12 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
+               if (!d->metacopy || d->last)
+                       goto out;
+       } else {
++              if (ovl_lookup_trap_inode(d->sb, this)) {
++                      /* Caught in a trap of overlapping layers */
++                      err = -ELOOP;
++                      goto out_err;
++              }
++
+               if (last_element)
+                       d->is_dir = true;
+               if (d->last)
+@@ -819,6 +826,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+       int err;
+       bool metacopy = false;
+       struct ovl_lookup_data d = {
++              .sb = dentry->d_sb,
+               .name = dentry->d_name,
+               .is_dir = false,
+               .opaque = false,
+diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
+index 80fb66426760..265bf9cfde08 100644
+--- a/fs/overlayfs/overlayfs.h
++++ b/fs/overlayfs/overlayfs.h
+@@ -270,6 +270,7 @@ void ovl_clear_flag(unsigned long flag, struct inode *inode);
+ bool ovl_test_flag(unsigned long flag, struct inode *inode);
+ bool ovl_inuse_trylock(struct dentry *dentry);
+ void ovl_inuse_unlock(struct dentry *dentry);
++bool ovl_is_inuse(struct dentry *dentry);
+ bool ovl_need_index(struct dentry *dentry);
+ int ovl_nlink_start(struct dentry *dentry, bool *locked);
+ void ovl_nlink_end(struct dentry *dentry, bool locked);
+@@ -366,6 +367,8 @@ struct ovl_inode_params {
+ struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
+ struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
+                              bool is_upper);
++bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir);
++struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir);
+ struct inode *ovl_get_inode(struct super_block *sb,
+                           struct ovl_inode_params *oip);
+ static inline void ovl_copyattr(struct inode *from, struct inode *to)
+diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
+index ec237035333a..6ed1ace8f8b3 100644
+--- a/fs/overlayfs/ovl_entry.h
++++ b/fs/overlayfs/ovl_entry.h
+@@ -29,6 +29,8 @@ struct ovl_sb {
+ struct ovl_layer {
+       struct vfsmount *mnt;
++      /* Trap in ovl inode cache */
++      struct inode *trap;
+       struct ovl_sb *fs;
+       /* Index of this layer in fs root (upper idx == 0) */
+       int idx;
+@@ -65,6 +67,10 @@ struct ovl_fs {
+       /* Did we take the inuse lock? */
+       bool upperdir_locked;
+       bool workdir_locked;
++      /* Traps in ovl inode cache */
++      struct inode *upperdir_trap;
++      struct inode *workdir_trap;
++      struct inode *indexdir_trap;
+       /* Inode numbers in all layers do not use the high xino_bits */
+       unsigned int xino_bits;
+ };
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 0fb0a59a5e5c..4e268f981b4d 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -217,6 +217,9 @@ static void ovl_free_fs(struct ovl_fs *ofs)
+ {
+       unsigned i;
++      iput(ofs->indexdir_trap);
++      iput(ofs->workdir_trap);
++      iput(ofs->upperdir_trap);
+       dput(ofs->indexdir);
+       dput(ofs->workdir);
+       if (ofs->workdir_locked)
+@@ -225,8 +228,10 @@ static void ovl_free_fs(struct ovl_fs *ofs)
+       if (ofs->upperdir_locked)
+               ovl_inuse_unlock(ofs->upper_mnt->mnt_root);
+       mntput(ofs->upper_mnt);
+-      for (i = 0; i < ofs->numlower; i++)
++      for (i = 0; i < ofs->numlower; i++) {
++              iput(ofs->lower_layers[i].trap);
+               mntput(ofs->lower_layers[i].mnt);
++      }
+       for (i = 0; i < ofs->numlowerfs; i++)
+               free_anon_bdev(ofs->lower_fs[i].pseudo_dev);
+       kfree(ofs->lower_layers);
+@@ -984,7 +989,26 @@ static const struct xattr_handler *ovl_xattr_handlers[] = {
+       NULL
+ };
+-static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
++static int ovl_setup_trap(struct super_block *sb, struct dentry *dir,
++                        struct inode **ptrap, const char *name)
++{
++      struct inode *trap;
++      int err;
++
++      trap = ovl_get_trap_inode(sb, dir);
++      err = PTR_ERR(trap);
++      if (IS_ERR(trap)) {
++              if (err == -ELOOP)
++                      pr_err("overlayfs: conflicting %s path\n", name);
++              return err;
++      }
++
++      *ptrap = trap;
++      return 0;
++}
++
++static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs,
++                       struct path *upperpath)
+ {
+       struct vfsmount *upper_mnt;
+       int err;
+@@ -1004,6 +1028,11 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
+       if (err)
+               goto out;
++      err = ovl_setup_trap(sb, upperpath->dentry, &ofs->upperdir_trap,
++                           "upperdir");
++      if (err)
++              goto out;
++
+       upper_mnt = clone_private_mount(upperpath);
+       err = PTR_ERR(upper_mnt);
+       if (IS_ERR(upper_mnt)) {
+@@ -1030,7 +1059,8 @@ static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
+       return err;
+ }
+-static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
++static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
++                          struct path *workpath)
+ {
+       struct vfsmount *mnt = ofs->upper_mnt;
+       struct dentry *temp;
+@@ -1045,6 +1075,10 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
+       if (!ofs->workdir)
+               goto out;
++      err = ovl_setup_trap(sb, ofs->workdir, &ofs->workdir_trap, "workdir");
++      if (err)
++              goto out;
++
+       /*
+        * Upper should support d_type, else whiteouts are visible.  Given
+        * workdir and upper are on same fs, we can do iterate_dir() on
+@@ -1105,7 +1139,8 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
+       return err;
+ }
+-static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
++static int ovl_get_workdir(struct super_block *sb, struct ovl_fs *ofs,
++                         struct path *upperpath)
+ {
+       int err;
+       struct path workpath = { };
+@@ -1136,19 +1171,16 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
+               pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
+       }
+-      err = ovl_make_workdir(ofs, &workpath);
+-      if (err)
+-              goto out;
++      err = ovl_make_workdir(sb, ofs, &workpath);
+-      err = 0;
+ out:
+       path_put(&workpath);
+       return err;
+ }
+-static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe,
+-                          struct path *upperpath)
++static int ovl_get_indexdir(struct super_block *sb, struct ovl_fs *ofs,
++                          struct ovl_entry *oe, struct path *upperpath)
+ {
+       struct vfsmount *mnt = ofs->upper_mnt;
+       int err;
+@@ -1167,6 +1199,11 @@ static int ovl_get_indexdir(struct ovl_fs *ofs, struct ovl_entry *oe,
+       ofs->indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true);
+       if (ofs->indexdir) {
++              err = ovl_setup_trap(sb, ofs->indexdir, &ofs->indexdir_trap,
++                                   "indexdir");
++              if (err)
++                      goto out;
++
+               /*
+                * Verify upper root is exclusively associated with index dir.
+                * Older kernels stored upper fh in "trusted.overlay.origin"
+@@ -1226,8 +1263,8 @@ static int ovl_get_fsid(struct ovl_fs *ofs, struct super_block *sb)
+       return ofs->numlowerfs;
+ }
+-static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
+-                              unsigned int numlower)
++static int ovl_get_lower_layers(struct super_block *sb, struct ovl_fs *ofs,
++                              struct path *stack, unsigned int numlower)
+ {
+       int err;
+       unsigned int i;
+@@ -1245,16 +1282,28 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
+       for (i = 0; i < numlower; i++) {
+               struct vfsmount *mnt;
++              struct inode *trap;
+               int fsid;
+               err = fsid = ovl_get_fsid(ofs, stack[i].mnt->mnt_sb);
+               if (err < 0)
+                       goto out;
++              err = -EBUSY;
++              if (ovl_is_inuse(stack[i].dentry)) {
++                      pr_err("overlayfs: lowerdir is in-use as upperdir/workdir\n");
++                      goto out;
++              }
++
++              err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir");
++              if (err)
++                      goto out;
++
+               mnt = clone_private_mount(&stack[i]);
+               err = PTR_ERR(mnt);
+               if (IS_ERR(mnt)) {
+                       pr_err("overlayfs: failed to clone lowerpath\n");
++                      iput(trap);
+                       goto out;
+               }
+@@ -1264,6 +1313,7 @@ static int ovl_get_lower_layers(struct ovl_fs *ofs, struct path *stack,
+                */
+               mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
++              ofs->lower_layers[ofs->numlower].trap = trap;
+               ofs->lower_layers[ofs->numlower].mnt = mnt;
+               ofs->lower_layers[ofs->numlower].idx = i + 1;
+               ofs->lower_layers[ofs->numlower].fsid = fsid;
+@@ -1358,7 +1408,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
+               goto out_err;
+       }
+-      err = ovl_get_lower_layers(ofs, stack, numlower);
++      err = ovl_get_lower_layers(sb, ofs, stack, numlower);
+       if (err)
+               goto out_err;
+@@ -1390,6 +1440,85 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
+       goto out;
+ }
++/*
++ * Check if this layer root is a descendant of:
++ * - another layer of this overlayfs instance
++ * - upper/work dir of any overlayfs instance
++ * - a disconnected dentry (detached root)
++ */
++static int ovl_check_layer(struct super_block *sb, struct dentry *dentry,
++                         const char *name)
++{
++      struct dentry *next, *parent;
++      bool is_root = false;
++      int err = 0;
++
++      if (!dentry || dentry == dentry->d_sb->s_root)
++              return 0;
++
++      next = dget(dentry);
++      /* Walk back ancestors to fs root (inclusive) looking for traps */
++      do {
++              parent = dget_parent(next);
++              is_root = (parent == next);
++              if (ovl_is_inuse(parent)) {
++                      err = -EBUSY;
++                      pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n",
++                             name);
++              } else if (ovl_lookup_trap_inode(sb, parent)) {
++                      err = -ELOOP;
++                      pr_err("overlayfs: overlapping %s path\n", name);
++              }
++              dput(next);
++              next = parent;
++      } while (!err && !is_root);
++
++      /* Did we really walk to fs root or found a detached root? */
++      if (!err && next != dentry->d_sb->s_root) {
++              err = -ESTALE;
++              pr_err("overlayfs: disconnected %s path\n", name);
++      }
++
++      dput(next);
++
++      return err;
++}
++
++/*
++ * Check if any of the layers or work dirs overlap.
++ */
++static int ovl_check_overlapping_layers(struct super_block *sb,
++                                      struct ovl_fs *ofs)
++{
++      int i, err;
++
++      if (ofs->upper_mnt) {
++              err = ovl_check_layer(sb, ofs->upper_mnt->mnt_root, "upperdir");
++              if (err)
++                      return err;
++
++              /*
++               * Checking workbasedir avoids hitting ovl_is_inuse(parent) of
++               * this instance and covers overlapping work and index dirs,
++               * unless work or index dir have been moved since created inside
++               * workbasedir.  In that case, we already have their traps in
++               * inode cache and we will catch that case on lookup.
++               */
++              err = ovl_check_layer(sb, ofs->workbasedir, "workdir");
++              if (err)
++                      return err;
++      }
++
++      for (i = 0; i < ofs->numlower; i++) {
++              err = ovl_check_layer(sb, ofs->lower_layers[i].mnt->mnt_root,
++                                    "lowerdir");
++              if (err)
++                      return err;
++      }
++
++      return 0;
++}
++
+ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+ {
+       struct path upperpath = { };
+@@ -1429,17 +1558,20 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+       if (ofs->config.xino != OVL_XINO_OFF)
+               ofs->xino_bits = BITS_PER_LONG - 32;
++      /* alloc/destroy_inode needed for setting up traps in inode cache */
++      sb->s_op = &ovl_super_operations;
++
+       if (ofs->config.upperdir) {
+               if (!ofs->config.workdir) {
+                       pr_err("overlayfs: missing 'workdir'\n");
+                       goto out_err;
+               }
+-              err = ovl_get_upper(ofs, &upperpath);
++              err = ovl_get_upper(sb, ofs, &upperpath);
+               if (err)
+                       goto out_err;
+-              err = ovl_get_workdir(ofs, &upperpath);
++              err = ovl_get_workdir(sb, ofs, &upperpath);
+               if (err)
+                       goto out_err;
+@@ -1460,7 +1592,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+               sb->s_flags |= SB_RDONLY;
+       if (!(ovl_force_readonly(ofs)) && ofs->config.index) {
+-              err = ovl_get_indexdir(ofs, oe, &upperpath);
++              err = ovl_get_indexdir(sb, ofs, oe, &upperpath);
+               if (err)
+                       goto out_free_oe;
+@@ -1473,6 +1605,10 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+       }
++      err = ovl_check_overlapping_layers(sb, ofs);
++      if (err)
++              goto out_free_oe;
++
+       /* Show index=off in /proc/mounts for forced r/o mount */
+       if (!ofs->indexdir) {
+               ofs->config.index = false;
+@@ -1494,7 +1630,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+       cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
+       sb->s_magic = OVERLAYFS_SUPER_MAGIC;
+-      sb->s_op = &ovl_super_operations;
+       sb->s_xattr = ovl_xattr_handlers;
+       sb->s_fs_info = ofs;
+       sb->s_flags |= SB_POSIXACL;
+diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
+index c9a2e3c6d537..db8bdb29b320 100644
+--- a/fs/overlayfs/util.c
++++ b/fs/overlayfs/util.c
+@@ -653,6 +653,18 @@ void ovl_inuse_unlock(struct dentry *dentry)
+       }
+ }
++bool ovl_is_inuse(struct dentry *dentry)
++{
++      struct inode *inode = d_inode(dentry);
++      bool inuse;
++
++      spin_lock(&inode->i_lock);
++      inuse = (inode->i_state & I_OVL_INUSE);
++      spin_unlock(&inode->i_lock);
++
++      return inuse;
++}
++
+ /*
+  * Does this overlay dentry need to be indexed on copy up?
+  */
+-- 
+2.20.1
+
diff --git a/queue-4.19/ovl-don-t-fail-with-disconnected-lower-nfs.patch b/queue-4.19/ovl-don-t-fail-with-disconnected-lower-nfs.patch
new file mode 100644 (file)
index 0000000..1d34dea
--- /dev/null
@@ -0,0 +1,79 @@
+From c3860d1b1b755a9b4e1888bbc4b1d643a9f69fa6 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@redhat.com>
+Date: Tue, 18 Jun 2019 15:06:16 +0200
+Subject: ovl: don't fail with disconnected lower NFS
+
+[ Upstream commit 9179c21dc6ed1c993caa5fe4da876a6765c26af7 ]
+
+NFS mounts can be disconnected from fs root.  Don't fail the overlapping
+layer check because of this.
+
+The check is not authoritative anyway, since topology can change during or
+after the check.
+
+Reported-by: Antti Antinoja <antti@fennosys.fi>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Fixes: 146d62e5a586 ("ovl: detect overlapping layers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/super.c | 26 +++++++++-----------------
+ 1 file changed, 9 insertions(+), 17 deletions(-)
+
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index 4e268f981b4d..d6e60a7156a1 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -1444,23 +1444,20 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
+  * Check if this layer root is a descendant of:
+  * - another layer of this overlayfs instance
+  * - upper/work dir of any overlayfs instance
+- * - a disconnected dentry (detached root)
+  */
+ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry,
+                          const char *name)
+ {
+-      struct dentry *next, *parent;
+-      bool is_root = false;
++      struct dentry *next = dentry, *parent;
+       int err = 0;
+-      if (!dentry || dentry == dentry->d_sb->s_root)
++      if (!dentry)
+               return 0;
+-      next = dget(dentry);
+-      /* Walk back ancestors to fs root (inclusive) looking for traps */
+-      do {
+-              parent = dget_parent(next);
+-              is_root = (parent == next);
++      parent = dget_parent(next);
++
++      /* Walk back ancestors to root (inclusive) looking for traps */
++      while (!err && parent != next) {
+               if (ovl_is_inuse(parent)) {
+                       err = -EBUSY;
+                       pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n",
+@@ -1469,17 +1466,12 @@ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry,
+                       err = -ELOOP;
+                       pr_err("overlayfs: overlapping %s path\n", name);
+               }
+-              dput(next);
+               next = parent;
+-      } while (!err && !is_root);
+-
+-      /* Did we really walk to fs root or found a detached root? */
+-      if (!err && next != dentry->d_sb->s_root) {
+-              err = -ESTALE;
+-              pr_err("overlayfs: disconnected %s path\n", name);
++              parent = dget_parent(next);
++              dput(next);
+       }
+-      dput(next);
++      dput(parent);
+       return err;
+ }
+-- 
+2.20.1
+
diff --git a/queue-4.19/ovl-fix-bogus-wmaybe-unitialized-warning.patch b/queue-4.19/ovl-fix-bogus-wmaybe-unitialized-warning.patch
new file mode 100644 (file)
index 0000000..fffc9e0
--- /dev/null
@@ -0,0 +1,45 @@
+From 68836aa4843eeb2306649eedd4749410fdd14159 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Mon, 17 Jun 2019 14:39:29 +0200
+Subject: ovl: fix bogus -Wmaybe-unitialized warning
+
+[ Upstream commit 1dac6f5b0ed2601be21bb4e27a44b0c3e667b7f4 ]
+
+gcc gets a bit confused by the logic in ovl_setup_trap() and
+can't figure out whether the local 'trap' variable in the caller
+was initialized or not:
+
+fs/overlayfs/super.c: In function 'ovl_fill_super':
+fs/overlayfs/super.c:1333:4: error: 'trap' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+    iput(trap);
+    ^~~~~~~~~~
+fs/overlayfs/super.c:1312:17: note: 'trap' was declared here
+
+Reword slightly to make it easier for the compiler to understand.
+
+Fixes: 146d62e5a586 ("ovl: detect overlapping layers")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/super.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
+index d6e60a7156a1..2d028c02621f 100644
+--- a/fs/overlayfs/super.c
++++ b/fs/overlayfs/super.c
+@@ -996,8 +996,8 @@ static int ovl_setup_trap(struct super_block *sb, struct dentry *dir,
+       int err;
+       trap = ovl_get_trap_inode(sb, dir);
+-      err = PTR_ERR(trap);
+-      if (IS_ERR(trap)) {
++      err = PTR_ERR_OR_ZERO(trap);
++      if (err) {
+               if (err == -ELOOP)
+                       pr_err("overlayfs: conflicting %s path\n", name);
+               return err;
+-- 
+2.20.1
+
diff --git a/queue-4.19/ovl-fix-wrong-flags-check-in-fs_ioc_fs-sg-etxattr-io.patch b/queue-4.19/ovl-fix-wrong-flags-check-in-fs_ioc_fs-sg-etxattr-io.patch
new file mode 100644 (file)
index 0000000..dde82ff
--- /dev/null
@@ -0,0 +1,152 @@
+From 16fa3104ff72cb88af22bc67d4fe47f6313262fc Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Tue, 11 Jun 2019 18:09:28 +0300
+Subject: ovl: fix wrong flags check in FS_IOC_FS[SG]ETXATTR ioctls
+
+[ Upstream commit 941d935ac7636911a3fd8fa80e758e52b0b11e20 ]
+
+The ioctl argument was parsed as the wrong type.
+
+Fixes: b21d9c435f93 ("ovl: support the FS_IOC_FS[SG]ETXATTR ioctls")
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/file.c | 91 ++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 65 insertions(+), 26 deletions(-)
+
+diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
+index 749532fd51d7..0bd276e4ccbe 100644
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -409,37 +409,16 @@ static long ovl_real_ioctl(struct file *file, unsigned int cmd,
+       return ret;
+ }
+-static unsigned int ovl_get_inode_flags(struct inode *inode)
+-{
+-      unsigned int flags = READ_ONCE(inode->i_flags);
+-      unsigned int ovl_iflags = 0;
+-
+-      if (flags & S_SYNC)
+-              ovl_iflags |= FS_SYNC_FL;
+-      if (flags & S_APPEND)
+-              ovl_iflags |= FS_APPEND_FL;
+-      if (flags & S_IMMUTABLE)
+-              ovl_iflags |= FS_IMMUTABLE_FL;
+-      if (flags & S_NOATIME)
+-              ovl_iflags |= FS_NOATIME_FL;
+-
+-      return ovl_iflags;
+-}
+-
+ static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
+-                              unsigned long arg)
++                              unsigned long arg, unsigned int iflags)
+ {
+       long ret;
+       struct inode *inode = file_inode(file);
+-      unsigned int flags;
+-      unsigned int old_flags;
++      unsigned int old_iflags;
+       if (!inode_owner_or_capable(inode))
+               return -EACCES;
+-      if (get_user(flags, (int __user *) arg))
+-              return -EFAULT;
+-
+       ret = mnt_want_write_file(file);
+       if (ret)
+               return ret;
+@@ -448,8 +427,8 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
+       /* Check the capability before cred override */
+       ret = -EPERM;
+-      old_flags = ovl_get_inode_flags(inode);
+-      if (((flags ^ old_flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
++      old_iflags = READ_ONCE(inode->i_flags);
++      if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) &&
+           !capable(CAP_LINUX_IMMUTABLE))
+               goto unlock;
+@@ -469,6 +448,63 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
+ }
++static unsigned int ovl_fsflags_to_iflags(unsigned int flags)
++{
++      unsigned int iflags = 0;
++
++      if (flags & FS_SYNC_FL)
++              iflags |= S_SYNC;
++      if (flags & FS_APPEND_FL)
++              iflags |= S_APPEND;
++      if (flags & FS_IMMUTABLE_FL)
++              iflags |= S_IMMUTABLE;
++      if (flags & FS_NOATIME_FL)
++              iflags |= S_NOATIME;
++
++      return iflags;
++}
++
++static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd,
++                                unsigned long arg)
++{
++      unsigned int flags;
++
++      if (get_user(flags, (int __user *) arg))
++              return -EFAULT;
++
++      return ovl_ioctl_set_flags(file, cmd, arg,
++                                 ovl_fsflags_to_iflags(flags));
++}
++
++static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags)
++{
++      unsigned int iflags = 0;
++
++      if (xflags & FS_XFLAG_SYNC)
++              iflags |= S_SYNC;
++      if (xflags & FS_XFLAG_APPEND)
++              iflags |= S_APPEND;
++      if (xflags & FS_XFLAG_IMMUTABLE)
++              iflags |= S_IMMUTABLE;
++      if (xflags & FS_XFLAG_NOATIME)
++              iflags |= S_NOATIME;
++
++      return iflags;
++}
++
++static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd,
++                                 unsigned long arg)
++{
++      struct fsxattr fa;
++
++      memset(&fa, 0, sizeof(fa));
++      if (copy_from_user(&fa, (void __user *) arg, sizeof(fa)))
++              return -EFAULT;
++
++      return ovl_ioctl_set_flags(file, cmd, arg,
++                                 ovl_fsxflags_to_iflags(fa.fsx_xflags));
++}
++
+ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ {
+       long ret;
+@@ -480,8 +516,11 @@ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+               break;
+       case FS_IOC_SETFLAGS:
++              ret = ovl_ioctl_set_fsflags(file, cmd, arg);
++              break;
++
+       case FS_IOC_FSSETXATTR:
+-              ret = ovl_ioctl_set_flags(file, cmd, arg);
++              ret = ovl_ioctl_set_fsxflags(file, cmd, arg);
+               break;
+       default:
+-- 
+2.20.1
+
diff --git a/queue-4.19/ovl-make-i_ino-consistent-with-st_ino-in-more-cases.patch b/queue-4.19/ovl-make-i_ino-consistent-with-st_ino-in-more-cases.patch
new file mode 100644 (file)
index 0000000..8ad22a8
--- /dev/null
@@ -0,0 +1,53 @@
+From aded172679503e13da91a5a12dda390b2e39de85 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 9 Jun 2019 19:03:44 +0300
+Subject: ovl: make i_ino consistent with st_ino in more cases
+
+[ Upstream commit 6dde1e42f497b2d4e22466f23019016775607947 ]
+
+Relax the condition that overlayfs supports nfs export, to require
+that i_ino is consistent with st_ino/d_ino.
+
+It is enough to require that st_ino and d_ino are consistent.
+
+This fixes the failure of xfstest generic/504, due to mismatch of
+st_ino to inode number in the output of /proc/locks.
+
+Fixes: 12574a9f4c9c ("ovl: consistent i_ino for non-samefs with xino")
+Cc: <stable@vger.kernel.org> # v4.19
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/inode.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
+index b48273e846ad..373ccff9880c 100644
+--- a/fs/overlayfs/inode.c
++++ b/fs/overlayfs/inode.c
+@@ -553,15 +553,15 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,
+       int xinobits = ovl_xino_bits(inode->i_sb);
+       /*
+-       * When NFS export is enabled and d_ino is consistent with st_ino
+-       * (samefs or i_ino has enough bits to encode layer), set the same
+-       * value used for d_ino to i_ino, because nfsd readdirplus compares
+-       * d_ino values to i_ino values of child entries. When called from
++       * When d_ino is consistent with st_ino (samefs or i_ino has enough
++       * bits to encode layer), set the same value used for st_ino to i_ino,
++       * so inode number exposed via /proc/locks and a like will be
++       * consistent with d_ino and st_ino values. An i_ino value inconsistent
++       * with d_ino also causes nfsd readdirplus to fail.  When called from
+        * ovl_new_inode(), ino arg is 0, so i_ino will be updated to real
+        * upper inode i_ino on ovl_inode_init() or ovl_inode_update().
+        */
+-      if (inode->i_sb->s_export_op &&
+-          (ovl_same_sb(inode->i_sb) || xinobits)) {
++      if (ovl_same_sb(inode->i_sb) || xinobits) {
+               inode->i_ino = ino;
+               if (xinobits && fsid && !(ino >> (64 - xinobits)))
+                       inode->i_ino |= (unsigned long)fsid << (64 - xinobits);
+-- 
+2.20.1
+
diff --git a/queue-4.19/ovl-support-the-fs_ioc_fs-sg-etxattr-ioctls.patch b/queue-4.19/ovl-support-the-fs_ioc_fs-sg-etxattr-ioctls.patch
new file mode 100644 (file)
index 0000000..2df4c6a
--- /dev/null
@@ -0,0 +1,64 @@
+From 1ca682dc2a92aaa68309e03485a5d4cddb5bc523 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 26 May 2019 09:28:25 +0300
+Subject: ovl: support the FS_IOC_FS[SG]ETXATTR ioctls
+
+[ Upstream commit b21d9c435f935014d3e3fa6914f2e4fbabb0e94d ]
+
+They are the extended version of FS_IOC_FS[SG]ETFLAGS ioctls.
+xfs_io -c "chattr <flags>" uses the new ioctls for setting flags.
+
+This used to work in kernel pre v4.19, before stacked file ops
+introduced the ovl_ioctl whitelist.
+
+Reported-by: Dave Chinner <david@fromorbit.com>
+Fixes: d1d04ef8572b ("ovl: stack file ops")
+Cc: <stable@vger.kernel.org> # v4.19
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/overlayfs/file.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
+index 00338b828f76..749532fd51d7 100644
+--- a/fs/overlayfs/file.c
++++ b/fs/overlayfs/file.c
+@@ -426,7 +426,8 @@ static unsigned int ovl_get_inode_flags(struct inode *inode)
+       return ovl_iflags;
+ }
+-static long ovl_ioctl_set_flags(struct file *file, unsigned long arg)
++static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd,
++                              unsigned long arg)
+ {
+       long ret;
+       struct inode *inode = file_inode(file);
+@@ -456,7 +457,7 @@ static long ovl_ioctl_set_flags(struct file *file, unsigned long arg)
+       if (ret)
+               goto unlock;
+-      ret = ovl_real_ioctl(file, FS_IOC_SETFLAGS, arg);
++      ret = ovl_real_ioctl(file, cmd, arg);
+       ovl_copyflags(ovl_inode_real(inode), inode);
+ unlock:
+@@ -474,11 +475,13 @@ static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+       switch (cmd) {
+       case FS_IOC_GETFLAGS:
++      case FS_IOC_FSGETXATTR:
+               ret = ovl_real_ioctl(file, cmd, arg);
+               break;
+       case FS_IOC_SETFLAGS:
+-              ret = ovl_ioctl_set_flags(file, arg);
++      case FS_IOC_FSSETXATTR:
++              ret = ovl_ioctl_set_flags(file, cmd, arg);
+               break;
+       default:
+-- 
+2.20.1
+
diff --git a/queue-4.19/s390-ap-rework-assembler-functions-to-use-unions-for.patch b/queue-4.19/s390-ap-rework-assembler-functions-to-use-unions-for.patch
new file mode 100644 (file)
index 0000000..5b4e397
--- /dev/null
@@ -0,0 +1,86 @@
+From e2a889526f14636917cfce020a4f2ab912df0950 Mon Sep 17 00:00:00 2001
+From: Harald Freudenberger <freude@linux.ibm.com>
+Date: Fri, 16 Nov 2018 15:48:10 +0100
+Subject: s390/ap: rework assembler functions to use unions for in/out register
+ variables
+
+[ Upstream commit 159491f3b509bd8101199944dc7b0673b881c734 ]
+
+The inline assembler functions ap_aqic() and ap_qact() used two
+variables declared on the very same register. One variable was for
+input only, the other for output. Looks like newer versions of the gcc
+don't like this. Anyway it is a better coding to use one variable
+(which may have a union data type) on one register for input and
+output. So this patch introduces unions and uses only one variable now
+for input and output for GR1 for the PQAP(QACT) and PQAP(QIC)
+invocation.
+
+Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
+Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/ap.h | 28 +++++++++++++++++++---------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/arch/s390/include/asm/ap.h b/arch/s390/include/asm/ap.h
+index 8c00fd509c45..1a6a7092d942 100644
+--- a/arch/s390/include/asm/ap.h
++++ b/arch/s390/include/asm/ap.h
+@@ -221,16 +221,22 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
+                                            void *ind)
+ {
+       register unsigned long reg0 asm ("0") = qid | (3UL << 24);
+-      register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl;
+-      register struct ap_queue_status reg1_out asm ("1");
++      register union {
++              unsigned long value;
++              struct ap_qirq_ctrl qirqctrl;
++              struct ap_queue_status status;
++      } reg1 asm ("1");
+       register void *reg2 asm ("2") = ind;
++      reg1.qirqctrl = qirqctrl;
++
+       asm volatile(
+               ".long 0xb2af0000"              /* PQAP(AQIC) */
+-              : "=d" (reg1_out)
+-              : "d" (reg0), "d" (reg1_in), "d" (reg2)
++              : "+d" (reg1)
++              : "d" (reg0), "d" (reg2)
+               : "cc");
+-      return reg1_out;
++
++      return reg1.status;
+ }
+ /*
+@@ -264,17 +270,21 @@ static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
+ {
+       register unsigned long reg0 asm ("0") = qid | (5UL << 24)
+               | ((ifbit & 0x01) << 22);
+-      register unsigned long reg1_in asm ("1") = apinfo->val;
+-      register struct ap_queue_status reg1_out asm ("1");
++      register union {
++              unsigned long value;
++              struct ap_queue_status status;
++      } reg1 asm ("1");
+       register unsigned long reg2 asm ("2");
++      reg1.value = apinfo->val;
++
+       asm volatile(
+               ".long 0xb2af0000"              /* PQAP(QACT) */
+-              : "+d" (reg1_in), "=d" (reg1_out), "=d" (reg2)
++              : "+d" (reg1), "=d" (reg2)
+               : "d" (reg0)
+               : "cc");
+       apinfo->val = reg2;
+-      return reg1_out;
++      return reg1.status;
+ }
+ /**
+-- 
+2.20.1
+
diff --git a/queue-4.19/s390-jump_label-use-jdd-constraint-on-gcc9.patch b/queue-4.19/s390-jump_label-use-jdd-constraint-on-gcc9.patch
new file mode 100644 (file)
index 0000000..41b9406
--- /dev/null
@@ -0,0 +1,75 @@
+From 42449e3341fdbe8209742950c33e313417c1284d Mon Sep 17 00:00:00 2001
+From: Ilya Leoshkevich <iii@linux.ibm.com>
+Date: Fri, 21 Jun 2019 17:39:12 +0200
+Subject: s390/jump_label: Use "jdd" constraint on gcc9
+
+[ Upstream commit 146448524bddbf6dfc62de31957e428de001cbda ]
+
+[heiko.carstens@de.ibm.com]:
+-----
+Laura Abbott reported that the kernel doesn't build anymore with gcc 9,
+due to the "X" constraint. Ilya provided the gcc 9 patch "S/390:
+Introduce jdd constraint" which introduces the new "jdd" constraint
+which fixes this.
+-----
+
+The support for section anchors on S/390 introduced in gcc9 has changed
+the behavior of "X" constraint, which can now produce register
+references. Since existing constraints, in particular, "i", do not fit
+the intended use case on S/390, the new machine-specific "jdd"
+constraint was introduced. This patch makes jump labels use "jdd"
+constraint when building with gcc9.
+
+Reported-by: Laura Abbott <labbott@redhat.com>
+Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/jump_label.h | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
+index 40f651292aa7..9c7dc970e966 100644
+--- a/arch/s390/include/asm/jump_label.h
++++ b/arch/s390/include/asm/jump_label.h
+@@ -10,6 +10,12 @@
+ #define JUMP_LABEL_NOP_SIZE 6
+ #define JUMP_LABEL_NOP_OFFSET 2
++#if __GNUC__ < 9
++#define JUMP_LABEL_STATIC_KEY_CONSTRAINT "X"
++#else
++#define JUMP_LABEL_STATIC_KEY_CONSTRAINT "jdd"
++#endif
++
+ /*
+  * We use a brcl 0,2 instruction for jump labels at compile time so it
+  * can be easily distinguished from a hotpatch generated instruction.
+@@ -19,9 +25,9 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
+       asm_volatile_goto("0:   brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
+               ".pushsection __jump_table, \"aw\"\n"
+               ".balign 8\n"
+-              ".quad 0b, %l[label], %0\n"
++              ".quad 0b, %l[label], %0+%1\n"
+               ".popsection\n"
+-              : : "X" (&((char *)key)[branch]) : : label);
++              : : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label);
+       return false;
+ label:
+@@ -33,9 +39,9 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
+       asm_volatile_goto("0:   brcl 15, %l[label]\n"
+               ".pushsection __jump_table, \"aw\"\n"
+               ".balign 8\n"
+-              ".quad 0b, %l[label], %0\n"
++              ".quad 0b, %l[label], %0+%1\n"
+               ".popsection\n"
+-              : : "X" (&((char *)key)[branch]) : : label);
++              : : JUMP_LABEL_STATIC_KEY_CONSTRAINT (key), "i" (branch) : : label);
+       return false;
+ label:
+-- 
+2.20.1
+
index ce8ad94d48d15511e232dcb2e931d0ddbd669436..9b8bdec0f50f872f0cb5b0dd90d4d79bbf163c7f 100644 (file)
@@ -1,3 +1,11 @@
 tracing-silence-gcc-9-array-bounds-warning.patch
 objtool-support-per-function-rodata-sections.patch
 gcc-9-silence-address-of-packed-member-warning.patch
+ovl-support-the-fs_ioc_fs-sg-etxattr-ioctls.patch
+ovl-fix-wrong-flags-check-in-fs_ioc_fs-sg-etxattr-io.patch
+ovl-make-i_ino-consistent-with-st_ino-in-more-cases.patch
+ovl-detect-overlapping-layers.patch
+ovl-don-t-fail-with-disconnected-lower-nfs.patch
+ovl-fix-bogus-wmaybe-unitialized-warning.patch
+s390-jump_label-use-jdd-constraint-on-gcc9.patch
+s390-ap-rework-assembler-functions-to-use-unions-for.patch