From: Sasha Levin Date: Fri, 28 Feb 2025 04:41:23 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v6.6.81~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4a9c92d1d3d2ade6faca55b5c8effea8c0ba4470;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/ib-mlx5-set-and-get-correct-qp_num-for-a-dct-qp.patch b/queue-5.15/ib-mlx5-set-and-get-correct-qp_num-for-a-dct-qp.patch new file mode 100644 index 0000000000..7769c2a7ef --- /dev/null +++ b/queue-5.15/ib-mlx5-set-and-get-correct-qp_num-for-a-dct-qp.patch @@ -0,0 +1,50 @@ +From 32c05d58b1efaf02576efd954028712c1c6d9266 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jan 2025 14:39:46 +0200 +Subject: IB/mlx5: Set and get correct qp_num for a DCT QP + +From: Mark Zhang + +[ Upstream commit 12d044770e12c4205fa69535b4fa8a9981fea98f ] + +When a DCT QP is created on an active lag, it's dctc.port is assigned +in a round-robin way, which is from 1 to dev->lag_port. In this case +when querying this QP, we may get qp_attr.port_num > 2. +Fix this by setting qp->port when modifying a DCT QP, and read port_num +from qp->port instead of dctc.port when querying it. + +Fixes: 7c4b1ab9f167 ("IB/mlx5: Add DCT RoCE LAG support") +Signed-off-by: Mark Zhang +Reviewed-by: Maher Sanalla +Link: https://patch.msgid.link/94c76bf0adbea997f87ffa27674e0a7118ad92a9.1737290358.git.leon@kernel.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/qp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c +index d2b4db783b254..d58ed4a09cd93 100644 +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -4461,6 +4461,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr, + + set_id = mlx5_ib_get_counters_id(dev, attr->port_num - 1); + MLX5_SET(dctc, dctc, counter_set_id, set_id); ++ ++ qp->port = attr->port_num; + } else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) { + struct mlx5_ib_modify_qp_resp resp = {}; + u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {}; +@@ -4949,7 +4951,7 @@ static int mlx5_ib_dct_query_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *mqp, + } + + if (qp_attr_mask & IB_QP_PORT) +- qp_attr->port_num = MLX5_GET(dctc, dctc, port); ++ qp_attr->port_num = mqp->port; + if (qp_attr_mask & IB_QP_MIN_RNR_TIMER) + qp_attr->min_rnr_timer = MLX5_GET(dctc, dctc, min_rnr_nak); + if (qp_attr_mask & IB_QP_AV) { +-- +2.39.5 + diff --git a/queue-5.15/ovl-fix-uaf-in-ovl_dentry_update_reval-by-moving-dpu.patch b/queue-5.15/ovl-fix-uaf-in-ovl_dentry_update_reval-by-moving-dpu.patch new file mode 100644 index 0000000000..3b37944ca5 --- /dev/null +++ b/queue-5.15/ovl-fix-uaf-in-ovl_dentry_update_reval-by-moving-dpu.patch @@ -0,0 +1,71 @@ +From 8dec2b20fa70493d01edc457f87aab3b9f18aaca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Feb 2025 00:51:48 +0300 +Subject: ovl: fix UAF in ovl_dentry_update_reval by moving dput() in + ovl_link_up + +From: Vasiliy Kovalev + +[ Upstream commit c84e125fff2615b4d9c259e762596134eddd2f27 ] + +The issue was caused by dput(upper) being called before +ovl_dentry_update_reval(), while upper->d_flags was still +accessed in ovl_dentry_remote(). + +Move dput(upper) after its last use to prevent use-after-free. + +BUG: KASAN: slab-use-after-free in ovl_dentry_remote fs/overlayfs/util.c:162 [inline] +BUG: KASAN: slab-use-after-free in ovl_dentry_update_reval+0xd2/0xf0 fs/overlayfs/util.c:167 + +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:114 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0xc3/0x620 mm/kasan/report.c:488 + kasan_report+0xd9/0x110 mm/kasan/report.c:601 + ovl_dentry_remote fs/overlayfs/util.c:162 [inline] + ovl_dentry_update_reval+0xd2/0xf0 fs/overlayfs/util.c:167 + ovl_link_up fs/overlayfs/copy_up.c:610 [inline] + ovl_copy_up_one+0x2105/0x3490 fs/overlayfs/copy_up.c:1170 + ovl_copy_up_flags+0x18d/0x200 fs/overlayfs/copy_up.c:1223 + ovl_rename+0x39e/0x18c0 fs/overlayfs/dir.c:1136 + vfs_rename+0xf84/0x20a0 fs/namei.c:4893 +... + + +Fixes: b07d5cc93e1b ("ovl: update of dentry revalidate flags after copy up") +Reported-by: syzbot+316db8a1191938280eb6@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=316db8a1191938280eb6 +Signed-off-by: Vasiliy Kovalev +Link: https://lore.kernel.org/r/20250214215148.761147-1-kovalev@altlinux.org +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/overlayfs/copy_up.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 205238c73dbc5..5fc32483afed8 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -537,7 +537,6 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) + err = PTR_ERR(upper); + if (!IS_ERR(upper)) { + err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper); +- dput(upper); + + if (!err) { + /* Restore timestamps on parent (best effort) */ +@@ -545,6 +544,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) + ovl_dentry_set_upper_alias(c->dentry); + ovl_dentry_update_reval(c->dentry, upper); + } ++ dput(upper); + } + inode_unlock(udir); + if (err) +-- +2.39.5 + diff --git a/queue-5.15/ovl-pass-ofs-to-creation-operations.patch b/queue-5.15/ovl-pass-ofs-to-creation-operations.patch new file mode 100644 index 0000000000..dc38b2ac60 --- /dev/null +++ b/queue-5.15/ovl-pass-ofs-to-creation-operations.patch @@ -0,0 +1,815 @@ +From 37979f156d697a7a89ee79d406457e512e5f4ba9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 12:51:43 +0200 +Subject: ovl: pass ofs to creation operations + +From: Christian Brauner + +[ Upstream commit 576bb263450bbba6601a9f528d0cf601d97a13e6 ] + +Pass down struct ovl_fs to all creation helpers so we can ultimately +retrieve the relevant upper mount and take the mount's idmapping into +account when creating new filesystem objects. This is needed to support +idmapped base layers with overlay. + +Cc: +Tested-by: Giuseppe Scrivano +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Miklos Szeredi +Stable-dep-of: c84e125fff26 ("ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/copy_up.c | 21 +++++----- + fs/overlayfs/dir.c | 85 +++++++++++++++++++++------------------- + fs/overlayfs/overlayfs.h | 54 +++++++++++++++---------- + fs/overlayfs/readdir.c | 28 +++++++------ + fs/overlayfs/super.c | 28 +++++++------ + fs/overlayfs/util.c | 2 +- + 6 files changed, 121 insertions(+), 97 deletions(-) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 80e7ae8152fdd..205238c73dbc5 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -474,7 +474,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, + if (err) + return err; + +- temp = ovl_create_temp(indexdir, OVL_CATTR(S_IFDIR | 0)); ++ temp = ovl_create_temp(ofs, indexdir, OVL_CATTR(S_IFDIR | 0)); + err = PTR_ERR(temp); + if (IS_ERR(temp)) + goto free_name; +@@ -487,12 +487,12 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin, + if (IS_ERR(index)) { + err = PTR_ERR(index); + } else { +- err = ovl_do_rename(dir, temp, dir, index, 0); ++ err = ovl_do_rename(ofs, dir, temp, dir, index, 0); + dput(index); + } + out: + if (err) +- ovl_cleanup(dir, temp); ++ ovl_cleanup(ofs, dir, temp); + dput(temp); + free_name: + kfree(name.name); +@@ -519,6 +519,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) + int err; + struct dentry *upper; + struct dentry *upperdir = ovl_dentry_upper(c->parent); ++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); + struct inode *udir = d_inode(upperdir); + + /* Mark parent "impure" because it may now contain non-pure upper */ +@@ -535,7 +536,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c) + c->dentry->d_name.len); + err = PTR_ERR(upper); + if (!IS_ERR(upper)) { +- err = ovl_do_link(ovl_dentry_upper(c->dentry), udir, upper); ++ err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper); + dput(upper); + + if (!err) { +@@ -658,6 +659,7 @@ static void ovl_revert_cu_creds(struct ovl_cu_creds *cc) + */ + static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + { ++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); + struct inode *inode; + struct inode *udir = d_inode(c->destdir), *wdir = d_inode(c->workdir); + struct dentry *temp, *upper; +@@ -679,7 +681,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + if (err) + goto unlock; + +- temp = ovl_create_temp(c->workdir, &cattr); ++ temp = ovl_create_temp(ofs, c->workdir, &cattr); + ovl_revert_cu_creds(&cc); + + err = PTR_ERR(temp); +@@ -701,7 +703,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + if (IS_ERR(upper)) + goto cleanup; + +- err = ovl_do_rename(wdir, temp, udir, upper, 0); ++ err = ovl_do_rename(ofs, wdir, temp, udir, upper, 0); + dput(upper); + if (err) + goto cleanup; +@@ -718,7 +720,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + return err; + + cleanup: +- ovl_cleanup(wdir, temp); ++ ovl_cleanup(ofs, wdir, temp); + dput(temp); + goto unlock; + } +@@ -726,6 +728,7 @@ static int ovl_copy_up_workdir(struct ovl_copy_up_ctx *c) + /* Copyup using O_TMPFILE which does not require cross dir locking */ + static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) + { ++ struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); + struct inode *udir = d_inode(c->destdir); + struct dentry *temp, *upper; + struct ovl_cu_creds cc; +@@ -735,7 +738,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) + if (err) + return err; + +- temp = ovl_do_tmpfile(c->workdir, c->stat.mode); ++ temp = ovl_do_tmpfile(ofs, c->workdir, c->stat.mode); + ovl_revert_cu_creds(&cc); + + if (IS_ERR(temp)) +@@ -750,7 +753,7 @@ static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c) + upper = lookup_one_len(c->destname.name, c->destdir, c->destname.len); + err = PTR_ERR(upper); + if (!IS_ERR(upper)) { +- err = ovl_do_link(temp, udir, upper); ++ err = ovl_do_link(ofs, temp, udir, upper); + dput(upper); + } + inode_unlock(udir); +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 5e9005a0afaad..584b78f0bfa1a 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -23,15 +23,15 @@ MODULE_PARM_DESC(redirect_max, + + static int ovl_set_redirect(struct dentry *dentry, bool samedir); + +-int ovl_cleanup(struct inode *wdir, struct dentry *wdentry) ++int ovl_cleanup(struct ovl_fs *ofs, struct inode *wdir, struct dentry *wdentry) + { + int err; + + dget(wdentry); + if (d_is_dir(wdentry)) +- err = ovl_do_rmdir(wdir, wdentry); ++ err = ovl_do_rmdir(ofs, wdir, wdentry); + else +- err = ovl_do_unlink(wdir, wdentry); ++ err = ovl_do_unlink(ofs, wdir, wdentry); + dput(wdentry); + + if (err) { +@@ -42,7 +42,7 @@ int ovl_cleanup(struct inode *wdir, struct dentry *wdentry) + return err; + } + +-struct dentry *ovl_lookup_temp(struct dentry *workdir) ++struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir) + { + struct dentry *temp; + char name[20]; +@@ -70,11 +70,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs) + struct inode *wdir = workdir->d_inode; + + if (!ofs->whiteout) { +- whiteout = ovl_lookup_temp(workdir); ++ whiteout = ovl_lookup_temp(ofs, workdir); + if (IS_ERR(whiteout)) + goto out; + +- err = ovl_do_whiteout(wdir, whiteout); ++ err = ovl_do_whiteout(ofs, wdir, whiteout); + if (err) { + dput(whiteout); + whiteout = ERR_PTR(err); +@@ -84,11 +84,11 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs) + } + + if (ofs->share_whiteout) { +- whiteout = ovl_lookup_temp(workdir); ++ whiteout = ovl_lookup_temp(ofs, workdir); + if (IS_ERR(whiteout)) + goto out; + +- err = ovl_do_link(ofs->whiteout, wdir, whiteout); ++ err = ovl_do_link(ofs, ofs->whiteout, wdir, whiteout); + if (!err) + goto out; + +@@ -122,27 +122,28 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct inode *dir, + if (d_is_dir(dentry)) + flags = RENAME_EXCHANGE; + +- err = ovl_do_rename(wdir, whiteout, dir, dentry, flags); ++ err = ovl_do_rename(ofs, wdir, whiteout, dir, dentry, flags); + if (err) + goto kill_whiteout; + if (flags) +- ovl_cleanup(wdir, dentry); ++ ovl_cleanup(ofs, wdir, dentry); + + out: + dput(whiteout); + return err; + + kill_whiteout: +- ovl_cleanup(wdir, whiteout); ++ ovl_cleanup(ofs, wdir, whiteout); + goto out; + } + +-int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) ++int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir, ++ struct dentry **newdentry, umode_t mode) + { + int err; + struct dentry *d, *dentry = *newdentry; + +- err = ovl_do_mkdir(dir, dentry, mode); ++ err = ovl_do_mkdir(ofs, dir, dentry, mode); + if (err) + return err; + +@@ -167,8 +168,8 @@ int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode) + return 0; + } + +-struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, +- struct ovl_cattr *attr) ++struct dentry *ovl_create_real(struct ovl_fs *ofs, struct inode *dir, ++ struct dentry *newdentry, struct ovl_cattr *attr) + { + int err; + +@@ -180,28 +181,28 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, + goto out; + + if (attr->hardlink) { +- err = ovl_do_link(attr->hardlink, dir, newdentry); ++ err = ovl_do_link(ofs, attr->hardlink, dir, newdentry); + } else { + switch (attr->mode & S_IFMT) { + case S_IFREG: +- err = ovl_do_create(dir, newdentry, attr->mode); ++ err = ovl_do_create(ofs, dir, newdentry, attr->mode); + break; + + case S_IFDIR: + /* mkdir is special... */ +- err = ovl_mkdir_real(dir, &newdentry, attr->mode); ++ err = ovl_mkdir_real(ofs, dir, &newdentry, attr->mode); + break; + + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: + case S_IFSOCK: +- err = ovl_do_mknod(dir, newdentry, attr->mode, ++ err = ovl_do_mknod(ofs, dir, newdentry, attr->mode, + attr->rdev); + break; + + case S_IFLNK: +- err = ovl_do_symlink(dir, newdentry, attr->link); ++ err = ovl_do_symlink(ofs, dir, newdentry, attr->link); + break; + + default: +@@ -223,10 +224,11 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, + return newdentry; + } + +-struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr) ++struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, ++ struct ovl_cattr *attr) + { +- return ovl_create_real(d_inode(workdir), ovl_lookup_temp(workdir), +- attr); ++ return ovl_create_real(ofs, d_inode(workdir), ++ ovl_lookup_temp(ofs, workdir), attr); + } + + static int ovl_set_opaque_xerr(struct dentry *dentry, struct dentry *upper, +@@ -329,7 +331,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, + attr->mode &= ~current_umask(); + + inode_lock_nested(udir, I_MUTEX_PARENT); +- newdentry = ovl_create_real(udir, ++ newdentry = ovl_create_real(ofs, udir, + lookup_one_len(dentry->d_name.name, + upperdir, + dentry->d_name.len), +@@ -352,7 +354,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, + return err; + + out_cleanup: +- ovl_cleanup(udir, newdentry); ++ ovl_cleanup(ofs, udir, newdentry); + dput(newdentry); + goto out_unlock; + } +@@ -360,6 +362,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, + static struct dentry *ovl_clear_empty(struct dentry *dentry, + struct list_head *list) + { ++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *workdir = ovl_workdir(dentry); + struct inode *wdir = workdir->d_inode; + struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); +@@ -390,7 +393,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, + if (upper->d_parent->d_inode != udir) + goto out_unlock; + +- opaquedir = ovl_create_temp(workdir, OVL_CATTR(stat.mode)); ++ opaquedir = ovl_create_temp(ofs, workdir, OVL_CATTR(stat.mode)); + err = PTR_ERR(opaquedir); + if (IS_ERR(opaquedir)) + goto out_unlock; +@@ -409,12 +412,12 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, + if (err) + goto out_cleanup; + +- err = ovl_do_rename(wdir, opaquedir, udir, upper, RENAME_EXCHANGE); ++ err = ovl_do_rename(ofs, wdir, opaquedir, udir, upper, RENAME_EXCHANGE); + if (err) + goto out_cleanup; + +- ovl_cleanup_whiteouts(upper, list); +- ovl_cleanup(wdir, upper); ++ ovl_cleanup_whiteouts(ofs, upper, list); ++ ovl_cleanup(ofs, wdir, upper); + unlock_rename(workdir, upperdir); + + /* dentry's upper doesn't match now, get rid of it */ +@@ -423,7 +426,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, + return opaquedir; + + out_cleanup: +- ovl_cleanup(wdir, opaquedir); ++ ovl_cleanup(ofs, wdir, opaquedir); + dput(opaquedir); + out_unlock: + unlock_rename(workdir, upperdir); +@@ -494,7 +497,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, + if (d_is_negative(upper) || !IS_WHITEOUT(d_inode(upper))) + goto out_dput; + +- newdentry = ovl_create_temp(workdir, cattr); ++ newdentry = ovl_create_temp(ofs, workdir, cattr); + err = PTR_ERR(newdentry); + if (IS_ERR(newdentry)) + goto out_dput; +@@ -532,20 +535,20 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, + if (err) + goto out_cleanup; + +- err = ovl_do_rename(wdir, newdentry, udir, upper, ++ err = ovl_do_rename(ofs, wdir, newdentry, udir, upper, + RENAME_EXCHANGE); + if (err) + goto out_cleanup; + +- ovl_cleanup(wdir, upper); ++ ovl_cleanup(ofs, wdir, upper); + } else { +- err = ovl_do_rename(wdir, newdentry, udir, upper, 0); ++ err = ovl_do_rename(ofs, wdir, newdentry, udir, upper, 0); + if (err) + goto out_cleanup; + } + err = ovl_instantiate(dentry, inode, newdentry, hardlink); + if (err) { +- ovl_cleanup(udir, newdentry); ++ ovl_cleanup(ofs, udir, newdentry); + dput(newdentry); + } + out_dput: +@@ -560,7 +563,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, + return err; + + out_cleanup: +- ovl_cleanup(wdir, newdentry); ++ ovl_cleanup(ofs, wdir, newdentry); + dput(newdentry); + goto out_dput; + } +@@ -814,6 +817,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, + static int ovl_remove_upper(struct dentry *dentry, bool is_dir, + struct list_head *list) + { ++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); + struct inode *dir = upperdir->d_inode; + struct dentry *upper; +@@ -840,9 +844,9 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir, + goto out_dput_upper; + + if (is_dir) +- err = vfs_rmdir(&init_user_ns, dir, upper); ++ err = ovl_do_rmdir(ofs, dir, upper); + else +- err = vfs_unlink(&init_user_ns, dir, upper, NULL); ++ err = ovl_do_unlink(ofs, dir, upper); + ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry)); + + /* +@@ -1107,6 +1111,7 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, + bool samedir = olddir == newdir; + struct dentry *opaquedir = NULL; + const struct cred *old_cred = NULL; ++ struct ovl_fs *ofs = OVL_FS(old->d_sb); + LIST_HEAD(list); + + err = -EINVAL; +@@ -1263,13 +1268,13 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, + if (err) + goto out_dput; + +- err = ovl_do_rename(old_upperdir->d_inode, olddentry, ++ err = ovl_do_rename(ofs, old_upperdir->d_inode, olddentry, + new_upperdir->d_inode, newdentry, flags); + if (err) + goto out_dput; + + if (cleanup_whiteout) +- ovl_cleanup(old_upperdir->d_inode, newdentry); ++ ovl_cleanup(ofs, old_upperdir->d_inode, newdentry); + + if (overwrite && d_inode(new)) { + if (new_is_dir) +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 3f4655b9c71ca..43b211cf437cc 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -122,7 +122,8 @@ static inline const char *ovl_xattr(struct ovl_fs *ofs, enum ovl_xattr ox) + return ovl_xattr_table[ox][ofs->config.userxattr]; + } + +-static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) ++static inline int ovl_do_rmdir(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry) + { + int err = vfs_rmdir(&init_user_ns, dir, dentry); + +@@ -130,7 +131,8 @@ static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) + return err; + } + +-static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry) ++static inline int ovl_do_unlink(struct ovl_fs *ofs, struct inode *dir, ++ struct dentry *dentry) + { + int err = vfs_unlink(&init_user_ns, dir, dentry, NULL); + +@@ -138,8 +140,8 @@ static inline int ovl_do_unlink(struct inode *dir, struct dentry *dentry) + return err; + } + +-static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir, +- struct dentry *new_dentry) ++static inline int ovl_do_link(struct ovl_fs *ofs, struct dentry *old_dentry, ++ struct inode *dir, struct dentry *new_dentry) + { + int err = vfs_link(old_dentry, &init_user_ns, dir, new_dentry, NULL); + +@@ -147,7 +149,8 @@ static inline int ovl_do_link(struct dentry *old_dentry, struct inode *dir, + return err; + } + +-static inline int ovl_do_create(struct inode *dir, struct dentry *dentry, ++static inline int ovl_do_create(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry, + umode_t mode) + { + int err = vfs_create(&init_user_ns, dir, dentry, mode, true); +@@ -156,7 +159,8 @@ static inline int ovl_do_create(struct inode *dir, struct dentry *dentry, + return err; + } + +-static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry, ++static inline int ovl_do_mkdir(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry, + umode_t mode) + { + int err = vfs_mkdir(&init_user_ns, dir, dentry, mode); +@@ -164,7 +168,8 @@ static inline int ovl_do_mkdir(struct inode *dir, struct dentry *dentry, + return err; + } + +-static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry, ++static inline int ovl_do_mknod(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t dev) + { + int err = vfs_mknod(&init_user_ns, dir, dentry, mode, dev); +@@ -173,7 +178,8 @@ static inline int ovl_do_mknod(struct inode *dir, struct dentry *dentry, + return err; + } + +-static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry, ++static inline int ovl_do_symlink(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry, + const char *oldname) + { + int err = vfs_symlink(&init_user_ns, dir, dentry, oldname); +@@ -233,9 +239,9 @@ static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry, + return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox)); + } + +-static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, +- struct inode *newdir, struct dentry *newdentry, +- unsigned int flags) ++static inline int ovl_do_rename(struct ovl_fs *ofs, struct inode *olddir, ++ struct dentry *olddentry, struct inode *newdir, ++ struct dentry *newdentry, unsigned int flags) + { + int err; + struct renamedata rd = { +@@ -257,14 +263,16 @@ static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, + return err; + } + +-static inline int ovl_do_whiteout(struct inode *dir, struct dentry *dentry) ++static inline int ovl_do_whiteout(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *dentry) + { + int err = vfs_whiteout(&init_user_ns, dir, dentry); + pr_debug("whiteout(%pd2) = %i\n", dentry, err); + return err; + } + +-static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode) ++static inline struct dentry *ovl_do_tmpfile(struct ovl_fs *ofs, ++ struct dentry *dentry, umode_t mode) + { + struct dentry *ret = vfs_tmpfile(&init_user_ns, dentry, mode, 0); + int err = PTR_ERR_OR_ZERO(ret); +@@ -483,12 +491,13 @@ static inline int ovl_verify_upper(struct ovl_fs *ofs, struct dentry *index, + extern const struct file_operations ovl_dir_operations; + struct file *ovl_dir_real_file(const struct file *file, bool want_upper); + int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list); +-void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); ++void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper, ++ struct list_head *list); + void ovl_cache_free(struct list_head *list); + void ovl_dir_cache_free(struct inode *inode); + int ovl_check_d_type_supported(struct path *realpath); +-int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, +- struct dentry *dentry, int level); ++int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir, ++ struct vfsmount *mnt, struct dentry *dentry, int level); + int ovl_indexdir_cleanup(struct ovl_fs *ofs); + + /* +@@ -583,12 +592,15 @@ struct ovl_cattr { + + #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) }) + +-int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode); +-struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry, ++int ovl_mkdir_real(struct ovl_fs *ofs, struct inode *dir, ++ struct dentry **newdentry, umode_t mode); ++struct dentry *ovl_create_real(struct ovl_fs *ofs, ++ struct inode *dir, struct dentry *newdentry, ++ struct ovl_cattr *attr); ++int ovl_cleanup(struct ovl_fs *ofs, struct inode *dir, struct dentry *dentry); ++struct dentry *ovl_lookup_temp(struct ovl_fs *ofs, struct dentry *workdir); ++struct dentry *ovl_create_temp(struct ovl_fs *ofs, struct dentry *workdir, + struct ovl_cattr *attr); +-int ovl_cleanup(struct inode *dir, struct dentry *dentry); +-struct dentry *ovl_lookup_temp(struct dentry *workdir); +-struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr); + + /* file.c */ + extern const struct file_operations ovl_file_operations; +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index c7b542331065c..9c580ef8cd6fc 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -1001,7 +1001,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) + return err; + } + +-void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) ++void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper, ++ struct list_head *list) + { + struct ovl_cache_entry *p; + +@@ -1020,7 +1021,7 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) + continue; + } + if (dentry->d_inode) +- ovl_cleanup(upper->d_inode, dentry); ++ ovl_cleanup(ofs, upper->d_inode, dentry); + dput(dentry); + } + inode_unlock(upper->d_inode); +@@ -1064,7 +1065,8 @@ int ovl_check_d_type_supported(struct path *realpath) + + #define OVL_INCOMPATDIR_NAME "incompat" + +-static int ovl_workdir_cleanup_recurse(struct path *path, int level) ++static int ovl_workdir_cleanup_recurse(struct ovl_fs *ofs, struct path *path, ++ int level) + { + int err; + struct inode *dir = path->dentry->d_inode; +@@ -1115,7 +1117,7 @@ static int ovl_workdir_cleanup_recurse(struct path *path, int level) + if (IS_ERR(dentry)) + continue; + if (dentry->d_inode) +- err = ovl_workdir_cleanup(dir, path->mnt, dentry, level); ++ err = ovl_workdir_cleanup(ofs, dir, path->mnt, dentry, level); + dput(dentry); + if (err) + break; +@@ -1126,24 +1128,24 @@ static int ovl_workdir_cleanup_recurse(struct path *path, int level) + return err; + } + +-int ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, +- struct dentry *dentry, int level) ++int ovl_workdir_cleanup(struct ovl_fs *ofs, struct inode *dir, ++ struct vfsmount *mnt, struct dentry *dentry, int level) + { + int err; + + if (!d_is_dir(dentry) || level > 1) { +- return ovl_cleanup(dir, dentry); ++ return ovl_cleanup(ofs, dir, dentry); + } + +- err = ovl_do_rmdir(dir, dentry); ++ err = ovl_do_rmdir(ofs, dir, dentry); + if (err) { + struct path path = { .mnt = mnt, .dentry = dentry }; + + inode_unlock(dir); +- err = ovl_workdir_cleanup_recurse(&path, level + 1); ++ err = ovl_workdir_cleanup_recurse(ofs, &path, level + 1); + inode_lock_nested(dir, I_MUTEX_PARENT); + if (!err) +- err = ovl_cleanup(dir, dentry); ++ err = ovl_cleanup(ofs, dir, dentry); + } + + return err; +@@ -1187,7 +1189,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) + } + /* Cleanup leftover from index create/cleanup attempt */ + if (index->d_name.name[0] == '#') { +- err = ovl_workdir_cleanup(dir, path.mnt, index, 1); ++ err = ovl_workdir_cleanup(ofs, dir, path.mnt, index, 1); + if (err) + break; + goto next; +@@ -1197,7 +1199,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) + goto next; + } else if (err == -ESTALE) { + /* Cleanup stale index entries */ +- err = ovl_cleanup(dir, index); ++ err = ovl_cleanup(ofs, dir, index); + } else if (err != -ENOENT) { + /* + * Abort mount to avoid corrupting the index if +@@ -1213,7 +1215,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs) + err = ovl_cleanup_and_whiteout(ofs, dir, index); + } else { + /* Cleanup orphan index entries */ +- err = ovl_cleanup(dir, index); ++ err = ovl_cleanup(ofs, dir, index); + } + + if (err) +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 1dad3dabe0099..2ad1f8652ce61 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -784,7 +784,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, + goto out_unlock; + + retried = true; +- err = ovl_workdir_cleanup(dir, mnt, work, 0); ++ err = ovl_workdir_cleanup(ofs, dir, mnt, work, 0); + dput(work); + if (err == -EINVAL) { + work = ERR_PTR(err); +@@ -793,7 +793,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, + goto retry; + } + +- err = ovl_mkdir_real(dir, &work, attr.ia_mode); ++ err = ovl_mkdir_real(ofs, dir, &work, attr.ia_mode); + if (err) + goto out_dput; + +@@ -1262,8 +1262,9 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, + * Returns 1 if RENAME_WHITEOUT is supported, 0 if not supported and + * negative values if error is encountered. + */ +-static int ovl_check_rename_whiteout(struct dentry *workdir) ++static int ovl_check_rename_whiteout(struct ovl_fs *ofs) + { ++ struct dentry *workdir = ofs->workdir; + struct inode *dir = d_inode(workdir); + struct dentry *temp; + struct dentry *dest; +@@ -1273,12 +1274,12 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) + + inode_lock_nested(dir, I_MUTEX_PARENT); + +- temp = ovl_create_temp(workdir, OVL_CATTR(S_IFREG | 0)); ++ temp = ovl_create_temp(ofs, workdir, OVL_CATTR(S_IFREG | 0)); + err = PTR_ERR(temp); + if (IS_ERR(temp)) + goto out_unlock; + +- dest = ovl_lookup_temp(workdir); ++ dest = ovl_lookup_temp(ofs, workdir); + err = PTR_ERR(dest); + if (IS_ERR(dest)) { + dput(temp); +@@ -1287,7 +1288,7 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) + + /* Name is inline and stable - using snapshot as a copy helper */ + take_dentry_name_snapshot(&name, temp); +- err = ovl_do_rename(dir, temp, dir, dest, RENAME_WHITEOUT); ++ err = ovl_do_rename(ofs, dir, temp, dir, dest, RENAME_WHITEOUT); + if (err) { + if (err == -EINVAL) + err = 0; +@@ -1303,11 +1304,11 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) + + /* Best effort cleanup of whiteout and temp file */ + if (err) +- ovl_cleanup(dir, whiteout); ++ ovl_cleanup(ofs, dir, whiteout); + dput(whiteout); + + cleanup_temp: +- ovl_cleanup(dir, temp); ++ ovl_cleanup(ofs, dir, temp); + release_dentry_name_snapshot(&name); + dput(temp); + dput(dest); +@@ -1318,7 +1319,8 @@ static int ovl_check_rename_whiteout(struct dentry *workdir) + return err; + } + +-static struct dentry *ovl_lookup_or_create(struct dentry *parent, ++static struct dentry *ovl_lookup_or_create(struct ovl_fs *ofs, ++ struct dentry *parent, + const char *name, umode_t mode) + { + size_t len = strlen(name); +@@ -1327,7 +1329,7 @@ static struct dentry *ovl_lookup_or_create(struct dentry *parent, + inode_lock_nested(parent->d_inode, I_MUTEX_PARENT); + child = lookup_one_len(name, parent, len); + if (!IS_ERR(child) && !child->d_inode) +- child = ovl_create_real(parent->d_inode, child, ++ child = ovl_create_real(ofs, parent->d_inode, child, + OVL_CATTR(mode)); + inode_unlock(parent->d_inode); + dput(parent); +@@ -1349,7 +1351,7 @@ static int ovl_create_volatile_dirty(struct ovl_fs *ofs) + const char *const *name = volatile_path; + + for (ctr = ARRAY_SIZE(volatile_path); ctr; ctr--, name++) { +- d = ovl_lookup_or_create(d, *name, ctr > 1 ? S_IFDIR : S_IFREG); ++ d = ovl_lookup_or_create(ofs, d, *name, ctr > 1 ? S_IFDIR : S_IFREG); + if (IS_ERR(d)) + return PTR_ERR(d); + } +@@ -1397,7 +1399,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, + pr_warn("upper fs needs to support d_type.\n"); + + /* Check if upper/work fs supports O_TMPFILE */ +- temp = ovl_do_tmpfile(ofs->workdir, S_IFREG | 0); ++ temp = ovl_do_tmpfile(ofs, ofs->workdir, S_IFREG | 0); + ofs->tmpfile = !IS_ERR(temp); + if (ofs->tmpfile) + dput(temp); +@@ -1406,7 +1408,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, + + + /* Check if upper/work fs supports RENAME_WHITEOUT */ +- err = ovl_check_rename_whiteout(ofs->workdir); ++ err = ovl_check_rename_whiteout(ofs); + if (err < 0) + goto out; + +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index eea9ec8f8c57a..8a9980ab2ad8f 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -866,7 +866,7 @@ static void ovl_cleanup_index(struct dentry *dentry) + dir, index); + } else { + /* Cleanup orphan index entries */ +- err = ovl_cleanup(dir, index); ++ err = ovl_cleanup(ofs, dir, index); + } + + inode_unlock(dir); +-- +2.39.5 + diff --git a/queue-5.15/ovl-use-wrappers-to-all-vfs_-xattr-calls.patch b/queue-5.15/ovl-use-wrappers-to-all-vfs_-xattr-calls.patch new file mode 100644 index 0000000000..4503667d9c --- /dev/null +++ b/queue-5.15/ovl-use-wrappers-to-all-vfs_-xattr-calls.patch @@ -0,0 +1,449 @@ +From 2e851b734612edad5c0cdbc46191b7cdb13e9efb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 12:51:42 +0200 +Subject: ovl: use wrappers to all vfs_*xattr() calls + +From: Amir Goldstein + +[ Upstream commit c914c0e27eb0843b7cf3bec71d6f34d53a3a671e ] + +Use helpers ovl_*xattr() to access user/trusted.overlay.* xattrs +and use helpers ovl_do_*xattr() to access generic xattrs. This is a +preparatory patch for using idmapped base layers with overlay. + +Note that a few of those places called vfs_*xattr() calls directly to +reduce the amount of debug output. But as Miklos pointed out since +overlayfs has been stable for quite some time the debug output isn't all +that relevant anymore and the additional debug in all locations was +actually quite helpful when developing this patch series. + +Cc: +Tested-by: Giuseppe Scrivano +Reviewed-by: Christian Brauner (Microsoft) +Signed-off-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Miklos Szeredi +Stable-dep-of: c84e125fff26 ("ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/copy_up.c | 21 +++++++++++---------- + fs/overlayfs/dir.c | 15 ++++++++------- + fs/overlayfs/inode.c | 17 +++++++++-------- + fs/overlayfs/namei.c | 6 +++--- + fs/overlayfs/overlayfs.h | 38 ++++++++++++++++++++++++++++---------- + fs/overlayfs/readdir.c | 4 ++-- + fs/overlayfs/super.c | 12 ++++++------ + fs/overlayfs/util.c | 16 ++++++++-------- + 8 files changed, 75 insertions(+), 54 deletions(-) + +diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c +index 0ed70eff9cb9e..80e7ae8152fdd 100644 +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -117,7 +117,7 @@ int ovl_copy_xattr(struct super_block *sb, struct dentry *old, + goto retry; + } + +- error = vfs_setxattr(&init_user_ns, new, name, value, size, 0); ++ error = ovl_do_setxattr(OVL_FS(sb), new, name, value, size, 0); + if (error) { + if (error != -EOPNOTSUPP || ovl_must_copy_xattr(name)) + break; +@@ -433,7 +433,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper, + if (IS_ERR(fh)) + return PTR_ERR(fh); + +- err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); ++ err = ovl_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len); + + kfree(fh); + return err; +@@ -868,12 +868,13 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode, + return true; + } + +-static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) ++static ssize_t ovl_getxattr_value(struct ovl_fs *ofs, struct dentry *dentry, ++ char *name, char **value) + { + ssize_t res; + char *buf; + +- res = vfs_getxattr(&init_user_ns, dentry, name, NULL, 0); ++ res = ovl_do_getxattr(ofs, dentry, name, NULL, 0); + if (res == -ENODATA || res == -EOPNOTSUPP) + res = 0; + +@@ -882,7 +883,7 @@ static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value) + if (!buf) + return -ENOMEM; + +- res = vfs_getxattr(&init_user_ns, dentry, name, buf, res); ++ res = ovl_do_getxattr(ofs, dentry, name, buf, res); + if (res < 0) + kfree(buf); + else +@@ -909,8 +910,8 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) + return -EIO; + + if (c->stat.size) { +- err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS, +- &capability); ++ err = cap_size = ovl_getxattr_value(ofs, upperpath.dentry, ++ XATTR_NAME_CAPS, &capability); + if (cap_size < 0) + goto out; + } +@@ -924,14 +925,14 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) + * don't want that to happen for normal copy-up operation. + */ + if (capability) { +- err = vfs_setxattr(&init_user_ns, upperpath.dentry, +- XATTR_NAME_CAPS, capability, cap_size, 0); ++ err = ovl_do_setxattr(ofs, upperpath.dentry, XATTR_NAME_CAPS, ++ capability, cap_size, 0); + if (err) + goto out_free; + } + + +- err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); ++ err = ovl_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY); + if (err) + goto out_free; + +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 519193ce7d575..5e9005a0afaad 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -431,8 +431,8 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry, + return ERR_PTR(err); + } + +-static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, +- const struct posix_acl *acl) ++static int ovl_set_upper_acl(struct ovl_fs *ofs, struct dentry *upperdentry, ++ const char *name, const struct posix_acl *acl) + { + void *buffer; + size_t size; +@@ -450,7 +450,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, + if (err < 0) + goto out_free; + +- err = vfs_setxattr(&init_user_ns, upperdentry, name, buffer, size, XATTR_CREATE); ++ err = ovl_do_setxattr(ofs, upperdentry, name, buffer, size, XATTR_CREATE); + out_free: + kfree(buffer); + return err; +@@ -459,6 +459,7 @@ static int ovl_set_upper_acl(struct dentry *upperdentry, const char *name, + static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, + struct ovl_cattr *cattr) + { ++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *workdir = ovl_workdir(dentry); + struct inode *wdir = workdir->d_inode; + struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent); +@@ -515,13 +516,13 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, + goto out_cleanup; + } + if (!hardlink) { +- err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_ACCESS, +- acl); ++ err = ovl_set_upper_acl(ofs, newdentry, ++ XATTR_NAME_POSIX_ACL_ACCESS, acl); + if (err) + goto out_cleanup; + +- err = ovl_set_upper_acl(newdentry, XATTR_NAME_POSIX_ACL_DEFAULT, +- default_acl); ++ err = ovl_set_upper_acl(ofs, newdentry, ++ XATTR_NAME_POSIX_ACL_DEFAULT, default_acl); + if (err) + goto out_cleanup; + } +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index 7961d6888c520..aa8513aac4728 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -342,6 +342,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, + const void *value, size_t size, int flags) + { + int err; ++ struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *upperdentry = ovl_i_dentry_upper(inode); + struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); + const struct cred *old_cred; +@@ -367,12 +368,12 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, + } + + old_cred = ovl_override_creds(dentry->d_sb); +- if (value) +- err = vfs_setxattr(&init_user_ns, realdentry, name, value, size, +- flags); +- else { ++ if (value) { ++ err = ovl_do_setxattr(ofs, realdentry, name, value, size, ++ flags); ++ } else { + WARN_ON(flags != XATTR_REPLACE); +- err = vfs_removexattr(&init_user_ns, realdentry, name); ++ err = ovl_do_removexattr(ofs, realdentry, name); + } + revert_creds(old_cred); + +@@ -887,8 +888,8 @@ static int ovl_set_nlink_common(struct dentry *dentry, + if (WARN_ON(len >= sizeof(buf))) + return -EIO; + +- return ovl_do_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry), +- OVL_XATTR_NLINK, buf, len); ++ return ovl_setxattr(OVL_FS(inode->i_sb), ovl_dentry_upper(dentry), ++ OVL_XATTR_NLINK, buf, len); + } + + int ovl_set_nlink_upper(struct dentry *dentry) +@@ -913,7 +914,7 @@ unsigned int ovl_get_nlink(struct ovl_fs *ofs, struct dentry *lowerdentry, + if (!lowerdentry || !upperdentry || d_inode(lowerdentry)->i_nlink == 1) + return fallback; + +- err = ovl_do_getxattr(ofs, upperdentry, OVL_XATTR_NLINK, ++ err = ovl_getxattr(ofs, upperdentry, OVL_XATTR_NLINK, + &buf, sizeof(buf) - 1); + if (err < 0) + goto fail; +diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c +index 9c055d11a95de..00d74311aa0d3 100644 +--- a/fs/overlayfs/namei.c ++++ b/fs/overlayfs/namei.c +@@ -111,7 +111,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry, + int res, err; + struct ovl_fh *fh = NULL; + +- res = ovl_do_getxattr(ofs, dentry, ox, NULL, 0); ++ res = ovl_getxattr(ofs, dentry, ox, NULL, 0); + if (res < 0) { + if (res == -ENODATA || res == -EOPNOTSUPP) + return NULL; +@@ -125,7 +125,7 @@ static struct ovl_fh *ovl_get_fh(struct ovl_fs *ofs, struct dentry *dentry, + if (!fh) + return ERR_PTR(-ENOMEM); + +- res = ovl_do_getxattr(ofs, dentry, ox, fh->buf, res); ++ res = ovl_getxattr(ofs, dentry, ox, fh->buf, res); + if (res < 0) + goto fail; + +@@ -464,7 +464,7 @@ int ovl_verify_set_fh(struct ovl_fs *ofs, struct dentry *dentry, + + err = ovl_verify_fh(ofs, dentry, ox, fh); + if (set && err == -ENODATA) +- err = ovl_do_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); ++ err = ovl_setxattr(ofs, dentry, ox, fh->buf, fh->fb.len); + if (err) + goto fail; + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index a96b67586f817..3f4655b9c71ca 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -183,10 +183,9 @@ static inline int ovl_do_symlink(struct inode *dir, struct dentry *dentry, + } + + static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, void *value, ++ const char *name, void *value, + size_t size) + { +- const char *name = ovl_xattr(ofs, ox); + int err = vfs_getxattr(&init_user_ns, dentry, name, value, size); + int len = (value && err > 0) ? err : 0; + +@@ -195,26 +194,45 @@ static inline ssize_t ovl_do_getxattr(struct ovl_fs *ofs, struct dentry *dentry, + return err; + } + ++static inline ssize_t ovl_getxattr(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, void *value, ++ size_t size) ++{ ++ return ovl_do_getxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size); ++} ++ + static inline int ovl_do_setxattr(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox, const void *value, +- size_t size) ++ const char *name, const void *value, ++ size_t size, int flags) + { +- const char *name = ovl_xattr(ofs, ox); +- int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, 0); +- pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, 0) = %i\n", +- dentry, name, min((int)size, 48), value, size, err); ++ int err = vfs_setxattr(&init_user_ns, dentry, name, value, size, flags); ++ ++ pr_debug("setxattr(%pd2, \"%s\", \"%*pE\", %zu, %d) = %i\n", ++ dentry, name, min((int)size, 48), value, size, flags, err); + return err; + } + ++static inline int ovl_setxattr(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox, const void *value, ++ size_t size) ++{ ++ return ovl_do_setxattr(ofs, dentry, ovl_xattr(ofs, ox), value, size, 0); ++} ++ + static inline int ovl_do_removexattr(struct ovl_fs *ofs, struct dentry *dentry, +- enum ovl_xattr ox) ++ const char *name) + { +- const char *name = ovl_xattr(ofs, ox); + int err = vfs_removexattr(&init_user_ns, dentry, name); + pr_debug("removexattr(%pd2, \"%s\") = %i\n", dentry, name, err); + return err; + } + ++static inline int ovl_removexattr(struct ovl_fs *ofs, struct dentry *dentry, ++ enum ovl_xattr ox) ++{ ++ return ovl_do_removexattr(ofs, dentry, ovl_xattr(ofs, ox)); ++} ++ + static inline int ovl_do_rename(struct inode *olddir, struct dentry *olddentry, + struct inode *newdir, struct dentry *newdentry, + unsigned int flags) +diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c +index 150fdf3bc68d4..c7b542331065c 100644 +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -623,8 +623,8 @@ static struct ovl_dir_cache *ovl_cache_get_impure(struct path *path) + * Removing the "impure" xattr is best effort. + */ + if (!ovl_want_write(dentry)) { +- ovl_do_removexattr(ofs, ovl_dentry_upper(dentry), +- OVL_XATTR_IMPURE); ++ ovl_removexattr(ofs, ovl_dentry_upper(dentry), ++ OVL_XATTR_IMPURE); + ovl_drop_write(dentry); + } + ovl_clear_flag(OVL_IMPURE, d_inode(dentry)); +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 5310271cf2e38..1dad3dabe0099 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -815,13 +815,13 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, + * allowed as upper are limited to "normal" ones, where checking + * for the above two errors is sufficient. + */ +- err = vfs_removexattr(&init_user_ns, work, +- XATTR_NAME_POSIX_ACL_DEFAULT); ++ err = ovl_do_removexattr(ofs, work, ++ XATTR_NAME_POSIX_ACL_DEFAULT); + if (err && err != -ENODATA && err != -EOPNOTSUPP) + goto out_dput; + +- err = vfs_removexattr(&init_user_ns, work, +- XATTR_NAME_POSIX_ACL_ACCESS); ++ err = ovl_do_removexattr(ofs, work, ++ XATTR_NAME_POSIX_ACL_ACCESS); + if (err && err != -ENODATA && err != -EOPNOTSUPP) + goto out_dput; + +@@ -1417,7 +1417,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, + /* + * Check if upper/work fs supports (trusted|user).overlay.* xattr + */ +- err = ovl_do_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); ++ err = ovl_setxattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE, "0", 1); + if (err) { + pr_warn("failed to set xattr on upper\n"); + ofs->noxattr = true; +@@ -1438,7 +1438,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs, + pr_info("try mounting with 'userxattr' option\n"); + err = 0; + } else { +- ovl_do_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE); ++ ovl_removexattr(ofs, ofs->workdir, OVL_XATTR_OPAQUE); + } + + /* +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index 747b47048b3aa..eea9ec8f8c57a 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -586,7 +586,7 @@ bool ovl_check_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry) + { + int res; + +- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); ++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_ORIGIN, NULL, 0); + + /* Zero size value means "copied up but origin unknown" */ + if (res >= 0) +@@ -604,7 +604,7 @@ bool ovl_check_dir_xattr(struct super_block *sb, struct dentry *dentry, + if (!d_is_dir(dentry)) + return false; + +- res = ovl_do_getxattr(OVL_FS(sb), dentry, ox, &val, 1); ++ res = ovl_getxattr(OVL_FS(sb), dentry, ox, &val, 1); + if (res == 1 && val == 'y') + return true; + +@@ -644,7 +644,7 @@ int ovl_check_setxattr(struct ovl_fs *ofs, struct dentry *upperdentry, + if (ofs->noxattr) + return xerr; + +- err = ovl_do_setxattr(ofs, upperdentry, ox, value, size); ++ err = ovl_setxattr(ofs, upperdentry, ox, value, size); + + if (err == -EOPNOTSUPP) { + pr_warn("cannot set %s xattr on upper\n", ovl_xattr(ofs, ox)); +@@ -684,7 +684,7 @@ void ovl_check_protattr(struct inode *inode, struct dentry *upper) + char buf[OVL_PROTATTR_MAX+1]; + int res, n; + +- res = ovl_do_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf, ++ res = ovl_getxattr(ofs, upper, OVL_XATTR_PROTATTR, buf, + OVL_PROTATTR_MAX); + if (res < 0) + return; +@@ -740,7 +740,7 @@ int ovl_set_protattr(struct inode *inode, struct dentry *upper, + err = ovl_check_setxattr(ofs, upper, OVL_XATTR_PROTATTR, + buf, len, -EPERM); + } else if (inode->i_flags & OVL_PROT_I_FLAGS_MASK) { +- err = ovl_do_removexattr(ofs, upper, OVL_XATTR_PROTATTR); ++ err = ovl_removexattr(ofs, upper, OVL_XATTR_PROTATTR); + if (err == -EOPNOTSUPP || err == -ENODATA) + err = 0; + } +@@ -983,7 +983,7 @@ int ovl_check_metacopy_xattr(struct ovl_fs *ofs, struct dentry *dentry) + if (!S_ISREG(d_inode(dentry)->i_mode)) + return 0; + +- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); ++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_METACOPY, NULL, 0); + if (res < 0) { + if (res == -ENODATA || res == -EOPNOTSUPP) + return 0; +@@ -1025,7 +1025,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, + int res; + char *s, *next, *buf = NULL; + +- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); ++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, NULL, 0); + if (res == -ENODATA || res == -EOPNOTSUPP) + return NULL; + if (res < 0) +@@ -1037,7 +1037,7 @@ char *ovl_get_redirect_xattr(struct ovl_fs *ofs, struct dentry *dentry, + if (!buf) + return ERR_PTR(-ENOMEM); + +- res = ovl_do_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); ++ res = ovl_getxattr(ofs, dentry, OVL_XATTR_REDIRECT, buf, res); + if (res < 0) + goto fail; + if (res == 0) +-- +2.39.5 + diff --git a/queue-5.15/rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch b/queue-5.15/rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch new file mode 100644 index 0000000000..9e781082fd --- /dev/null +++ b/queue-5.15/rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch @@ -0,0 +1,63 @@ +From dd16e257721f61a0e279d885ef8a99e1092f2f92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Feb 2025 08:47:10 +0200 +Subject: RDMA/mlx5: Fix bind QP error cleanup flow + +From: Patrisious Haddad + +[ Upstream commit e1a0bdbdfdf08428f0ede5ae49c7f4139ac73ef5 ] + +When there is a failure during bind QP, the cleanup flow destroys the +counter regardless if it is the one that created it or not, which is +problematic since if it isn't the one that created it, that counter could +still be in use. + +Fix that by destroying the counter only if it was created during this call. + +Fixes: 45842fc627c7 ("IB/mlx5: Support statistic q counter configuration") +Signed-off-by: Patrisious Haddad +Reviewed-by: Mark Zhang +Link: https://patch.msgid.link/25dfefddb0ebefa668c32e06a94d84e3216257cf.1740033937.git.leon@kernel.org +Reviewed-by: Zhu Yanjun +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/counters.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/mlx5/counters.c b/drivers/infiniband/hw/mlx5/counters.c +index 1a0ecf439c099..870a089198116 100644 +--- a/drivers/infiniband/hw/mlx5/counters.c ++++ b/drivers/infiniband/hw/mlx5/counters.c +@@ -337,6 +337,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter, + struct ib_qp *qp) + { + struct mlx5_ib_dev *dev = to_mdev(qp->device); ++ bool new = false; + int err; + + if (!counter->id) { +@@ -351,6 +352,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter, + return err; + counter->id = + MLX5_GET(alloc_q_counter_out, out, counter_set_id); ++ new = true; + } + + err = mlx5_ib_qp_set_counter(qp, counter); +@@ -360,8 +362,10 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter, + return 0; + + fail_set_counter: +- mlx5_ib_counter_dealloc(counter); +- counter->id = 0; ++ if (new) { ++ mlx5_ib_counter_dealloc(counter); ++ counter->id = 0; ++ } + + return err; + } +-- +2.39.5 + diff --git a/queue-5.15/scsi-core-clear-driver-private-data-when-retrying-re.patch b/queue-5.15/scsi-core-clear-driver-private-data-when-retrying-re.patch new file mode 100644 index 0000000000..c44003d9e0 --- /dev/null +++ b/queue-5.15/scsi-core-clear-driver-private-data-when-retrying-re.patch @@ -0,0 +1,68 @@ +From a55b12cb7d3b0d403df8996092c40cbe2aa81b51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Feb 2025 10:16:28 +0800 +Subject: scsi: core: Clear driver private data when retrying request + +From: Ye Bin + +[ Upstream commit dce5c4afd035e8090a26e5d776b1682c0e649683 ] + +After commit 1bad6c4a57ef ("scsi: zero per-cmd private driver data for each +MQ I/O"), the xen-scsifront/virtio_scsi/snic drivers all removed code that +explicitly zeroed driver-private command data. + +In combination with commit 464a00c9e0ad ("scsi: core: Kill DRIVER_SENSE"), +after virtio_scsi performs a capacity expansion, the first request will +return a unit attention to indicate that the capacity has changed. And then +the original command is retried. As driver-private command data was not +cleared, the request would return UA again and eventually time out and fail. + +Zero driver-private command data when a request is retried. + +Fixes: f7de50da1479 ("scsi: xen-scsifront: Remove code that zeroes driver-private command data") +Fixes: c2bb87318baa ("scsi: virtio_scsi: Remove code that zeroes driver-private command data") +Fixes: c3006a926468 ("scsi: snic: Remove code that zeroes driver-private command data") +Signed-off-by: Ye Bin +Reviewed-by: Bart Van Assche +Link: https://lore.kernel.org/r/20250217021628.2929248-1-yebin@huaweicloud.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_lib.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index ddaffaea2c32c..c8be41d8eb247 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1532,13 +1532,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req) + if (in_flight) + __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); + +- /* +- * Only clear the driver-private command data if the LLD does not supply +- * a function to initialize that data. +- */ +- if (!shost->hostt->init_cmd_priv) +- memset(cmd + 1, 0, shost->hostt->cmd_size); +- + cmd->prot_op = SCSI_PROT_NORMAL; + if (blk_rq_bytes(req)) + cmd->sc_data_direction = rq_dma_dir(req); +@@ -1675,6 +1668,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, + if (!scsi_host_queue_ready(q, shost, sdev, cmd)) + goto out_dec_target_busy; + ++ /* ++ * Only clear the driver-private command data if the LLD does not supply ++ * a function to initialize that data. ++ */ ++ if (shost->hostt->cmd_size && !shost->hostt->init_cmd_priv) ++ memset(cmd + 1, 0, shost->hostt->cmd_size); ++ + if (!(req->rq_flags & RQF_DONTPREP)) { + ret = scsi_prepare_cmd(req); + if (ret != BLK_STS_OK) +-- +2.39.5 + diff --git a/queue-5.15/scsi-core-don-t-memset-the-entire-scsi_cmnd-in-scsi_.patch b/queue-5.15/scsi-core-don-t-memset-the-entire-scsi_cmnd-in-scsi_.patch new file mode 100644 index 0000000000..4ac4c23380 --- /dev/null +++ b/queue-5.15/scsi-core-don-t-memset-the-entire-scsi_cmnd-in-scsi_.patch @@ -0,0 +1,121 @@ +From 3039005b7ab8db780c75d240d5c329f48129722b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 18:55:46 +0100 +Subject: scsi: core: Don't memset() the entire scsi_cmnd in + scsi_init_command() + +From: Christoph Hellwig + +[ Upstream commit 71bada345b33b9297e7cc9415db6328c99b554f9 ] + +Replace the big fat memset that requires saving and restoring various +fields with just initializing those fields that need initialization. + +All the clearing to 0 is moved to scsi_prepare_cmd() as scsi_ioctl_reset() +alreadly uses kzalloc() to allocate a pre-zeroed command. + +This is still conservative and can probably be optimized further. + +Link: https://lore.kernel.org/r/20220224175552.988286-3-hch@lst.de +Reviewed-by: Bart Van Assche +Reviewed-by: John Garry +Signed-off-by: Christoph Hellwig +Signed-off-by: Martin K. Petersen +Stable-dep-of: dce5c4afd035 ("scsi: core: Clear driver private data when retrying request") +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_lib.c | 60 +++++++++++++++++++---------------------- + 1 file changed, 28 insertions(+), 32 deletions(-) + +diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c +index 9721984fd9bc6..ddaffaea2c32c 100644 +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1114,45 +1114,16 @@ static void scsi_cleanup_rq(struct request *rq) + /* Called before a request is prepared. See also scsi_mq_prep_fn(). */ + void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) + { +- void *buf = cmd->sense_buffer; +- void *prot = cmd->prot_sdb; + struct request *rq = scsi_cmd_to_rq(cmd); +- unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS; +- unsigned long jiffies_at_alloc; +- int retries, to_clear; +- bool in_flight; +- int budget_token = cmd->budget_token; +- +- if (!blk_rq_is_passthrough(rq) && !(flags & SCMD_INITIALIZED)) { +- flags |= SCMD_INITIALIZED; ++ ++ if (!blk_rq_is_passthrough(rq) && !(cmd->flags & SCMD_INITIALIZED)) { ++ cmd->flags |= SCMD_INITIALIZED; + scsi_initialize_rq(rq); + } + +- jiffies_at_alloc = cmd->jiffies_at_alloc; +- retries = cmd->retries; +- in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state); +- /* +- * Zero out the cmd, except for the embedded scsi_request. Only clear +- * the driver-private command data if the LLD does not supply a +- * function to initialize that data. +- */ +- to_clear = sizeof(*cmd) - sizeof(cmd->req); +- if (!dev->host->hostt->init_cmd_priv) +- to_clear += dev->host->hostt->cmd_size; +- memset((char *)cmd + sizeof(cmd->req), 0, to_clear); +- + cmd->device = dev; +- cmd->sense_buffer = buf; +- cmd->prot_sdb = prot; +- cmd->flags = flags; + INIT_LIST_HEAD(&cmd->eh_entry); + INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); +- cmd->jiffies_at_alloc = jiffies_at_alloc; +- cmd->retries = retries; +- if (in_flight) +- __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); +- cmd->budget_token = budget_token; +- + } + + static blk_status_t scsi_setup_scsi_cmnd(struct scsi_device *sdev, +@@ -1539,10 +1510,35 @@ static blk_status_t scsi_prepare_cmd(struct request *req) + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + struct scsi_device *sdev = req->q->queuedata; + struct Scsi_Host *shost = sdev->host; ++ bool in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state); + struct scatterlist *sg; + + scsi_init_command(sdev, cmd); + ++ cmd->eh_eflags = 0; ++ cmd->allowed = 0; ++ cmd->prot_type = 0; ++ cmd->prot_flags = 0; ++ cmd->submitter = 0; ++ cmd->cmd_len = 0; ++ cmd->cmnd = NULL; ++ memset(&cmd->sdb, 0, sizeof(cmd->sdb)); ++ cmd->underflow = 0; ++ cmd->transfersize = 0; ++ cmd->host_scribble = NULL; ++ cmd->result = 0; ++ cmd->extra_len = 0; ++ cmd->state = 0; ++ if (in_flight) ++ __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); ++ ++ /* ++ * Only clear the driver-private command data if the LLD does not supply ++ * a function to initialize that data. ++ */ ++ if (!shost->hostt->init_cmd_priv) ++ memset(cmd + 1, 0, shost->hostt->cmd_size); ++ + cmd->prot_op = SCSI_PROT_NORMAL; + if (blk_rq_bytes(req)) + cmd->sc_data_direction = rq_dma_dir(req); +-- +2.39.5 + diff --git a/queue-5.15/series b/queue-5.15/series index 539253133a..a2e0b1b2b4 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -487,3 +487,11 @@ mtd-rawnand-cadence-fix-error-code-in-cadence_nand_init.patch mtd-rawnand-cadence-use-dma_map_resource-for-sdma-address.patch mtd-rawnand-cadence-fix-incorrect-device-in-dma_unmap_single.patch x86-cpu-kvm-srso-fix-possible-missing-ibpb-on-vm-exit.patch +ib-mlx5-set-and-get-correct-qp_num-for-a-dct-qp.patch +ovl-use-wrappers-to-all-vfs_-xattr-calls.patch +ovl-pass-ofs-to-creation-operations.patch +ovl-fix-uaf-in-ovl_dentry_update_reval-by-moving-dpu.patch +scsi-core-don-t-memset-the-entire-scsi_cmnd-in-scsi_.patch +scsi-core-clear-driver-private-data-when-retrying-re.patch +rdma-mlx5-fix-bind-qp-error-cleanup-flow.patch +sunrpc-suppress-warnings-for-unused-procfs-functions.patch diff --git a/queue-5.15/sunrpc-suppress-warnings-for-unused-procfs-functions.patch b/queue-5.15/sunrpc-suppress-warnings-for-unused-procfs-functions.patch new file mode 100644 index 0000000000..f38a3a81c6 --- /dev/null +++ b/queue-5.15/sunrpc-suppress-warnings-for-unused-procfs-functions.patch @@ -0,0 +1,71 @@ +From d85cb2eee17af738e1ba719ef712541c12a16ebd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 15:52:21 +0100 +Subject: sunrpc: suppress warnings for unused procfs functions + +From: Arnd Bergmann + +[ Upstream commit 1f7a4f98c11fbeb18ed21f3b3a497e90a50ad2e0 ] + +There is a warning about unused variables when building with W=1 and no procfs: + +net/sunrpc/cache.c:1660:30: error: 'cache_flush_proc_ops' defined but not used [-Werror=unused-const-variable=] + 1660 | static const struct proc_ops cache_flush_proc_ops = { + | ^~~~~~~~~~~~~~~~~~~~ +net/sunrpc/cache.c:1622:30: error: 'content_proc_ops' defined but not used [-Werror=unused-const-variable=] + 1622 | static const struct proc_ops content_proc_ops = { + | ^~~~~~~~~~~~~~~~ +net/sunrpc/cache.c:1598:30: error: 'cache_channel_proc_ops' defined but not used [-Werror=unused-const-variable=] + 1598 | static const struct proc_ops cache_channel_proc_ops = { + | ^~~~~~~~~~~~~~~~~~~~~~ + +These are used inside of an #ifdef, so replacing that with an +IS_ENABLED() check lets the compiler see how they are used while +still dropping them during dead code elimination. + +Fixes: dbf847ecb631 ("knfsd: allow cache_register to return error on failure") +Reviewed-by: Jeff Layton +Acked-by: Chuck Lever +Signed-off-by: Arnd Bergmann +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + net/sunrpc/cache.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c +index 8c9597b9a3f2e..95aab48d32e67 100644 +--- a/net/sunrpc/cache.c ++++ b/net/sunrpc/cache.c +@@ -1659,12 +1659,14 @@ static void remove_cache_proc_entries(struct cache_detail *cd) + } + } + +-#ifdef CONFIG_PROC_FS + static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) + { + struct proc_dir_entry *p; + struct sunrpc_net *sn; + ++ if (!IS_ENABLED(CONFIG_PROC_FS)) ++ return 0; ++ + sn = net_generic(net, sunrpc_net_id); + cd->procfs = proc_mkdir(cd->name, sn->proc_net_rpc); + if (cd->procfs == NULL) +@@ -1692,12 +1694,6 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) + remove_cache_proc_entries(cd); + return -ENOMEM; + } +-#else /* CONFIG_PROC_FS */ +-static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) +-{ +- return 0; +-} +-#endif + + void __init cache_initialize(void) + { +-- +2.39.5 +