summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2021-03-20 10:26:22 -0400
committerMike Pagano <mpagano@gentoo.org>2021-03-20 10:26:22 -0400
commit6a53709581956033128a6cbb16fb300b611decca (patch)
treedd27cf997082ccd29e66f87db06b2043764e6cea
parentLinux patch 4.19.181 (diff)
downloadlinux-patches-6a53709581956033128a6cbb16fb300b611decca.tar.gz
linux-patches-6a53709581956033128a6cbb16fb300b611decca.tar.bz2
linux-patches-6a53709581956033128a6cbb16fb300b611decca.zip
Linux patch 4.19.1824.19-181
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1181_linux-4.19.182.patch607
2 files changed, 611 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 3095bd68..edcc0c79 100644
--- a/0000_README
+++ b/0000_README
@@ -763,6 +763,10 @@ Patch: 1180_linux-4.19.181.patch
From: https://www.kernel.org
Desc: Linux 4.19.181
+Patch: 1181_linux-4.19.182.patch
+From: https://www.kernel.org
+Desc: Linux 4.19.182
+
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/1181_linux-4.19.182.patch b/1181_linux-4.19.182.patch
new file mode 100644
index 00000000..b00bc69c
--- /dev/null
+++ b/1181_linux-4.19.182.patch
@@ -0,0 +1,607 @@
+diff --git a/Makefile b/Makefile
+index 29930269b4860..5956638e0f4d0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 19
+-SUBLEVEL = 181
++SUBLEVEL = 182
+ EXTRAVERSION =
+ NAME = "People's Front"
+
+diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
+index 384c343976198..5f52d6d670e95 100644
+--- a/arch/arm64/include/asm/kvm_hyp.h
++++ b/arch/arm64/include/asm/kvm_hyp.h
+@@ -144,6 +144,9 @@ void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
+
+ void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
+ void __debug_switch_to_host(struct kvm_vcpu *vcpu);
++void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu);
++void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu);
++
+
+ void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
+ void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
+diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c
+index 50009766e5e56..3c5414633bb7c 100644
+--- a/arch/arm64/kvm/hyp/debug-sr.c
++++ b/arch/arm64/kvm/hyp/debug-sr.c
+@@ -149,6 +149,21 @@ static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
+ write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1);
+ }
+
++void __hyp_text __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
++{
++ /*
++ * Non-VHE: Disable and flush SPE data generation
++ * VHE: The vcpu can run, but it can't hide.
++ */
++ __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
++
++}
++
++void __hyp_text __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
++{
++ __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
++}
++
+ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
+ {
+ struct kvm_cpu_context *host_ctxt;
+@@ -156,13 +171,6 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
+ struct kvm_guest_debug_arch *host_dbg;
+ struct kvm_guest_debug_arch *guest_dbg;
+
+- /*
+- * Non-VHE: Disable and flush SPE data generation
+- * VHE: The vcpu can run, but it can't hide.
+- */
+- if (!has_vhe())
+- __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
+-
+ if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
+ return;
+
+@@ -182,8 +190,6 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
+ struct kvm_guest_debug_arch *host_dbg;
+ struct kvm_guest_debug_arch *guest_dbg;
+
+- if (!has_vhe())
+- __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
+
+ if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
+ return;
+diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
+index 15312e429b7d1..1d16ce0b7e0d6 100644
+--- a/arch/arm64/kvm/hyp/switch.c
++++ b/arch/arm64/kvm/hyp/switch.c
+@@ -560,6 +560,7 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
+ guest_ctxt = &vcpu->arch.ctxt;
+
+ __sysreg_save_state_nvhe(host_ctxt);
++ __debug_save_host_buffers_nvhe(vcpu);
+
+ __activate_traps(vcpu);
+ __activate_vm(kern_hyp_va(vcpu->kvm));
+@@ -599,11 +600,12 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
+ if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
+ __fpsimd_save_fpexc32(vcpu);
+
++ __debug_switch_to_host(vcpu);
+ /*
+ * This must come after restoring the host sysregs, since a non-VHE
+ * system may enable SPE here and make use of the TTBRs.
+ */
+- __debug_switch_to_host(vcpu);
++ __debug_restore_host_buffers_nvhe(vcpu);
+
+ return exit_code;
+ }
+diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
+index 335ce1e849044..7eaeab65d39f5 100644
+--- a/drivers/net/dsa/b53/b53_common.c
++++ b/drivers/net/dsa/b53/b53_common.c
+@@ -507,12 +507,27 @@ void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
+ }
+ EXPORT_SYMBOL(b53_imp_vlan_setup);
+
++static void b53_port_set_learning(struct b53_device *dev, int port,
++ bool learning)
++{
++ u16 reg;
++
++ b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, &reg);
++ if (learning)
++ reg &= ~BIT(port);
++ else
++ reg |= BIT(port);
++ b53_write16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, reg);
++}
++
+ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
+ {
+ struct b53_device *dev = ds->priv;
+ unsigned int cpu_port = ds->ports[port].cpu_dp->index;
+ u16 pvlan;
+
++ b53_port_set_learning(dev, port, false);
++
+ /* Clear the Rx and Tx disable bits and set to no spanning tree */
+ b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0);
+
+@@ -620,6 +635,7 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port)
+ b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);
+
+ b53_brcm_hdr_setup(dev->ds, port);
++ b53_port_set_learning(dev, port, false);
+ }
+
+ static void b53_enable_mib(struct b53_device *dev)
+@@ -1517,6 +1533,8 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br)
+ b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
+ dev->ports[port].vlan_ctl_mask = pvlan;
+
++ b53_port_set_learning(dev, port, true);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(b53_br_join);
+@@ -1564,6 +1582,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
+ vl->untag |= BIT(port) | BIT(cpu_port);
+ b53_set_vlan_entry(dev, pvid, vl);
+ }
++ b53_port_set_learning(dev, port, false);
+ }
+ EXPORT_SYMBOL(b53_br_leave);
+
+diff --git a/drivers/net/dsa/b53/b53_regs.h b/drivers/net/dsa/b53/b53_regs.h
+index c90985c294a2e..b2c539a421545 100644
+--- a/drivers/net/dsa/b53/b53_regs.h
++++ b/drivers/net/dsa/b53/b53_regs.h
+@@ -115,6 +115,7 @@
+ #define B53_UC_FLOOD_MASK 0x32
+ #define B53_MC_FLOOD_MASK 0x34
+ #define B53_IPMC_FLOOD_MASK 0x36
++#define B53_DIS_LEARNING 0x3c
+
+ /*
+ * Override Ports 0-7 State on devices with xMII interfaces (8 bit)
+diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
+index 613f03f9d9eca..e9fe3897bd9cc 100644
+--- a/drivers/net/dsa/bcm_sf2.c
++++ b/drivers/net/dsa/bcm_sf2.c
+@@ -173,11 +173,6 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
+ reg &= ~P_TXQ_PSM_VDD(port);
+ core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
+
+- /* Enable learning */
+- reg = core_readl(priv, CORE_DIS_LEARN);
+- reg &= ~BIT(port);
+- core_writel(priv, reg, CORE_DIS_LEARN);
+-
+ /* Enable Broadcom tags for that port if requested */
+ if (priv->brcm_tag_mask & BIT(port))
+ b53_brcm_hdr_setup(ds, port);
+diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c
+index f22a89cdb4072..1ea8fc9ff048f 100644
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -24,6 +24,7 @@ struct ext4_system_zone {
+ struct rb_node node;
+ ext4_fsblk_t start_blk;
+ unsigned int count;
++ u32 ino;
+ };
+
+ static struct kmem_cache *ext4_system_zone_cachep;
+@@ -45,7 +46,8 @@ void ext4_exit_system_zone(void)
+ static inline int can_merge(struct ext4_system_zone *entry1,
+ struct ext4_system_zone *entry2)
+ {
+- if ((entry1->start_blk + entry1->count) == entry2->start_blk)
++ if ((entry1->start_blk + entry1->count) == entry2->start_blk &&
++ entry1->ino == entry2->ino)
+ return 1;
+ return 0;
+ }
+@@ -66,7 +68,7 @@ static void release_system_zone(struct ext4_system_blocks *system_blks)
+ */
+ static int add_system_zone(struct ext4_system_blocks *system_blks,
+ ext4_fsblk_t start_blk,
+- unsigned int count)
++ unsigned int count, u32 ino)
+ {
+ struct ext4_system_zone *new_entry, *entry;
+ struct rb_node **n = &system_blks->root.rb_node, *node;
+@@ -89,6 +91,7 @@ static int add_system_zone(struct ext4_system_blocks *system_blks,
+ return -ENOMEM;
+ new_entry->start_blk = start_blk;
+ new_entry->count = count;
++ new_entry->ino = ino;
+ new_node = &new_entry->node;
+
+ rb_link_node(new_node, parent, n);
+@@ -145,7 +148,7 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
+ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
+ struct ext4_system_blocks *system_blks,
+ ext4_fsblk_t start_blk,
+- unsigned int count)
++ unsigned int count, ino_t ino)
+ {
+ struct ext4_system_zone *entry;
+ struct rb_node *n;
+@@ -169,7 +172,7 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi,
+ n = n->rb_right;
+ else {
+ sbi->s_es->s_last_error_block = cpu_to_le64(start_blk);
+- return 0;
++ return entry->ino == ino;
+ }
+ }
+ return 1;
+@@ -204,17 +207,16 @@ static int ext4_protect_reserved_inode(struct super_block *sb,
+ if (n == 0) {
+ i++;
+ } else {
+- if (!ext4_data_block_valid_rcu(sbi, system_blks,
+- map.m_pblk, n)) {
+- ext4_error(sb, "blocks %llu-%llu from inode %u "
++ err = add_system_zone(system_blks, map.m_pblk, n, ino);
++ if (err < 0) {
++ if (err == -EFSCORRUPTED) {
++ ext4_error(sb,
++ "blocks %llu-%llu from inode %u "
+ "overlap system zone", map.m_pblk,
+ map.m_pblk + map.m_len - 1, ino);
+- err = -EFSCORRUPTED;
++ }
+ break;
+ }
+- err = add_system_zone(system_blks, map.m_pblk, n);
+- if (err < 0)
+- break;
+ i += n;
+ }
+ }
+@@ -259,19 +261,19 @@ int ext4_setup_system_zone(struct super_block *sb)
+ ((i < 5) || ((i % flex_size) == 0)))
+ add_system_zone(system_blks,
+ ext4_group_first_block_no(sb, i),
+- ext4_bg_num_gdb(sb, i) + 1);
++ ext4_bg_num_gdb(sb, i) + 1, 0);
+ gdp = ext4_get_group_desc(sb, i, NULL);
+ ret = add_system_zone(system_blks,
+- ext4_block_bitmap(sb, gdp), 1);
++ ext4_block_bitmap(sb, gdp), 1, 0);
+ if (ret)
+ goto err;
+ ret = add_system_zone(system_blks,
+- ext4_inode_bitmap(sb, gdp), 1);
++ ext4_inode_bitmap(sb, gdp), 1, 0);
+ if (ret)
+ goto err;
+ ret = add_system_zone(system_blks,
+ ext4_inode_table(sb, gdp),
+- sbi->s_itb_per_group);
++ sbi->s_itb_per_group, 0);
+ if (ret)
+ goto err;
+ }
+@@ -320,7 +322,7 @@ void ext4_release_system_zone(struct super_block *sb)
+ call_rcu(&system_blks->rcu, ext4_destroy_system_zone);
+ }
+
+-int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
++int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk,
+ unsigned int count)
+ {
+ struct ext4_system_blocks *system_blks;
+@@ -332,9 +334,9 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk,
+ * mount option.
+ */
+ rcu_read_lock();
+- system_blks = rcu_dereference(sbi->system_blks);
+- ret = ext4_data_block_valid_rcu(sbi, system_blks, start_blk,
+- count);
++ system_blks = rcu_dereference(EXT4_SB(inode->i_sb)->system_blks);
++ ret = ext4_data_block_valid_rcu(EXT4_SB(inode->i_sb), system_blks,
++ start_blk, count, inode->i_ino);
+ rcu_read_unlock();
+ return ret;
+ }
+@@ -354,8 +356,7 @@ int ext4_check_blockref(const char *function, unsigned int line,
+ while (bref < p+max) {
+ blk = le32_to_cpu(*bref++);
+ if (blk &&
+- unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+- blk, 1))) {
++ unlikely(!ext4_inode_block_valid(inode, blk, 1))) {
+ es->s_last_error_block = cpu_to_le64(blk);
+ ext4_error_inode(inode, function, line, blk,
+ "invalid block");
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index a436307eed001..6938dff9f04bd 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -3180,9 +3180,9 @@ extern void ext4_release_system_zone(struct super_block *sb);
+ extern int ext4_setup_system_zone(struct super_block *sb);
+ extern int __init ext4_init_system_zone(void);
+ extern void ext4_exit_system_zone(void);
+-extern int ext4_data_block_valid(struct ext4_sb_info *sbi,
+- ext4_fsblk_t start_blk,
+- unsigned int count);
++extern int ext4_inode_block_valid(struct inode *inode,
++ ext4_fsblk_t start_blk,
++ unsigned int count);
+ extern int ext4_check_blockref(const char *, unsigned int,
+ struct inode *, __le32 *, unsigned int);
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 3a4570e37cb0b..36708d9d71cbb 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -377,7 +377,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
+ */
+ if (lblock + len <= lblock)
+ return 0;
+- return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
++ return ext4_inode_block_valid(inode, block, len);
+ }
+
+ static int ext4_valid_extent_idx(struct inode *inode,
+@@ -385,7 +385,7 @@ static int ext4_valid_extent_idx(struct inode *inode,
+ {
+ ext4_fsblk_t block = ext4_idx_pblock(ext_idx);
+
+- return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, 1);
++ return ext4_inode_block_valid(inode, block, 1);
+ }
+
+ static int ext4_valid_extent_entries(struct inode *inode,
+@@ -542,14 +542,10 @@ __read_extent_tree_block(const char *function, unsigned int line,
+ }
+ if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
+ return bh;
+- if (!ext4_has_feature_journal(inode->i_sb) ||
+- (inode->i_ino !=
+- le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) {
+- err = __ext4_ext_check(function, line, inode,
+- ext_block_hdr(bh), depth, pblk);
+- if (err)
+- goto errout;
+- }
++ err = __ext4_ext_check(function, line, inode,
++ ext_block_hdr(bh), depth, pblk);
++ if (err)
++ goto errout;
+ set_buffer_verified(bh);
+ /*
+ * If this is a leaf block, cache all of its entries
+diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
+index e1801b288847a..a5442528a60d2 100644
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -842,8 +842,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode,
+ else if (ext4_should_journal_data(inode))
+ flags |= EXT4_FREE_BLOCKS_FORGET;
+
+- if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free,
+- count)) {
++ if (!ext4_inode_block_valid(inode, block_to_free, count)) {
+ EXT4_ERROR_INODE(inode, "attempt to clear invalid "
+ "blocks %llu len %lu",
+ (unsigned long long) block_to_free, count);
+@@ -1005,8 +1004,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
+ if (!nr)
+ continue; /* A hole */
+
+- if (!ext4_data_block_valid(EXT4_SB(inode->i_sb),
+- nr, 1)) {
++ if (!ext4_inode_block_valid(inode, nr, 1)) {
+ EXT4_ERROR_INODE(inode,
+ "invalid indirect mapped "
+ "block %lu (level %d)",
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index edeb837081c80..296ffe92e2503 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -421,8 +421,7 @@ static int __check_block_validity(struct inode *inode, const char *func,
+ (inode->i_ino ==
+ le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
+ return 0;
+- if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+- map->m_len)) {
++ if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) {
+ ext4_error_inode(inode, func, line, map->m_pblk,
+ "lblock %lu mapped to illegal pblock %llu "
+ "(length %d)", (unsigned long) map->m_lblk,
+@@ -5072,7 +5071,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
+
+ ret = 0;
+ if (ei->i_file_acl &&
+- !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
++ !ext4_inode_block_valid(inode, ei->i_file_acl, 1)) {
+ ext4_error_inode(inode, function, line, 0,
+ "iget: bad extended attribute block %llu",
+ ei->i_file_acl);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index ec6f65c91d93c..db47a06cfb74e 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2990,7 +2990,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+ block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
+
+ len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+- if (!ext4_data_block_valid(sbi, block, len)) {
++ if (!ext4_inode_block_valid(ac->ac_inode, block, len)) {
+ ext4_error(sb, "Allocating blocks %llu-%llu which overlap "
+ "fs metadata", block, block+len);
+ /* File system mounted not to panic on error
+@@ -4755,7 +4755,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
+
+ sbi = EXT4_SB(sb);
+ if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) &&
+- !ext4_data_block_valid(sbi, block, count)) {
++ !ext4_inode_block_valid(inode, block, count)) {
+ ext4_error(sb, "Freeing blocks not in datazone - "
+ "block = %llu, count = %lu", block, count);
+ goto error_return;
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index daf0a9637d73a..a0cdb6c4a330f 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2734,24 +2734,29 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
+ {
+ bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
+ (opcode == BPF_SUB && !off_is_neg);
+- u32 off;
++ u32 off, max;
+
+ switch (ptr_reg->type) {
+ case PTR_TO_STACK:
++ /* Offset 0 is out-of-bounds, but acceptable start for the
++ * left direction, see BPF_REG_FP.
++ */
++ max = MAX_BPF_STACK + mask_to_left;
+ off = ptr_reg->off + ptr_reg->var_off.value;
+ if (mask_to_left)
+ *ptr_limit = MAX_BPF_STACK + off;
+ else
+- *ptr_limit = -off;
+- return 0;
++ *ptr_limit = -off - 1;
++ return *ptr_limit >= max ? -ERANGE : 0;
+ case PTR_TO_MAP_VALUE:
++ max = ptr_reg->map_ptr->value_size;
+ if (mask_to_left) {
+ *ptr_limit = ptr_reg->umax_value + ptr_reg->off;
+ } else {
+ off = ptr_reg->smin_value + ptr_reg->off;
+- *ptr_limit = ptr_reg->map_ptr->value_size - off;
++ *ptr_limit = ptr_reg->map_ptr->value_size - off - 1;
+ }
+- return 0;
++ return *ptr_limit >= max ? -ERANGE : 0;
+ default:
+ return -EINVAL;
+ }
+@@ -2804,6 +2809,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
+ u32 alu_state, alu_limit;
+ struct bpf_reg_state tmp;
+ bool ret;
++ int err;
+
+ if (can_skip_alu_sanitation(env, insn))
+ return 0;
+@@ -2819,10 +2825,13 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
+ alu_state |= ptr_is_dst_reg ?
+ BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST;
+
+- if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg))
+- return 0;
+- if (update_alu_sanitation_state(aux, alu_state, alu_limit))
+- return -EACCES;
++ err = retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg);
++ if (err < 0)
++ return err;
++
++ err = update_alu_sanitation_state(aux, alu_state, alu_limit);
++ if (err < 0)
++ return err;
+ do_sim:
+ /* Simulate and find potential out-of-bounds access under
+ * speculative execution from truncation as a result of
+@@ -2920,7 +2929,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ case BPF_ADD:
+ ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0);
+ if (ret < 0) {
+- verbose(env, "R%d tried to add from different maps or paths\n", dst);
++ verbose(env, "R%d tried to add from different maps, paths, or prohibited types\n", dst);
+ return ret;
+ }
+ /* We can take a fixed offset as long as it doesn't overflow
+@@ -2975,7 +2984,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
+ case BPF_SUB:
+ ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0);
+ if (ret < 0) {
+- verbose(env, "R%d tried to sub from different maps or paths\n", dst);
++ verbose(env, "R%d tried to sub from different maps, paths, or prohibited types\n", dst);
+ return ret;
+ }
+ if (dst_reg == off_reg) {
+@@ -6085,7 +6094,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
+ off_reg = issrc ? insn->src_reg : insn->dst_reg;
+ if (isneg)
+ *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
+- *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit - 1);
++ *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit);
+ *patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
+ *patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
+ *patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);
+diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
+index 6574425ad94c1..1f57dce969f70 100644
+--- a/net/dsa/tag_mtk.c
++++ b/net/dsa/tag_mtk.c
+@@ -20,6 +20,7 @@
+ #define MTK_HDR_LEN 4
+ #define MTK_HDR_XMIT_UNTAGGED 0
+ #define MTK_HDR_XMIT_TAGGED_TPID_8100 1
++#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2
+ #define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0)
+ #define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0)
+ #define MTK_HDR_XMIT_SA_DIS BIT(6)
+@@ -28,8 +29,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+ struct dsa_port *dp = dsa_slave_to_port(dev);
++ u8 xmit_tpid;
+ u8 *mtk_tag;
+- bool is_vlan_skb = true;
+ unsigned char *dest = eth_hdr(skb)->h_dest;
+ bool is_multicast_skb = is_multicast_ether_addr(dest) &&
+ !is_broadcast_ether_addr(dest);
+@@ -40,13 +41,20 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+ * the both special and VLAN tag at the same time and then look up VLAN
+ * table with VID.
+ */
+- if (!skb_vlan_tagged(skb)) {
++ switch (skb->protocol) {
++ case htons(ETH_P_8021Q):
++ xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100;
++ break;
++ case htons(ETH_P_8021AD):
++ xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8;
++ break;
++ default:
+ if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+ return NULL;
+
++ xmit_tpid = MTK_HDR_XMIT_UNTAGGED;
+ skb_push(skb, MTK_HDR_LEN);
+ memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+- is_vlan_skb = false;
+ }
+
+ mtk_tag = skb->data + 2 * ETH_ALEN;
+@@ -54,8 +62,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+ /* Mark tag attribute on special tag insertion to notify hardware
+ * whether that's a combined special tag with 802.1Q header.
+ */
+- mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 :
+- MTK_HDR_XMIT_UNTAGGED;
++ mtk_tag[0] = xmit_tpid;
+ mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
+
+ /* Disable SA learning for multicast frames */
+@@ -63,7 +70,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+ mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS;
+
+ /* Tag control information is kept for 802.1Q */
+- if (!is_vlan_skb) {
++ if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) {
+ mtk_tag[2] = 0;
+ mtk_tag[3] = 0;
+ }