diff options
author | Mike Pagano <mpagano@gentoo.org> | 2022-02-05 07:13:52 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2022-02-05 07:13:52 -0500 |
commit | 11b7c95cbb05d5a5dd38478c10dfcac7b008d57a (patch) | |
tree | b0bf691f1be5fa5ca3806e955ac02d497fbec93c | |
parent | Linux patch 5.4.176 (diff) | |
download | linux-patches-5.4-181.tar.gz linux-patches-5.4-181.tar.bz2 linux-patches-5.4-181.zip |
Linux patch 5.4.1775.4-181
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1176_linux-5.4.177.patch | 468 |
2 files changed, 472 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 347c7e70..d82773a6 100644 --- a/0000_README +++ b/0000_README @@ -747,6 +747,10 @@ Patch: 1175_linux-5.4.176.patch From: http://www.kernel.org Desc: Linux 5.4.176 +Patch: 1176_linux-5.4.177.patch +From: http://www.kernel.org +Desc: Linux 5.4.177 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1176_linux-5.4.177.patch b/1176_linux-5.4.177.patch new file mode 100644 index 00000000..6bd43941 --- /dev/null +++ b/1176_linux-5.4.177.patch @@ -0,0 +1,468 @@ +diff --git a/Documentation/accounting/psi.rst b/Documentation/accounting/psi.rst +index 621111ce57401..28c0461ba2e1b 100644 +--- a/Documentation/accounting/psi.rst ++++ b/Documentation/accounting/psi.rst +@@ -90,7 +90,8 @@ Triggers can be set on more than one psi metric and more than one trigger + for the same psi metric can be specified. However for each trigger a separate + file descriptor is required to be able to poll it separately from others, + therefore for each trigger a separate open() syscall should be made even +-when opening the same psi interface file. ++when opening the same psi interface file. Write operations to a file descriptor ++with an already existing psi trigger will fail with EBUSY. + + Monitors activate only when system enters stall state for the monitored + psi metric and deactivates upon exit from the stall state. While system is +diff --git a/Makefile b/Makefile +index b23aa51ada93e..324939b64d7b7 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 4 +-SUBLEVEL = 176 ++SUBLEVEL = 177 + EXTRAVERSION = + NAME = Kleptomaniac Octopus + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index da8c2c4aca7ef..0442d7e1cd20b 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -721,7 +721,9 @@ static void xgbe_stop_timers(struct xgbe_prv_data *pdata) + if (!channel->tx_ring) + break; + ++ /* Deactivate the Tx timer */ + del_timer_sync(&channel->tx_timer); ++ channel->tx_timer_active = 0; + } + } + +@@ -2765,6 +2767,14 @@ read_again: + buf2_len = xgbe_rx_buf2_len(rdata, packet, len); + len += buf2_len; + ++ if (buf2_len > rdata->rx.buf.dma_len) { ++ /* Hardware inconsistency within the descriptors ++ * that has resulted in a length underflow. ++ */ ++ error = 1; ++ goto skip_data; ++ } ++ + if (!skb) { + skb = xgbe_create_skb(pdata, napi, rdata, + buf1_len); +@@ -2794,8 +2804,10 @@ skip_data: + if (!last || context_next) + goto read_again; + +- if (!skb) ++ if (!skb || error) { ++ dev_kfree_skb(skb); + goto next_packet; ++ } + + /* Be sure we don't exceed the configured MTU */ + max_len = netdev->mtu + ETH_HLEN; +diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c +index 345576f1a7470..73ad78f47763c 100644 +--- a/drivers/net/usb/ipheth.c ++++ b/drivers/net/usb/ipheth.c +@@ -121,7 +121,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) + if (tx_buf == NULL) + goto free_rx_urb; + +- rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, ++ rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + GFP_KERNEL, &rx_urb->transfer_dma); + if (rx_buf == NULL) + goto free_tx_buf; +@@ -146,7 +146,7 @@ error_nomem: + + static void ipheth_free_urbs(struct ipheth_device *iphone) + { +- usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf, ++ usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf, + iphone->rx_urb->transfer_dma); + usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, + iphone->tx_urb->transfer_dma); +@@ -317,7 +317,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) + + usb_fill_bulk_urb(dev->rx_urb, udev, + usb_rcvbulkpipe(udev, dev->bulk_in), +- dev->rx_buf, IPHETH_BUF_SIZE, ++ dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + ipheth_rcvbulk_callback, + dev); + dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c +index 88b996764ff95..907b8be86ce04 100644 +--- a/drivers/pci/hotplug/pciehp_hpc.c ++++ b/drivers/pci/hotplug/pciehp_hpc.c +@@ -577,6 +577,8 @@ read_status: + */ + if (ctrl->power_fault_detected) + status &= ~PCI_EXP_SLTSTA_PFD; ++ else if (status & PCI_EXP_SLTSTA_PFD) ++ ctrl->power_fault_detected = true; + + events |= status; + if (!events) { +@@ -586,7 +588,7 @@ read_status: + } + + if (status) { +- pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events); ++ pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status); + + /* + * In MSI mode, all event bits must be zero before the port +@@ -660,8 +662,7 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) + } + + /* Check Power Fault Detected */ +- if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { +- ctrl->power_fault_detected = 1; ++ if (events & PCI_EXP_SLTSTA_PFD) { + ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl)); + pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, + PCI_EXP_SLTCTL_ATTN_IND_ON); +diff --git a/include/linux/psi.h b/include/linux/psi.h +index 7b3de73212199..7712b58009276 100644 +--- a/include/linux/psi.h ++++ b/include/linux/psi.h +@@ -31,7 +31,7 @@ void cgroup_move_task(struct task_struct *p, struct css_set *to); + + struct psi_trigger *psi_trigger_create(struct psi_group *group, + char *buf, size_t nbytes, enum psi_res res); +-void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *t); ++void psi_trigger_destroy(struct psi_trigger *t); + + __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file, + poll_table *wait); +diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h +index 07aaf9b822416..0023052eab23f 100644 +--- a/include/linux/psi_types.h ++++ b/include/linux/psi_types.h +@@ -120,9 +120,6 @@ struct psi_trigger { + * events to one per window + */ + u64 last_event_time; +- +- /* Refcounting to prevent premature destruction */ +- struct kref refcount; + }; + + struct psi_group { +diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c +index 2d0ef613ca070..5e465c4b1e64c 100644 +--- a/kernel/cgroup/cgroup-v1.c ++++ b/kernel/cgroup/cgroup-v1.c +@@ -549,6 +549,14 @@ static ssize_t cgroup_release_agent_write(struct kernfs_open_file *of, + + BUILD_BUG_ON(sizeof(cgrp->root->release_agent_path) < PATH_MAX); + ++ /* ++ * Release agent gets called with all capabilities, ++ * require capabilities to set release agent. ++ */ ++ if ((of->file->f_cred->user_ns != &init_user_ns) || ++ !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + cgrp = cgroup_kn_lock_live(of->kn, false); + if (!cgrp) + return -ENODEV; +@@ -961,6 +969,12 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param) + /* Specifying two release agents is forbidden */ + if (ctx->release_agent) + return cg_invalf(fc, "cgroup1: release_agent respecified"); ++ /* ++ * Release agent gets called with all capabilities, ++ * require capabilities to set release agent. ++ */ ++ if ((fc->user_ns != &init_user_ns) || !capable(CAP_SYS_ADMIN)) ++ return cg_invalf(fc, "cgroup1: Setting release_agent not allowed"); + ctx->release_agent = param->string; + param->string = NULL; + break; +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 1904ffcee0f1e..ce1745ac7b8c0 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -3659,6 +3659,12 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf, + cgroup_get(cgrp); + cgroup_kn_unlock(of->kn); + ++ /* Allow only one trigger per file descriptor */ ++ if (of->priv) { ++ cgroup_put(cgrp); ++ return -EBUSY; ++ } ++ + psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi; + new = psi_trigger_create(psi, buf, nbytes, res); + if (IS_ERR(new)) { +@@ -3666,8 +3672,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf, + return PTR_ERR(new); + } + +- psi_trigger_replace(&of->priv, new); +- ++ smp_store_release(&of->priv, new); + cgroup_put(cgrp); + + return nbytes; +@@ -3702,7 +3707,7 @@ static __poll_t cgroup_pressure_poll(struct kernfs_open_file *of, + + static void cgroup_pressure_release(struct kernfs_open_file *of) + { +- psi_trigger_replace(&of->priv, NULL); ++ psi_trigger_destroy(of->priv); + } + #endif /* CONFIG_PSI */ + +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index badfa8f153599..411be8b2e837e 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -1558,8 +1558,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, + * Make sure that subparts_cpus is a subset of cpus_allowed. + */ + if (cs->nr_subparts_cpus) { +- cpumask_andnot(cs->subparts_cpus, cs->subparts_cpus, +- cs->cpus_allowed); ++ cpumask_and(cs->subparts_cpus, cs->subparts_cpus, cs->cpus_allowed); + cs->nr_subparts_cpus = cpumask_weight(cs->subparts_cpus); + } + spin_unlock_irq(&callback_lock); +diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c +index 9154e745f0978..9dd83eb74a9da 100644 +--- a/kernel/sched/psi.c ++++ b/kernel/sched/psi.c +@@ -1046,7 +1046,6 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, + t->event = 0; + t->last_event_time = 0; + init_waitqueue_head(&t->event_wait); +- kref_init(&t->refcount); + + mutex_lock(&group->trigger_lock); + +@@ -1079,15 +1078,19 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, + return t; + } + +-static void psi_trigger_destroy(struct kref *ref) ++void psi_trigger_destroy(struct psi_trigger *t) + { +- struct psi_trigger *t = container_of(ref, struct psi_trigger, refcount); +- struct psi_group *group = t->group; ++ struct psi_group *group; + struct kthread_worker *kworker_to_destroy = NULL; + +- if (static_branch_likely(&psi_disabled)) ++ /* ++ * We do not check psi_disabled since it might have been disabled after ++ * the trigger got created. ++ */ ++ if (!t) + return; + ++ group = t->group; + /* + * Wakeup waiters to stop polling. Can happen if cgroup is deleted + * from under a polling process. +@@ -1122,9 +1125,9 @@ static void psi_trigger_destroy(struct kref *ref) + mutex_unlock(&group->trigger_lock); + + /* +- * Wait for both *trigger_ptr from psi_trigger_replace and +- * poll_kworker RCUs to complete their read-side critical sections +- * before destroying the trigger and optionally the poll_kworker ++ * Wait for psi_schedule_poll_work RCU to complete its read-side ++ * critical section before destroying the trigger and optionally the ++ * poll_task. + */ + synchronize_rcu(); + /* +@@ -1146,18 +1149,6 @@ static void psi_trigger_destroy(struct kref *ref) + kfree(t); + } + +-void psi_trigger_replace(void **trigger_ptr, struct psi_trigger *new) +-{ +- struct psi_trigger *old = *trigger_ptr; +- +- if (static_branch_likely(&psi_disabled)) +- return; +- +- rcu_assign_pointer(*trigger_ptr, new); +- if (old) +- kref_put(&old->refcount, psi_trigger_destroy); +-} +- + __poll_t psi_trigger_poll(void **trigger_ptr, + struct file *file, poll_table *wait) + { +@@ -1167,24 +1158,15 @@ __poll_t psi_trigger_poll(void **trigger_ptr, + if (static_branch_likely(&psi_disabled)) + return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI; + +- rcu_read_lock(); +- +- t = rcu_dereference(*(void __rcu __force **)trigger_ptr); +- if (!t) { +- rcu_read_unlock(); ++ t = smp_load_acquire(trigger_ptr); ++ if (!t) + return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI; +- } +- kref_get(&t->refcount); +- +- rcu_read_unlock(); + + poll_wait(file, &t->event_wait, wait); + + if (cmpxchg(&t->event, 1, 0) == 1) + ret |= EPOLLPRI; + +- kref_put(&t->refcount, psi_trigger_destroy); +- + return ret; + } + +@@ -1208,14 +1190,24 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf, + + buf[buf_size - 1] = '\0'; + +- new = psi_trigger_create(&psi_system, buf, nbytes, res); +- if (IS_ERR(new)) +- return PTR_ERR(new); +- + seq = file->private_data; ++ + /* Take seq->lock to protect seq->private from concurrent writes */ + mutex_lock(&seq->lock); +- psi_trigger_replace(&seq->private, new); ++ ++ /* Allow only one trigger per file descriptor */ ++ if (seq->private) { ++ mutex_unlock(&seq->lock); ++ return -EBUSY; ++ } ++ ++ new = psi_trigger_create(&psi_system, buf, nbytes, res); ++ if (IS_ERR(new)) { ++ mutex_unlock(&seq->lock); ++ return PTR_ERR(new); ++ } ++ ++ smp_store_release(&seq->private, new); + mutex_unlock(&seq->lock); + + return nbytes; +@@ -1250,7 +1242,7 @@ static int psi_fop_release(struct inode *inode, struct file *file) + { + struct seq_file *seq = file->private_data; + +- psi_trigger_replace(&seq->private, NULL); ++ psi_trigger_destroy(seq->private); + return single_release(inode, file); + } + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 55c0f32b9375b..dbc9b2f53649d 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3022,8 +3022,8 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, + struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1]; + unsigned char name_assign_type = NET_NAME_USER; + struct nlattr *linkinfo[IFLA_INFO_MAX + 1]; +- const struct rtnl_link_ops *m_ops = NULL; +- struct net_device *master_dev = NULL; ++ const struct rtnl_link_ops *m_ops; ++ struct net_device *master_dev; + struct net *net = sock_net(skb->sk); + const struct rtnl_link_ops *ops; + struct nlattr *tb[IFLA_MAX + 1]; +@@ -3063,6 +3063,8 @@ replay: + dev = NULL; + } + ++ master_dev = NULL; ++ m_ops = NULL; + if (dev) { + master_dev = netdev_master_upper_dev_get(dev); + if (master_dev) +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 839e1caa57a59..ed11013d4b953 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1729,7 +1729,10 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) + err = -ENOSPC; + if (refcount_read(&match->sk_ref) < PACKET_FANOUT_MAX) { + __dev_remove_pack(&po->prot_hook); +- po->fanout = match; ++ ++ /* Paired with packet_setsockopt(PACKET_FANOUT_DATA) */ ++ WRITE_ONCE(po->fanout, match); ++ + po->rollover = rollover; + rollover = NULL; + refcount_set(&match->sk_ref, refcount_read(&match->sk_ref) + 1); +@@ -3876,7 +3879,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv + } + case PACKET_FANOUT_DATA: + { +- if (!po->fanout) ++ /* Paired with the WRITE_ONCE() in fanout_add() */ ++ if (!READ_ONCE(po->fanout)) + return -EINVAL; + + return fanout_set_data(po, optval, optlen); +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index a4c61205462ac..80205b138d113 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -1928,9 +1928,9 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, + bool prio_allocate; + u32 parent; + u32 chain_index; +- struct Qdisc *q = NULL; ++ struct Qdisc *q; + struct tcf_chain_info chain_info; +- struct tcf_chain *chain = NULL; ++ struct tcf_chain *chain; + struct tcf_block *block; + struct tcf_proto *tp; + unsigned long cl; +@@ -1958,6 +1958,8 @@ replay: + tp = NULL; + cl = 0; + block = NULL; ++ q = NULL; ++ chain = NULL; + + if (prio == 0) { + /* If no priority is provided by the user, +@@ -2764,8 +2766,8 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, + struct tcmsg *t; + u32 parent; + u32 chain_index; +- struct Qdisc *q = NULL; +- struct tcf_chain *chain = NULL; ++ struct Qdisc *q; ++ struct tcf_chain *chain; + struct tcf_block *block; + unsigned long cl; + int err; +@@ -2775,6 +2777,7 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, + return -EPERM; + + replay: ++ q = NULL; + err = nlmsg_parse_deprecated(n, sizeof(*t), tca, TCA_MAX, + rtm_tca_policy, extack); + if (err < 0) |