diff --git a/include/depends.mk b/include/depends.mk
index 0080b97876..465e4e952a 100644
--- a/include/depends.mk
+++ b/include/depends.mk
@@ -11,7 +11,7 @@
 
 DEP_FINDPARAMS := -x "*/.svn*" -x ".*" -x "*:*" -x "*\!*" -x "* *" -x "*\\\#*" -x "*/.*_check" -x "*/.*.swp" -x "*/.pkgdir*"
 
-find_md5=find $(wildcard $(1)) -type f $(patsubst -x,-and -not -path,$(DEP_FINDPARAMS) $(2)) -printf "%p%T@\n" | sort | mkhash md5
+find_md5=find $(wildcard $(1)) -type f $(patsubst -x,-and -not -path,$(DEP_FINDPARAMS) $(2)) -printf "%p%T@\n" | sort | $(MKHASH) md5
 
 define rdep
   .PRECIOUS: $(2)
diff --git a/include/download.mk b/include/download.mk
index 4bf055e611..609956b004 100644
--- a/include/download.mk
+++ b/include/download.mk
@@ -74,7 +74,7 @@ else
   check_warn = $(if $(filter-out undefined,$(origin F_$(1))),$(filter ,$(shell $(call F_$(1),$(2),$(3),$(4)) >&2)),$(check_warn_nofix))
 endif
 
-gen_sha256sum = $(shell mkhash sha256 $(DL_DIR)/$(1))
+gen_sha256sum = $(shell $(MKHASH) sha256 $(DL_DIR)/$(1))
 
 ifdef FIXUP
 F_hash_deprecated = $(SCRIPT_DIR)/fixup-makefile.pl $(CURDIR)/Makefile fix-hash $(3) $(call gen_sha256sum,$(1)) $(2)
diff --git a/include/image-commands.mk b/include/image-commands.mk
index 9702d029d7..fa36885038 100644
--- a/include/image-commands.mk
+++ b/include/image-commands.mk
@@ -198,7 +198,7 @@ define Build/elx-header
 			dd bs=20 count=1 conv=sync; \
 		echo -ne "$$(printf '%08x' $$(stat -c%s $@) | fold -s2 | xargs -I {} echo \\x{} | tr -d '\n')" | \
 			dd bs=8 count=1 conv=sync; \
-		echo -ne "$$($(STAGING_DIR_HOST)/bin/mkhash md5 $@ | fold -s2 | xargs -I {} echo \\x{} | tr -d '\n')" | \
+		echo -ne "$$($(MKHASH) md5 $@ | fold -s2 | xargs -I {} echo \\x{} | tr -d '\n')" | \
 			dd bs=58 count=1 conv=sync; \
 	) > $(KDIR)/tmp/$(DEVICE_NAME).header
 	$(call Build/xor-image,-p $(xor_pattern) -x)
@@ -272,8 +272,11 @@ define Build/jffs2
 endef
 
 define Build/kernel2minor
-	kernel2minor -k $@ -r $@.new $(1)
-	mv $@.new $@
+	$(eval temp_file := $(shell mktemp))
+	cp $@ $(temp_file)
+	kernel2minor -k $(temp_file) -r $(temp_file).new $(1)
+	mv $(temp_file).new $@
+	rm -f $(temp_file)
 endef
 
 define Build/kernel-bin
diff --git a/include/image.mk b/include/image.mk
index 0ab616dbcf..d838cf5800 100644
--- a/include/image.mk
+++ b/include/image.mk
@@ -26,7 +26,7 @@ param_get_default = $(firstword $(call param_get,$(1),$(2)) $(3))
 param_mangle = $(subst $(space),_,$(strip $(1)))
 param_unmangle = $(subst _,$(space),$(1))
 
-mkfs_packages_id = $(shell echo $(sort $(1)) | mkhash md5 | cut -b1-8)
+mkfs_packages_id = $(shell echo $(sort $(1)) | $(MKHASH) md5 | cut -b1-8)
 mkfs_target_dir = $(if $(call param_get,pkg,$(1)),$(KDIR)/target-dir-$(call param_get,pkg,$(1)),$(TARGET_DIR))
 
 KDIR=$(KERNEL_BUILD_DIR)
@@ -40,8 +40,8 @@ IMG_PREFIX_VERCODE:=$(if $(CONFIG_VERSION_CODE_FILENAMES),$(call sanitize,$(VERS
 IMG_PREFIX:=$(VERSION_DIST_SANITIZED)-$(IMG_PREFIX_VERNUM)$(IMG_PREFIX_VERCODE)$(IMG_PREFIX_EXTRA)$(BOARD)$(if $(SUBTARGET),-$(SUBTARGET))
 IMG_ROOTFS:=$(IMG_PREFIX)-rootfs
 IMG_COMBINED:=$(IMG_PREFIX)-combined
-IMG_PART_SIGNATURE:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | cut -b1-8)
-IMG_PART_DISKGUID:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{10})../\1-\2-\3-\4-\500/')
+IMG_PART_SIGNATURE:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | $(MKHASH) md5 | cut -b1-8)
+IMG_PART_DISKGUID:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | $(MKHASH) md5 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{10})../\1-\2-\3-\4-\500/')
 
 MKFS_DEVTABLE_OPT := -D $(INCLUDE_DIR)/device_table.txt
 
diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk
index 4b0b136a03..82bc32256d 100644
--- a/include/kernel-defaults.mk
+++ b/include/kernel-defaults.mk
@@ -116,7 +116,7 @@ define Kernel/Configure/Default
 		cp $(LINUX_DIR)/.config.set $(LINUX_DIR)/.config.prev; \
 	}
 	$(_SINGLE) [ -d $(LINUX_DIR)/user_headers ] || $(KERNEL_MAKE) INSTALL_HDR_PATH=$(LINUX_DIR)/user_headers headers_install
-	grep '=[ym]' $(LINUX_DIR)/.config.set | LC_ALL=C sort | mkhash md5 > $(LINUX_DIR)/.vermagic
+	grep '=[ym]' $(LINUX_DIR)/.config.set | LC_ALL=C sort | $(MKHASH) md5 > $(LINUX_DIR)/.vermagic
 endef
 
 define Kernel/Configure/Initramfs
@@ -186,5 +186,3 @@ define Kernel/Clean/Default
 	rm -f $(LINUX_KERNEL)
 	$(_SINGLE)$(MAKE) -C $(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION) clean
 endef
-
-
diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk
index c2017cd220..b066e116f7 100644
--- a/include/package-ipkg.mk
+++ b/include/package-ipkg.mk
@@ -221,7 +221,7 @@ $(_endef)
     ifneq ($$(CONFIG_IPK_FILES_CHECKSUMS),)
 	(cd $$(IDIR_$(1)); \
 		( \
-			find . -type f \! -path ./CONTROL/\* -exec mkhash sha256 -n \{\} \; 2> /dev/null | \
+			find . -type f \! -path ./CONTROL/\* -exec $(MKHASH) sha256 -n \{\} \; 2> /dev/null | \
 			sed 's|\([[:blank:]]\)\./| \1/|' > $$(IDIR_$(1))/CONTROL/files-sha256sum \
 		) || true \
 	)
diff --git a/include/quilt.mk b/include/quilt.mk
index 00597ca0f2..6d25469daf 100644
--- a/include/quilt.mk
+++ b/include/quilt.mk
@@ -159,7 +159,7 @@ define Quilt/Template
 		false; \
 	}
 	@[ -n "$$$$(ls $(1)/patches/series)" -o \
-	   "$$$$(cat $(1)/patches/series | mkhash md5)" = "$$(sort $(1)/patches/series | mkhash md5)" ] || { \
+	   "$$$$(cat $(1)/patches/series | $(MKHASH) md5)" = "$$(sort $(1)/patches/series | $(MKHASH) md5)" ] || { \
 		echo "The patches are not sorted in the right order. Please fix."; \
 		false; \
 	}
diff --git a/include/scan.mk b/include/scan.mk
index 7df5dc6486..aee24cb3e5 100644
--- a/include/scan.mk
+++ b/include/scan.mk
@@ -1,4 +1,5 @@
 include $(TOPDIR)/include/verbose.mk
+include $(TOPDIR)/rules.mk
 TMP_DIR:=$(TOPDIR)/tmp
 
 all: $(TMP_DIR)/.$(SCAN_TARGET)
@@ -100,7 +101,7 @@ $(TMP_DIR)/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
 $(TARGET_STAMP)::
 	+( \
 		$(NO_TRACE_MAKE) $(FILELIST); \
-		MD5SUM=$$(cat $(FILELIST) $(OVERRIDELIST) | mkhash md5 | awk '{print $$1}'); \
+		MD5SUM=$$(cat $(FILELIST) $(OVERRIDELIST) | $(MKHASH) md5 | awk '{print $$1}'); \
 		[ -f "$@.$$MD5SUM" ] || { \
 			rm -f $@.*; \
 			touch $@.$$MD5SUM; \
diff --git a/package/Makefile b/package/Makefile
index ec503dc527..209be34674 100644
--- a/package/Makefile
+++ b/package/Makefile
@@ -66,8 +66,10 @@ $(curdir)/install: $(TMP_DIR)/.build $(curdir)/merge $(if $(CONFIG_TARGET_PER_DE
 	- find $(STAGING_DIR_ROOT) -type d | $(XARGS) chmod 0755
 	rm -rf $(TARGET_DIR) $(TARGET_DIR_ORIG)
 	mkdir -p $(TARGET_DIR)/tmp
-	$(call opkg,$(TARGET_DIR)) install \
-		$(call opkg_package_files,$(foreach pkg,$(shell cat $(PACKAGE_INSTALL_FILES) 2>/dev/null),$(pkg)$(call GetABISuffix,$(pkg))))
+	$(file >$(TMP_DIR)/opkg_install_list,\
+	  $(call opkg_package_files,\
+	    $(foreach pkg,$(shell cat $(PACKAGE_INSTALL_FILES) 2>/dev/null),$(pkg)$(call GetABISuffix,$(pkg)))))
+	$(call opkg,$(TARGET_DIR)) install $$(cat $(TMP_DIR)/opkg_install_list)
 	@for file in $(PACKAGE_INSTALL_FILES); do \
 		[ -s $$file.flags ] || continue; \
 		for flag in `cat $$file.flags`; do \
diff --git a/package/base-files/Makefile b/package/base-files/Makefile
index 8a1ddf96f5..d8d093a306 100644
--- a/package/base-files/Makefile
+++ b/package/base-files/Makefile
@@ -30,7 +30,7 @@ PKG_CONFIG_DEPENDS += \
 include $(INCLUDE_DIR)/package.mk
 
 ifneq ($(DUMP),1)
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | mkhash md5)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | $(MKHASH) md5)
   TARGET:=-$(BOARD)
 endif
 
diff --git a/package/base-files/files/etc/shinit b/package/base-files/files/etc/shinit
index 0a1ebcc832..6b682d8769 100644
--- a/package/base-files/files/etc/shinit
+++ b/package/base-files/files/etc/shinit
@@ -22,7 +22,7 @@ service() {
 			printf "%-30s\t%10s\t%10s\n"  "$F" \
 			$( $($F enabled) && echo "enabled" || echo "disabled" ) \
 			$( [ "$(ubus call service list "{ 'verbose': true, 'name': '$(basename $F)' }" \
-			| jsonfilter -q -e "@.$(basename $F).instances[*].running" | uniq)" = "true" ] \
+			| jsonfilter -q -e "@['$(basename $F)'].instances[*].running" | uniq)" = "true" ] \
 			&& echo "running" || echo "stopped" )
 		done;
 		return 1
diff --git a/package/kernel/linux/Makefile b/package/kernel/linux/Makefile
index 39b9e82c27..9fa68d78f7 100644
--- a/package/kernel/linux/Makefile
+++ b/package/kernel/linux/Makefile
@@ -24,7 +24,7 @@ export SHELL:=/bin/sh
 include $(INCLUDE_DIR)/package.mk
 
 ifeq ($(DUMP),)
-  STAMP_BUILT:=$(STAMP_BUILT)_$(shell $(SCRIPT_DIR)/kconfig.pl $(LINUX_DIR)/.config | mkhash md5)
+  STAMP_BUILT:=$(STAMP_BUILT)_$(shell $(SCRIPT_DIR)/kconfig.pl $(LINUX_DIR)/.config | $(MKHASH) md5)
   -include $(LINUX_DIR)/.config
 endif
 
diff --git a/package/kernel/linux/modules/leds.mk b/package/kernel/linux/modules/leds.mk
index 4dde833664..fdd5280fe4 100644
--- a/package/kernel/linux/modules/leds.mk
+++ b/package/kernel/linux/modules/leds.mk
@@ -145,3 +145,17 @@ define KernelPackage/leds-pwm/description
 endef
 
 $(eval $(call KernelPackage,leds-pwm))
+
+define KernelPackage/leds-uleds
+  SUBMENU:=$(LEDS_MENU)
+  TITLE:=Userspace LEDs
+  KCONFIG:=CONFIG_LEDS_USER
+  FILES:=$(LINUX_DIR)/drivers/leds/uleds.ko
+  AUTOLOAD:=$(call AutoLoad,60,leds-uleds,1)
+endef
+
+define KernelPackage/leds-uleds/description
+ This option enables support for userspace LEDs.
+endef
+
+$(eval $(call KernelPackage,leds-uleds))
diff --git a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch b/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch
index de6f9d9bb0..55d48daa79 100644
--- a/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch
+++ b/package/kernel/mac80211/patches/ath/080-ath10k_thermal_config.patch
@@ -37,7 +37,7 @@
  void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
 --- a/local-symbols
 +++ b/local-symbols
-@@ -142,6 +142,7 @@ ATH10K_SNOC=
+@@ -143,6 +143,7 @@ ATH10K_SNOC=
  ATH10K_DEBUG=
  ATH10K_DEBUGFS=
  ATH10K_SPECTRAL=
diff --git a/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch b/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
new file mode 100644
index 0000000000..0ce49b22ab
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
@@ -0,0 +1,180 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:52 +0200
+Subject: [PATCH] ath10k: add CCMP PN replay protection for fragmented
+ frames for PCIe
+
+PN replay check for not fragmented frames is finished in the firmware,
+but this was not done for fragmented frames when ath10k is used with
+QCA6174/QCA6377 PCIe. mac80211 has the function
+ieee80211_rx_h_defragment() for PN replay check for fragmented frames,
+but this does not get checked with QCA6174 due to the
+ieee80211_has_protected() condition not matching the cleared Protected
+bit case.
+
+Validate the PN of received fragmented frames within ath10k when CCMP is
+used and drop the fragment if the PN is not correct (incremented by
+exactly one from the previous fragment). This applies only for
+QCA6174/QCA6377 PCIe.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt.h
++++ b/drivers/net/wireless/ath/ath10k/htt.h
+@@ -846,6 +846,7 @@ enum htt_security_types {
+ 
+ #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2
+ #define ATH10K_TXRX_NUM_EXT_TIDS 19
++#define ATH10K_TXRX_NON_QOS_TID 16
+ 
+ enum htt_security_flags {
+ #define HTT_SECURITY_TYPE_MASK 0x7F
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1746,16 +1746,87 @@ static void ath10k_htt_rx_h_csum_offload
+ 	msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
+ }
+ 
++static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
++				  u16 offset,
++				  enum htt_rx_mpdu_encrypt_type enctype)
++{
++	struct ieee80211_hdr *hdr;
++	u64 pn = 0;
++	u8 *ehdr;
++
++	hdr = (struct ieee80211_hdr *)(skb->data + offset);
++	ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control);
++
++	if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) {
++		pn = ehdr[0];
++		pn |= (u64)ehdr[1] << 8;
++		pn |= (u64)ehdr[4] << 16;
++		pn |= (u64)ehdr[5] << 24;
++		pn |= (u64)ehdr[6] << 32;
++		pn |= (u64)ehdr[7] << 40;
++	}
++	return pn;
++}
++
++static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
++					  struct sk_buff *skb,
++					  u16 peer_id,
++					  u16 offset,
++					  enum htt_rx_mpdu_encrypt_type enctype)
++{
++	struct ath10k_peer *peer;
++	union htt_rx_pn_t *last_pn, new_pn = {0};
++	struct ieee80211_hdr *hdr;
++	bool more_frags;
++	u8 tid, frag_number;
++	u32 seq;
++
++	peer = ath10k_peer_find_by_id(ar, peer_id);
++	if (!peer) {
++		ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n");
++		return false;
++	}
++
++	hdr = (struct ieee80211_hdr *)(skb->data + offset);
++	if (ieee80211_is_data_qos(hdr->frame_control))
++		tid = ieee80211_get_tid(hdr);
++	else
++		tid = ATH10K_TXRX_NON_QOS_TID;
++
++	last_pn = &peer->frag_tids_last_pn[tid];
++	new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype);
++	more_frags = ieee80211_has_morefrags(hdr->frame_control);
++	frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
++	seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
++
++	if (frag_number == 0) {
++		last_pn->pn48 = new_pn.pn48;
++		peer->frag_tids_seq[tid] = seq;
++	} else {
++		if (seq != peer->frag_tids_seq[tid])
++			return false;
++
++		if (new_pn.pn48 != last_pn->pn48 + 1)
++			return false;
++
++		last_pn->pn48 = new_pn.pn48;
++	}
++
++	return true;
++}
++
+ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
+ 				 struct sk_buff_head *amsdu,
+ 				 struct ieee80211_rx_status *status,
+ 				 bool fill_crypt_header,
+ 				 u8 *rx_hdr,
+-				 enum ath10k_pkt_rx_err *err)
++				 enum ath10k_pkt_rx_err *err,
++				 u16 peer_id,
++				 bool frag)
+ {
+ 	struct sk_buff *first;
+ 	struct sk_buff *last;
+-	struct sk_buff *msdu;
++	struct sk_buff *msdu, *temp;
+ 	struct htt_rx_desc *rxd;
+ 	struct ieee80211_hdr *hdr;
+ 	enum htt_rx_mpdu_encrypt_type enctype;
+@@ -1768,6 +1839,7 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 	bool is_decrypted;
+ 	bool is_mgmt;
+ 	u32 attention;
++	bool frag_pn_check = true;
+ 
+ 	if (skb_queue_empty(amsdu))
+ 		return;
+@@ -1866,6 +1938,24 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 	}
+ 
+ 	skb_queue_walk(amsdu, msdu) {
++		if (frag && !fill_crypt_header && is_decrypted &&
++		    enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
++			frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar,
++								      msdu,
++								      peer_id,
++								      0,
++								      enctype);
++
++		if (!frag_pn_check) {
++			/* Discard the fragment with invalid PN */
++			temp = msdu->prev;
++			__skb_unlink(msdu, amsdu);
++			dev_kfree_skb_any(msdu);
++			msdu = temp;
++			frag_pn_check = true;
++			continue;
++		}
++
+ 		ath10k_htt_rx_h_csum_offload(msdu);
+ 		ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
+ 					is_decrypted);
+@@ -2071,7 +2161,8 @@ static int ath10k_htt_rx_handle_amsdu(st
+ 		ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);
+ 
+ 	ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
+-	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
++	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0,
++			     false);
+ 	msdus_to_queue = skb_queue_len(&amsdu);
+ 	ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);
+ 
+@@ -3027,7 +3118,7 @@ static int ath10k_htt_rx_in_ord_ind(stru
+ 			ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
+ 			ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
+ 			ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
+-					     NULL);
++					     NULL, peer_id, frag);
+ 			ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
+ 			break;
+ 		case -EAGAIN:
diff --git a/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch b/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
new file mode 100644
index 0000000000..7288c66612
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
@@ -0,0 +1,66 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:53 +0200
+Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe
+
+Fragmentation is not used with multicast frames. Discard unexpected
+fragments with multicast DA. This fixes CVE-2020-26145.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1768,6 +1768,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct
+ 	return pn;
+ }
+ 
++static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar,
++						 struct sk_buff *skb,
++						 u16 offset)
++{
++	struct ieee80211_hdr *hdr;
++
++	hdr = (struct ieee80211_hdr *)(skb->data + offset);
++	return !is_multicast_ether_addr(hdr->addr1);
++}
++
+ static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
+ 					  struct sk_buff *skb,
+ 					  u16 peer_id,
+@@ -1839,7 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 	bool is_decrypted;
+ 	bool is_mgmt;
+ 	u32 attention;
+-	bool frag_pn_check = true;
++	bool frag_pn_check = true, multicast_check = true;
+ 
+ 	if (skb_queue_empty(amsdu))
+ 		return;
+@@ -1946,13 +1956,20 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 								      0,
+ 								      enctype);
+ 
+-		if (!frag_pn_check) {
+-			/* Discard the fragment with invalid PN */
++		if (frag)
++			multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar,
++									       msdu,
++									       0);
++
++		if (!frag_pn_check || !multicast_check) {
++			/* Discard the fragment with invalid PN or multicast DA
++			 */
+ 			temp = msdu->prev;
+ 			__skb_unlink(msdu, amsdu);
+ 			dev_kfree_skb_any(msdu);
+ 			msdu = temp;
+ 			frag_pn_check = true;
++			multicast_check = true;
+ 			continue;
+ 		}
+ 
diff --git a/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch b/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
new file mode 100644
index 0000000000..85d9ce65e2
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
@@ -0,0 +1,40 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:54 +0200
+Subject: [PATCH] ath10k: drop fragments with multicast DA for SDIO
+
+Fragmentation is not used with multicast frames. Discard unexpected
+fragments with multicast DA. This fixes CVE-2020-26145.
+
+Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -2617,6 +2617,13 @@ static bool ath10k_htt_rx_proc_rx_frag_i
+ 	rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len);
+ 	rx_desc_info = __le32_to_cpu(rx_desc->info);
+ 
++	hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
++
++	if (is_multicast_ether_addr(hdr->addr1)) {
++		/* Discard the fragment with multicast DA */
++		goto err;
++	}
++
+ 	if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) {
+ 		spin_unlock_bh(&ar->data_lock);
+ 		return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,
+@@ -2624,8 +2631,6 @@ static bool ath10k_htt_rx_proc_rx_frag_i
+ 						    HTT_RX_NON_TKIP_MIC);
+ 	}
+ 
+-	hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
+-
+ 	if (ieee80211_has_retry(hdr->frame_control))
+ 		goto err;
+ 
diff --git a/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch b/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
new file mode 100644
index 0000000000..03bce4231b
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
@@ -0,0 +1,54 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:55 +0200
+Subject: [PATCH] ath10k: drop MPDU which has discard flag set by firmware
+ for SDIO
+
+When the discard flag is set by the firmware for an MPDU, it should be
+dropped. This allows a mitigation for CVE-2020-24588 to be implemented
+in the firmware.
+
+Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -2312,6 +2312,11 @@ static bool ath10k_htt_rx_proc_rx_ind_hl
+ 	fw_desc = &rx->fw_desc;
+ 	rx_desc_len = fw_desc->len;
+ 
++	if (fw_desc->u.bits.discard) {
++		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n");
++		goto err;
++	}
++
+ 	/* I have not yet seen any case where num_mpdu_ranges > 1.
+ 	 * qcacld does not seem handle that case either, so we introduce the
+ 	 * same limitiation here as well.
+--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
+@@ -1282,7 +1282,19 @@ struct fw_rx_desc_base {
+ #define FW_RX_DESC_UDP              (1 << 6)
+ 
+ struct fw_rx_desc_hl {
+-	u8 info0;
++	union {
++		struct {
++		u8 discard:1,
++		   forward:1,
++		   any_err:1,
++		   dup_err:1,
++		   reserved:1,
++		   inspect:1,
++		   extension:2;
++		} bits;
++		u8 info0;
++	} u;
++
+ 	u8 version;
+ 	u8 len;
+ 	u8 flags;
diff --git a/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch b/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
new file mode 100644
index 0000000000..da9d6802bd
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
@@ -0,0 +1,48 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:56 +0200
+Subject: [PATCH] ath10k: Fix TKIP Michael MIC verification for PCIe
+
+TKIP Michael MIC was not verified properly for PCIe cases since the
+validation steps in ieee80211_rx_h_michael_mic_verify() in mac80211 did
+not get fully executed due to unexpected flag values in
+ieee80211_rx_status.
+
+Fix this by setting the flags property to meet mac80211 expectations for
+performing Michael MIC validation there. This fixes CVE-2020-26141. It
+does the same as ath10k_htt_rx_proc_rx_ind_hl() for SDIO which passed
+MIC verification case. This applies only to QCA6174/QCA9377 PCIe.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1974,6 +1974,11 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 		}
+ 
+ 		ath10k_htt_rx_h_csum_offload(msdu);
++
++		if (frag && !fill_crypt_header &&
++		    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
++			status->flag &= ~RX_FLAG_MMIC_STRIPPED;
++
+ 		ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
+ 					is_decrypted);
+ 
+@@ -1991,6 +1996,11 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 
+ 		hdr = (void *)msdu->data;
+ 		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++
++		if (frag && !fill_crypt_header &&
++		    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
++			status->flag &= ~RX_FLAG_IV_STRIPPED &
++					~RX_FLAG_MMIC_STRIPPED;
+ 	}
+ }
+ 
diff --git a/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch b/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch
new file mode 100644
index 0000000000..0bdbed78d5
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch
@@ -0,0 +1,109 @@
+From: Sriram R <srirrama@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:57 +0200
+Subject: [PATCH] ath10k: Validate first subframe of A-MSDU before
+ processing the list
+
+In certain scenarios a normal MSDU can be received as an A-MSDU when
+the A-MSDU present bit of a QoS header gets flipped during reception.
+Since this bit is unauthenticated, the hardware crypto engine can pass
+the frame to the driver without any error indication.
+
+This could result in processing unintended subframes collected in the
+A-MSDU list. Hence, validate A-MSDU list by checking if the first frame
+has a valid subframe header.
+
+Comparing the non-aggregated MSDU and an A-MSDU, the fields of the first
+subframe DA matches the LLC/SNAP header fields of a normal MSDU.
+In order to avoid processing such frames, add a validation to
+filter such A-MSDU frames where the first subframe header DA matches
+with the LLC/SNAP header pattern.
+
+Tested-on: QCA9984 hw1.0 PCI 10.4-3.10-00047
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Sriram R <srirrama@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -2108,14 +2108,62 @@ static void ath10k_htt_rx_h_unchain(stru
+ 	ath10k_unchain_msdu(amsdu, unchain_cnt);
+ }
+ 
++static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
++					 struct sk_buff_head *amsdu)
++{
++	u8 *subframe_hdr;
++	struct sk_buff *first;
++	bool is_first, is_last;
++	struct htt_rx_desc *rxd;
++	struct ieee80211_hdr *hdr;
++	size_t hdr_len, crypto_len;
++	enum htt_rx_mpdu_encrypt_type enctype;
++	int bytes_aligned = ar->hw_params.decap_align_bytes;
++
++	first = skb_peek(amsdu);
++
++	rxd = (void *)first->data - sizeof(*rxd);
++	hdr = (void *)rxd->rx_hdr_status;
++
++	is_first = !!(rxd->msdu_end.common.info0 &
++		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
++	is_last = !!(rxd->msdu_end.common.info0 &
++		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
++
++	/* Return in case of non-aggregated msdu */
++	if (is_first && is_last)
++		return true;
++
++	/* First msdu flag is not set for the first msdu of the list */
++	if (!is_first)
++		return false;
++
++	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
++		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
++
++	hdr_len = ieee80211_hdrlen(hdr->frame_control);
++	crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
++
++	subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) +
++		       crypto_len;
++
++	/* Validate if the amsdu has a proper first subframe.
++	 * There are chances a single msdu can be received as amsdu when
++	 * the unauthenticated amsdu flag of a QoS header
++	 * gets flipped in non-SPP AMSDU's, in such cases the first
++	 * subframe has llc/snap header in place of a valid da.
++	 * return false if the da matches rfc1042 pattern
++	 */
++	if (ether_addr_equal(subframe_hdr, rfc1042_header))
++		return false;
++
++	return true;
++}
++
+ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
+ 					struct sk_buff_head *amsdu,
+ 					struct ieee80211_rx_status *rx_status)
+ {
+-	/* FIXME: It might be a good idea to do some fuzzy-testing to drop
+-	 * invalid/dangerous frames.
+-	 */
+-
+ 	if (!rx_status->freq) {
+ 		ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n");
+ 		return false;
+@@ -2126,6 +2174,11 @@ static bool ath10k_htt_rx_amsdu_allowed(
+ 		return false;
+ 	}
+ 
++	if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) {
++		ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n");
++		return false;
++	}
++
+ 	return true;
+ }
+ 
diff --git a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch
index bf87d3551a..3c9180b113 100644
--- a/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch
+++ b/package/kernel/mac80211/patches/ath/402-ath_regd_optional.patch
@@ -82,7 +82,7 @@
  	help
 --- a/local-symbols
 +++ b/local-symbols
-@@ -85,6 +85,7 @@ ADM8211=
+@@ -86,6 +86,7 @@ ADM8211=
  ATH_COMMON=
  WLAN_VENDOR_ATH=
  ATH_DEBUG=
diff --git a/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch b/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch
index acb9ad443c..cd2bdbf1a0 100644
--- a/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch
+++ b/package/kernel/mac80211/patches/ath/551-ath9k_ubnt_uap_plus_hsr.patch
@@ -371,7 +371,7 @@
  
 --- a/local-symbols
 +++ b/local-symbols
-@@ -112,6 +112,7 @@ ATH9K_WOW=
+@@ -113,6 +113,7 @@ ATH9K_WOW=
  ATH9K_RFKILL=
  ATH9K_CHANNEL_CONTEXT=
  ATH9K_PCOEM=
diff --git a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch b/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch
index abce361673..8f7a60eec8 100644
--- a/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch
+++ b/package/kernel/mac80211/patches/ath/922-ath10k-increase-rx-buffer-size-to-2048.patch
@@ -26,7 +26,7 @@ Forwarded: https://patchwork.kernel.org/patch/11367055/
 
 --- a/drivers/net/wireless/ath/ath10k/htt.h
 +++ b/drivers/net/wireless/ath/ath10k/htt.h
-@@ -2242,7 +2242,7 @@ struct htt_rx_chan_info {
+@@ -2243,7 +2243,7 @@ struct htt_rx_chan_info {
   * Should be: sizeof(struct htt_host_rx_desc) + max rx MSDU size,
   * rounded up to a cache line size.
   */
diff --git a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
index ac46e35b67..5e74687826 100644
--- a/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
+++ b/package/kernel/mac80211/patches/ath/974-ath10k_add-LED-and-GPIO-controlling-support-for-various-chipsets.patch
@@ -114,7 +114,7 @@ v13:
  ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
 --- a/local-symbols
 +++ b/local-symbols
-@@ -145,6 +145,7 @@ ATH10K_DEBUG=
+@@ -146,6 +146,7 @@ ATH10K_DEBUG=
  ATH10K_DEBUGFS=
  ATH10K_SPECTRAL=
  ATH10K_THERMAL=
diff --git a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch
index e74d9a9aa0..1c52132da6 100644
--- a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch
+++ b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch
@@ -1,6 +1,6 @@
 --- a/local-symbols
 +++ b/local-symbols
-@@ -332,6 +332,7 @@ RT2X00_LIB_FIRMWARE=
+@@ -333,6 +333,7 @@ RT2X00_LIB_FIRMWARE=
  RT2X00_LIB_CRYPTO=
  RT2X00_LIB_LEDS=
  RT2X00_LIB_DEBUGFS=
diff --git a/package/kernel/mac80211/patches/subsys/380-mac80211-assure-all-fragments-are-encrypted.patch b/package/kernel/mac80211/patches/subsys/380-mac80211-assure-all-fragments-are-encrypted.patch
new file mode 100644
index 0000000000..69398459f1
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/380-mac80211-assure-all-fragments-are-encrypted.patch
@@ -0,0 +1,69 @@
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:42 +0200
+Subject: [PATCH] mac80211: assure all fragments are encrypted
+
+Do not mix plaintext and encrypted fragments in protected Wi-Fi
+networks. This fixes CVE-2020-26147.
+
+Previously, an attacker was able to first forward a legitimate encrypted
+fragment towards a victim, followed by a plaintext fragment. The
+encrypted and plaintext fragment would then be reassembled. For further
+details see Section 6.3 and Appendix D in the paper "Fragment and Forge:
+Breaking Wi-Fi Through Frame Aggregation and Fragmentation".
+
+Because of this change there are now two equivalent conditions in the
+code to determine if a received fragment requires sequential PNs, so we
+also move this test to a separate function to make the code easier to
+maintain.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2204,6 +2204,16 @@ ieee80211_reassemble_find(struct ieee802
+ 	return NULL;
+ }
+ 
++static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
++{
++	return rx->key &&
++		(rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
++		 rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
++		 rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
++		 rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
++		ieee80211_has_protected(fc);
++}
++
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
+@@ -2248,12 +2258,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 		/* This is the first fragment of a new frame. */
+ 		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+ 						 rx->seqno_idx, &(rx->skb));
+-		if (rx->key &&
+-		    (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+-		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
+-		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+-		     rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
+-		    ieee80211_has_protected(fc)) {
++		if (requires_sequential_pn(rx, fc)) {
+ 			int queue = rx->security_idx;
+ 
+ 			/* Store CCMP/GCMP PN so that we can verify that the
+@@ -2295,11 +2300,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 		u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+ 		int queue;
+ 
+-		if (!rx->key ||
+-		    (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
+-		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+-		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
+-		     rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
++		if (!requires_sequential_pn(rx, fc))
+ 			return RX_DROP_UNUSABLE;
+ 		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+ 		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
diff --git a/package/kernel/mac80211/patches/subsys/381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch b/package/kernel/mac80211/patches/subsys/381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch
new file mode 100644
index 0000000000..de0f89a5b0
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/381-mac80211-prevent-mixed-key-and-fragment-cache-attack.patch
@@ -0,0 +1,87 @@
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:43 +0200
+Subject: [PATCH] mac80211: prevent mixed key and fragment cache attacks
+
+Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment
+cache attacks (CVE-2020-24586). This is accomplished by assigning a
+unique color to every key (per interface) and using this to track which
+key was used to decrypt a fragment. When reassembling frames, it is
+now checked whether all fragments were decrypted using the same key.
+
+To assure that fragment cache attacks are also prevented, the ID that is
+assigned to keys is unique even over (re)associations and (re)connects.
+This means fragments separated by a (re)association or (re)connect will
+not be reassembled. Because mac80211 now also prevents the reassembly of
+mixed encrypted and plaintext fragments, all cache attacks are prevented.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -97,6 +97,7 @@ struct ieee80211_fragment_entry {
+ 	u8 rx_queue;
+ 	bool check_sequential_pn; /* needed for CCMP/GCMP */
+ 	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
++	unsigned int key_color;
+ };
+ 
+ 
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -799,6 +799,7 @@ int ieee80211_key_link(struct ieee80211_
+ 		       struct ieee80211_sub_if_data *sdata,
+ 		       struct sta_info *sta)
+ {
++	static atomic_t key_color = ATOMIC_INIT(0);
+ 	struct ieee80211_key *old_key;
+ 	int idx = key->conf.keyidx;
+ 	bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
+@@ -850,6 +851,12 @@ int ieee80211_key_link(struct ieee80211_
+ 	key->sdata = sdata;
+ 	key->sta = sta;
+ 
++	/*
++	 * Assign a unique ID to every key so we can easily prevent mixed
++	 * key and fragment cache attacks.
++	 */
++	key->color = atomic_inc_return(&key_color);
++
+ 	increment_tailroom_need_count(sdata);
+ 
+ 	ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -128,6 +128,8 @@ struct ieee80211_key {
+ 	} debugfs;
+ #endif
+ 
++	unsigned int color;
++
+ 	/*
+ 	 * key config, must be last because it contains key
+ 	 * material as variable length member
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2265,6 +2265,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 			 * next fragment has a sequential PN value.
+ 			 */
+ 			entry->check_sequential_pn = true;
++			entry->key_color = rx->key->color;
+ 			memcpy(entry->last_pn,
+ 			       rx->key->u.ccmp.rx_pn[queue],
+ 			       IEEE80211_CCMP_PN_LEN);
+@@ -2302,6 +2303,11 @@ ieee80211_rx_h_defragment(struct ieee802
+ 
+ 		if (!requires_sequential_pn(rx, fc))
+ 			return RX_DROP_UNUSABLE;
++
++		/* Prevent mixed key and fragment cache attacks */
++		if (entry->key_color != rx->key->color)
++			return RX_DROP_UNUSABLE;
++
+ 		memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+ 		for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+ 			pn[i]++;
diff --git a/package/kernel/mac80211/patches/subsys/382-mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch b/package/kernel/mac80211/patches/subsys/382-mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch
new file mode 100644
index 0000000000..3fdabde219
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/382-mac80211-properly-handle-A-MSDUs-that-start-with-an-.patch
@@ -0,0 +1,66 @@
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:44 +0200
+Subject: [PATCH] mac80211: properly handle A-MSDUs that start with an
+ RFC 1042 header
+
+Properly parse A-MSDUs whose first 6 bytes happen to equal a rfc1042
+header. This can occur in practice when the destination MAC address
+equals AA:AA:03:00:00:00. More importantly, this simplifies the next
+patch to mitigate A-MSDU injection attacks.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -5628,7 +5628,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s
+  */
+ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ 				  const u8 *addr, enum nl80211_iftype iftype,
+-				  u8 data_offset);
++				  u8 data_offset, bool is_amsdu);
+ 
+ /**
+  * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
+@@ -5640,7 +5640,7 @@ int ieee80211_data_to_8023_exthdr(struct
+ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+ 					 enum nl80211_iftype iftype)
+ {
+-	return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
++	return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0, false);
+ }
+ 
+ /**
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2696,7 +2696,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
+ 	if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
+ 					  rx->sdata->vif.addr,
+ 					  rx->sdata->vif.type,
+-					  data_offset))
++					  data_offset, true))
+ 		return RX_DROP_UNUSABLE;
+ 
+ 	ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -541,7 +541,7 @@ EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen)
+ 
+ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ 				  const u8 *addr, enum nl80211_iftype iftype,
+-				  u8 data_offset)
++				  u8 data_offset, bool is_amsdu)
+ {
+ 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ 	struct {
+@@ -629,7 +629,7 @@ int ieee80211_data_to_8023_exthdr(struct
+ 	skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
+ 	tmp.h_proto = payload.proto;
+ 
+-	if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
++	if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
+ 		    tmp.h_proto != htons(ETH_P_AARP) &&
+ 		    tmp.h_proto != htons(ETH_P_IPX)) ||
+ 		   ether_addr_equal(payload.hdr, bridge_tunnel_header)))
diff --git a/package/kernel/mac80211/patches/subsys/383-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch b/package/kernel/mac80211/patches/subsys/383-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch
new file mode 100644
index 0000000000..8ea78dca84
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/383-cfg80211-mitigate-A-MSDU-aggregation-attacks.patch
@@ -0,0 +1,40 @@
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:45 +0200
+Subject: [PATCH] cfg80211: mitigate A-MSDU aggregation attacks
+
+Mitigate A-MSDU injection attacks (CVE-2020-24588) by detecting if the
+destination address of a subframe equals an RFC1042 (i.e., LLC/SNAP)
+header, and if so dropping the complete A-MSDU frame. This mitigates
+known attacks, although new (unknown) aggregation-based attacks may
+remain possible.
+
+This defense works because in A-MSDU aggregation injection attacks, a
+normal encrypted Wi-Fi frame is turned into an A-MSDU frame. This means
+the first 6 bytes of the first A-MSDU subframe correspond to an RFC1042
+header. In other words, the destination MAC address of the first A-MSDU
+subframe contains the start of an RFC1042 header during an aggregation
+attack. We can detect this and thereby prevent this specific attack.
+For details, see Section 7.2 of "Fragment and Forge: Breaking Wi-Fi
+Through Frame Aggregation and Fragmentation".
+
+Note that for kernel 4.9 and above this patch depends on "mac80211:
+properly handle A-MSDUs that start with a rfc1042 header". Otherwise
+this patch has no impact and attacks will remain possible.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -775,6 +775,9 @@ void ieee80211_amsdu_to_8023s(struct sk_
+ 		remaining = skb->len - offset;
+ 		if (subframe_len > remaining)
+ 			goto purge;
++		/* mitigate A-MSDU aggregation injection attacks */
++		if (ether_addr_equal(eth.h_dest, rfc1042_header))
++			goto purge;
+ 
+ 		offset += sizeof(struct ethhdr);
+ 		last = remaining <= subframe_len + padding;
diff --git a/package/kernel/mac80211/patches/subsys/384-mac80211-drop-A-MSDUs-on-old-ciphers.patch b/package/kernel/mac80211/patches/subsys/384-mac80211-drop-A-MSDUs-on-old-ciphers.patch
new file mode 100644
index 0000000000..1b5084c37d
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/384-mac80211-drop-A-MSDUs-on-old-ciphers.patch
@@ -0,0 +1,54 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:46 +0200
+Subject: [PATCH] mac80211: drop A-MSDUs on old ciphers
+
+With old ciphers (WEP and TKIP) we shouldn't be using A-MSDUs
+since A-MSDUs are only supported if we know that they are, and
+the only practical way for that is HT support which doesn't
+support old ciphers.
+
+However, we would normally accept them anyway. Since we check
+the MMIC before deaggregating A-MSDUs, and the A-MSDU bit in
+the QoS header is not protected in TKIP (or WEP), this enables
+attacks similar to CVE-2020-24588. To prevent that, drop A-MSDUs
+completely with old ciphers.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -6,7 +6,7 @@
+  * Copyright 2007-2010	Johannes Berg <johannes@sipsolutions.net>
+  * Copyright 2013-2014  Intel Mobile Communications GmbH
+  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+  */
+ 
+ #include <linux/jiffies.h>
+@@ -2753,6 +2753,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
+ 	if (is_multicast_ether_addr(hdr->addr1))
+ 		return RX_DROP_UNUSABLE;
+ 
++	if (rx->key) {
++		/*
++		 * We should not receive A-MSDUs on pre-HT connections,
++		 * and HT connections cannot use old ciphers. Thus drop
++		 * them, as in those cases we couldn't even have SPP
++		 * A-MSDUs or such.
++		 */
++		switch (rx->key->conf.cipher) {
++		case WLAN_CIPHER_SUITE_WEP40:
++		case WLAN_CIPHER_SUITE_WEP104:
++		case WLAN_CIPHER_SUITE_TKIP:
++			return RX_DROP_UNUSABLE;
++		default:
++			break;
++		}
++	}
++
+ 	return __ieee80211_rx_h_amsdu(rx, 0);
+ }
+ 
diff --git a/package/kernel/mac80211/patches/subsys/385-mac80211-add-fragment-cache-to-sta_info.patch b/package/kernel/mac80211/patches/subsys/385-mac80211-add-fragment-cache-to-sta_info.patch
new file mode 100644
index 0000000000..b536126d38
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/385-mac80211-add-fragment-cache-to-sta_info.patch
@@ -0,0 +1,313 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:47 +0200
+Subject: [PATCH] mac80211: add fragment cache to sta_info
+
+Prior patches protected against fragmentation cache attacks
+by coloring keys, but this shows that it can lead to issues
+when multiple stations use the same sequence number. Add a
+fragment cache to struct sta_info (in addition to the one in
+the interface) to separate fragments for different stations
+properly.
+
+This then automatically clear most of the fragment cache when a
+station disconnects (or reassociates) from an AP, or when client
+interfaces disconnect from the network, etc.
+
+On the way, also fix the comment there since this brings us in line
+with the recommendation in 802.11-2016 ("An AP should support ...").
+Additionally, remove a useless condition (since there's no problem
+purging an already empty list).
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -50,12 +50,6 @@ struct ieee80211_local;
+ #define IEEE80211_ENCRYPT_HEADROOM 8
+ #define IEEE80211_ENCRYPT_TAILROOM 18
+ 
+-/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
+- * reception of at least three fragmented frames. This limit can be increased
+- * by changing this define, at the cost of slower frame reassembly and
+- * increased memory use (about 2 kB of RAM per entry). */
+-#define IEEE80211_FRAGMENT_MAX 4
+-
+ /* power level hasn't been configured (or set to automatic) */
+ #define IEEE80211_UNSET_POWER_LEVEL	INT_MIN
+ 
+@@ -88,19 +82,6 @@ extern const u8 ieee80211_ac_to_qos_mask
+ 
+ #define IEEE80211_MAX_NAN_INSTANCE_ID 255
+ 
+-struct ieee80211_fragment_entry {
+-	struct sk_buff_head skb_list;
+-	unsigned long first_frag_time;
+-	u16 seq;
+-	u16 extra_len;
+-	u16 last_frag;
+-	u8 rx_queue;
+-	bool check_sequential_pn; /* needed for CCMP/GCMP */
+-	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+-	unsigned int key_color;
+-};
+-
+-
+ struct ieee80211_bss {
+ 	u32 device_ts_beacon, device_ts_presp;
+ 
+@@ -912,9 +893,7 @@ struct ieee80211_sub_if_data {
+ 
+ 	char name[IFNAMSIZ];
+ 
+-	/* Fragment table for host-based reassembly */
+-	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
+-	unsigned int fragment_next;
++	struct ieee80211_fragment_cache frags;
+ 
+ 	/* TID bitmap for NoAck policy */
+ 	u16 noack_map;
+@@ -2329,4 +2308,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
+ #define debug_noinline
+ #endif
+ 
++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache);
++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache);
++
+ #endif /* IEEE80211_I_H */
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -8,7 +8,7 @@
+  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+  * Copyright 2013-2014  Intel Mobile Communications GmbH
+  * Copyright (c) 2016        Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+  */
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+@@ -679,16 +679,12 @@ static void ieee80211_set_multicast_list
+  */
+ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
+ {
+-	int i;
+-
+ 	/* free extra data */
+ 	ieee80211_free_keys(sdata, false);
+ 
+ 	ieee80211_debugfs_remove_netdev(sdata);
+ 
+-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+-		__skb_queue_purge(&sdata->fragments[i].skb_list);
+-	sdata->fragment_next = 0;
++	ieee80211_destroy_frag_cache(&sdata->frags);
+ 
+ 	if (ieee80211_vif_is_mesh(&sdata->vif))
+ 		ieee80211_mesh_teardown_sdata(sdata);
+@@ -2038,8 +2034,7 @@ int ieee80211_if_add(struct ieee80211_lo
+ 	sdata->wdev.wiphy = local->hw.wiphy;
+ 	sdata->local = local;
+ 
+-	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+-		skb_queue_head_init(&sdata->fragments[i].skb_list);
++	ieee80211_init_frag_cache(&sdata->frags);
+ 
+ 	INIT_LIST_HEAD(&sdata->key_list);
+ 
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2133,19 +2133,34 @@ ieee80211_rx_h_decrypt(struct ieee80211_
+ 	return result;
+ }
+ 
++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
++		skb_queue_head_init(&cache->entries[i].skb_list);
++}
++
++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
++		__skb_queue_purge(&cache->entries[i].skb_list);
++}
++
+ static inline struct ieee80211_fragment_entry *
+-ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
++ieee80211_reassemble_add(struct ieee80211_fragment_cache *cache,
+ 			 unsigned int frag, unsigned int seq, int rx_queue,
+ 			 struct sk_buff **skb)
+ {
+ 	struct ieee80211_fragment_entry *entry;
+ 
+-	entry = &sdata->fragments[sdata->fragment_next++];
+-	if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
+-		sdata->fragment_next = 0;
++	entry = &cache->entries[cache->next++];
++	if (cache->next >= IEEE80211_FRAGMENT_MAX)
++		cache->next = 0;
+ 
+-	if (!skb_queue_empty(&entry->skb_list))
+-		__skb_queue_purge(&entry->skb_list);
++	__skb_queue_purge(&entry->skb_list);
+ 
+ 	__skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
+ 	*skb = NULL;
+@@ -2160,14 +2175,14 @@ ieee80211_reassemble_add(struct ieee8021
+ }
+ 
+ static inline struct ieee80211_fragment_entry *
+-ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
++ieee80211_reassemble_find(struct ieee80211_fragment_cache *cache,
+ 			  unsigned int frag, unsigned int seq,
+ 			  int rx_queue, struct ieee80211_hdr *hdr)
+ {
+ 	struct ieee80211_fragment_entry *entry;
+ 	int i, idx;
+ 
+-	idx = sdata->fragment_next;
++	idx = cache->next;
+ 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+ 		struct ieee80211_hdr *f_hdr;
+ 		struct sk_buff *f_skb;
+@@ -2176,7 +2191,7 @@ ieee80211_reassemble_find(struct ieee802
+ 		if (idx < 0)
+ 			idx = IEEE80211_FRAGMENT_MAX - 1;
+ 
+-		entry = &sdata->fragments[idx];
++		entry = &cache->entries[idx];
+ 		if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
+ 		    entry->rx_queue != rx_queue ||
+ 		    entry->last_frag + 1 != frag)
+@@ -2217,6 +2232,7 @@ static bool requires_sequential_pn(struc
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
++	struct ieee80211_fragment_cache *cache = &rx->sdata->frags;
+ 	struct ieee80211_hdr *hdr;
+ 	u16 sc;
+ 	__le16 fc;
+@@ -2238,6 +2254,9 @@ ieee80211_rx_h_defragment(struct ieee802
+ 		goto out_no_led;
+ 	}
+ 
++	if (rx->sta)
++		cache = &rx->sta->frags;
++
+ 	if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
+ 		goto out;
+ 
+@@ -2256,7 +2275,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 
+ 	if (frag == 0) {
+ 		/* This is the first fragment of a new frame. */
+-		entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
++		entry = ieee80211_reassemble_add(cache, frag, seq,
+ 						 rx->seqno_idx, &(rx->skb));
+ 		if (requires_sequential_pn(rx, fc)) {
+ 			int queue = rx->security_idx;
+@@ -2284,7 +2303,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 	/* This is a fragment for a frame that should already be pending in
+ 	 * fragment cache. Add this fragment to the end of the pending entry.
+ 	 */
+-	entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
++	entry = ieee80211_reassemble_find(cache, frag, seq,
+ 					  rx->seqno_idx, hdr);
+ 	if (!entry) {
+ 		I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -4,7 +4,7 @@
+  * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
+  * Copyright 2013-2014  Intel Mobile Communications GmbH
+  * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+  */
+ 
+ #include <linux/module.h>
+@@ -393,6 +393,8 @@ struct sta_info *sta_info_alloc(struct i
+ 
+ 	u64_stats_init(&sta->rx_stats.syncp);
+ 
++	ieee80211_init_frag_cache(&sta->frags);
++
+ 	sta->sta_state = IEEE80211_STA_NONE;
+ 
+ 	/* Mark TID as unreserved */
+@@ -1103,6 +1105,8 @@ static void __sta_info_destroy_part2(str
+ 
+ 	ieee80211_sta_debugfs_remove(sta);
+ 
++	ieee80211_destroy_frag_cache(&sta->frags);
++
+ 	cleanup_single_sta(sta);
+ }
+ 
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -3,7 +3,7 @@
+  * Copyright 2002-2005, Devicescape Software, Inc.
+  * Copyright 2013-2014  Intel Mobile Communications GmbH
+  * Copyright(c) 2015-2017 Intel Deutschland GmbH
+- * Copyright(c) 2020 Intel Corporation
++ * Copyright(c) 2020-2021 Intel Corporation
+  */
+ 
+ #ifndef STA_INFO_H
+@@ -439,6 +439,33 @@ struct ieee80211_sta_rx_stats {
+ };
+ 
+ /*
++ * IEEE 802.11-2016 (10.6 "Defragmentation") recommends support for "concurrent
++ * reception of at least one MSDU per access category per associated STA"
++ * on APs, or "at least one MSDU per access category" on other interface types.
++ *
++ * This limit can be increased by changing this define, at the cost of slower
++ * frame reassembly and increased memory use while fragments are pending.
++ */
++#define IEEE80211_FRAGMENT_MAX 4
++
++struct ieee80211_fragment_entry {
++	struct sk_buff_head skb_list;
++	unsigned long first_frag_time;
++	u16 seq;
++	u16 extra_len;
++	u16 last_frag;
++	u8 rx_queue;
++	bool check_sequential_pn; /* needed for CCMP/GCMP */
++	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
++	unsigned int key_color;
++};
++
++struct ieee80211_fragment_cache {
++	struct ieee80211_fragment_entry	entries[IEEE80211_FRAGMENT_MAX];
++	unsigned int next;
++};
++
++/*
+  * The bandwidth threshold below which the per-station CoDel parameters will be
+  * scaled to be more lenient (to prevent starvation of slow stations). This
+  * value will be scaled by the number of active stations when it is being
+@@ -531,6 +558,7 @@ struct ieee80211_sta_rx_stats {
+  * @status_stats.last_ack_signal: last ACK signal
+  * @status_stats.ack_signal_filled: last ACK signal validity
+  * @status_stats.avg_ack_signal: average ACK signal
++ * @frags: fragment cache
+  */
+ struct sta_info {
+ 	/* General information, mostly static */
+@@ -639,6 +667,8 @@ struct sta_info {
+ 
+ 	struct cfg80211_chan_def tdls_chandef;
+ 
++	struct ieee80211_fragment_cache frags;
++
+ 	/* keep last! */
+ 	struct ieee80211_sta sta;
+ };
diff --git a/package/kernel/mac80211/patches/subsys/386-mac80211-check-defrag-PN-against-current-frame.patch b/package/kernel/mac80211/patches/subsys/386-mac80211-check-defrag-PN-against-current-frame.patch
new file mode 100644
index 0000000000..fb2747a609
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/386-mac80211-check-defrag-PN-against-current-frame.patch
@@ -0,0 +1,109 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:48 +0200
+Subject: [PATCH] mac80211: check defrag PN against current frame
+
+As pointed out by Mathy Vanhoef, we implement the RX PN check
+on fragmented frames incorrectly - we check against the last
+received PN prior to the new frame, rather than to the one in
+this frame itself.
+
+Prior patches addressed the security issue here, but in order
+to be able to reason better about the code, fix it to really
+compare against the current frame's PN, not the last stored
+one.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -227,8 +227,15 @@ struct ieee80211_rx_data {
+ 	 */
+ 	int security_idx;
+ 
+-	u32 tkip_iv32;
+-	u16 tkip_iv16;
++	union {
++		struct {
++			u32 iv32;
++			u16 iv16;
++		} tkip;
++		struct {
++			u8 pn[IEEE80211_CCMP_PN_LEN];
++		} ccm_gcm;
++	};
+ };
+ 
+ struct ieee80211_csa_settings {
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2318,7 +2318,6 @@ ieee80211_rx_h_defragment(struct ieee802
+ 	if (entry->check_sequential_pn) {
+ 		int i;
+ 		u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+-		int queue;
+ 
+ 		if (!requires_sequential_pn(rx, fc))
+ 			return RX_DROP_UNUSABLE;
+@@ -2333,8 +2332,8 @@ ieee80211_rx_h_defragment(struct ieee802
+ 			if (pn[i])
+ 				break;
+ 		}
+-		queue = rx->security_idx;
+-		rpn = rx->key->u.ccmp.rx_pn[queue];
++
++		rpn = rx->ccm_gcm.pn;
+ 		if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
+ 			return RX_DROP_UNUSABLE;
+ 		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -3,6 +3,7 @@
+  * Copyright 2002-2004, Instant802 Networks, Inc.
+  * Copyright 2008, Jouni Malinen <j@w1.fi>
+  * Copyright (C) 2016-2017 Intel Deutschland GmbH
++ * Copyright (C) 2020-2021 Intel Corporation
+  */
+ 
+ #include <linux/netdevice.h>
+@@ -167,8 +168,8 @@ ieee80211_rx_h_michael_mic_verify(struct
+ 
+ update_iv:
+ 	/* update IV in key information to be able to detect replays */
+-	rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
+-	rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
++	rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip.iv32;
++	rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip.iv16;
+ 
+ 	return RX_CONTINUE;
+ 
+@@ -294,8 +295,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
+ 					  key, skb->data + hdrlen,
+ 					  skb->len - hdrlen, rx->sta->sta.addr,
+ 					  hdr->addr1, hwaccel, rx->security_idx,
+-					  &rx->tkip_iv32,
+-					  &rx->tkip_iv16);
++					  &rx->tkip.iv32,
++					  &rx->tkip.iv16);
+ 	if (res != TKIP_DECRYPT_OK)
+ 		return RX_DROP_UNUSABLE;
+ 
+@@ -552,6 +553,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+ 		}
+ 
+ 		memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
++		if (unlikely(ieee80211_is_frag(hdr)))
++			memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
+ 	}
+ 
+ 	/* Remove CCMP header and MIC */
+@@ -782,6 +785,8 @@ ieee80211_crypto_gcmp_decrypt(struct iee
+ 		}
+ 
+ 		memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
++		if (unlikely(ieee80211_is_frag(hdr)))
++			memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
+ 	}
+ 
+ 	/* Remove GCMP header and MIC */
diff --git a/package/kernel/mac80211/patches/subsys/387-mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch b/package/kernel/mac80211/patches/subsys/387-mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch
new file mode 100644
index 0000000000..bc582a6cc2
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/387-mac80211-prevent-attacks-on-TKIP-WEP-as-well.patch
@@ -0,0 +1,62 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:49 +0200
+Subject: [PATCH] mac80211: prevent attacks on TKIP/WEP as well
+
+Similar to the issues fixed in previous patches, TKIP and WEP
+should be protected even if for TKIP we have the Michael MIC
+protecting it, and WEP is broken anyway.
+
+However, this also somewhat protects potential other algorithms
+that drivers might implement.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2284,6 +2284,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 			 * next fragment has a sequential PN value.
+ 			 */
+ 			entry->check_sequential_pn = true;
++			entry->is_protected = true;
+ 			entry->key_color = rx->key->color;
+ 			memcpy(entry->last_pn,
+ 			       rx->key->u.ccmp.rx_pn[queue],
+@@ -2296,6 +2297,9 @@ ieee80211_rx_h_defragment(struct ieee802
+ 				     sizeof(rx->key->u.gcmp.rx_pn[queue]));
+ 			BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+ 				     IEEE80211_GCMP_PN_LEN);
++		} else if (rx->key && ieee80211_has_protected(fc)) {
++			entry->is_protected = true;
++			entry->key_color = rx->key->color;
+ 		}
+ 		return RX_QUEUED;
+ 	}
+@@ -2337,6 +2341,14 @@ ieee80211_rx_h_defragment(struct ieee802
+ 		if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
+ 			return RX_DROP_UNUSABLE;
+ 		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
++	} else if (entry->is_protected &&
++		   (!rx->key || !ieee80211_has_protected(fc) ||
++		    rx->key->color != entry->key_color)) {
++		/* Drop this as a mixed key or fragment cache attack, even
++		 * if for TKIP Michael MIC should protect us, and WEP is a
++		 * lost cause anyway.
++		 */
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+ 	skb_pull(rx->skb, ieee80211_hdrlen(fc));
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -455,7 +455,8 @@ struct ieee80211_fragment_entry {
+ 	u16 extra_len;
+ 	u16 last_frag;
+ 	u8 rx_queue;
+-	bool check_sequential_pn; /* needed for CCMP/GCMP */
++	u8 check_sequential_pn:1, /* needed for CCMP/GCMP */
++	   is_protected:1;
+ 	u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+ 	unsigned int key_color;
+ };
diff --git a/package/kernel/mac80211/patches/subsys/388-mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch b/package/kernel/mac80211/patches/subsys/388-mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch
new file mode 100644
index 0000000000..9a0b78def1
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/388-mac80211-do-not-accept-forward-invalid-EAPOL-frames.patch
@@ -0,0 +1,94 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:50 +0200
+Subject: [PATCH] mac80211: do not accept/forward invalid EAPOL frames
+
+EAPOL frames are used for authentication and key management between the
+AP and each individual STA associated in the BSS. Those frames are not
+supposed to be sent by one associated STA to another associated STA
+(either unicast for broadcast/multicast).
+
+Similarly, in 802.11 they're supposed to be sent to the authenticator
+(AP) address.
+
+Since it is possible for unexpected EAPOL frames to result in misbehavior
+in supplicant implementations, it is better for the AP to not allow such
+cases to be forwarded to other clients either directly, or indirectly if
+the AP interface is part of a bridge.
+
+Accept EAPOL (control port) frames only if they're transmitted to the
+own address, or, due to interoperability concerns, to the PAE group
+address.
+
+Disable forwarding of EAPOL (or well, the configured control port
+protocol) frames back to wireless medium in all cases. Previously, these
+frames were accepted from fully authenticated and authorized stations
+and also from unauthenticated stations for one of the cases.
+
+Additionally, to avoid forwarding by the bridge, rewrite the PAE group
+address case to the local MAC address.
+
+Cc: stable@vger.kernel.org
+Co-developed-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2541,13 +2541,13 @@ static bool ieee80211_frame_allowed(stru
+ 	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
+ 
+ 	/*
+-	 * Allow EAPOL frames to us/the PAE group address regardless
+-	 * of whether the frame was encrypted or not.
++	 * Allow EAPOL frames to us/the PAE group address regardless of
++	 * whether the frame was encrypted or not, and always disallow
++	 * all other destination addresses for them.
+ 	 */
+-	if (ehdr->h_proto == rx->sdata->control_port_protocol &&
+-	    (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
+-	     ether_addr_equal(ehdr->h_dest, pae_group_addr)))
+-		return true;
++	if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol))
++		return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
++		       ether_addr_equal(ehdr->h_dest, pae_group_addr);
+ 
+ 	if (ieee80211_802_1x_port_control(rx) ||
+ 	    ieee80211_drop_unencrypted(rx, fc))
+@@ -2572,8 +2572,28 @@ static void ieee80211_deliver_skb_to_loc
+ 		cfg80211_rx_control_port(dev, skb, noencrypt);
+ 		dev_kfree_skb(skb);
+ 	} else {
++		struct ethhdr *ehdr = (void *)skb_mac_header(skb);
++
+ 		memset(skb->cb, 0, sizeof(skb->cb));
+ 
++		/*
++		 * 802.1X over 802.11 requires that the authenticator address
++		 * be used for EAPOL frames. However, 802.1X allows the use of
++		 * the PAE group address instead. If the interface is part of
++		 * a bridge and we pass the frame with the PAE group address,
++		 * then the bridge will forward it to the network (even if the
++		 * client was not associated yet), which isn't supposed to
++		 * happen.
++		 * To avoid that, rewrite the destination address to our own
++		 * address, so that the authenticator (e.g. hostapd) will see
++		 * the frame, but bridge won't forward it anywhere else. Note
++		 * that due to earlier filtering, the only other address can
++		 * be the PAE group address.
++		 */
++		if (unlikely(skb->protocol == sdata->control_port_protocol &&
++			     !ether_addr_equal(ehdr->h_dest, sdata->vif.addr)))
++			ether_addr_copy(ehdr->h_dest, sdata->vif.addr);
++
+ 		/* deliver to local stack */
+ 		if (rx->list)
+ #if LINUX_VERSION_IS_GEQ(4,19,0)
+@@ -2617,6 +2637,7 @@ ieee80211_deliver_skb(struct ieee80211_r
+ 	if ((sdata->vif.type == NL80211_IFTYPE_AP ||
+ 	     sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+ 	    !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
++	    ehdr->h_proto != rx->sdata->control_port_protocol &&
+ 	    (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
+ 		if (is_multicast_ether_addr(ehdr->h_dest) &&
+ 		    ieee80211_vif_get_num_mcast_if(sdata) != 0) {
diff --git a/package/kernel/mac80211/patches/subsys/389-mac80211-extend-protection-against-mixed-key-and-fra.patch b/package/kernel/mac80211/patches/subsys/389-mac80211-extend-protection-against-mixed-key-and-fra.patch
new file mode 100644
index 0000000000..17809263e9
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/389-mac80211-extend-protection-against-mixed-key-and-fra.patch
@@ -0,0 +1,68 @@
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:51 +0200
+Subject: [PATCH] mac80211: extend protection against mixed key and
+ fragment cache attacks
+
+For some chips/drivers, e.g., QCA6174 with ath10k, the decryption is
+done by the hardware, and the Protected bit in the Frame Control field
+is cleared in the lower level driver before the frame is passed to
+mac80211. In such cases, the condition for ieee80211_has_protected() is
+not met in ieee80211_rx_h_defragment() of mac80211 and the new security
+validation steps are not executed.
+
+Extend mac80211 to cover the case where the Protected bit has been
+cleared, but the frame is indicated as having been decrypted by the
+hardware. This extends protection against mixed key and fragment cache
+attack for additional drivers/chips. This fixes CVE-2020-24586 and
+CVE-2020-24587 for such cases.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2239,6 +2239,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ 	unsigned int frag, seq;
+ 	struct ieee80211_fragment_entry *entry;
+ 	struct sk_buff *skb;
++	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+ 
+ 	hdr = (struct ieee80211_hdr *)rx->skb->data;
+ 	fc = hdr->frame_control;
+@@ -2297,7 +2298,9 @@ ieee80211_rx_h_defragment(struct ieee802
+ 				     sizeof(rx->key->u.gcmp.rx_pn[queue]));
+ 			BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+ 				     IEEE80211_GCMP_PN_LEN);
+-		} else if (rx->key && ieee80211_has_protected(fc)) {
++		} else if (rx->key &&
++			   (ieee80211_has_protected(fc) ||
++			    (status->flag & RX_FLAG_DECRYPTED))) {
+ 			entry->is_protected = true;
+ 			entry->key_color = rx->key->color;
+ 		}
+@@ -2342,13 +2345,19 @@ ieee80211_rx_h_defragment(struct ieee802
+ 			return RX_DROP_UNUSABLE;
+ 		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
+ 	} else if (entry->is_protected &&
+-		   (!rx->key || !ieee80211_has_protected(fc) ||
++		   (!rx->key ||
++		    (!ieee80211_has_protected(fc) &&
++		     !(status->flag & RX_FLAG_DECRYPTED)) ||
+ 		    rx->key->color != entry->key_color)) {
+ 		/* Drop this as a mixed key or fragment cache attack, even
+ 		 * if for TKIP Michael MIC should protect us, and WEP is a
+ 		 * lost cause anyway.
+ 		 */
+ 		return RX_DROP_UNUSABLE;
++	} else if (entry->is_protected && rx->key &&
++		   entry->key_color != rx->key->color &&
++		   (status->flag & RX_FLAG_DECRYPTED)) {
++		return RX_DROP_UNUSABLE;
+ 	}
+ 
+ 	skb_pull(rx->skb, ieee80211_hdrlen(fc));
diff --git a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
index 5d5dcd51ad..eb967f77d7 100644
--- a/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/package/kernel/mac80211/patches/subsys/500-mac80211_configure_antenna_gain.patch
@@ -87,7 +87,7 @@
  	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -1403,6 +1403,7 @@ struct ieee80211_local {
+@@ -1390,6 +1390,7 @@ struct ieee80211_local {
  	int dynamic_ps_forced_timeout;
  
  	int user_power_level; /* in dBm, for all interfaces */
diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile
index 2986aff431..9f36a83aca 100644
--- a/package/kernel/mt76/Makefile
+++ b/package/kernel/mt76/Makefile
@@ -8,9 +8,9 @@ PKG_LICENSE_FILES:=
 
 PKG_SOURCE_URL:=https://github.com/openwrt/mt76
 PKG_SOURCE_PROTO:=git
-PKG_SOURCE_DATE:=2021-05-10
-PKG_SOURCE_VERSION:=ff8bbe22dd87d86b69be7d5619d88fd187ce3017
-PKG_MIRROR_HASH:=aaaac3f9ec2c7836254f594696179369dd7e42c2ded8fb4ad62fbf5359f8c875
+PKG_SOURCE_DATE:=2021-05-13
+PKG_SOURCE_VERSION:=e969ab10a03403e6c869e91d4d41a71c6340657b
+PKG_MIRROR_HASH:=eb57d82267d5765c270fc394ad81baacd8d02cde859f813236ad76a89c5ea944
 
 PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
 PKG_BUILD_PARALLEL:=1
diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile
index 989fd29349..e3d1c3c601 100644
--- a/package/libs/openssl/Makefile
+++ b/package/libs/openssl/Makefile
@@ -324,7 +324,7 @@ endif
 
 OPENSSL_TARGET:=linux-$(call qstrip,$(CONFIG_ARCH))-openwrt
 
-STAMP_CONFIGURED := $(STAMP_CONFIGURED)_$(shell echo $(OPENSSL_OPTIONS) | mkhash md5)
+STAMP_CONFIGURED := $(STAMP_CONFIGURED)_$(shell echo $(OPENSSL_OPTIONS) | $(MKHASH) md5)
 
 define Build/Configure
 	(cd $(PKG_BUILD_DIR); \
diff --git a/package/network/services/dropbear/Makefile b/package/network/services/dropbear/Makefile
index 8bbb26f829..77887f39db 100644
--- a/package/network/services/dropbear/Makefile
+++ b/package/network/services/dropbear/Makefile
@@ -37,7 +37,7 @@ PKG_CONFIG_DEPENDS:= \
 include $(INCLUDE_DIR)/package.mk
 
 ifneq ($(DUMP),1)
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | mkhash md5)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | $(MKHASH) md5)
 endif
 
 define Package/dropbear/Default
diff --git a/package/network/utils/iptables/Makefile b/package/network/utils/iptables/Makefile
index 207e221d75..fcd5f1a208 100644
--- a/package/network/utils/iptables/Makefile
+++ b/package/network/utils/iptables/Makefile
@@ -28,7 +28,7 @@ include $(INCLUDE_DIR)/package.mk
 ifeq ($(DUMP),)
   -include $(LINUX_DIR)/.config
   include $(INCLUDE_DIR)/netfilter.mk
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep 'NETFILTER' $(LINUX_DIR)/.config | mkhash md5)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep 'NETFILTER' $(LINUX_DIR)/.config | $(MKHASH) md5)
 endif
 
 
diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile
index 4c34bab6f1..2b0ea6d119 100644
--- a/package/system/procd/Makefile
+++ b/package/system/procd/Makefile
@@ -32,7 +32,7 @@ include $(INCLUDE_DIR)/package.mk
 include $(INCLUDE_DIR)/cmake.mk
 
 ifeq ($(DUMP),)
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | mkhash md5)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell echo $(CONFIG_TARGET_INIT_PATH) | $(MKHASH) md5)
 endif
 
 CMAKE_OPTIONS += -DEARLY_PATH="$(TARGET_INIT_PATH)"
diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile
index 58bc1e6795..76a910361e 100644
--- a/package/utils/busybox/Makefile
+++ b/package/utils/busybox/Makefile
@@ -8,14 +8,14 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=busybox
-PKG_VERSION:=1.33.0
-PKG_RELEASE:=3
+PKG_VERSION:=1.33.1
+PKG_RELEASE:=1
 PKG_FLAGS:=essential
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=https://www.busybox.net/downloads \
 		http://sources.buildroot.net
-PKG_HASH:=d568681c91a85edc6710770cebc1e80e042ad74d305b5c2e6d57a5f3de3b8fbd
+PKG_HASH:=12cec6bd2b16d8a9446dd16130f2b92982f1819f6e1c5f5887b6db03f5660d28
 
 PKG_BUILD_DEPENDS:=BUSYBOX_CONFIG_PAM:libpam
 PKG_BUILD_PARALLEL:=1
@@ -38,7 +38,7 @@ endif
 include $(INCLUDE_DIR)/package.mk
 
 ifeq ($(DUMP),)
-  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | mkhash md5)
+  STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell grep '^CONFIG_BUSYBOX_' $(TOPDIR)/.config | $(MKHASH) md5)
 endif
 
 # All files provided by busybox will serve as fallback alternatives by opkg.
diff --git a/package/utils/busybox/patches/001-backport1330fix-ash-make-strdup-copy.patch b/package/utils/busybox/patches/001-backport1330fix-ash-make-strdup-copy.patch
deleted file mode 100644
index b495227d9f..0000000000
--- a/package/utils/busybox/patches/001-backport1330fix-ash-make-strdup-copy.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 67cc582d4289c5de521d11b08307c8ab26ee1e28 Mon Sep 17 00:00:00 2001
-From: Denys Vlasenko <vda.linux@googlemail.com>
-Date: Sun, 3 Jan 2021 10:55:39 +0100
-Subject: ash: make a strdup copy of $HISTFILE for line editing
-
-Otherwise if $HISTFILE is unset or reassigned, bad things can happen.
-
-function                                             old     new   delta
-ash_main                                            1210    1218      +8
-
-Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
----
- shell/ash.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/shell/ash.c b/shell/ash.c
-index f16d7fb6a..ecbfbf091 100644
---- a/shell/ash.c
-+++ b/shell/ash.c
-@@ -14499,7 +14499,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
- 
- 	if (sflag || minusc == NULL) {
- #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
--		if (iflag) {
-+		if (line_input_state) {
- 			const char *hp = lookupvar("HISTFILE");
- 			if (!hp) {
- 				hp = lookupvar("HOME");
-@@ -14513,7 +14513,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
- 				}
- 			}
- 			if (hp)
--				line_input_state->hist_file = hp;
-+				line_input_state->hist_file = xstrdup(hp);
- # if ENABLE_FEATURE_SH_HISTFILESIZE
- 			hp = lookupvar("HISTFILESIZE");
- 			line_input_state->max_history = size_from_HISTFILESIZE(hp);
--- 
-cgit v1.2.1
-
diff --git a/package/utils/busybox/patches/002-backport1330fix-traceroute.patch b/package/utils/busybox/patches/002-backport1330fix-traceroute.patch
deleted file mode 100644
index eb03094eee..0000000000
--- a/package/utils/busybox/patches/002-backport1330fix-traceroute.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 89358a7131d3e75c74af834bb117b4fad7914983 Mon Sep 17 00:00:00 2001
-From: Denys Vlasenko <vda.linux@googlemail.com>
-Date: Tue, 2 Feb 2021 13:48:21 +0100
-Subject: traceroute: fix option parsing
-
-Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
----
- networking/traceroute.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/networking/traceroute.c b/networking/traceroute.c
-index 3f1a9ab46..29f5e480b 100644
---- a/networking/traceroute.c
-+++ b/networking/traceroute.c
-@@ -896,7 +896,7 @@ traceroute_init(int op, char **argv)
- 
- 	op |= getopt32(argv, "^"
- 		OPT_STRING
--		"\0" "-1:x-x" /* minimum 1 arg */
-+		"\0" "-1" /* minimum 1 arg */
- 		, &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
- 		, &source, &waittime_str, &pausemsecs_str, &first_ttl_str
- 	);
--- 
-cgit v1.2.1
-
diff --git a/package/utils/busybox/patches/005-backport-CVE-2021-28831.patch b/package/utils/busybox/patches/005-backport-CVE-2021-28831.patch
deleted file mode 100644
index 7637679a69..0000000000
--- a/package/utils/busybox/patches/005-backport-CVE-2021-28831.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From f25d254dfd4243698c31a4f3153d4ac72aa9e9bd Mon Sep 17 00:00:00 2001
-From: Samuel Sapalski <samuel.sapalski@nokia.com>
-Date: Wed, 3 Mar 2021 16:31:22 +0100
-Subject: decompress_gunzip: Fix DoS if gzip is corrupt
-
-On certain corrupt gzip files, huft_build will set the error bit on
-the result pointer. If afterwards abort_unzip is called huft_free
-might run into a segmentation fault or an invalid pointer to
-free(p).
-
-In order to mitigate this, we check in huft_free if the error bit
-is set and clear it before the linked list is freed.
-
-Signed-off-by: Samuel Sapalski <samuel.sapalski@nokia.com>
-Signed-off-by: Peter Kaestle <peter.kaestle@nokia.com>
-Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
----
- archival/libarchive/decompress_gunzip.c | 12 ++++++++++--
- 1 file changed, 10 insertions(+), 2 deletions(-)
-
---- a/archival/libarchive/decompress_gunzip.c
-+++ b/archival/libarchive/decompress_gunzip.c
-@@ -220,10 +220,20 @@ static const uint8_t border[] ALIGN1 = {
-  * each table.
-  * t: table to free
-  */
-+#define BAD_HUFT(p) ((uintptr_t)(p) & 1)
-+#define ERR_RET     ((huft_t*)(uintptr_t)1)
- static void huft_free(huft_t *p)
- {
- 	huft_t *q;
- 
-+	/*
-+	 * If 'p' has the error bit set we have to clear it, otherwise we might run
-+	 * into a segmentation fault or an invalid pointer to free(p)
-+	 */
-+	if (BAD_HUFT(p)) {
-+		p = (huft_t*)((uintptr_t)(p) ^ (uintptr_t)(ERR_RET));
-+	}
-+
- 	/* Go through linked list, freeing from the malloced (t[-1]) address. */
- 	while (p) {
- 		q = (--p)->v.t;
-@@ -289,8 +299,6 @@ static unsigned fill_bitbuffer(STATE_PAR
-  * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table
-  * is given: "fixed inflate" decoder feeds us such data.
-  */
--#define BAD_HUFT(p) ((uintptr_t)(p) & 1)
--#define ERR_RET     ((huft_t*)(uintptr_t)1)
- static huft_t* huft_build(const unsigned *b, const unsigned n,
- 			const unsigned s, const struct cp_ext *cp_ext,
- 			unsigned *m)
diff --git a/package/utils/busybox/patches/010-fix-wrong-variable.patch b/package/utils/busybox/patches/010-fix-wrong-variable.patch
deleted file mode 100644
index 1b6fa7be61..0000000000
--- a/package/utils/busybox/patches/010-fix-wrong-variable.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/libbb/update_passwd.c
-+++ b/libbb/update_passwd.c
-@@ -48,7 +48,7 @@ static void check_selinux_update_passwd(
- 			bb_simple_error_msg_and_die("SELinux: access denied");
- 	}
- 	if (ENABLE_FEATURE_CLEAN_UP)
--		freecon(context);
-+		freecon(seuser);
- }
- #else
- # define check_selinux_update_passwd(username) ((void)0)
diff --git a/package/utils/busybox/patches/230-add_nslookup_lede.patch b/package/utils/busybox/patches/230-add_nslookup_lede.patch
index 446b01c3f1..280d4e238e 100644
--- a/package/utils/busybox/patches/230-add_nslookup_lede.patch
+++ b/package/utils/busybox/patches/230-add_nslookup_lede.patch
@@ -34,7 +34,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
  # However, on *other platforms* it fails when some of those flags
 --- /dev/null
 +++ b/networking/nslookup_lede.c
-@@ -0,0 +1,914 @@
+@@ -0,0 +1,934 @@
 +/*
 + * nslookup_lede - musl compatible replacement for busybox nslookup
 + *
@@ -128,6 +128,7 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
 +	{ ns_t_cname, "CNAME" },
 +	{ ns_t_mx,    "MX"    },
 +	{ ns_t_txt,   "TXT"   },
++	{ ns_t_srv,   "SRV"   },
 +	{ ns_t_ptr,   "PTR"   },
 +	{ ns_t_any,   "ANY"   },
 +	{ }
@@ -259,6 +260,25 @@ Signed-off-by: Jo-Philipp Wich <jo@mein.io>
 +			}
 +			break;
 +
++		case ns_t_srv:
++			if (rdlen < 6) {
++				//printf("SRV record too short\n");
++				return -1;
++			}
++
++			cp = ns_rr_rdata(rr);
++			n = ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle),
++			                       cp + 6, dname, sizeof(dname));
++
++			if (n < 0) {
++				//printf("Unable to uncompress domain: %s\n", strerror(errno));
++				return -1;
++			}
++
++			printf("%s\tservice = %hu %hu %hu %s\n", ns_rr_name(rr),
++				ns_get16(cp), ns_get16(cp + 2), ns_get16(cp + 4), dname);
++			break;
++
 +		case ns_t_soa:
 +			if (rdlen < 20) {
 +				//fprintf(stderr, "SOA record too short\n");
diff --git a/rules.mk b/rules.mk
index f31d9bb113..51f822e3f1 100644
--- a/rules.mk
+++ b/rules.mk
@@ -27,7 +27,7 @@ empty:=
 space:= $(empty) $(empty)
 comma:=,
 merge=$(subst $(space),,$(1))
-confvar=$(shell echo '$(foreach v,$(1),$(v)=$(subst ','\'',$($(v))))' | $(STAGING_DIR_HOST)/bin/mkhash md5)
+confvar=$(shell echo '$(foreach v,$(1),$(v)=$(subst ','\'',$($(v))))' | $(MKHASH) md5)
 strip_last=$(patsubst %.$(lastword $(subst .,$(space),$(1))),%,$(1))
 
 paren_left = (
@@ -266,6 +266,9 @@ TARGET_CXX:=$(TARGET_CROSS)g++
 KPATCH:=$(SCRIPT_DIR)/patch-kernel.sh
 SED:=$(STAGING_DIR_HOST)/bin/sed -i -e
 ESED:=$(STAGING_DIR_HOST)/bin/sed -E -i -e
+MKHASH:=$(STAGING_DIR_HOST)/bin/mkhash
+# MKHASH is used in /scripts, so we export it here.
+export MKHASH
 CP:=cp -fpR
 LN:=ln -sf
 XARGS:=xargs -r
@@ -399,7 +402,7 @@ endef
 # $(2) => If set, recurse into subdirectories
 define sha256sums
 	(cd $(1); find . $(if $(2),,-maxdepth 1) -type f -not -name 'sha256sums' -printf "%P\n" | sort | \
-		xargs -r $(STAGING_DIR_HOST)/bin/mkhash -n sha256 | sed -ne 's!^\(.*\) \(.*\)$$!\1 *\2!p' > sha256sums)
+		xargs -r $(MKHASH) -n sha256 | sed -ne 's!^\(.*\) \(.*\)$$!\1 *\2!p' > sha256sums)
 endef
 
 # file extension
diff --git a/scripts/combined-ext-image.sh b/scripts/combined-ext-image.sh
index 7ff287bde7..c20203f23b 100755
--- a/scripts/combined-ext-image.sh
+++ b/scripts/combined-ext-image.sh
@@ -63,7 +63,7 @@ while [ "$#" -gt 1 ]
 
       [ ! -f "$file" ] && echo "$ME: Not a valid file: $file" && usage
       FILES="$FILES $file"
-      md5=$(mkhash md5 "$file")
+      md5=$($MKHASH md5 "$file")
       printf "%-32s%08x%32s" "$filename" $(stat -c "%s" "$file") "${md5%% *}" >> "${IMG_TMP_OUT}"
       shift 2
    done
diff --git a/scripts/combined-image.sh b/scripts/combined-image.sh
index 4e00cb89a2..a365fbc536 100755
--- a/scripts/combined-image.sh
+++ b/scripts/combined-image.sh
@@ -16,7 +16,7 @@ dd if="$1" of="$kern" bs=$BLKSZ conv=sync 2>/dev/null
 dd if="$2" of="$root" bs=$BLKSZ conv=sync 2>/dev/null
 
 # Calculate md5sum over combined kernel and rootfs image.
-md5=$(cat "$kern" "$root" | mkhash md5)
+md5=$(cat "$kern" "$root" | $MKHASH md5)
 
 # Write image header followed by kernel and rootfs image.
 # The header is padded to 64k, format is:
diff --git a/scripts/download.pl b/scripts/download.pl
index 5db19ff468..4e77581268 100755
--- a/scripts/download.pl
+++ b/scripts/download.pl
@@ -65,8 +65,8 @@ sub hash_cmd() {
 	my $len = length($file_hash);
 	my $cmd;
 
-	$len == 64 and return "mkhash sha256";
-	$len == 32 and return "mkhash md5";
+	$len == 64 and return "$ENV{'MKHASH'} sha256";
+	$len == 32 and return "$ENV{'MKHASH'} md5";
 	return undef;
 }
 
@@ -316,4 +316,3 @@ while (!-f "$target/$filename") {
 }
 
 $SIG{INT} = \&cleanup;
-
diff --git a/scripts/ipkg-make-index.sh b/scripts/ipkg-make-index.sh
index f6f15d7dd8..8965d0aa18 100755
--- a/scripts/ipkg-make-index.sh
+++ b/scripts/ipkg-make-index.sh
@@ -18,7 +18,7 @@ for pkg in `find $pkg_dir -name '*.ipk' | sort`; do
 	[[ "$name" = "libc" ]] && continue
 	echo "Generating index for package $pkg" >&2
 	file_size=$(stat -L -c%s $pkg)
-	sha256sum=$(mkhash sha256 $pkg)
+	sha256sum=$($MKHASH sha256 $pkg)
 	# Take pains to make variable value sed-safe
 	sed_safe_pkg=`echo $pkg | sed -e 's/^\.\///g' -e 's/\\//\\\\\\//g'`
 	tar -xzOf $pkg ./control.tar.gz | tar xzOf - ./control | sed -e "s/^Description:/Filename: $sed_safe_pkg\\
diff --git a/scripts/om-fwupgradecfg-gen.sh b/scripts/om-fwupgradecfg-gen.sh
index bf7c047c5b..c3858416a6 100755
--- a/scripts/om-fwupgradecfg-gen.sh
+++ b/scripts/om-fwupgradecfg-gen.sh
@@ -54,8 +54,8 @@ esac
 CHECK_BS=65536
 
 KERNEL_SIZE=$(stat -c%s "$KERNEL_PATH")
-KERNEL_MD5=$(mkhash md5 $KERNEL_PATH)
-KERNEL_SHA256=$(mkhash sha256 $KERNEL_PATH)
+KERNEL_MD5=$($MKHASH md5 $KERNEL_PATH)
+KERNEL_SHA256=$($MKHASH sha256 $KERNEL_PATH)
 KERNEL_PART_SIZE_KB=$((KERNEL_SIZE / 1024))
 KERNEL_PART_SIZE=$(printf $SIZE_FORMAT $(($KERNEL_PART_SIZE_KB * $SIZE_FACTOR)))
 
@@ -63,9 +63,9 @@ ROOTFS_FLASH_ADDR=$(addr=$(($KERNEL_FLASH_ADDR + ($KERNEL_PART_SIZE_KB * 1024)))
 ROOTFS_SIZE=$(stat -c%s "$ROOTFS_PATH")
 ROOTFS_SQUASHFS_SIZE=$((ROOTFS_SIZE-4))
 ROOTFS_CHECK_BLOCKS=$((ROOTFS_SQUASHFS_SIZE / CHECK_BS))
-ROOTFS_MD5=$(dd if=$ROOTFS_PATH bs=$CHECK_BS count=$ROOTFS_CHECK_BLOCKS 2>&- | mkhash md5)
-ROOTFS_MD5_FULL=$(mkhash md5 $ROOTFS_PATH)
-ROOTFS_SHA256_FULL=$(mkhash sha256 $ROOTFS_PATH)
+ROOTFS_MD5=$(dd if=$ROOTFS_PATH bs=$CHECK_BS count=$ROOTFS_CHECK_BLOCKS 2>&- | $MKHASH md5)
+ROOTFS_MD5_FULL=$($MKHASH md5 $ROOTFS_PATH)
+ROOTFS_SHA256_FULL=$($MKHASH sha256 $ROOTFS_PATH)
 ROOTFS_CHECK_SIZE=$(printf '0x%x' $ROOTFS_SQUASHFS_SIZE)
 ROOTFS_PART_SIZE_KB=$(($MAX_PART_SIZE - $KERNEL_PART_SIZE_KB))
 ROOTFS_PART_SIZE=$(printf $SIZE_FORMAT $(($ROOTFS_PART_SIZE_KB * $SIZE_FACTOR)))
diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk
index 3382b98e6f..525799e08b 100644
--- a/target/linux/ath79/image/generic.mk
+++ b/target/linux/ath79/image/generic.mk
@@ -35,7 +35,7 @@ define Build/addpattern
 endef
 
 define Build/append-md5sum-bin
-	$(STAGING_DIR_HOST)/bin/mkhash md5 $@ | sed 's/../\\\\x&/g' |\
+	$(MKHASH) md5 $@ | sed 's/../\\\\x&/g' |\
 		xargs echo -ne >> $@
 endef
 
diff --git a/target/linux/generic/pending-5.10/103-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch b/target/linux/generic/backport-5.10/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch
similarity index 100%
rename from target/linux/generic/pending-5.10/103-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch
rename to target/linux/generic/backport-5.10/103-v5.13-MIPS-select-CPU_MIPS64-for-remaining-MIPS64-CPUs.patch
diff --git a/target/linux/generic/pending-5.10/311-MIPS-zboot-put-appended-dtb-into-a-section.patch b/target/linux/generic/backport-5.10/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch
similarity index 100%
rename from target/linux/generic/pending-5.10/311-MIPS-zboot-put-appended-dtb-into-a-section.patch
rename to target/linux/generic/backport-5.10/311-v5.11-MIPS-zboot-put-appended-dtb-into-a-section.patch
diff --git a/target/linux/generic/pending-5.10/499-mtd-don-t-lock-when-recursively-deleting-partitions.patch b/target/linux/generic/backport-5.10/499-v5.13-mtd-don-t-lock-when-recursively-deleting-partitions.patch
similarity index 92%
rename from target/linux/generic/pending-5.10/499-mtd-don-t-lock-when-recursively-deleting-partitions.patch
rename to target/linux/generic/backport-5.10/499-v5.13-mtd-don-t-lock-when-recursively-deleting-partitions.patch
index 505131b684..d34248fbc7 100644
--- a/target/linux/generic/pending-5.10/499-mtd-don-t-lock-when-recursively-deleting-partitions.patch
+++ b/target/linux/generic/backport-5.10/499-v5.13-mtd-don-t-lock-when-recursively-deleting-partitions.patch
@@ -13,7 +13,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
 
 --- a/drivers/mtd/mtdpart.c
 +++ b/drivers/mtd/mtdpart.c
-@@ -474,7 +474,7 @@ static int __del_mtd_partitions(struct m
+@@ -331,7 +331,7 @@ static int __del_mtd_partitions(struct m
  
  	list_for_each_entry_safe(child, next, &mtd->partitions, part.node) {
  		if (mtd_has_partitions(child))
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
index 41dea98b5e..e6a6928896 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
@@ -697,10 +697,13 @@ int __init rb_hardconfig_init(struct kobject *rb_kobj)
 
 	hc_buflen = mtd->size;
 	hc_buf = kmalloc(hc_buflen, GFP_KERNEL);
-	if (!hc_buf)
+	if (!hc_buf) {
+		put_mtd_device(mtd);
 		return -ENOMEM;
+	}
 
 	ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf);
+	put_mtd_device(mtd);
 
 	if (ret)
 		goto fail;
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
index 54e263df8c..070bd32d5a 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
@@ -686,6 +686,8 @@ static ssize_t sc_commit_store(struct kobject *kobj, struct kobj_attribute *attr
 	}
 	write_unlock(&sc_bufrwl);
 
+	put_mtd_device(mtd);
+
 	if (ret)
 		goto mtdfail;
 
@@ -721,10 +723,13 @@ int __init rb_softconfig_init(struct kobject *rb_kobj)
 
 	sc_buflen = mtd->size;
 	sc_buf = kmalloc(sc_buflen, GFP_KERNEL);
-	if (!sc_buf)
+	if (!sc_buf) {
+		put_mtd_device(mtd);
 		return -ENOMEM;
+	}
 
 	ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf);
+	put_mtd_device(mtd);
 
 	if (ret)
 		goto fail;
diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount
index 7a54c34dba..cb32a4ed35 100755
--- a/target/linux/ipq806x/base-files/etc/init.d/bootcount
+++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount
@@ -2,15 +2,12 @@
 
 START=99
 
-. /lib/upgrade/asrock.sh
+. "$IPKG_INSTROOT/lib/upgrade/asrock.sh"
 
 boot() {
 	case $(board_name) in
 	asrock,g10)
-		asrock_bootconfig_mangle "bootcheck"
-		if [ $? -eq 0 ]; then
-			reboot
-		fi
+		asrock_bootconfig_mangle "bootcheck" && reboot
 		;;
 	edgecore,ecw5410)
 		fw_setenv bootcount 0
diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile
index 5937970a37..fc5223f3a4 100644
--- a/target/linux/ramips/image/Makefile
+++ b/target/linux/ramips/image/Makefile
@@ -91,7 +91,7 @@ endef
 
 define Build/netis-tail
 	echo -n $(1) >> $@
-	echo -n $(UIMAGE_NAME)-yun | $(STAGING_DIR_HOST)/bin/mkhash md5 | \
+	echo -n $(UIMAGE_NAME)-yun | $(MKHASH) md5 | \
 		sed 's/../\\\\x&/g' | xargs echo -ne >> $@
 endef
 
diff --git a/target/linux/ramips/image/mt7620.mk b/target/linux/ramips/image/mt7620.mk
index 64dc0715ed..3caeecebee 100644
--- a/target/linux/ramips/image/mt7620.mk
+++ b/target/linux/ramips/image/mt7620.mk
@@ -9,9 +9,9 @@ DEVICE_VARS += DLINK_ROM_ID DLINK_FAMILY_MEMBER DLINK_FIRMWARE_SIZE DLINK_IMAGE_
 define Build/elecom-header
 	cp $@ $(KDIR)/v_0.0.0.bin
 	( \
-		mkhash md5 $(KDIR)/v_0.0.0.bin && \
+		$(MKHASH) md5 $(KDIR)/v_0.0.0.bin && \
 		echo 458 \
-	) | mkhash md5 > $(KDIR)/v_0.0.0.md5
+	) | $(MKHASH) md5 > $(KDIR)/v_0.0.0.md5
 	$(STAGING_DIR_HOST)/bin/tar -c \
 		$(if $(SOURCE_DATE_EPOCH),--mtime=@$(SOURCE_DATE_EPOCH)) \
 		--owner=0 --group=0 -f $@ -C $(KDIR) v_0.0.0.bin v_0.0.0.md5
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
index e0b2b8dce9..c059ac15b7 100644
--- a/target/linux/ramips/image/mt7621.mk
+++ b/target/linux/ramips/image/mt7621.mk
@@ -13,7 +13,7 @@ define Build/elecom-wrc-gs-factory
 	$(eval product=$(word 1,$(1)))
 	$(eval version=$(word 2,$(1)))
 	$(eval hash_opt=$(word 3,$(1)))
-	$(STAGING_DIR_HOST)/bin/mkhash md5 $(hash_opt) $@ >> $@
+	$(MKHASH) md5 $(hash_opt) $@ >> $@
 	( \
 		echo -n "ELECOM $(product) v$(version)" | \
 			dd bs=32 count=1 conv=sync; \
@@ -61,13 +61,13 @@ define Build/ubnt-erx-factory-image
 		$(TAR) -cf $(1) --transform='s/^.*/compat/' $(1).compat; \
 		\
 		$(TAR) -rf $(1) --transform='s/^.*/vmlinux.tmp/' $(KDIR)/tmp/$(KERNEL_INITRAMFS_IMAGE); \
-		mkhash md5 $(KDIR)/tmp/$(KERNEL_INITRAMFS_IMAGE) > $(1).md5; \
+		$(MKHASH) md5 $(KDIR)/tmp/$(KERNEL_INITRAMFS_IMAGE) > $(1).md5; \
 		$(TAR) -rf $(1) --transform='s/^.*/vmlinux.tmp.md5/' $(1).md5; \
 		\
 		echo "dummy" > $(1).rootfs; \
 		$(TAR) -rf $(1) --transform='s/^.*/squashfs.tmp/' $(1).rootfs; \
 		\
-		mkhash md5 $(1).rootfs > $(1).md5; \
+		$(MKHASH) md5 $(1).rootfs > $(1).md5; \
 		$(TAR) -rf $(1) --transform='s/^.*/squashfs.tmp.md5/' $(1).md5; \
 		\
 		echo '$(BOARD) $(VERSION_CODE) $(VERSION_NUMBER)' > $(1).version; \