From 4a61268a1c97cec8208879b1e65acc83777ca023 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 22 Jun 2020 21:30:15 -0400 Subject: [PATCH] Fixes for 5.7 Signed-off-by: Sasha Levin --- ...-utf8_strncasecmp-with-unstable-name.patch | 66 ++++++++ ...-f2fs_d_compare-from-f2fs_match_name.patch | 152 ++++++++++++++++++ ...x5-dr-fix-freeing-in-dr_create_rc_qp.patch | 37 +++++ queue-5.7/series | 3 + 4 files changed, 258 insertions(+) create mode 100644 queue-5.7/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch create mode 100644 queue-5.7/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch create mode 100644 queue-5.7/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch diff --git a/queue-5.7/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch b/queue-5.7/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch new file mode 100644 index 00000000000..413cab36115 --- /dev/null +++ b/queue-5.7/f2fs-avoid-utf8_strncasecmp-with-unstable-name.patch @@ -0,0 +1,66 @@ +From ef85a057b5ffa75faeb5ffc8aa9bcf0b96b65f59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Jun 2020 13:08:05 -0700 +Subject: f2fs: avoid utf8_strncasecmp() with unstable name + +From: Eric Biggers + +[ 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: # v5.4+ +Cc: Al Viro +Cc: Daniel Rosenberg +Cc: Gabriel Krisman Bertazi +Signed-off-by: Eric Biggers +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/dir.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c +index 44eb12a00cd0e..54e90dbb09e78 100644 +--- a/fs/f2fs/dir.c ++++ b/fs/f2fs/dir.c +@@ -1076,11 +1076,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.7/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch b/queue-5.7/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch new file mode 100644 index 00000000000..5b1c22eb2c6 --- /dev/null +++ b/queue-5.7/f2fs-split-f2fs_d_compare-from-f2fs_match_name.patch @@ -0,0 +1,152 @@ +From c451a515920bdc58e07752bf901ffc02bc8594d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 May 2020 00:59:03 -0700 +Subject: f2fs: split f2fs_d_compare() from f2fs_match_name() + +From: Eric Biggers + +[ 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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 44bfc464df787..44eb12a00cd0e 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], +@@ -1080,17 +1072,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 555c84953ea81..5a0f95dfbac2b 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -3101,11 +3101,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.7/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch b/queue-5.7/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch new file mode 100644 index 00000000000..b20e17ed988 --- /dev/null +++ b/queue-5.7/net-mlx5-dr-fix-freeing-in-dr_create_rc_qp.patch @@ -0,0 +1,37 @@ +From 2dc42b46d9f30301a974d47aacce2bcfa8091a4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Jun 2020 19:45:26 +0300 +Subject: net/mlx5: DR, Fix freeing in dr_create_rc_qp() + +From: Denis Efremov + +[ 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 +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + 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 18719acb7e547..eff8bb64899d6 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 + diff --git a/queue-5.7/series b/queue-5.7/series index 24184dd9922..6405825ac83 100644 --- a/queue-5.7/series +++ b/queue-5.7/series @@ -436,3 +436,6 @@ io_uring-reap-poll-completions-while-waiting-for-refs-to-drop-on-exit.patch io_uring-fix-possible-race-condition-against-req_f_need_cleanup.patch ext4-avoid-race-conditions-when-remounting-with-opti.patch drm-dp_mst-increase-act-retry-timeout-to-3s.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 -- 2.47.3