summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlice Ferrazzi <alicef@gentoo.org>2018-11-04 16:21:49 +0000
committerMike Pagano <mpagano@gentoo.org>2018-11-13 19:46:44 -0500
commit421d5534f563efc013380ae2668e5d50aca27769 (patch)
tree165b505c79e61a0aee80efa83002882764f5ea02 /1000_linux_4.19.1.patch
parentCreate 4.19 branch and port relevant patches (diff)
downloadlinux-patches-421d5534f563efc013380ae2668e5d50aca27769.tar.gz
linux-patches-421d5534f563efc013380ae2668e5d50aca27769.tar.bz2
linux-patches-421d5534f563efc013380ae2668e5d50aca27769.zip
linux kernel 4.19.1
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
Diffstat (limited to '1000_linux_4.19.1.patch')
-rw-r--r--1000_linux_4.19.1.patch966
1 files changed, 966 insertions, 0 deletions
diff --git a/1000_linux_4.19.1.patch b/1000_linux_4.19.1.patch
new file mode 100644
index 00000000..2274982f
--- /dev/null
+++ b/1000_linux_4.19.1.patch
@@ -0,0 +1,966 @@
+diff --git a/Makefile b/Makefile
+index 69fa5c0310d8..abcd8ca4966f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 19
+-SUBLEVEL = 0
++SUBLEVEL = 1
+ EXTRAVERSION =
+ NAME = "People's Front"
+
+diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
+index 4ff29b1406a9..b1d4e2e3210f 100644
+--- a/arch/sparc/include/asm/switch_to_64.h
++++ b/arch/sparc/include/asm/switch_to_64.h
+@@ -67,6 +67,7 @@ do { save_and_clear_fpu(); \
+ } while(0)
+
+ void synchronize_user_stack(void);
+-void fault_in_user_windows(void);
++struct pt_regs;
++void fault_in_user_windows(struct pt_regs *);
+
+ #endif /* __SPARC64_SWITCH_TO_64_H */
+diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
+index 6c086086ca8f..59eaf6227af1 100644
+--- a/arch/sparc/kernel/process_64.c
++++ b/arch/sparc/kernel/process_64.c
+@@ -36,6 +36,7 @@
+ #include <linux/sysrq.h>
+ #include <linux/nmi.h>
+ #include <linux/context_tracking.h>
++#include <linux/signal.h>
+
+ #include <linux/uaccess.h>
+ #include <asm/page.h>
+@@ -521,7 +522,12 @@ static void stack_unaligned(unsigned long sp)
+ force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0, current);
+ }
+
+-void fault_in_user_windows(void)
++static const char uwfault32[] = KERN_INFO \
++ "%s[%d]: bad register window fault: SP %08lx (orig_sp %08lx) TPC %08lx O7 %08lx\n";
++static const char uwfault64[] = KERN_INFO \
++ "%s[%d]: bad register window fault: SP %016lx (orig_sp %016lx) TPC %08lx O7 %016lx\n";
++
++void fault_in_user_windows(struct pt_regs *regs)
+ {
+ struct thread_info *t = current_thread_info();
+ unsigned long window;
+@@ -534,9 +540,9 @@ void fault_in_user_windows(void)
+ do {
+ struct reg_window *rwin = &t->reg_window[window];
+ int winsize = sizeof(struct reg_window);
+- unsigned long sp;
++ unsigned long sp, orig_sp;
+
+- sp = t->rwbuf_stkptrs[window];
++ orig_sp = sp = t->rwbuf_stkptrs[window];
+
+ if (test_thread_64bit_stack(sp))
+ sp += STACK_BIAS;
+@@ -547,8 +553,16 @@ void fault_in_user_windows(void)
+ stack_unaligned(sp);
+
+ if (unlikely(copy_to_user((char __user *)sp,
+- rwin, winsize)))
++ rwin, winsize))) {
++ if (show_unhandled_signals)
++ printk_ratelimited(is_compat_task() ?
++ uwfault32 : uwfault64,
++ current->comm, current->pid,
++ sp, orig_sp,
++ regs->tpc,
++ regs->u_regs[UREG_I7]);
+ goto barf;
++ }
+ } while (window--);
+ }
+ set_thread_wsaved(0);
+@@ -556,8 +570,7 @@ void fault_in_user_windows(void)
+
+ barf:
+ set_thread_wsaved(window + 1);
+- user_exit();
+- do_exit(SIGILL);
++ force_sig(SIGSEGV, current);
+ }
+
+ asmlinkage long sparc_do_fork(unsigned long clone_flags,
+diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
+index 4073e2b87dd0..29aa34f11720 100644
+--- a/arch/sparc/kernel/rtrap_64.S
++++ b/arch/sparc/kernel/rtrap_64.S
+@@ -39,6 +39,7 @@ __handle_preemption:
+ wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate
+
+ __handle_user_windows:
++ add %sp, PTREGS_OFF, %o0
+ call fault_in_user_windows
+ 661: wrpr %g0, RTRAP_PSTATE, %pstate
+ /* If userspace is using ADI, it could potentially pass
+diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
+index 44d379db3f64..4c5b3fcbed94 100644
+--- a/arch/sparc/kernel/signal32.c
++++ b/arch/sparc/kernel/signal32.c
+@@ -371,7 +371,11 @@ static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs,
+ get_sigframe(ksig, regs, sigframe_size);
+
+ if (invalid_frame_pointer(sf, sigframe_size)) {
+- do_exit(SIGILL);
++ if (show_unhandled_signals)
++ pr_info("%s[%d] bad frame in setup_frame32: %08lx TPC %08lx O7 %08lx\n",
++ current->comm, current->pid, (unsigned long)sf,
++ regs->tpc, regs->u_regs[UREG_I7]);
++ force_sigsegv(ksig->sig, current);
+ return -EINVAL;
+ }
+
+@@ -501,7 +505,11 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs,
+ get_sigframe(ksig, regs, sigframe_size);
+
+ if (invalid_frame_pointer(sf, sigframe_size)) {
+- do_exit(SIGILL);
++ if (show_unhandled_signals)
++ pr_info("%s[%d] bad frame in setup_rt_frame32: %08lx TPC %08lx O7 %08lx\n",
++ current->comm, current->pid, (unsigned long)sf,
++ regs->tpc, regs->u_regs[UREG_I7]);
++ force_sigsegv(ksig->sig, current);
+ return -EINVAL;
+ }
+
+diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
+index 48366e5eb5b2..e9de1803a22e 100644
+--- a/arch/sparc/kernel/signal_64.c
++++ b/arch/sparc/kernel/signal_64.c
+@@ -370,7 +370,11 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
+ get_sigframe(ksig, regs, sf_size);
+
+ if (invalid_frame_pointer (sf)) {
+- do_exit(SIGILL); /* won't return, actually */
++ if (show_unhandled_signals)
++ pr_info("%s[%d] bad frame in setup_rt_frame: %016lx TPC %016lx O7 %016lx\n",
++ current->comm, current->pid, (unsigned long)sf,
++ regs->tpc, regs->u_regs[UREG_I7]);
++ force_sigsegv(ksig->sig, current);
+ return -EINVAL;
+ }
+
+diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
+index bb68c805b891..ff9389a1c9f3 100644
+--- a/arch/sparc/kernel/systbls_64.S
++++ b/arch/sparc/kernel/systbls_64.S
+@@ -47,9 +47,9 @@ sys_call_table32:
+ .word sys_recvfrom, sys_setreuid16, sys_setregid16, sys_rename, compat_sys_truncate
+ /*130*/ .word compat_sys_ftruncate, sys_flock, compat_sys_lstat64, sys_sendto, sys_shutdown
+ .word sys_socketpair, sys_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
+-/*140*/ .word sys_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, compat_sys_getrlimit
++/*140*/ .word sys_sendfile64, sys_getpeername, compat_sys_futex, sys_gettid, compat_sys_getrlimit
+ .word compat_sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
+-/*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
++/*150*/ .word sys_getsockname, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
+ .word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
+ /*160*/ .word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
+ .word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys_setxattr
+diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
+index f396048a0d68..39822f611c01 100644
+--- a/arch/sparc/mm/init_64.c
++++ b/arch/sparc/mm/init_64.c
+@@ -1383,6 +1383,7 @@ int __node_distance(int from, int to)
+ }
+ return numa_latency[from][to];
+ }
++EXPORT_SYMBOL(__node_distance);
+
+ static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
+ {
+diff --git a/crypto/af_alg.c b/crypto/af_alg.c
+index b053179e0bc5..17eb09d222ff 100644
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -1071,7 +1071,7 @@ __poll_t af_alg_poll(struct file *file, struct socket *sock,
+ struct af_alg_ctx *ctx = ask->private;
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ if (!ctx->more || ctx->used)
+diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
+index 9697977b80f0..6b9ad8673218 100644
+--- a/drivers/net/bonding/bond_netlink.c
++++ b/drivers/net/bonding/bond_netlink.c
+@@ -638,8 +638,7 @@ static int bond_fill_info(struct sk_buff *skb,
+ goto nla_put_failure;
+
+ if (nla_put(skb, IFLA_BOND_AD_ACTOR_SYSTEM,
+- sizeof(bond->params.ad_actor_system),
+- &bond->params.ad_actor_system))
++ ETH_ALEN, &bond->params.ad_actor_system))
+ goto nla_put_failure;
+ }
+ if (!bond_3ad_get_active_agg_info(bond, &info)) {
+diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
+index 58bcee8f0a58..ce041c90adb0 100644
+--- a/drivers/net/ethernet/emulex/benet/be.h
++++ b/drivers/net/ethernet/emulex/benet/be.h
+@@ -185,6 +185,7 @@ static inline void queue_tail_inc(struct be_queue_info *q)
+
+ struct be_eq_obj {
+ struct be_queue_info q;
++ char desc[32];
+
+ struct be_adapter *adapter;
+ struct napi_struct napi;
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index 534787291b44..bff74752cef1 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -3488,11 +3488,9 @@ static int be_msix_register(struct be_adapter *adapter)
+ int status, i, vec;
+
+ for_all_evt_queues(adapter, eqo, i) {
+- char irq_name[IFNAMSIZ+4];
+-
+- snprintf(irq_name, sizeof(irq_name), "%s-q%d", netdev->name, i);
++ sprintf(eqo->desc, "%s-q%d", netdev->name, i);
+ vec = be_msix_vec_get(adapter, eqo);
+- status = request_irq(vec, be_msix, 0, irq_name, eqo);
++ status = request_irq(vec, be_msix, 0, eqo->desc, eqo);
+ if (status)
+ goto err_msix;
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+index 00172dee5339..a144146b769c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+@@ -696,43 +696,15 @@ static inline bool is_last_ethertype_ip(struct sk_buff *skb, int *network_depth)
+ return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
+ }
+
+-static __be32 mlx5e_get_fcs(struct sk_buff *skb)
++static u32 mlx5e_get_fcs(const struct sk_buff *skb)
+ {
+- int last_frag_sz, bytes_in_prev, nr_frags;
+- u8 *fcs_p1, *fcs_p2;
+- skb_frag_t *last_frag;
+- __be32 fcs_bytes;
++ const void *fcs_bytes;
++ u32 _fcs_bytes;
+
+- if (!skb_is_nonlinear(skb))
+- return *(__be32 *)(skb->data + skb->len - ETH_FCS_LEN);
++ fcs_bytes = skb_header_pointer(skb, skb->len - ETH_FCS_LEN,
++ ETH_FCS_LEN, &_fcs_bytes);
+
+- nr_frags = skb_shinfo(skb)->nr_frags;
+- last_frag = &skb_shinfo(skb)->frags[nr_frags - 1];
+- last_frag_sz = skb_frag_size(last_frag);
+-
+- /* If all FCS data is in last frag */
+- if (last_frag_sz >= ETH_FCS_LEN)
+- return *(__be32 *)(skb_frag_address(last_frag) +
+- last_frag_sz - ETH_FCS_LEN);
+-
+- fcs_p2 = (u8 *)skb_frag_address(last_frag);
+- bytes_in_prev = ETH_FCS_LEN - last_frag_sz;
+-
+- /* Find where the other part of the FCS is - Linear or another frag */
+- if (nr_frags == 1) {
+- fcs_p1 = skb_tail_pointer(skb);
+- } else {
+- skb_frag_t *prev_frag = &skb_shinfo(skb)->frags[nr_frags - 2];
+-
+- fcs_p1 = skb_frag_address(prev_frag) +
+- skb_frag_size(prev_frag);
+- }
+- fcs_p1 -= bytes_in_prev;
+-
+- memcpy(&fcs_bytes, fcs_p1, bytes_in_prev);
+- memcpy(((u8 *)&fcs_bytes) + bytes_in_prev, fcs_p2, last_frag_sz);
+-
+- return fcs_bytes;
++ return __get_unaligned_cpu32(fcs_bytes);
+ }
+
+ static inline void mlx5e_handle_csum(struct net_device *netdev,
+@@ -765,8 +737,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
+ network_depth - ETH_HLEN,
+ skb->csum);
+ if (unlikely(netdev->features & NETIF_F_RXFCS))
+- skb->csum = csum_add(skb->csum,
+- (__force __wsum)mlx5e_get_fcs(skb));
++ skb->csum = csum_block_add(skb->csum,
++ (__force __wsum)mlx5e_get_fcs(skb),
++ skb->len - ETH_FCS_LEN);
+ stats->csum_complete++;
+ return;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
+index 937d0ace699a..30f751e69698 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
+@@ -943,8 +943,8 @@ static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink,
+ mlxsw_core->bus,
+ mlxsw_core->bus_priv, true,
+ devlink);
+- if (err)
+- mlxsw_core->reload_fail = true;
++ mlxsw_core->reload_fail = !!err;
++
+ return err;
+ }
+
+@@ -1083,8 +1083,15 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
+ {
+ struct devlink *devlink = priv_to_devlink(mlxsw_core);
+
+- if (mlxsw_core->reload_fail)
+- goto reload_fail;
++ if (mlxsw_core->reload_fail) {
++ if (!reload)
++ /* Only the parts that were not de-initialized in the
++ * failed reload attempt need to be de-initialized.
++ */
++ goto reload_fail_deinit;
++ else
++ return;
++ }
+
+ if (mlxsw_core->driver->fini)
+ mlxsw_core->driver->fini(mlxsw_core);
+@@ -1098,9 +1105,12 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
+ if (!reload)
+ devlink_resources_unregister(devlink, NULL);
+ mlxsw_core->bus->fini(mlxsw_core->bus_priv);
+- if (reload)
+- return;
+-reload_fail:
++
++ return;
++
++reload_fail_deinit:
++ devlink_unregister(devlink);
++ devlink_resources_unregister(devlink, NULL);
+ devlink_free(devlink);
+ }
+ EXPORT_SYMBOL(mlxsw_core_bus_device_unregister);
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+index db715da7bab7..7715f1ed2bcb 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+@@ -2317,8 +2317,6 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
+ break;
+ case SWITCHDEV_FDB_DEL_TO_DEVICE:
+ fdb_info = &switchdev_work->fdb_info;
+- if (!fdb_info->added_by_user)
+- break;
+ mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
+ break;
+ case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
+diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
+index 2c350099b83c..4930e0375c1d 100644
+--- a/drivers/net/ethernet/realtek/r8169.c
++++ b/drivers/net/ethernet/realtek/r8169.c
+@@ -4175,10 +4175,15 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
+
+ static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
+ {
+- if (!netif_running(tp->dev) || !__rtl8169_get_wol(tp))
++ struct phy_device *phydev;
++
++ if (!__rtl8169_get_wol(tp))
+ return false;
+
+- phy_speed_down(tp->dev->phydev, false);
++ /* phydev may not be attached to netdevice */
++ phydev = mdiobus_get_phy(tp->mii_bus, 0);
++
++ phy_speed_down(phydev, false);
+ rtl_wol_suspend_quirk(tp);
+
+ return true;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+index b72ef171477e..bdd351597b55 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+@@ -243,7 +243,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
+ */
+ int stmmac_mdio_reset(struct mii_bus *bus)
+ {
+-#if defined(CONFIG_STMMAC_PLATFORM)
++#if IS_ENABLED(CONFIG_STMMAC_PLATFORM)
+ struct net_device *ndev = bus->priv;
+ struct stmmac_priv *priv = netdev_priv(ndev);
+ unsigned int mii_address = priv->hw->mii.addr;
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index b13c6b4b2c66..eb95daa3e5a5 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -30,6 +30,7 @@
+ #include <linux/sched/mm.h>
+ #include <linux/sched/signal.h>
+ #include <linux/interval_tree_generic.h>
++#include <linux/nospec.h>
+
+ #include "vhost.h"
+
+@@ -1397,6 +1398,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
+ if (idx >= d->nvqs)
+ return -ENOBUFS;
+
++ idx = array_index_nospec(idx, d->nvqs);
+ vq = d->vqs[idx];
+
+ mutex_lock(&vq->mutex);
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 433f45fc2d68..c64a1cff9eb3 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2057,14 +2057,20 @@ static inline bool skwq_has_sleeper(struct socket_wq *wq)
+ /**
+ * sock_poll_wait - place memory barrier behind the poll_wait call.
+ * @filp: file
++ * @sock: socket to wait on
+ * @p: poll_table
+ *
+ * See the comments in the wq_has_sleeper function.
++ *
++ * Do not derive sock from filp->private_data here. An SMC socket establishes
++ * an internal TCP socket that is used in the fallback case. All socket
++ * operations on the SMC socket are then forwarded to the TCP socket. In case of
++ * poll, the filp->private_data pointer references the SMC socket because the
++ * TCP socket has no file assigned.
+ */
+-static inline void sock_poll_wait(struct file *filp, poll_table *p)
++static inline void sock_poll_wait(struct file *filp, struct socket *sock,
++ poll_table *p)
+ {
+- struct socket *sock = filp->private_data;
+-
+ if (!poll_does_not_wait(p)) {
+ poll_wait(filp, &sock->wq->wait, p);
+ /* We need to be sure we are in sync with the
+diff --git a/net/atm/common.c b/net/atm/common.c
+index 9f8cb0d2e71e..a38c174fc766 100644
+--- a/net/atm/common.c
++++ b/net/atm/common.c
+@@ -653,7 +653,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
+ struct atm_vcc *vcc;
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ vcc = ATM_SD(sock);
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 20ed7adcf1cc..6dec8e9b3451 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -1420,7 +1420,14 @@ static void br_multicast_query_received(struct net_bridge *br,
+ return;
+
+ br_multicast_update_query_timer(br, query, max_delay);
+- br_multicast_mark_router(br, port);
++
++ /* Based on RFC4541, section 2.1.1 IGMP Forwarding Rules,
++ * the arrival port for IGMP Queries where the source address
++ * is 0.0.0.0 should not be added to router port list.
++ */
++ if ((saddr->proto == htons(ETH_P_IP) && saddr->u.ip4) ||
++ saddr->proto == htons(ETH_P_IPV6))
++ br_multicast_mark_router(br, port);
+ }
+
+ static void br_ip4_multicast_query(struct net_bridge *br,
+diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
+index d18965f3291f..416717c57cd1 100644
+--- a/net/caif/caif_socket.c
++++ b/net/caif/caif_socket.c
+@@ -941,7 +941,7 @@ static __poll_t caif_poll(struct file *file,
+ __poll_t mask;
+ struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ /* exceptional events? */
+diff --git a/net/core/datagram.c b/net/core/datagram.c
+index 9aac0d63d53e..57f3a6fcfc1e 100644
+--- a/net/core/datagram.c
++++ b/net/core/datagram.c
+@@ -808,8 +808,9 @@ int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
+ return -EINVAL;
+ }
+
+- if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
+- netdev_rx_csum_fault(skb->dev);
++ if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
++ !skb->csum_complete_sw)
++ netdev_rx_csum_fault(NULL);
+ }
+ return 0;
+ fault:
+@@ -837,7 +838,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock,
+ struct sock *sk = sock->sk;
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ /* exceptional events? */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 93243479085f..e16ba3625400 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -5431,6 +5431,7 @@ static void gro_flush_oldest(struct list_head *head)
+ * SKB to the chain.
+ */
+ list_del(&oldest->list);
++ oldest->next = NULL;
+ napi_gro_complete(oldest);
+ }
+
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index 37c7936124e6..6e5d61a20a70 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -3530,6 +3530,11 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
+ return -EINVAL;
+ }
+
++ if (dev->type != ARPHRD_ETHER) {
++ NL_SET_ERR_MSG(extack, "FDB delete only supported for Ethernet devices");
++ return -EINVAL;
++ }
++
+ addr = nla_data(tb[NDA_LLADDR]);
+
+ err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
+@@ -3634,6 +3639,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
+ return -EINVAL;
+ }
+
++ if (dev->type != ARPHRD_ETHER) {
++ NL_SET_ERR_MSG(extack, "FDB add only supported for Ethernet devices");
++ return -EINVAL;
++ }
++
+ addr = nla_data(tb[NDA_LLADDR]);
+
+ err = fdb_vid_parse(tb[NDA_VLAN], &vid, extack);
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index 875858c8b059..43733accf58e 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -325,7 +325,7 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
+ __poll_t mask;
+ struct sock *sk = sock->sk;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ if (sk->sk_state == DCCP_LISTEN)
+ return inet_csk_listen_poll(sk);
+
+diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
+index e7227128df2c..cb8fa5d7afe1 100644
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -720,10 +720,14 @@ struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
+ if (ip_is_fragment(&iph)) {
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb) {
+- if (!pskb_may_pull(skb, netoff + iph.ihl * 4))
+- return skb;
+- if (pskb_trim_rcsum(skb, netoff + len))
+- return skb;
++ if (!pskb_may_pull(skb, netoff + iph.ihl * 4)) {
++ kfree_skb(skb);
++ return NULL;
++ }
++ if (pskb_trim_rcsum(skb, netoff + len)) {
++ kfree_skb(skb);
++ return NULL;
++ }
+ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+ if (ip_defrag(net, skb, user))
+ return NULL;
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 10c6246396cc..bbd07736fb0f 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -507,7 +507,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
+ const struct tcp_sock *tp = tcp_sk(sk);
+ int state;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+
+ state = inet_sk_state_load(sk);
+ if (state == TCP_LISTEN)
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index c32a4c16b7ff..f8183fdce5b2 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -2120,8 +2120,24 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
+ /* Note, we are only interested in != 0 or == 0, thus the
+ * force to int.
+ */
+- return (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+- inet_compute_pseudo);
++ err = (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
++ inet_compute_pseudo);
++ if (err)
++ return err;
++
++ if (skb->ip_summed == CHECKSUM_COMPLETE && !skb->csum_valid) {
++ /* If SW calculated the value, we know it's bad */
++ if (skb->csum_complete_sw)
++ return 1;
++
++ /* HW says the value is bad. Let's validate that.
++ * skb->csum is no longer the full packet checksum,
++ * so don't treat it as such.
++ */
++ skb_checksum_complete_unset(skb);
++ }
++
++ return 0;
+ }
+
+ /* wrapper for udp_queue_rcv_skb tacking care of csum conversion and
+diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c
+index 547515e8450a..377717045f8f 100644
+--- a/net/ipv6/ip6_checksum.c
++++ b/net/ipv6/ip6_checksum.c
+@@ -88,8 +88,24 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
+ * Note, we are only interested in != 0 or == 0, thus the
+ * force to int.
+ */
+- return (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+- ip6_compute_pseudo);
++ err = (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
++ ip6_compute_pseudo);
++ if (err)
++ return err;
++
++ if (skb->ip_summed == CHECKSUM_COMPLETE && !skb->csum_valid) {
++ /* If SW calculated the value, we know it's bad */
++ if (skb->csum_complete_sw)
++ return 1;
++
++ /* HW says the value is bad. Let's validate that.
++ * skb->csum is no longer the full packet checksum,
++ * so don't treat is as such.
++ */
++ skb_checksum_complete_unset(skb);
++ }
++
++ return 0;
+ }
+ EXPORT_SYMBOL(udp6_csum_init);
+
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 0ec273997d1d..673a4a932f2a 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -1732,10 +1732,9 @@ int ndisc_rcv(struct sk_buff *skb)
+ return 0;
+ }
+
+- memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
+-
+ switch (msg->icmph.icmp6_type) {
+ case NDISC_NEIGHBOUR_SOLICITATION:
++ memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
+ ndisc_recv_ns(skb);
+ break;
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index abcb5ae77319..1cf00d857fc1 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -2799,6 +2799,8 @@ static int ip6_route_check_nh_onlink(struct net *net,
+ grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
+ if (grt) {
+ if (!grt->dst.error &&
++ /* ignore match if it is the default route */
++ grt->from && !ipv6_addr_any(&grt->from->fib6_dst.addr) &&
+ (grt->rt6i_flags & flags || dev != grt->dst.dev)) {
+ NL_SET_ERR_MSG(extack,
+ "Nexthop has invalid gateway or device mismatch");
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index e2f16a0173a9..f024914da1b2 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1505,7 +1505,7 @@ __poll_t iucv_sock_poll(struct file *file, struct socket *sock,
+ struct sock *sk = sock->sk;
+ __poll_t mask = 0;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+
+ if (sk->sk_state == IUCV_LISTEN)
+ return iucv_accept_poll(sk);
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index dd4adf8b1167..ae296273ce3d 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -556,7 +556,7 @@ static __poll_t llcp_sock_poll(struct file *file, struct socket *sock,
+
+ pr_debug("%p\n", sk);
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+
+ if (sk->sk_state == LLCP_LISTEN)
+ return llcp_accept_poll(sk);
+diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
+index a70097ecf33c..865ecef68196 100644
+--- a/net/openvswitch/flow_netlink.c
++++ b/net/openvswitch/flow_netlink.c
+@@ -3030,7 +3030,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
+ * is already present */
+ if (mac_proto != MAC_PROTO_NONE)
+ return -EINVAL;
+- mac_proto = MAC_PROTO_NONE;
++ mac_proto = MAC_PROTO_ETHERNET;
+ break;
+
+ case OVS_ACTION_ATTR_POP_ETH:
+@@ -3038,7 +3038,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
+ return -EINVAL;
+ if (vlan_tci & htons(VLAN_TAG_PRESENT))
+ return -EINVAL;
+- mac_proto = MAC_PROTO_ETHERNET;
++ mac_proto = MAC_PROTO_NONE;
+ break;
+
+ case OVS_ACTION_ATTR_PUSH_NSH:
+diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
+index ac44d8afffb1..3c39b8805d01 100644
+--- a/net/rxrpc/af_rxrpc.c
++++ b/net/rxrpc/af_rxrpc.c
+@@ -741,7 +741,7 @@ static __poll_t rxrpc_poll(struct file *file, struct socket *sock,
+ struct rxrpc_sock *rx = rxrpc_sk(sk);
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ /* the socket is readable if there are any messages waiting on the Rx
+diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
+index cbe4831f46f4..4a042abf844c 100644
+--- a/net/sched/sch_gred.c
++++ b/net/sched/sch_gred.c
+@@ -413,7 +413,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt,
+ if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL) {
+ if (tb[TCA_GRED_LIMIT] != NULL)
+ sch->limit = nla_get_u32(tb[TCA_GRED_LIMIT]);
+- return gred_change_table_def(sch, opt);
++ return gred_change_table_def(sch, tb[TCA_GRED_DPS]);
+ }
+
+ if (tb[TCA_GRED_PARMS] == NULL ||
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index c1c1bda334a4..c1693e28aed4 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -7101,14 +7101,15 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
+ }
+
+ policy = params.sprstat_policy;
+- if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
++ if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
++ ((policy & SCTP_PR_SCTP_ALL) && (policy & SCTP_PR_SCTP_MASK)))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
+ if (!asoc)
+ goto out;
+
+- if (policy & SCTP_PR_SCTP_ALL) {
++ if (policy == SCTP_PR_SCTP_ALL) {
+ params.sprstat_abandoned_unsent = 0;
+ params.sprstat_abandoned_sent = 0;
+ for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) {
+@@ -7160,7 +7161,8 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
+ }
+
+ policy = params.sprstat_policy;
+- if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
++ if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
++ ((policy & SCTP_PR_SCTP_ALL) && (policy & SCTP_PR_SCTP_MASK)))
+ goto out;
+
+ asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 015231789ed2..80e2119f1c70 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -1543,7 +1543,7 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
+ mask |= EPOLLERR;
+ } else {
+ if (sk->sk_state != SMC_CLOSED)
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ if (sk->sk_err)
+ mask |= EPOLLERR;
+ if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
+diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
+index e871368500e3..18daebcef181 100644
+--- a/net/smc/smc_core.c
++++ b/net/smc/smc_core.c
+@@ -122,22 +122,17 @@ static void __smc_lgr_unregister_conn(struct smc_connection *conn)
+ sock_put(&smc->sk); /* sock_hold in smc_lgr_register_conn() */
+ }
+
+-/* Unregister connection and trigger lgr freeing if applicable
++/* Unregister connection from lgr
+ */
+ static void smc_lgr_unregister_conn(struct smc_connection *conn)
+ {
+ struct smc_link_group *lgr = conn->lgr;
+- int reduced = 0;
+
+ write_lock_bh(&lgr->conns_lock);
+ if (conn->alert_token_local) {
+- reduced = 1;
+ __smc_lgr_unregister_conn(conn);
+ }
+ write_unlock_bh(&lgr->conns_lock);
+- if (!reduced || lgr->conns_num)
+- return;
+- smc_lgr_schedule_free_work(lgr);
+ }
+
+ /* Send delete link, either as client to request the initiation
+@@ -291,7 +286,8 @@ out:
+ return rc;
+ }
+
+-static void smc_buf_unuse(struct smc_connection *conn)
++static void smc_buf_unuse(struct smc_connection *conn,
++ struct smc_link_group *lgr)
+ {
+ if (conn->sndbuf_desc)
+ conn->sndbuf_desc->used = 0;
+@@ -301,8 +297,6 @@ static void smc_buf_unuse(struct smc_connection *conn)
+ conn->rmb_desc->used = 0;
+ } else {
+ /* buf registration failed, reuse not possible */
+- struct smc_link_group *lgr = conn->lgr;
+-
+ write_lock_bh(&lgr->rmbs_lock);
+ list_del(&conn->rmb_desc->list);
+ write_unlock_bh(&lgr->rmbs_lock);
+@@ -315,16 +309,21 @@ static void smc_buf_unuse(struct smc_connection *conn)
+ /* remove a finished connection from its link group */
+ void smc_conn_free(struct smc_connection *conn)
+ {
+- if (!conn->lgr)
++ struct smc_link_group *lgr = conn->lgr;
++
++ if (!lgr)
+ return;
+- if (conn->lgr->is_smcd) {
++ if (lgr->is_smcd) {
+ smc_ism_unset_conn(conn);
+ tasklet_kill(&conn->rx_tsklet);
+ } else {
+ smc_cdc_tx_dismiss_slots(conn);
+ }
+- smc_lgr_unregister_conn(conn);
+- smc_buf_unuse(conn);
++ smc_lgr_unregister_conn(conn); /* unsets conn->lgr */
++ smc_buf_unuse(conn, lgr); /* allow buffer reuse */
++
++ if (!lgr->conns_num)
++ smc_lgr_schedule_free_work(lgr);
+ }
+
+ static void smc_link_clear(struct smc_link *lnk)
+diff --git a/net/tipc/socket.c b/net/tipc/socket.c
+index 49810fdff4c5..0bf8ad486c5e 100644
+--- a/net/tipc/socket.c
++++ b/net/tipc/socket.c
+@@ -715,7 +715,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock,
+ struct tipc_sock *tsk = tipc_sk(sk);
+ __poll_t revents = 0;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ revents |= EPOLLRDHUP | EPOLLIN | EPOLLRDNORM;
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index d1edfa3cad61..c754f3a90a2e 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2640,7 +2640,7 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa
+ struct sock *sk = sock->sk;
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ /* exceptional events? */
+@@ -2677,7 +2677,7 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock,
+ unsigned int writable;
+ __poll_t mask;
+
+- sock_poll_wait(file, wait);
++ sock_poll_wait(file, sock, wait);
+ mask = 0;
+
+ /* exceptional events? */
+diff --git a/tools/testing/selftests/net/fib-onlink-tests.sh b/tools/testing/selftests/net/fib-onlink-tests.sh
+index 3991ad1a368d..864f865eee55 100755
+--- a/tools/testing/selftests/net/fib-onlink-tests.sh
++++ b/tools/testing/selftests/net/fib-onlink-tests.sh
+@@ -167,8 +167,8 @@ setup()
+ # add vrf table
+ ip li add ${VRF} type vrf table ${VRF_TABLE}
+ ip li set ${VRF} up
+- ip ro add table ${VRF_TABLE} unreachable default
+- ip -6 ro add table ${VRF_TABLE} unreachable default
++ ip ro add table ${VRF_TABLE} unreachable default metric 8192
++ ip -6 ro add table ${VRF_TABLE} unreachable default metric 8192
+
+ # create test interfaces
+ ip li add ${NETIFS[p1]} type veth peer name ${NETIFS[p2]}
+@@ -185,20 +185,20 @@ setup()
+ for n in 1 3 5 7; do
+ ip li set ${NETIFS[p${n}]} up
+ ip addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
+- ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
++ ip addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
+ done
+
+ # move peer interfaces to namespace and add addresses
+ for n in 2 4 6 8; do
+ ip li set ${NETIFS[p${n}]} netns ${PEER_NS} up
+ ip -netns ${PEER_NS} addr add ${V4ADDRS[p${n}]}/24 dev ${NETIFS[p${n}]}
+- ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]}
++ ip -netns ${PEER_NS} addr add ${V6ADDRS[p${n}]}/64 dev ${NETIFS[p${n}]} nodad
+ done
+
+- set +e
++ ip -6 ro add default via ${V6ADDRS[p3]/::[0-9]/::64}
++ ip -6 ro add table ${VRF_TABLE} default via ${V6ADDRS[p7]/::[0-9]/::64}
+
+- # let DAD complete - assume default of 1 probe
+- sleep 1
++ set +e
+ }
+
+ cleanup()