diff options
author | Mike Pagano <mpagano@gentoo.org> | 2021-10-17 09:14:14 -0400 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2021-10-17 09:14:14 -0400 |
commit | afc4f366b7eba5142a76771c67c034493f4441f4 (patch) | |
tree | e55b474a1af5ca11b3be8867614492136c5c3b10 | |
parent | Linux patch 4.9.286 (diff) | |
download | linux-patches-4.9-291.tar.gz linux-patches-4.9-291.tar.bz2 linux-patches-4.9-291.zip |
Linux patch 4.9.2874.9-291
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1286_linux-4.9.287.patch | 543 |
2 files changed, 547 insertions, 0 deletions
diff --git a/0000_README b/0000_README index af7e1352..6a1cf525 100644 --- a/0000_README +++ b/0000_README @@ -1187,6 +1187,10 @@ Patch: 1285_linux-4.9.286.patch From: http://www.kernel.org Desc: Linux 4.9.286 +Patch: 1286_linux-4.9.287.patch +From: http://www.kernel.org +Desc: Linux 4.9.287 + 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/1286_linux-4.9.287.patch b/1286_linux-4.9.287.patch new file mode 100644 index 00000000..f3751ccb --- /dev/null +++ b/1286_linux-4.9.287.patch @@ -0,0 +1,543 @@ +diff --git a/Makefile b/Makefile +index 68f2c6f3869e2..76eff0f592346 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 4 + PATCHLEVEL = 9 +-SUBLEVEL = 286 ++SUBLEVEL = 287 + EXTRAVERSION = + NAME = Roaring Lionus + +diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/omap3430-sdp.dts +index abd6921143beb..e0ba97bd41b79 100644 +--- a/arch/arm/boot/dts/omap3430-sdp.dts ++++ b/arch/arm/boot/dts/omap3430-sdp.dts +@@ -104,7 +104,7 @@ + + nand@1,0 { + compatible = "ti,omap2-nand"; +- reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ ++ reg = <1 0 4>; /* CS1, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ +diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c +index 6da26692f2fde..950c9f2ffe005 100644 +--- a/arch/arm/mach-imx/pm-imx6.c ++++ b/arch/arm/mach-imx/pm-imx6.c +@@ -15,6 +15,7 @@ + #include <linux/io.h> + #include <linux/irq.h> + #include <linux/genalloc.h> ++#include <linux/irqchip/arm-gic.h> + #include <linux/mfd/syscon.h> + #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> + #include <linux/of.h> +@@ -606,6 +607,7 @@ static void __init imx6_pm_common_init(const struct imx6_pm_socdata + + static void imx6_pm_stby_poweroff(void) + { ++ gic_cpu_if_down(0); + imx6_set_lpm(STOP_POWER_OFF); + imx6q_suspend_finish(0); + +diff --git a/arch/powerpc/boot/dts/fsl/t1023rdb.dts b/arch/powerpc/boot/dts/fsl/t1023rdb.dts +index 29757623e5baf..f5f8f969dd586 100644 +--- a/arch/powerpc/boot/dts/fsl/t1023rdb.dts ++++ b/arch/powerpc/boot/dts/fsl/t1023rdb.dts +@@ -125,7 +125,7 @@ + + fm1mac3: ethernet@e4000 { + phy-handle = <&sgmii_aqr_phy3>; +- phy-connection-type = "sgmii-2500"; ++ phy-connection-type = "2500base-x"; + sleep = <&rcpm 0x20000000>; + }; + +diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c +index c26cca506f646..c20df6a3540c2 100644 +--- a/arch/x86/events/core.c ++++ b/arch/x86/events/core.c +@@ -2075,6 +2075,7 @@ static int x86_pmu_event_init(struct perf_event *event) + if (err) { + if (event->destroy) + event->destroy(event); ++ event->destroy = NULL; + } + + if (ACCESS_ONCE(x86_pmu.attr_rdpmc)) +diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c +index 441694464b1e4..fbbc24b914e30 100644 +--- a/arch/xtensa/kernel/irq.c ++++ b/arch/xtensa/kernel/irq.c +@@ -144,7 +144,7 @@ unsigned xtensa_get_ext_irq_no(unsigned irq) + + void __init init_IRQ(void) + { +-#ifdef CONFIG_OF ++#ifdef CONFIG_USE_OF + irqchip_init(); + #else + #ifdef CONFIG_HAVE_SMP +diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c +index 411c12cdb2499..bb516eb124213 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c ++++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c +@@ -178,6 +178,7 @@ static const struct file_operations nouveau_pstate_fops = { + .open = nouveau_debugfs_pstate_open, + .read = seq_read, + .write = nouveau_debugfs_pstate_set, ++ .release = single_release, + }; + + static struct drm_info_list nouveau_debugfs_list[] = { +diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c +index 959a9e38b4f54..149902619cbc8 100644 +--- a/drivers/hid/hid-apple.c ++++ b/drivers/hid/hid-apple.c +@@ -302,12 +302,19 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, + + /* + * MacBook JIS keyboard has wrong logical maximum ++ * Magic Keyboard JIS has wrong logical maximum + */ + static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) + { + struct apple_sc *asc = hid_get_drvdata(hdev); + ++ if(*rsize >=71 && rdesc[70] == 0x65 && rdesc[64] == 0x65) { ++ hid_info(hdev, ++ "fixing up Magic Keyboard JIS report descriptor\n"); ++ rdesc[64] = rdesc[70] = 0xe7; ++ } ++ + if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && + rdesc[53] == 0x65 && rdesc[59] == 0x65) { + hid_info(hdev, +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 832fffed4a1fa..e7585f6c4665b 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -6646,7 +6646,7 @@ static int i40e_get_capabilities(struct i40e_pf *pf) + if (pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) { + /* retry with a larger buffer */ + buf_len = data_size; +- } else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK) { ++ } else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK || err) { + dev_info(&pf->pdev->dev, + "capability discovery failed, err %s aq_err %s\n", + i40e_stat_str(&pf->hw, err), +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 8cc7563ab103b..92fb664b56fbb 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -316,6 +316,13 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner) + bus->dev.groups = NULL; + dev_set_name(&bus->dev, "%s", bus->id); + ++ /* We need to set state to MDIOBUS_UNREGISTERED to correctly release ++ * the device in mdiobus_free() ++ * ++ * State will be updated later in this function in case of success ++ */ ++ bus->state = MDIOBUS_UNREGISTERED; ++ + err = device_register(&bus->dev); + if (err) { + pr_err("mii_bus %s failed to register\n", bus->id); +diff --git a/drivers/ptp/ptp_pch.c b/drivers/ptp/ptp_pch.c +index 3aa22ae4d94c0..a911325fc0b4f 100644 +--- a/drivers/ptp/ptp_pch.c ++++ b/drivers/ptp/ptp_pch.c +@@ -698,6 +698,7 @@ static const struct pci_device_id pch_ieee1588_pcidev_id[] = { + }, + {0} + }; ++MODULE_DEVICE_TABLE(pci, pch_ieee1588_pcidev_id); + + static struct pci_driver pch_driver = { + .name = KBUILD_MODNAME, +diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c +index 69046d342bc5d..39396548f9b55 100644 +--- a/drivers/scsi/ses.c ++++ b/drivers/scsi/ses.c +@@ -120,7 +120,7 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code, + static int ses_send_diag(struct scsi_device *sdev, int page_code, + void *buf, int bufflen) + { +- u32 result; ++ int result; + + unsigned char cmd[] = { + SEND_DIAGNOSTIC, +diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c +index 7ba0031d3a738..d5575869a25c7 100644 +--- a/drivers/scsi/virtio_scsi.c ++++ b/drivers/scsi/virtio_scsi.c +@@ -343,7 +343,7 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, + } + break; + default: +- pr_info("Unsupport virtio scsi event reason %x\n", event->reason); ++ pr_info("Unsupported virtio scsi event reason %x\n", event->reason); + } + } + +@@ -396,7 +396,7 @@ static void virtscsi_handle_event(struct work_struct *work) + virtscsi_handle_param_change(vscsi, event); + break; + default: +- pr_err("Unsupport virtio scsi event %x\n", event->event); ++ pr_err("Unsupported virtio scsi event %x\n", event->event); + } + virtscsi_kick_event(vscsi, event_node); + } +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 0103f777b97ad..bff5a15e59c00 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -160,8 +160,7 @@ source "drivers/usb/gadget/Kconfig" + + config USB_LED_TRIG + bool "USB LED Triggers" +- depends on LEDS_CLASS && LEDS_TRIGGERS +- select USB_COMMON ++ depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS + help + This option adds LED triggers for USB host and/or gadget activity. + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index 23df1549eb0d8..b7b83ca83ba0d 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -349,6 +349,9 @@ static void acm_ctrl_irq(struct urb *urb) + acm->iocount.overrun++; + spin_unlock(&acm->read_lock); + ++ if (newctrl & ACM_CTRL_BRK) ++ tty_flip_buffer_push(&acm->port); ++ + if (difference) + wake_up_all(&acm->wioctl); + +@@ -408,11 +411,16 @@ static int acm_submit_read_urbs(struct acm *acm, gfp_t mem_flags) + + static void acm_process_read_urb(struct acm *acm, struct urb *urb) + { ++ unsigned long flags; ++ + if (!urb->actual_length) + return; + ++ spin_lock_irqsave(&acm->read_lock, flags); + tty_insert_flip_string(&acm->port, urb->transfer_buffer, + urb->actual_length); ++ spin_unlock_irqrestore(&acm->read_lock, flags); ++ + tty_flip_buffer_push(&acm->port); + } + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index b16a6c0363527..dc51011d670df 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -3028,15 +3028,18 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, + goto fail; + cd->rd_maxcount -= entry_bytes; + /* +- * RFC 3530 14.2.24 describes rd_dircount as only a "hint", so +- * let's always let through the first entry, at least: ++ * RFC 3530 14.2.24 describes rd_dircount as only a "hint", and ++ * notes that it could be zero. If it is zero, then the server ++ * should enforce only the rd_maxcount value. + */ +- if (!cd->rd_dircount) +- goto fail; +- name_and_cookie = 4 + 4 * XDR_QUADLEN(namlen) + 8; +- if (name_and_cookie > cd->rd_dircount && cd->cookie_offset) +- goto fail; +- cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie); ++ if (cd->rd_dircount) { ++ name_and_cookie = 4 + 4 * XDR_QUADLEN(namlen) + 8; ++ if (name_and_cookie > cd->rd_dircount && cd->cookie_offset) ++ goto fail; ++ cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie); ++ if (!cd->rd_dircount) ++ cd->rd_maxcount = 0; ++ } + + cd->cookie_offset = cookie_offset; + skip_entry: +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index 8546384a5fdfd..edd5979aca4f6 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -926,9 +926,13 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, + goto out_dput; + } + } else { +- if (!d_is_negative(newdentry) && +- (!new_opaque || !ovl_is_whiteout(newdentry))) +- goto out_dput; ++ if (!d_is_negative(newdentry)) { ++ if (!new_opaque || !ovl_is_whiteout(newdentry)) ++ goto out_dput; ++ } else { ++ if (flags & RENAME_EXCHANGE) ++ goto out_dput; ++ } + } + + if (olddentry == trap) +diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c +index 2fdf6f96f9762..6f09728cd1dd3 100644 +--- a/kernel/bpf/stackmap.c ++++ b/kernel/bpf/stackmap.c +@@ -28,7 +28,8 @@ struct bpf_stack_map { + + static int prealloc_elems_and_freelist(struct bpf_stack_map *smap) + { +- u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size; ++ u64 elem_size = sizeof(struct stack_map_bucket) + ++ (u64)smap->map.value_size; + int err; + + smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries); +diff --git a/mm/gup.c b/mm/gup.c +index 6bb7a8eb7f820..301dd96ef176c 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -61,13 +61,22 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, + } + + /* +- * FOLL_FORCE can write to even unwritable pte's, but only +- * after we've gone through a COW cycle and they are dirty. ++ * FOLL_FORCE or a forced COW break can write even to unwritable pte's, ++ * but only after we've gone through a COW cycle and they are dirty. + */ + static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) + { +- return pte_write(pte) || +- ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); ++ return pte_write(pte) || ((flags & FOLL_COW) && pte_dirty(pte)); ++} ++ ++/* ++ * A (separate) COW fault might break the page the other way and ++ * get_user_pages() would return the page from what is now the wrong ++ * VM. So we need to force a COW break at GUP time even for reads. ++ */ ++static inline bool should_force_cow_break(struct vm_area_struct *vma, unsigned int flags) ++{ ++ return is_cow_mapping(vma->vm_flags) && (flags & FOLL_GET); + } + + static struct page *follow_page_pte(struct vm_area_struct *vma, +@@ -577,12 +586,18 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + if (!vma || check_vma_flags(vma, gup_flags)) + return i ? : -EFAULT; + if (is_vm_hugetlb_page(vma)) { ++ if (should_force_cow_break(vma, foll_flags)) ++ foll_flags |= FOLL_WRITE; + i = follow_hugetlb_page(mm, vma, pages, vmas, + &start, &nr_pages, i, +- gup_flags); ++ foll_flags); + continue; + } + } ++ ++ if (should_force_cow_break(vma, foll_flags)) ++ foll_flags |= FOLL_WRITE; ++ + retry: + /* + * If we have a pending SIGKILL, don't keep faulting pages and +@@ -1503,6 +1518,10 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, + /* + * Like get_user_pages_fast() except it's IRQ-safe in that it won't fall back to + * the regular GUP. It will only return non-negative values. ++ * ++ * Careful, careful! COW breaking can go either way, so a non-write ++ * access can get ambiguous page results. If you call this function without ++ * 'write' set, you'd better be sure that you're ok with that ambiguity. + */ + int __get_user_pages_fast(unsigned long start, int nr_pages, int write, + struct page **pages) +@@ -1532,6 +1551,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, + * + * We do not adopt an rcu_read_lock(.) here as we also want to + * block IPIs that come from THPs splitting. ++ * ++ * NOTE! We allow read-only gup_fast() here, but you'd better be ++ * careful about possible COW pages. You'll get _a_ COW page, but ++ * not necessarily the one you intended to get depending on what ++ * COW event happens after this. COW may break the page copy in a ++ * random direction. + */ + + local_irq_save(flags); +@@ -1542,15 +1567,22 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, + next = pgd_addr_end(addr, end); + if (pgd_none(pgd)) + break; ++ /* ++ * The FAST_GUP case requires FOLL_WRITE even for pure reads, ++ * because get_user_pages() may need to cause an early COW in ++ * order to avoid confusing the normal COW routines. So only ++ * targets that are already writable are safe to do by just ++ * looking at the page tables. ++ */ + if (unlikely(pgd_huge(pgd))) { +- if (!gup_huge_pgd(pgd, pgdp, addr, next, write, ++ if (!gup_huge_pgd(pgd, pgdp, addr, next, 1, + pages, &nr)) + break; + } else if (unlikely(is_hugepd(__hugepd(pgd_val(pgd))))) { + if (!gup_huge_pd(__hugepd(pgd_val(pgd)), addr, +- PGDIR_SHIFT, next, write, pages, &nr)) ++ PGDIR_SHIFT, next, 1, pages, &nr)) + break; +- } else if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) ++ } else if (!gup_pud_range(pgd, addr, next, 1, pages, &nr)) + break; + } while (pgdp++, addr = next, addr != end); + local_irq_restore(flags); +diff --git a/mm/huge_memory.c b/mm/huge_memory.c +index 91f33bb43f178..3f3a86cc62b68 100644 +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -1135,13 +1135,12 @@ out_unlock: + } + + /* +- * FOLL_FORCE can write to even unwritable pmd's, but only +- * after we've gone through a COW cycle and they are dirty. ++ * FOLL_FORCE or a forced COW break can write even to unwritable pmd's, ++ * but only after we've gone through a COW cycle and they are dirty. + */ + static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags) + { +- return pmd_write(pmd) || +- ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd)); ++ return pmd_write(pmd) || ((flags & FOLL_COW) && pmd_dirty(pmd)); + } + + struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, +diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c +index 4f831225d34f4..ca8757090ae35 100644 +--- a/net/bridge/br_netlink.c ++++ b/net/bridge/br_netlink.c +@@ -1298,7 +1298,7 @@ static size_t br_get_linkxstats_size(const struct net_device *dev, int attr) + } + + return numvls * nla_total_size(sizeof(struct bridge_vlan_xstats)) + +- nla_total_size(sizeof(struct br_mcast_stats)) + ++ nla_total_size_64bit(sizeof(struct br_mcast_stats)) + + nla_total_size(0); + } + +diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c +index 911752e8a3e64..012143f313a87 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -3900,7 +3900,7 @@ nla_put_failure: + static size_t if_nlmsg_stats_size(const struct net_device *dev, + u32 filter_mask) + { +- size_t size = 0; ++ size_t size = NLMSG_ALIGN(sizeof(struct if_stats_msg)); + + if (stats_attr_valid(filter_mask, IFLA_STATS_LINK_64, 0)) + size += nla_total_size_64bit(sizeof(struct rtnl_link_stats64)); +diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c +index 579fda1bc45df..ce54e66b47a03 100644 +--- a/net/ipv6/netfilter/ip6_tables.c ++++ b/net/ipv6/netfilter/ip6_tables.c +@@ -290,6 +290,7 @@ ip6t_do_table(struct sk_buff *skb, + * things we don't know, ie. tcp syn flag or ports). If the + * rule is also a fragment-specific rule, non-fragments won't + * match it. */ ++ acpar.fragoff = 0; + acpar.hotdrop = false; + acpar.net = state->net; + acpar.in = state->in; +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index b40e71a5d7957..3dc370ad23bf6 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -3692,7 +3692,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) + if (!bssid) + return false; + if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || +- ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) ++ ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2) || ++ !is_valid_ether_addr(hdr->addr2)) + return false; + if (ieee80211_is_beacon(hdr->frame_control)) + return true; +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 453b0efdc0d71..1b70de5898c42 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -574,7 +574,10 @@ static int netlink_insert(struct sock *sk, u32 portid) + + /* We need to ensure that the socket is hashed and visible. */ + smp_wmb(); +- nlk_sk(sk)->bound = portid; ++ /* Paired with lockless reads from netlink_bind(), ++ * netlink_connect() and netlink_sendmsg(). ++ */ ++ WRITE_ONCE(nlk_sk(sk)->bound, portid); + + err: + release_sock(sk); +@@ -993,7 +996,8 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, + else if (nlk->ngroups < 8*sizeof(groups)) + groups &= (1UL << nlk->ngroups) - 1; + +- bound = nlk->bound; ++ /* Paired with WRITE_ONCE() in netlink_insert() */ ++ bound = READ_ONCE(nlk->bound); + if (bound) { + /* Ensure nlk->portid is up-to-date. */ + smp_rmb(); +@@ -1073,8 +1077,9 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, + + /* No need for barriers here as we return to user-space without + * using any of the bound attributes. ++ * Paired with WRITE_ONCE() in netlink_insert(). + */ +- if (!nlk->bound) ++ if (!READ_ONCE(nlk->bound)) + err = netlink_autobind(sock); + + if (err == 0) { +@@ -1821,7 +1826,8 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) + dst_group = nlk->dst_group; + } + +- if (!nlk->bound) { ++ /* Paired with WRITE_ONCE() in netlink_insert() */ ++ if (!READ_ONCE(nlk->bound)) { + err = netlink_autobind(sock); + if (err) + goto out; +diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c +index 1e37247656f80..8b7110cbcce4c 100644 +--- a/net/sched/sch_fifo.c ++++ b/net/sched/sch_fifo.c +@@ -151,6 +151,9 @@ int fifo_set_limit(struct Qdisc *q, unsigned int limit) + if (strncmp(q->ops->id + 1, "fifo", 4) != 0) + return 0; + ++ if (!q->ops->change) ++ return 0; ++ + nla = kmalloc(nla_attr_size(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); + if (nla) { + nla->nla_type = RTM_NEWQDISC; |