From: Sasha Levin Date: Mon, 21 Oct 2019 03:47:27 +0000 (-0400) Subject: fixes for 5.3 X-Git-Tag: v4.4.198~50^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0de3ef02f1e22280b411dbb101a020640d721c2;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 5.3 Signed-off-by: Sasha Levin --- diff --git a/queue-5.3/filldir-64-remove-warn_on_once-for-bad-directory-ent.patch b/queue-5.3/filldir-64-remove-warn_on_once-for-bad-directory-ent.patch new file mode 100644 index 00000000000..ccc90d1e0bd --- /dev/null +++ b/queue-5.3/filldir-64-remove-warn_on_once-for-bad-directory-ent.patch @@ -0,0 +1,44 @@ +From 584f5f87147fbdfde9dff556a6852cb698fb20b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Oct 2019 18:41:16 -0400 +Subject: filldir[64]: remove WARN_ON_ONCE() for bad directory entries + +From: Linus Torvalds + +[ Upstream commit b9959c7a347d6adbb558fba7e36e9fef3cba3b07 ] + +This was always meant to be a temporary thing, just for testing and to +see if it actually ever triggered. + +The only thing that reported it was syzbot doing disk image fuzzing, and +then that warning is expected. So let's just remove it before -rc4, +because the extra sanity testing should probably go to -stable, but we +don't want the warning to do so. + +Reported-by: syzbot+3031f712c7ad5dd4d926@syzkaller.appspotmail.com +Fixes: 8a23eb804ca4 ("Make filldir[64]() verify the directory entry filename is valid") +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/readdir.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/readdir.c b/fs/readdir.c +index 6e2623e57b2e8..d26d5ea4de7b8 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -105,9 +105,9 @@ EXPORT_SYMBOL(iterate_dir); + */ + static int verify_dirent_name(const char *name, int len) + { +- if (WARN_ON_ONCE(!len)) ++ if (!len) + return -EIO; +- if (WARN_ON_ONCE(memchr(name, '/', len))) ++ if (memchr(name, '/', len)) + return -EIO; + return 0; + } +-- +2.20.1 + diff --git a/queue-5.3/libata-ahci-fix-pcs-quirk-application.patch b/queue-5.3/libata-ahci-fix-pcs-quirk-application.patch new file mode 100644 index 00000000000..2a57e8d943a --- /dev/null +++ b/queue-5.3/libata-ahci-fix-pcs-quirk-application.patch @@ -0,0 +1,45 @@ +From 4cfc24c5e18e8769ef6c8ce70bc27772bfe7cec5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Oct 2019 12:54:17 -0700 +Subject: libata/ahci: Fix PCS quirk application + +From: Dan Williams + +[ Upstream commit 09d6ac8dc51a033ae0043c1fe40b4d02563c2496 ] + +Commit c312ef176399 "libata/ahci: Drop PCS quirk for Denverton and +beyond" got the polarity wrong on the check for which board-ids should +have the quirk applied. The board type board_ahci_pcs7 is defined at the +end of the list such that "pcs7" boards can be special cased in the +future if they need the quirk. All prior Intel board ids "< +board_ahci_pcs7" should proceed with applying the quirk. + +Reported-by: Andreas Friedrich +Reported-by: Stephen Douthit +Fixes: c312ef176399 ("libata/ahci: Drop PCS quirk for Denverton and beyond") +Cc: +Signed-off-by: Dan Williams +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/ata/ahci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 3e63294304c72..691852b8bb41f 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -1617,7 +1617,9 @@ static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hp + */ + if (!id || id->vendor != PCI_VENDOR_ID_INTEL) + return; +- if (((enum board_ids) id->driver_data) < board_ahci_pcs7) ++ ++ /* Skip applying the quirk on Denverton and beyond */ ++ if (((enum board_ids) id->driver_data) >= board_ahci_pcs7) + return; + + /* +-- +2.20.1 + diff --git a/queue-5.3/make-filldir-64-verify-the-directory-entry-filename-.patch b/queue-5.3/make-filldir-64-verify-the-directory-entry-filename-.patch new file mode 100644 index 00000000000..a1db45278a1 --- /dev/null +++ b/queue-5.3/make-filldir-64-verify-the-directory-entry-filename-.patch @@ -0,0 +1,145 @@ +From 5ec90a74a91bfe99b021932144e9c2101b4389fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 5 Oct 2019 11:32:52 -0700 +Subject: Make filldir[64]() verify the directory entry filename is valid + +From: Linus Torvalds + +[ Upstream commit 8a23eb804ca4f2be909e372cf5a9e7b30ae476cd ] + +This has been discussed several times, and now filesystem people are +talking about doing it individually at the filesystem layer, so head +that off at the pass and just do it in getdents{64}(). + +This is partially based on a patch by Jann Horn, but checks for NUL +bytes as well, and somewhat simplified. + +There's also commentary about how it might be better if invalid names +due to filesystem corruption don't cause an immediate failure, but only +an error at the end of the readdir(), so that people can still see the +filenames that are ok. + +There's also been discussion about just how much POSIX strictly speaking +requires this since it's about filesystem corruption. It's really more +"protect user space from bad behavior" as pointed out by Jann. But +since Eric Biederman looked up the POSIX wording, here it is for context: + + "From readdir: + + The readdir() function shall return a pointer to a structure + representing the directory entry at the current position in the + directory stream specified by the argument dirp, and position the + directory stream at the next entry. It shall return a null pointer + upon reaching the end of the directory stream. The structure dirent + defined in the header describes a directory entry. + + From definitions: + + 3.129 Directory Entry (or Link) + + An object that associates a filename with a file. Several directory + entries can associate names with the same file. + + ... + + 3.169 Filename + + A name consisting of 1 to {NAME_MAX} bytes used to name a file. The + characters composing the name may be selected from the set of all + character values excluding the slash character and the null byte. The + filenames dot and dot-dot have special meaning. A filename is + sometimes referred to as a 'pathname component'." + +Note that I didn't bother adding the checks to any legacy interfaces +that nobody uses. + +Also note that if this ends up being noticeable as a performance +regression, we can fix that to do a much more optimized model that +checks for both NUL and '/' at the same time one word at a time. + +We haven't really tended to optimize 'memchr()', and it only checks for +one pattern at a time anyway, and we really _should_ check for NUL too +(but see the comment about "soft errors" in the code about why it +currently only checks for '/') + +See the CONFIG_DCACHE_WORD_ACCESS case of hash_name() for how the name +lookup code looks for pathname terminating characters in parallel. + +Link: https://lore.kernel.org/lkml/20190118161440.220134-2-jannh@google.com/ +Cc: Alexander Viro +Cc: Jann Horn +Cc: Eric W. Biederman +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + fs/readdir.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/fs/readdir.c b/fs/readdir.c +index 579c8ea894ae3..19bea591c3f1d 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -118,6 +118,40 @@ out: + } + EXPORT_SYMBOL(iterate_dir); + ++/* ++ * POSIX says that a dirent name cannot contain NULL or a '/'. ++ * ++ * It's not 100% clear what we should really do in this case. ++ * The filesystem is clearly corrupted, but returning a hard ++ * error means that you now don't see any of the other names ++ * either, so that isn't a perfect alternative. ++ * ++ * And if you return an error, what error do you use? Several ++ * filesystems seem to have decided on EUCLEAN being the error ++ * code for EFSCORRUPTED, and that may be the error to use. Or ++ * just EIO, which is perhaps more obvious to users. ++ * ++ * In order to see the other file names in the directory, the ++ * caller might want to make this a "soft" error: skip the ++ * entry, and return the error at the end instead. ++ * ++ * Note that this should likely do a "memchr(name, 0, len)" ++ * check too, since that would be filesystem corruption as ++ * well. However, that case can't actually confuse user space, ++ * which has to do a strlen() on the name anyway to find the ++ * filename length, and the above "soft error" worry means ++ * that it's probably better left alone until we have that ++ * issue clarified. ++ */ ++static int verify_dirent_name(const char *name, int len) ++{ ++ if (WARN_ON_ONCE(!len)) ++ return -EIO; ++ if (WARN_ON_ONCE(memchr(name, '/', len))) ++ return -EIO; ++ return 0; ++} ++ + /* + * Traditional linux readdir() handling.. + * +@@ -227,6 +261,9 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, + int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, + sizeof(long)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +@@ -316,6 +353,9 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, + int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, + sizeof(u64)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +-- +2.20.1 + diff --git a/queue-5.3/md-raid0-fix-warning-message-for-parameter-default_l.patch b/queue-5.3/md-raid0-fix-warning-message-for-parameter-default_l.patch new file mode 100644 index 00000000000..a7773d4014f --- /dev/null +++ b/queue-5.3/md-raid0-fix-warning-message-for-parameter-default_l.patch @@ -0,0 +1,36 @@ +From 56716473080aff0f46464af07c97ed5d02c3c2c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Oct 2019 16:58:35 -0700 +Subject: md/raid0: fix warning message for parameter default_layout + +From: Song Liu + +[ Upstream commit 3874d73e06c9b9dc15de0b7382fc223986d75571 ] + +The message should match the parameter, i.e. raid0.default_layout. + +Fixes: c84a1372df92 ("md/raid0: avoid RAID0 data corruption due to layout confusion.") +Cc: NeilBrown +Reported-by: Ivan Topolsky +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 297bbc0f41f05..c3445d2cedb9d 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -151,7 +151,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) + } else { + pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n", + mdname(mddev)); +- pr_err("md/raid0: please set raid.default_layout to 1 or 2\n"); ++ pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n"); + err = -ENOTSUPP; + goto abort; + } +-- +2.20.1 + diff --git a/queue-5.3/net_sched-fix-backward-compatibility-for-tca_act_kin.patch b/queue-5.3/net_sched-fix-backward-compatibility-for-tca_act_kin.patch new file mode 100644 index 00000000000..3b0e7278e0a --- /dev/null +++ b/queue-5.3/net_sched-fix-backward-compatibility-for-tca_act_kin.patch @@ -0,0 +1,58 @@ +From 13da60032a8778fcb5f3495429869a8b146b75cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2019 13:26:29 -0700 +Subject: net_sched: fix backward compatibility for TCA_ACT_KIND + +From: Cong Wang + +[ Upstream commit 4b793feccae3b06764268377a4030eb774ed924e ] + +For TCA_ACT_KIND, we have to keep the backward compatibility too, +and rely on nla_strlcpy() to check and terminate the string with +a NUL. + +Note for TC actions, nla_strcmp() is already used to compare kind +strings, so we don't need to fix other places. + +Fixes: 199ce850ce11 ("net_sched: add policy validation for action attributes") +Reported-by: Marcelo Ricardo Leitner +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Reviewed-by: Marcelo Ricardo Leitner +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/act_api.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/sched/act_api.c b/net/sched/act_api.c +index 2558f00f6b3ed..4e7429c6f8649 100644 +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -832,8 +832,7 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb) + } + + static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = { +- [TCA_ACT_KIND] = { .type = NLA_NUL_STRING, +- .len = IFNAMSIZ - 1 }, ++ [TCA_ACT_KIND] = { .type = NLA_STRING }, + [TCA_ACT_INDEX] = { .type = NLA_U32 }, + [TCA_ACT_COOKIE] = { .type = NLA_BINARY, + .len = TC_COOKIE_MAX_SIZE }, +@@ -865,8 +864,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, + NL_SET_ERR_MSG(extack, "TC action kind must be specified"); + goto err_out; + } +- nla_strlcpy(act_name, kind, IFNAMSIZ); +- ++ if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) { ++ NL_SET_ERR_MSG(extack, "TC action name too long"); ++ goto err_out; ++ } + if (tb[TCA_ACT_COOKIE]) { + cookie = nla_memdup_cookie(tb); + if (!cookie) { +-- +2.20.1 + diff --git a/queue-5.3/net_sched-fix-backward-compatibility-for-tca_kind.patch b/queue-5.3/net_sched-fix-backward-compatibility-for-tca_kind.patch new file mode 100644 index 00000000000..ff07ebc5dd5 --- /dev/null +++ b/queue-5.3/net_sched-fix-backward-compatibility-for-tca_kind.patch @@ -0,0 +1,157 @@ +From f2e63e9ad19abaa18fa796d35b8bcfeec965855d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2019 13:26:28 -0700 +Subject: net_sched: fix backward compatibility for TCA_KIND + +From: Cong Wang + +[ Upstream commit 6f96c3c6904c26cea9ca2726d5d8a9b0b8205b3c ] + +Marcelo noticed a backward compatibility issue of TCA_KIND +after we move from NLA_STRING to NLA_NUL_STRING, so it is probably +too late to change it. + +Instead, to make everyone happy, we can just insert a NUL to +terminate the string with nla_strlcpy() like we do for TC actions. + +Fixes: 62794fc4fbf5 ("net_sched: add max len check for TCA_KIND") +Reported-by: Marcelo Ricardo Leitner +Cc: Jamal Hadi Salim +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Reviewed-by: Marcelo Ricardo Leitner +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/cls_api.c | 36 +++++++++++++++++++++++++++++++++--- + net/sched/sch_api.c | 3 +-- + 2 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index 9aef93300f1c1..6b12883e04b8f 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -160,11 +160,22 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) + return TC_H_MAJ(first); + } + ++static bool tcf_proto_check_kind(struct nlattr *kind, char *name) ++{ ++ if (kind) ++ return nla_strlcpy(name, kind, IFNAMSIZ) >= IFNAMSIZ; ++ memset(name, 0, IFNAMSIZ); ++ return false; ++} ++ + static bool tcf_proto_is_unlocked(const char *kind) + { + const struct tcf_proto_ops *ops; + bool ret; + ++ if (strlen(kind) == 0) ++ return false; ++ + ops = tcf_proto_lookup_ops(kind, false, NULL); + /* On error return false to take rtnl lock. Proto lookup/create + * functions will perform lookup again and properly handle errors. +@@ -1976,6 +1987,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + { + struct net *net = sock_net(skb->sk); + struct nlattr *tca[TCA_MAX + 1]; ++ char name[IFNAMSIZ]; + struct tcmsg *t; + u32 protocol; + u32 prio; +@@ -2032,13 +2044,19 @@ replay: + if (err) + return err; + ++ if (tcf_proto_check_kind(tca[TCA_KIND], name)) { ++ NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); ++ err = -EINVAL; ++ goto errout; ++ } ++ + /* Take rtnl mutex if rtnl_held was set to true on previous iteration, + * block is shared (no qdisc found), qdisc is not unlocked, classifier + * type is not specified, classifier is not unlocked. + */ + if (rtnl_held || + (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || +- !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { ++ !tcf_proto_is_unlocked(name)) { + rtnl_held = true; + rtnl_lock(); + } +@@ -2196,6 +2214,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + { + struct net *net = sock_net(skb->sk); + struct nlattr *tca[TCA_MAX + 1]; ++ char name[IFNAMSIZ]; + struct tcmsg *t; + u32 protocol; + u32 prio; +@@ -2235,13 +2254,18 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + if (err) + return err; + ++ if (tcf_proto_check_kind(tca[TCA_KIND], name)) { ++ NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); ++ err = -EINVAL; ++ goto errout; ++ } + /* Take rtnl mutex if flushing whole chain, block is shared (no qdisc + * found), qdisc is not unlocked, classifier type is not specified, + * classifier is not unlocked. + */ + if (!prio || + (q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || +- !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { ++ !tcf_proto_is_unlocked(name)) { + rtnl_held = true; + rtnl_lock(); + } +@@ -2349,6 +2373,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + { + struct net *net = sock_net(skb->sk); + struct nlattr *tca[TCA_MAX + 1]; ++ char name[IFNAMSIZ]; + struct tcmsg *t; + u32 protocol; + u32 prio; +@@ -2385,12 +2410,17 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + if (err) + return err; + ++ if (tcf_proto_check_kind(tca[TCA_KIND], name)) { ++ NL_SET_ERR_MSG(extack, "Specified TC filter name too long"); ++ err = -EINVAL; ++ goto errout; ++ } + /* Take rtnl mutex if block is shared (no qdisc found), qdisc is not + * unlocked, classifier type is not specified, classifier is not + * unlocked. + */ + if ((q && !(q->ops->cl_ops->flags & QDISC_CLASS_OPS_DOIT_UNLOCKED)) || +- !tca[TCA_KIND] || !tcf_proto_is_unlocked(nla_data(tca[TCA_KIND]))) { ++ !tcf_proto_is_unlocked(name)) { + rtnl_held = true; + rtnl_lock(); + } +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index 81d58b2806122..1047825d9f48d 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -1390,8 +1390,7 @@ check_loop_fn(struct Qdisc *q, unsigned long cl, struct qdisc_walker *w) + } + + const struct nla_policy rtm_tca_policy[TCA_MAX + 1] = { +- [TCA_KIND] = { .type = NLA_NUL_STRING, +- .len = IFNAMSIZ - 1 }, ++ [TCA_KIND] = { .type = NLA_STRING }, + [TCA_RATE] = { .type = NLA_BINARY, + .len = sizeof(struct tc_estimator) }, + [TCA_STAB] = { .type = NLA_NESTED }, +-- +2.20.1 + diff --git a/queue-5.3/revert-drm-radeon-fix-eeh-during-kexec.patch b/queue-5.3/revert-drm-radeon-fix-eeh-during-kexec.patch new file mode 100644 index 00000000000..6f72f7622ef --- /dev/null +++ b/queue-5.3/revert-drm-radeon-fix-eeh-during-kexec.patch @@ -0,0 +1,49 @@ +From 4248e8e1bdad915d3e24ad97b85401355f7cf870 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Oct 2019 13:12:37 -0500 +Subject: Revert "drm/radeon: Fix EEH during kexec" + +From: Alex Deucher + +[ Upstream commit 8d13c187c42e110625d60094668a8f778c092879 ] + +This reverts commit 6f7fe9a93e6c09bf988c5059403f5f88e17e21e6. + +This breaks some boards. Maybe just enable this on PPC for +now? + +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=205147 +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/radeon/radeon_drv.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c +index 5cc0fbb04ab14..7033f3a38c878 100644 +--- a/drivers/gpu/drm/radeon/radeon_drv.c ++++ b/drivers/gpu/drm/radeon/radeon_drv.c +@@ -380,19 +380,11 @@ radeon_pci_remove(struct pci_dev *pdev) + static void + radeon_pci_shutdown(struct pci_dev *pdev) + { +- struct drm_device *ddev = pci_get_drvdata(pdev); +- + /* if we are running in a VM, make sure the device + * torn down properly on reboot/shutdown + */ + if (radeon_device_is_virtual()) + radeon_pci_remove(pdev); +- +- /* Some adapters need to be suspended before a +- * shutdown occurs in order to prevent an error +- * during kexec. +- */ +- radeon_suspend_kms(ddev, true, true, false); + } + + static int radeon_pmops_suspend(struct device *dev) +-- +2.20.1 + diff --git a/queue-5.3/series b/queue-5.3/series index 4ffc3674b4d..98fd3afa7ad 100644 --- a/queue-5.3/series +++ b/queue-5.3/series @@ -56,3 +56,11 @@ net-phy-fix-write-to-mii-ctrl1000-register.patch namespace-fix-namespace.pl-script-to-support-relativ.patch convert-filldir-64-from-__put_user-to-unsafe_put_use.patch elf-don-t-use-map_fixed_noreplace-for-elf-executable.patch +make-filldir-64-verify-the-directory-entry-filename-.patch +uaccess-implement-a-proper-unsafe_copy_to_user-and-s.patch +filldir-64-remove-warn_on_once-for-bad-directory-ent.patch +net_sched-fix-backward-compatibility-for-tca_kind.patch +net_sched-fix-backward-compatibility-for-tca_act_kin.patch +libata-ahci-fix-pcs-quirk-application.patch +md-raid0-fix-warning-message-for-parameter-default_l.patch +revert-drm-radeon-fix-eeh-during-kexec.patch diff --git a/queue-5.3/uaccess-implement-a-proper-unsafe_copy_to_user-and-s.patch b/queue-5.3/uaccess-implement-a-proper-unsafe_copy_to_user-and-s.patch new file mode 100644 index 00000000000..36630ac441f --- /dev/null +++ b/queue-5.3/uaccess-implement-a-proper-unsafe_copy_to_user-and-s.patch @@ -0,0 +1,175 @@ +From 7252d27593ada64e94a9666b6d27e71a731567ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Oct 2019 12:56:48 -0700 +Subject: uaccess: implement a proper unsafe_copy_to_user() and switch filldir + over to it + +From: Linus Torvalds + +[ Upstream commit c512c69187197fe08026cb5bbe7b9709f4f89b73 ] + +In commit 9f79b78ef744 ("Convert filldir[64]() from __put_user() to +unsafe_put_user()") I made filldir() use unsafe_put_user(), which +improves code generation on x86 enormously. + +But because we didn't have a "unsafe_copy_to_user()", the dirent name +copy was also done by hand with unsafe_put_user() in a loop, and it +turns out that a lot of other architectures didn't like that, because +unlike x86, they have various alignment issues. + +Most non-x86 architectures trap and fix it up, and some (like xtensa) +will just fail unaligned put_user() accesses unconditionally. Which +makes that "copy using put_user() in a loop" not work for them at all. + +I could make that code do explicit alignment etc, but the architectures +that don't like unaligned accesses also don't really use the fancy +"user_access_begin/end()" model, so they might just use the regular old +__copy_to_user() interface. + +So this commit takes that looping implementation, turns it into the x86 +version of "unsafe_copy_to_user()", and makes other architectures +implement the unsafe copy version as __copy_to_user() (the same way they +do for the other unsafe_xyz() accessor functions). + +Note that it only does this for the copying _to_ user space, and we +still don't have a unsafe version of copy_from_user(). + +That's partly because we have no current users of it, but also partly +because the copy_from_user() case is slightly different and cannot +efficiently be implemented in terms of a unsafe_get_user() loop (because +gcc can't do asm goto with outputs). + +It would be trivial to do this using "rep movsb", which would work +really nicely on newer x86 cores, but really badly on some older ones. + +Al Viro is looking at cleaning up all our user copy routines to make +this all a non-issue, but for now we have this simple-but-stupid version +for x86 that works fine for the dirent name copy case because those +names are short strings and we simply don't need anything fancier. + +Fixes: 9f79b78ef744 ("Convert filldir[64]() from __put_user() to unsafe_put_user()") +Reported-by: Guenter Roeck +Reported-and-tested-by: Tony Luck +Cc: Al Viro +Cc: Max Filippov +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/uaccess.h | 23 ++++++++++++++++++ + fs/readdir.c | 44 ++-------------------------------- + include/linux/uaccess.h | 6 +++-- + 3 files changed, 29 insertions(+), 44 deletions(-) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 35c225ede0e4f..61d93f062a36e 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -734,5 +734,28 @@ do { \ + if (unlikely(__gu_err)) goto err_label; \ + } while (0) + ++/* ++ * We want the unsafe accessors to always be inlined and use ++ * the error labels - thus the macro games. ++ */ ++#define unsafe_copy_loop(dst, src, len, type, label) \ ++ while (len >= sizeof(type)) { \ ++ unsafe_put_user(*(type *)src,(type __user *)dst,label); \ ++ dst += sizeof(type); \ ++ src += sizeof(type); \ ++ len -= sizeof(type); \ ++ } ++ ++#define unsafe_copy_to_user(_dst,_src,_len,label) \ ++do { \ ++ char __user *__ucu_dst = (_dst); \ ++ const char *__ucu_src = (_src); \ ++ size_t __ucu_len = (_len); \ ++ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \ ++ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \ ++ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \ ++ unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \ ++} while (0) ++ + #endif /* _ASM_X86_UACCESS_H */ + +diff --git a/fs/readdir.c b/fs/readdir.c +index 19bea591c3f1d..6e2623e57b2e8 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -27,53 +27,13 @@ + /* + * Note the "unsafe_put_user() semantics: we goto a + * label for errors. +- * +- * Also note how we use a "while()" loop here, even though +- * only the biggest size needs to loop. The compiler (well, +- * at least gcc) is smart enough to turn the smaller sizes +- * into just if-statements, and this way we don't need to +- * care whether 'u64' or 'u32' is the biggest size. +- */ +-#define unsafe_copy_loop(dst, src, len, type, label) \ +- while (len >= sizeof(type)) { \ +- unsafe_put_user(get_unaligned((type *)src), \ +- (type __user *)dst, label); \ +- dst += sizeof(type); \ +- src += sizeof(type); \ +- len -= sizeof(type); \ +- } +- +-/* +- * We avoid doing 64-bit copies on 32-bit architectures. They +- * might be better, but the component names are mostly small, +- * and the 64-bit cases can end up being much more complex and +- * put much more register pressure on the code, so it's likely +- * not worth the pain of unaligned accesses etc. +- * +- * So limit the copies to "unsigned long" size. I did verify +- * that at least the x86-32 case is ok without this limiting, +- * but I worry about random other legacy 32-bit cases that +- * might not do as well. +- */ +-#define unsafe_copy_type(dst, src, len, type, label) do { \ +- if (sizeof(type) <= sizeof(unsigned long)) \ +- unsafe_copy_loop(dst, src, len, type, label); \ +-} while (0) +- +-/* +- * Copy the dirent name to user space, and NUL-terminate +- * it. This should not be a function call, since we're doing +- * the copy inside a "user_access_begin/end()" section. + */ + #define unsafe_copy_dirent_name(_dst, _src, _len, label) do { \ + char __user *dst = (_dst); \ + const char *src = (_src); \ + size_t len = (_len); \ +- unsafe_copy_type(dst, src, len, u64, label); \ +- unsafe_copy_type(dst, src, len, u32, label); \ +- unsafe_copy_type(dst, src, len, u16, label); \ +- unsafe_copy_type(dst, src, len, u8, label); \ +- unsafe_put_user(0, dst, label); \ ++ unsafe_put_user(0, dst+len, label); \ ++ unsafe_copy_to_user(dst, src, len, label); \ + } while (0) + + +diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h +index 34a038563d979..d38051dd414fd 100644 +--- a/include/linux/uaccess.h ++++ b/include/linux/uaccess.h +@@ -284,8 +284,10 @@ extern long strnlen_unsafe_user(const void __user *unsafe_addr, long count); + #ifndef user_access_begin + #define user_access_begin(ptr,len) access_ok(ptr, len) + #define user_access_end() do { } while (0) +-#define unsafe_get_user(x, ptr, err) do { if (unlikely(__get_user(x, ptr))) goto err; } while (0) +-#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) ++#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0) ++#define unsafe_get_user(x,p,e) unsafe_op_wrap(__get_user(x,p),e) ++#define unsafe_put_user(x,p,e) unsafe_op_wrap(__put_user(x,p),e) ++#define unsafe_copy_to_user(d,s,l,e) unsafe_op_wrap(__copy_to_user(d,s,l),e) + static inline unsigned long user_access_save(void) { return 0UL; } + static inline void user_access_restore(unsigned long flags) { } + #endif +-- +2.20.1 +