]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Tue, 23 Jun 2020 01:30:15 +0000 (21:30 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 23 Jun 2020 01:30:15 +0000 (21:30 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/block-nr_sects_write-disable-preemption-on-seqcount-.patch [new file with mode: 0644]
queue-5.4/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch [new file with mode: 0644]
queue-5.4/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch [new file with mode: 0644]
queue-5.4/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/block-nr_sects_write-disable-preemption-on-seqcount-.patch b/queue-5.4/block-nr_sects_write-disable-preemption-on-seqcount-.patch
new file mode 100644 (file)
index 0000000..edf6c88
--- /dev/null
@@ -0,0 +1,48 @@
+From 1762b9dcce9e48f1edc777c1bfa1c562c0aa64a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2020 16:49:48 +0200
+Subject: block: nr_sects_write(): Disable preemption on seqcount write
+
+From: Ahmed S. Darwish <a.darwish@linutronix.de>
+
+[ Upstream commit 15b81ce5abdc4b502aa31dff2d415b79d2349d2f ]
+
+For optimized block readers not holding a mutex, the "number of sectors"
+64-bit value is protected from tearing on 32-bit architectures by a
+sequence counter.
+
+Disable preemption before entering that sequence counter's write side
+critical section. Otherwise, the read side can preempt the write side
+section and spin for the entire scheduler tick. If the reader belongs to
+a real-time scheduling class, it can spin forever and the kernel will
+livelock.
+
+Fixes: c83f6bf98dc1 ("block: add partition resize function to blkpg ioctl")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/genhd.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/genhd.h b/include/linux/genhd.h
+index 8b5330dd5ac09..62a2ec9f17df8 100644
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -750,9 +750,11 @@ static inline sector_t part_nr_sects_read(struct hd_struct *part)
+ static inline void part_nr_sects_write(struct hd_struct *part, sector_t size)
+ {
+ #if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++      preempt_disable();
+       write_seqcount_begin(&part->nr_sects_seq);
+       part->nr_sects = size;
+       write_seqcount_end(&part->nr_sects_seq);
++      preempt_enable();
+ #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
+       preempt_disable();
+       part->nr_sects = size;
+-- 
+2.25.1
+
diff --git a/queue-5.4/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch b/queue-5.4/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch
new file mode 100644 (file)
index 0000000..d368483
--- /dev/null
@@ -0,0 +1,66 @@
+From f23b0fd9ac38590ae89a6de9259a08fc5a066a82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2020 13:08:05 -0700
+Subject: f2fs: avoid utf8_strncasecmp() with unstable name
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit fc3bb095ab02b9e7d89a069ade2cead15c64c504 ]
+
+If the dentry name passed to ->d_compare() fits in dentry::d_iname, then
+it may be concurrently modified by a rename.  This can cause undefined
+behavior (possibly out-of-bounds memory accesses or crashes) in
+utf8_strncasecmp(), since fs/unicode/ isn't written to handle strings
+that may be concurrently modified.
+
+Fix this by first copying the filename to a stack buffer if needed.
+This way we get a stable snapshot of the filename.
+
+Fixes: 2c2eb7a300cd ("f2fs: Support case-insensitive file name lookups")
+Cc: <stable@vger.kernel.org> # v5.4+
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Daniel Rosenberg <drosen@google.com>
+Cc: Gabriel Krisman Bertazi <krisman@collabora.co.uk>
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/dir.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+index 594c9ad774d23..e9af46dc06f72 100644
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -1063,11 +1063,27 @@ static int f2fs_d_compare(const struct dentry *dentry, unsigned int len,
+       const struct inode *dir = READ_ONCE(parent->d_inode);
+       const struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
+       struct qstr entry = QSTR_INIT(str, len);
++      char strbuf[DNAME_INLINE_LEN];
+       int res;
+       if (!dir || !IS_CASEFOLDED(dir))
+               goto fallback;
++      /*
++       * If the dentry name is stored in-line, then it may be concurrently
++       * modified by a rename.  If this happens, the VFS will eventually retry
++       * the lookup, so it doesn't matter what ->d_compare() returns.
++       * However, it's unsafe to call utf8_strncasecmp() with an unstable
++       * string.  Therefore, we have to copy the name into a temporary buffer.
++       */
++      if (len <= DNAME_INLINE_LEN - 1) {
++              memcpy(strbuf, str, len);
++              strbuf[len] = 0;
++              entry.name = strbuf;
++              /* prevent compiler from optimizing out the temporary buffer */
++              barrier();
++      }
++
+       res = utf8_strncasecmp(sbi->s_encoding, name, &entry);
+       if (res >= 0)
+               return res;
+-- 
+2.25.1
+
diff --git a/queue-5.4/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch b/queue-5.4/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch
new file mode 100644 (file)
index 0000000..50e3c82
--- /dev/null
@@ -0,0 +1,152 @@
+From cca5692f9c4f4b9818c7d21055dc1a19b44a246b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2020 00:59:03 -0700
+Subject: f2fs: split f2fs_d_compare() from f2fs_match_name()
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit f874fa1c7c7905c1744a2037a11516558ed00a81 ]
+
+Sharing f2fs_ci_compare() between comparing cached dentries
+(f2fs_d_compare()) and comparing on-disk dentries (f2fs_match_name())
+doesn't work as well as intended, as these actions fundamentally differ
+in several ways (e.g. whether the task may sleep, whether the directory
+is stable, whether the casefolded name was precomputed, whether the
+dentry will need to be decrypted once we allow casefold+encrypt, etc.)
+
+Just make f2fs_d_compare() implement what it needs directly, and rework
+f2fs_ci_compare() to be specialized for f2fs_match_name().
+
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Chao Yu <yuchao0@huawei.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/dir.c  | 70 +++++++++++++++++++++++++-------------------------
+ fs/f2fs/f2fs.h |  5 ----
+ 2 files changed, 35 insertions(+), 40 deletions(-)
+
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+index 84280ad3786c3..594c9ad774d23 100644
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -107,36 +107,28 @@ static struct f2fs_dir_entry *find_in_block(struct inode *dir,
+ /*
+  * Test whether a case-insensitive directory entry matches the filename
+  * being searched for.
+- *
+- * Returns: 0 if the directory entry matches, more than 0 if it
+- * doesn't match or less than zero on error.
+  */
+-int f2fs_ci_compare(const struct inode *parent, const struct qstr *name,
+-                              const struct qstr *entry, bool quick)
++static bool f2fs_match_ci_name(const struct inode *dir, const struct qstr *name,
++                             const struct qstr *entry, bool quick)
+ {
+-      const struct f2fs_sb_info *sbi = F2FS_SB(parent->i_sb);
++      const struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
+       const struct unicode_map *um = sbi->s_encoding;
+-      int ret;
++      int res;
+       if (quick)
+-              ret = utf8_strncasecmp_folded(um, name, entry);
++              res = utf8_strncasecmp_folded(um, name, entry);
+       else
+-              ret = utf8_strncasecmp(um, name, entry);
+-
+-      if (ret < 0) {
+-              /* Handle invalid character sequence as either an error
+-               * or as an opaque byte sequence.
++              res = utf8_strncasecmp(um, name, entry);
++      if (res < 0) {
++              /*
++               * In strict mode, ignore invalid names.  In non-strict mode,
++               * fall back to treating them as opaque byte sequences.
+                */
+-              if (f2fs_has_strict_mode(sbi))
+-                      return -EINVAL;
+-
+-              if (name->len != entry->len)
+-                      return 1;
+-
+-              return !!memcmp(name->name, entry->name, name->len);
++              if (f2fs_has_strict_mode(sbi) || name->len != entry->len)
++                      return false;
++              return !memcmp(name->name, entry->name, name->len);
+       }
+-
+-      return ret;
++      return res == 0;
+ }
+ static void f2fs_fname_setup_ci_filename(struct inode *dir,
+@@ -188,10 +180,10 @@ static inline bool f2fs_match_name(struct f2fs_dentry_ptr *d,
+               if (cf_str->name) {
+                       struct qstr cf = {.name = cf_str->name,
+                                         .len = cf_str->len};
+-                      return !f2fs_ci_compare(parent, &cf, &entry, true);
++                      return f2fs_match_ci_name(parent, &cf, &entry, true);
+               }
+-              return !f2fs_ci_compare(parent, fname->usr_fname, &entry,
+-                                      false);
++              return f2fs_match_ci_name(parent, fname->usr_fname, &entry,
++                                        false);
+       }
+ #endif
+       if (fscrypt_match_name(fname, d->filename[bit_pos],
+@@ -1067,17 +1059,25 @@ const struct file_operations f2fs_dir_operations = {
+ static int f2fs_d_compare(const struct dentry *dentry, unsigned int len,
+                         const char *str, const struct qstr *name)
+ {
+-      struct qstr qstr = {.name = str, .len = len };
+       const struct dentry *parent = READ_ONCE(dentry->d_parent);
+-      const struct inode *inode = READ_ONCE(parent->d_inode);
+-
+-      if (!inode || !IS_CASEFOLDED(inode)) {
+-              if (len != name->len)
+-                      return -1;
+-              return memcmp(str, name->name, len);
+-      }
+-
+-      return f2fs_ci_compare(inode, name, &qstr, false);
++      const struct inode *dir = READ_ONCE(parent->d_inode);
++      const struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
++      struct qstr entry = QSTR_INIT(str, len);
++      int res;
++
++      if (!dir || !IS_CASEFOLDED(dir))
++              goto fallback;
++
++      res = utf8_strncasecmp(sbi->s_encoding, name, &entry);
++      if (res >= 0)
++              return res;
++
++      if (f2fs_has_strict_mode(sbi))
++              return -EINVAL;
++fallback:
++      if (len != name->len)
++              return 1;
++      return !!memcmp(str, name->name, len);
+ }
+ static int f2fs_d_hash(const struct dentry *dentry, struct qstr *str)
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index c22ca7d867ee5..03693d6b1c104 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2954,11 +2954,6 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
+                                                       bool hot, bool set);
+ struct dentry *f2fs_get_parent(struct dentry *child);
+-extern int f2fs_ci_compare(const struct inode *parent,
+-                         const struct qstr *name,
+-                         const struct qstr *entry,
+-                         bool quick);
+-
+ /*
+  * dir.c
+  */
+-- 
+2.25.1
+
diff --git a/queue-5.4/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch b/queue-5.4/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch
new file mode 100644 (file)
index 0000000..f4d6766
--- /dev/null
@@ -0,0 +1,37 @@
+From 80e79b519b782c173b78cf9540f0822dde6f8b49 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Jun 2020 19:45:26 +0300
+Subject: net/mlx5: DR, Fix freeing in dr_create_rc_qp()
+
+From: Denis Efremov <efremov@linux.com>
+
+[ Upstream commit 47a357de2b6b706af3c9471d5042f9ba8907031e ]
+
+Variable "in" in dr_create_rc_qp() is allocated with kvzalloc() and
+should be freed with kvfree().
+
+Fixes: 297cccebdc5a ("net/mlx5: DR, Expose an internal API to issue RDMA operations")
+Cc: stable@vger.kernel.org
+Signed-off-by: Denis Efremov <efremov@linux.com>
+Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
+index 7c77378accf04..f012aac83b10e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
+@@ -181,7 +181,7 @@ static struct mlx5dr_qp *dr_create_rc_qp(struct mlx5_core_dev *mdev,
+                                                        in, pas));
+       err = mlx5_core_create_qp(mdev, &dr_qp->mqp, in, inlen);
+-      kfree(in);
++      kvfree(in);
+       if (err) {
+               mlx5_core_warn(mdev, " Can't create QP\n");
+-- 
+2.25.1
+
index b1238c123d6cefecbb1d93d46c138c8fe6f422ff..b73c3429f0baf07870e1d4543af82ff6a81ea99d 100644 (file)
@@ -290,3 +290,7 @@ ext4-avoid-race-conditions-when-remounting-with-opti.patch
 drm-dp_mst-increase-act-retry-timeout-to-3s.patch
 drm-amd-display-use-swap-where-appropriate.patch
 x86-boot-compressed-relax-sed-symbol-type-regex-for-.patch
+block-nr_sects_write-disable-preemption-on-seqcount-.patch
+net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch
+f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch
+f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch