From: Sasha Levin Date: Sun, 27 Nov 2022 19:07:01 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v5.10.157~95 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3cec82d4713e9954d66e4f49cd8421d380989120;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/9p-fd-fix-issue-of-list_del-corruption-in-p9_fd_canc.patch b/queue-5.15/9p-fd-fix-issue-of-list_del-corruption-in-p9_fd_canc.patch new file mode 100644 index 00000000000..217ed538ec0 --- /dev/null +++ b/queue-5.15/9p-fd-fix-issue-of-list_del-corruption-in-p9_fd_canc.patch @@ -0,0 +1,75 @@ +From c3bba090ad52c6dac1fd0a006b81f9e1c089ccc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 20:26:06 +0800 +Subject: 9p/fd: fix issue of list_del corruption in p9_fd_cancel() + +From: Zhengchao Shao + +[ Upstream commit 11c10956515b8ec44cf4f2a7b9d8bf8b9dc05ec4 ] + +Syz reported the following issue: +kernel BUG at lib/list_debug.c:53! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN +RIP: 0010:__list_del_entry_valid.cold+0x5c/0x72 +Call Trace: + +p9_fd_cancel+0xb1/0x270 +p9_client_rpc+0x8ea/0xba0 +p9_client_create+0x9c0/0xed0 +v9fs_session_init+0x1e0/0x1620 +v9fs_mount+0xba/0xb80 +legacy_get_tree+0x103/0x200 +vfs_get_tree+0x89/0x2d0 +path_mount+0x4c0/0x1ac0 +__x64_sys_mount+0x33b/0x430 +do_syscall_64+0x35/0x80 +entry_SYSCALL_64_after_hwframe+0x46/0xb0 + + +The process is as follows: +Thread A: Thread B: +p9_poll_workfn() p9_client_create() +... ... + p9_conn_cancel() p9_fd_cancel() + list_del() ... + ... list_del() //list_del + corruption +There is no lock protection when deleting list in p9_conn_cancel(). After +deleting list in Thread A, thread B will delete the same list again. It +will cause issue of list_del corruption. + +Setting req->status to REQ_STATUS_ERROR under lock prevents other +cleanup paths from trying to manipulate req_list. +The other thread can safely check req->status because it still holds a +reference to req at this point. + +Link: https://lkml.kernel.org/r/20221110122606.383352-1-shaozhengchao@huawei.com +Fixes: 52f1c45dde91 ("9p: trans_fd/p9_conn_cancel: drop client lock earlier") +Reported-by: syzbot+9b69b8d10ab4a7d88056@syzkaller.appspotmail.com +Signed-off-by: Zhengchao Shao +[Dominique: add description of the fix in commit message] +Signed-off-by: Dominique Martinet +Signed-off-by: Sasha Levin +--- + net/9p/trans_fd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c +index a8c1f742148c..31f2026514f3 100644 +--- a/net/9p/trans_fd.c ++++ b/net/9p/trans_fd.c +@@ -204,9 +204,11 @@ static void p9_conn_cancel(struct p9_conn *m, int err) + + list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { + list_move(&req->req_list, &cancel_list); ++ req->status = REQ_STATUS_ERROR; + } + list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { + list_move(&req->req_list, &cancel_list); ++ req->status = REQ_STATUS_ERROR; + } + + spin_unlock(&m->req_lock); +-- +2.35.1 + diff --git a/queue-5.15/af_key-fix-send_acquire-race-with-pfkey_register.patch b/queue-5.15/af_key-fix-send_acquire-race-with-pfkey_register.patch new file mode 100644 index 00000000000..a70712ac2d5 --- /dev/null +++ b/queue-5.15/af_key-fix-send_acquire-race-with-pfkey_register.patch @@ -0,0 +1,147 @@ +From 2e8a017dc5cc90126051674f4dad6a702a4722e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 14:06:48 +0800 +Subject: af_key: Fix send_acquire race with pfkey_register + +From: Herbert Xu + +[ Upstream commit 7f57f8165cb6d2c206e2b9ada53b9e2d6d8af42f ] + +The function pfkey_send_acquire may race with pfkey_register +(which could even be in a different name space). This may result +in a buffer overrun. + +Allocating the maximum amount of memory that could be used prevents +this. + +Reported-by: syzbot+1e9af9185d8850e2c2fa@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Herbert Xu +Reviewed-by: Sabrina Dubroca +Reviewed-by: Eric Dumazet +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 32 ++++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 10 deletions(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index 53cca9019158..a654bd4bc437 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -2905,7 +2905,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t) + break; + if (!aalg->pfkey_supported) + continue; +- if (aalg_tmpl_set(t, aalg) && aalg->available) ++ if (aalg_tmpl_set(t, aalg)) + sz += sizeof(struct sadb_comb); + } + return sz + sizeof(struct sadb_prop); +@@ -2923,7 +2923,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) + if (!ealg->pfkey_supported) + continue; + +- if (!(ealg_tmpl_set(t, ealg) && ealg->available)) ++ if (!(ealg_tmpl_set(t, ealg))) + continue; + + for (k = 1; ; k++) { +@@ -2934,16 +2934,17 @@ static int count_esp_combs(const struct xfrm_tmpl *t) + if (!aalg->pfkey_supported) + continue; + +- if (aalg_tmpl_set(t, aalg) && aalg->available) ++ if (aalg_tmpl_set(t, aalg)) + sz += sizeof(struct sadb_comb); + } + } + return sz + sizeof(struct sadb_prop); + } + +-static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) ++static int dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) + { + struct sadb_prop *p; ++ int sz = 0; + int i; + + p = skb_put(skb, sizeof(struct sadb_prop)); +@@ -2971,13 +2972,17 @@ static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) + c->sadb_comb_soft_addtime = 20*60*60; + c->sadb_comb_hard_usetime = 8*60*60; + c->sadb_comb_soft_usetime = 7*60*60; ++ sz += sizeof(*c); + } + } ++ ++ return sz + sizeof(*p); + } + +-static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) ++static int dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) + { + struct sadb_prop *p; ++ int sz = 0; + int i, k; + + p = skb_put(skb, sizeof(struct sadb_prop)); +@@ -3019,8 +3024,11 @@ static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) + c->sadb_comb_soft_addtime = 20*60*60; + c->sadb_comb_hard_usetime = 8*60*60; + c->sadb_comb_soft_usetime = 7*60*60; ++ sz += sizeof(*c); + } + } ++ ++ return sz + sizeof(*p); + } + + static int key_notify_policy_expire(struct xfrm_policy *xp, const struct km_event *c) +@@ -3150,6 +3158,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct + struct sadb_x_sec_ctx *sec_ctx; + struct xfrm_sec_ctx *xfrm_ctx; + int ctx_size = 0; ++ int alg_size = 0; + + sockaddr_size = pfkey_sockaddr_size(x->props.family); + if (!sockaddr_size) +@@ -3161,16 +3170,16 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct + sizeof(struct sadb_x_policy); + + if (x->id.proto == IPPROTO_AH) +- size += count_ah_combs(t); ++ alg_size = count_ah_combs(t); + else if (x->id.proto == IPPROTO_ESP) +- size += count_esp_combs(t); ++ alg_size = count_esp_combs(t); + + if ((xfrm_ctx = x->security)) { + ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len); + size += sizeof(struct sadb_x_sec_ctx) + ctx_size; + } + +- skb = alloc_skb(size + 16, GFP_ATOMIC); ++ skb = alloc_skb(size + alg_size + 16, GFP_ATOMIC); + if (skb == NULL) + return -ENOMEM; + +@@ -3224,10 +3233,13 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct + pol->sadb_x_policy_priority = xp->priority; + + /* Set sadb_comb's. */ ++ alg_size = 0; + if (x->id.proto == IPPROTO_AH) +- dump_ah_combs(skb, t); ++ alg_size = dump_ah_combs(skb, t); + else if (x->id.proto == IPPROTO_ESP) +- dump_esp_combs(skb, t); ++ alg_size = dump_esp_combs(skb, t); ++ ++ hdr->sadb_msg_len += alg_size / 8; + + /* security context */ + if (xfrm_ctx) { +-- +2.35.1 + diff --git a/queue-5.15/arcnet-fix-potential-memory-leak-in-com20020_probe.patch b/queue-5.15/arcnet-fix-potential-memory-leak-in-com20020_probe.patch new file mode 100644 index 00000000000..76255cdb024 --- /dev/null +++ b/queue-5.15/arcnet-fix-potential-memory-leak-in-com20020_probe.patch @@ -0,0 +1,61 @@ +From 7e0fd95d3a1db31711adc9e3f86d27a92b82ff7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 14:24:38 +0800 +Subject: arcnet: fix potential memory leak in com20020_probe() + +From: Wang Hai + +[ Upstream commit 1c40cde6b5171d9c8dfc69be00464fd1c75e210b ] + +In com20020_probe(), if com20020_config() fails, dev and info +will not be freed, which will lead to a memory leak. + +This patch adds freeing dev and info after com20020_config() +fails to fix this bug. + +Compile tested only. + +Fixes: 15b99ac17295 ("[PATCH] pcmcia: add return value to _config() functions") +Signed-off-by: Wang Hai +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/com20020_cs.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c +index b88a109b3b15..26ee263d8f3a 100644 +--- a/drivers/net/arcnet/com20020_cs.c ++++ b/drivers/net/arcnet/com20020_cs.c +@@ -113,6 +113,7 @@ static int com20020_probe(struct pcmcia_device *p_dev) + struct com20020_dev *info; + struct net_device *dev; + struct arcnet_local *lp; ++ int ret = -ENOMEM; + + dev_dbg(&p_dev->dev, "com20020_attach()\n"); + +@@ -142,12 +143,18 @@ static int com20020_probe(struct pcmcia_device *p_dev) + info->dev = dev; + p_dev->priv = info; + +- return com20020_config(p_dev); ++ ret = com20020_config(p_dev); ++ if (ret) ++ goto fail_config; ++ ++ return 0; + ++fail_config: ++ free_arcdev(dev); + fail_alloc_dev: + kfree(info); + fail_alloc_info: +- return -ENOMEM; ++ return ret; + } /* com20020_attach */ + + static void com20020_detach(struct pcmcia_device *link) +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-am335x-pcm-953-define-fixed-regulators-in-ro.patch b/queue-5.15/arm-dts-am335x-pcm-953-define-fixed-regulators-in-ro.patch new file mode 100644 index 00000000000..db19b17b68b --- /dev/null +++ b/queue-5.15/arm-dts-am335x-pcm-953-define-fixed-regulators-in-ro.patch @@ -0,0 +1,66 @@ +From 86090bf033e2ef40e1e3bca0b9f118f19bf04c29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Oct 2022 16:31:15 +0200 +Subject: ARM: dts: am335x-pcm-953: Define fixed regulators in root node + +From: Dominik Haller + +[ Upstream commit 8950f345a67d8046d2472dd6ea81fa18ef5b4844 ] + +Remove the regulators node and define fixed regulators in the root node. +Prevents the sdhci-omap driver from waiting in probe deferral forever +because of the missing vmmc-supply and keeps am335x-pcm-953 consistent with +the other Phytec AM335 boards. + +Fixes: bb07a829ec38 ("ARM: dts: Add support for phyCORE-AM335x PCM-953 carrier board") +Signed-off-by: Dominik Haller +Message-Id: <20221011143115.248003-1-d.haller@phytec.de> +Signed-off-by: Tony Lindgren +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/am335x-pcm-953.dtsi | 28 +++++++++++++-------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/arch/arm/boot/dts/am335x-pcm-953.dtsi b/arch/arm/boot/dts/am335x-pcm-953.dtsi +index 124026fa0d09..f207499461b3 100644 +--- a/arch/arm/boot/dts/am335x-pcm-953.dtsi ++++ b/arch/arm/boot/dts/am335x-pcm-953.dtsi +@@ -12,22 +12,20 @@ / { + compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx"; + + /* Power */ +- regulators { +- vcc3v3: fixedregulator@1 { +- compatible = "regulator-fixed"; +- regulator-name = "vcc3v3"; +- regulator-min-microvolt = <3300000>; +- regulator-max-microvolt = <3300000>; +- regulator-boot-on; +- }; ++ vcc3v3: fixedregulator1 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ }; + +- vcc1v8: fixedregulator@2 { +- compatible = "regulator-fixed"; +- regulator-name = "vcc1v8"; +- regulator-min-microvolt = <1800000>; +- regulator-max-microvolt = <1800000>; +- regulator-boot-on; +- }; ++ vcc1v8: fixedregulator2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-boot-on; + }; + + /* User IO */ +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-at91-sam9g20ek-enable-udc-vbus-gpio-pinctrl.patch b/queue-5.15/arm-dts-at91-sam9g20ek-enable-udc-vbus-gpio-pinctrl.patch new file mode 100644 index 00000000000..0227a5117bd --- /dev/null +++ b/queue-5.15/arm-dts-at91-sam9g20ek-enable-udc-vbus-gpio-pinctrl.patch @@ -0,0 +1,57 @@ +From f9f1ba39ac4945d39ff6b6cdd205bab226319f12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 19:59:23 +0100 +Subject: ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl + +From: Michael Grzeschik + +[ Upstream commit 40a2226e8bfacb79dd154dea68febeead9d847e9 ] + +We set the PIOC to GPIO mode. This way the pin becomes an +input signal will be usable by the controller. Without +this change the udc on the 9g20ek does not work. + +Cc: nicolas.ferre@microchip.com +Cc: ludovic.desroches@microchip.com +Cc: alexandre.belloni@bootlin.com +Cc: linux-arm-kernel@lists.infradead.org +Cc: kernel@pengutronix.de +Fixes: 5cb4e73575e3 ("ARM: at91: add at91sam9g20ek boards dt support") +Signed-off-by: Michael Grzeschik +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20221114185923.1023249-3-m.grzeschik@pengutronix.de +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/at91sam9g20ek_common.dtsi | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +index ca03685f0f08..4783e657b4cb 100644 +--- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi ++++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +@@ -39,6 +39,13 @@ pinctrl_pck0_as_mck: pck0_as_mck { + + }; + ++ usb1 { ++ pinctrl_usb1_vbus_gpio: usb1_vbus_gpio { ++ atmel,pins = ++ ; /* PC5 GPIO */ ++ }; ++ }; ++ + mmc0_slot1 { + pinctrl_board_mmc0_slot1: mmc0_slot1-board { + atmel,pins = +@@ -84,6 +91,8 @@ macb0: ethernet@fffc4000 { + }; + + usb1: gadget@fffa4000 { ++ pinctrl-0 = <&pinctrl_usb1_vbus_gpio>; ++ pinctrl-names = "default"; + atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-imx6q-prti6q-fix-ref-tcxo-clock-frequency-pr.patch b/queue-5.15/arm-dts-imx6q-prti6q-fix-ref-tcxo-clock-frequency-pr.patch new file mode 100644 index 00000000000..f3774c91963 --- /dev/null +++ b/queue-5.15/arm-dts-imx6q-prti6q-fix-ref-tcxo-clock-frequency-pr.patch @@ -0,0 +1,43 @@ +From 226a5d4de6ec70c64a149a8dbdb6c96f26d5c3f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 10:41:02 -0300 +Subject: ARM: dts: imx6q-prti6q: Fix ref/tcxo-clock-frequency properties + +From: Fabio Estevam + +[ Upstream commit e68be7b39f21d8a9291a5a3019787cd3ca999dd7 ] + +make dtbs_check gives the following errors: + +ref-clock-frequency: size (9) error for type uint32 +tcxo-clock-frequency: size (9) error for type uint32 + +Fix it by passing the frequencies inside < > as documented in +Documentation/devicetree/bindings/net/wireless/ti,wlcore.yaml. + +Signed-off-by: Fabio Estevam +Fixes: 0d446a505592 ("ARM: dts: add Protonic PRTI6Q board") +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6q-prti6q.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/imx6q-prti6q.dts b/arch/arm/boot/dts/imx6q-prti6q.dts +index b4605edfd2ab..d8fa83effd63 100644 +--- a/arch/arm/boot/dts/imx6q-prti6q.dts ++++ b/arch/arm/boot/dts/imx6q-prti6q.dts +@@ -364,8 +364,8 @@ wifi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wifi>; + interrupts-extended = <&gpio1 30 IRQ_TYPE_LEVEL_HIGH>; +- ref-clock-frequency = "38400000"; +- tcxo-clock-frequency = "19200000"; ++ ref-clock-frequency = <38400000>; ++ tcxo-clock-frequency = <19200000>; + }; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm-mxs-fix-memory-leak-in-mxs_machine_init.patch b/queue-5.15/arm-mxs-fix-memory-leak-in-mxs_machine_init.patch new file mode 100644 index 00000000000..36c0eb7e8dc --- /dev/null +++ b/queue-5.15/arm-mxs-fix-memory-leak-in-mxs_machine_init.patch @@ -0,0 +1,40 @@ +From 7cc1550cedfd8e7f405aa75f3542873f37489c05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 06:20:11 +0000 +Subject: ARM: mxs: fix memory leak in mxs_machine_init() + +From: Zheng Yongjun + +[ Upstream commit f31e3c204d1844b8680a442a48868af5ac3d5481 ] + +If of_property_read_string() failed, 'soc_dev_attr' should be +freed before return. Otherwise there is a memory leak. + +Fixes: 2046338dcbc6 ("ARM: mxs: Use soc bus infrastructure") +Signed-off-by: Zheng Yongjun +Reviewed-by: Marco Felsch +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/mach-mxs/mach-mxs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c +index 25c9d184fa4c..1c57ac401649 100644 +--- a/arch/arm/mach-mxs/mach-mxs.c ++++ b/arch/arm/mach-mxs/mach-mxs.c +@@ -393,8 +393,10 @@ static void __init mxs_machine_init(void) + + root = of_find_node_by_path("/"); + ret = of_property_read_string(root, "model", &soc_dev_attr->machine); +- if (ret) ++ if (ret) { ++ kfree(soc_dev_attr); + return; ++ } + + soc_dev_attr->family = "Freescale MXS Family"; + soc_dev_attr->soc_id = mxs_get_soc_id(); +-- +2.35.1 + diff --git a/queue-5.15/asoc-hdac_hda-fix-hda-pcm-buffer-overflow-issue.patch b/queue-5.15/asoc-hdac_hda-fix-hda-pcm-buffer-overflow-issue.patch new file mode 100644 index 00000000000..98f1e35fd93 --- /dev/null +++ b/queue-5.15/asoc-hdac_hda-fix-hda-pcm-buffer-overflow-issue.patch @@ -0,0 +1,66 @@ +From dd4093322691e318c03715dde66e19ac397b5bf1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 07:40:23 +0800 +Subject: ASoC: hdac_hda: fix hda pcm buffer overflow issue + +From: Junxiao Chang + +[ Upstream commit 37882100cd0629d830db430a8cee0b724fe1fea3 ] + +When KASAN is enabled, below log might be dumped with Intel EHL hardware: +[ 48.583597] ================================================================== +[ 48.585921] BUG: KASAN: slab-out-of-bounds in hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] +[ 48.587995] Write of size 4 at addr ffff888103489708 by task pulseaudio/759 + +[ 48.589237] CPU: 2 PID: 759 Comm: pulseaudio Tainted: G U E 5.15.71-intel-ese-standard-lts #9 +[ 48.591272] Hardware name: Intel Corporation Elkhart Lake Embedded Platform/ElkhartLake LPDDR4x T3 CRB, BIOS EHLSFWI1.R00.4251.A01.2206130432 06/13/2022 +[ 48.593010] Call Trace: +[ 48.593648] +[ 48.593852] dump_stack_lvl+0x34/0x48 +[ 48.594404] print_address_description.constprop.0+0x1f/0x140 +[ 48.595174] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] +[ 48.595868] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] +[ 48.596519] kasan_report.cold+0x7f/0x11b +[ 48.597003] ? hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] +[ 48.597885] hdac_hda_dai_hw_params+0x20a/0x22b [snd_soc_hdac_hda] + +HDAC_LAST_DAI_ID is last index id, pcm buffer array size should +be +1 to avoid out of bound access. + +Fixes: 608b8c36c371 ("ASoC: hdac_hda: add support for HDMI/DP as a HDA codec") +Reviewed-by: Kai Vehmanen +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Junxiao Chang +Signed-off-by: Furong Zhou +Link: https://lore.kernel.org/r/20221109234023.3111035-1-junxiao.chang@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/hdac_hda.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h +index d0efc5e254ae..da0ed74758b0 100644 +--- a/sound/soc/codecs/hdac_hda.h ++++ b/sound/soc/codecs/hdac_hda.h +@@ -14,7 +14,7 @@ enum { + HDAC_HDMI_1_DAI_ID, + HDAC_HDMI_2_DAI_ID, + HDAC_HDMI_3_DAI_ID, +- HDAC_LAST_DAI_ID = HDAC_HDMI_3_DAI_ID, ++ HDAC_DAI_ID_NUM + }; + + struct hdac_hda_pcm { +@@ -24,7 +24,7 @@ struct hdac_hda_pcm { + + struct hdac_hda_priv { + struct hda_codec codec; +- struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID]; ++ struct hdac_hda_pcm pcm[HDAC_DAI_ID_NUM]; + bool need_display_power; + }; + +-- +2.35.1 + diff --git a/queue-5.15/asoc-max98373-add-checks-for-devm_kcalloc.patch b/queue-5.15/asoc-max98373-add-checks-for-devm_kcalloc.patch new file mode 100644 index 00000000000..732923c2d4d --- /dev/null +++ b/queue-5.15/asoc-max98373-add-checks-for-devm_kcalloc.patch @@ -0,0 +1,40 @@ +From 853896dcfd7950ef0375f74449569308f8a9ddf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 16:25:08 +0800 +Subject: ASoC: max98373: Add checks for devm_kcalloc + +From: Jiasheng Jiang + +[ Upstream commit 60591bbf6d5eb44f275eb733943b7757325c1b60 ] + +As the devm_kcalloc may return NULL pointer, +it should be better to check the return value +in order to avoid NULL poineter dereference. + +Fixes: 349dd23931d1 ("ASoC: max98373: don't access volatile registers in bias level off") +Signed-off-by: Jiasheng Jiang +Link: https://lore.kernel.org/r/20221116082508.17418-1-jiasheng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/max98373-i2c.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c +index ddb6436835d7..68497a4521dd 100644 +--- a/sound/soc/codecs/max98373-i2c.c ++++ b/sound/soc/codecs/max98373-i2c.c +@@ -551,6 +551,10 @@ static int max98373_i2c_probe(struct i2c_client *i2c, + max98373->cache = devm_kcalloc(&i2c->dev, max98373->cache_num, + sizeof(*max98373->cache), + GFP_KERNEL); ++ if (!max98373->cache) { ++ ret = -ENOMEM; ++ return ret; ++ } + + for (i = 0; i < max98373->cache_num; i++) + max98373->cache[i].reg = max98373_i2c_cache_reg[i]; +-- +2.35.1 + diff --git a/queue-5.15/asoc-sgtl5000-reset-the-chip_clk_ctrl-reg-on-remove.patch b/queue-5.15/asoc-sgtl5000-reset-the-chip_clk_ctrl-reg-on-remove.patch new file mode 100644 index 00000000000..cdc5f1267c8 --- /dev/null +++ b/queue-5.15/asoc-sgtl5000-reset-the-chip_clk_ctrl-reg-on-remove.patch @@ -0,0 +1,48 @@ +From 4e4ae9a2d1e8e68f63c4be48c6c3e14b5ab29a26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 14:06:12 -0500 +Subject: ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove + +From: Detlev Casanova + +[ Upstream commit 0bb8e9b36b5b7f2e77892981ff6c27ee831d8026 ] + +Since commit bf2aebccddef ("ASoC: sgtl5000: Fix noise on shutdown/remove"), +the device power control registers are reset when the driver is +removed/shutdown. + +This is an issue when the device is configured to use the PLL clock. The +device will stop responding if it is still configured to use the PLL +clock but the PLL clock is powered down. + +When rebooting linux, the probe function will show: +sgtl5000 0-000a: Error reading chip id -11 + +Make sure that the CHIP_CLK_CTRL is reset to its default value before +powering down the device. + +Fixes: bf2aebccddef ("ASoC: sgtl5000: Fix noise on shutdown/remove") +Signed-off-by: Detlev Casanova +Reviewed-by: Fabio Estevam +Link: https://lore.kernel.org/r/20221110190612.1341469-1-detlev.casanova@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/sgtl5000.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c +index dc56e6c6b668..3c5a4fe2fad6 100644 +--- a/sound/soc/codecs/sgtl5000.c ++++ b/sound/soc/codecs/sgtl5000.c +@@ -1797,6 +1797,7 @@ static int sgtl5000_i2c_remove(struct i2c_client *client) + { + struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); + ++ regmap_write(sgtl5000->regmap, SGTL5000_CHIP_CLK_CTRL, SGTL5000_CHIP_CLK_CTRL_DEFAULT); + regmap_write(sgtl5000->regmap, SGTL5000_CHIP_DIG_POWER, SGTL5000_DIG_POWER_DEFAULT); + regmap_write(sgtl5000->regmap, SGTL5000_CHIP_ANA_POWER, SGTL5000_ANA_POWER_DEFAULT); + +-- +2.35.1 + diff --git a/queue-5.15/asoc-soc-pcm-don-t-zero-tdm-masks-in-__soc_pcm_open.patch b/queue-5.15/asoc-soc-pcm-don-t-zero-tdm-masks-in-__soc_pcm_open.patch new file mode 100644 index 00000000000..6f5b6fe9b55 --- /dev/null +++ b/queue-5.15/asoc-soc-pcm-don-t-zero-tdm-masks-in-__soc_pcm_open.patch @@ -0,0 +1,47 @@ +From 87d791009cdb32c0912374febfe2c82c848c35db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 13:22:13 +0000 +Subject: ASoC: soc-pcm: Don't zero TDM masks in __soc_pcm_open() + +From: Richard Fitzgerald + +[ Upstream commit 39bd801d6908900e9ab0cdc2655150f95ddd4f1a ] + +The DAI tx_mask and rx_mask are set by snd_soc_dai_set_tdm_slot() +and used by later code that depends on the TDM settings. So +__soc_pcm_open() should not be obliterating those mask values. + +The code in __soc_pcm_hw_params() uses these masks to calculate the +active channels so that only the AIF_IN/AIF_OUT widgets for the +active TDM slots are enabled. The zeroing of the masks in +__soc_pcm_open() disables this functionality so all AIF widgets +were enabled even for channels that are not assigned to a TDM slot. + +Signed-off-by: Richard Fitzgerald +Fixes: 2e5894d73789 ("ASoC: pcm: Add support for DAI multicodec") +Link: https://lore.kernel.org/r/20221104132213.121847-1-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-pcm.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 48f71bb81a2f..f6dc71e8ea87 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -759,11 +759,6 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) + ret = snd_soc_dai_startup(dai, substream); + if (ret < 0) + goto err; +- +- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- dai->tx_mask = 0; +- else +- dai->rx_mask = 0; + } + + /* Dynamic PCM DAI links compat checks use dynamic capabilities */ +-- +2.35.1 + diff --git a/queue-5.15/bnx2x-fix-pci-device-refcount-leak-in-bnx2x_vf_is_pc.patch b/queue-5.15/bnx2x-fix-pci-device-refcount-leak-in-bnx2x_vf_is_pc.patch new file mode 100644 index 00000000000..eadb9e34c55 --- /dev/null +++ b/queue-5.15/bnx2x-fix-pci-device-refcount-leak-in-bnx2x_vf_is_pc.patch @@ -0,0 +1,58 @@ +From 454108f58d664111bfaf6d61e041b26f199fe16f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 15:02:02 +0800 +Subject: bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending() + +From: Yang Yingliang + +[ Upstream commit 3637a29ccbb6461b7268c5c5db525935d510afc6 ] + +As comment of pci_get_domain_bus_and_slot() says, it returns +a pci device with refcount increment, when finish using it, +the caller must decrement the reference count by calling +pci_dev_put(). Call pci_dev_put() before returning from +bnx2x_vf_is_pcie_pending() to avoid refcount leak. + +Fixes: b56e9670ffa4 ("bnx2x: Prepare device and initialize VF database") +Suggested-by: Jakub Kicinski +Signed-off-by: Yang Yingliang +Reviewed-by: Leon Romanovsky +Link: https://lore.kernel.org/r/20221119070202.1407648-1-yangyingliang@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +index 561395731450..a9f202bbada1 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +@@ -795,16 +795,20 @@ static void bnx2x_vf_enable_traffic(struct bnx2x *bp, struct bnx2x_virtf *vf) + + static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid) + { +- struct pci_dev *dev; + struct bnx2x_virtf *vf = bnx2x_vf_by_abs_fid(bp, abs_vfid); ++ struct pci_dev *dev; ++ bool pending; + + if (!vf) + return false; + + dev = pci_get_domain_bus_and_slot(vf->domain, vf->bus, vf->devfn); +- if (dev) +- return bnx2x_is_pcie_pending(dev); +- return false; ++ if (!dev) ++ return false; ++ pending = bnx2x_is_pcie_pending(dev); ++ pci_dev_put(dev); ++ ++ return pending; + } + + int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid) +-- +2.35.1 + diff --git a/queue-5.15/bus-sunxi-rsb-remove-the-shutdown-callback.patch b/queue-5.15/bus-sunxi-rsb-remove-the-shutdown-callback.patch new file mode 100644 index 00000000000..8f9490a31b6 --- /dev/null +++ b/queue-5.15/bus-sunxi-rsb-remove-the-shutdown-callback.patch @@ -0,0 +1,55 @@ +From a590925e4fd23b970b9dd2108f9693be228aeefc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 19:57:47 -0600 +Subject: bus: sunxi-rsb: Remove the shutdown callback + +From: Samuel Holland + +[ Upstream commit 5f4696ddca4b8a0bbbc36bd46829f97aab5a4552 ] + +Shutting down the RSB controller prevents communicating with a PMIC +inside pm_power_off(), since that gets called after device_shutdown(), +so it breaks system poweroff on some boards. + +Reported-by: Ivaylo Dimitrov +Tested-by: Ivaylo Dimitrov +Acked-by: Jernej Skrabec +Fixes: 843107498f91 ("bus: sunxi-rsb: Implement suspend/resume/shutdown callbacks") +Signed-off-by: Samuel Holland +Link: https://lore.kernel.org/r/20221114015749.28490-2-samuel@sholland.org +Signed-off-by: Jernej Skrabec +Signed-off-by: Sasha Levin +--- + drivers/bus/sunxi-rsb.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c +index 60b082fe2ed0..9c209492b267 100644 +--- a/drivers/bus/sunxi-rsb.c ++++ b/drivers/bus/sunxi-rsb.c +@@ -816,14 +816,6 @@ static int sunxi_rsb_remove(struct platform_device *pdev) + return 0; + } + +-static void sunxi_rsb_shutdown(struct platform_device *pdev) +-{ +- struct sunxi_rsb *rsb = platform_get_drvdata(pdev); +- +- pm_runtime_disable(&pdev->dev); +- sunxi_rsb_hw_exit(rsb); +-} +- + static const struct dev_pm_ops sunxi_rsb_dev_pm_ops = { + SET_RUNTIME_PM_OPS(sunxi_rsb_runtime_suspend, + sunxi_rsb_runtime_resume, NULL) +@@ -839,7 +831,6 @@ MODULE_DEVICE_TABLE(of, sunxi_rsb_of_match_table); + static struct platform_driver sunxi_rsb_driver = { + .probe = sunxi_rsb_probe, + .remove = sunxi_rsb_remove, +- .shutdown = sunxi_rsb_shutdown, + .driver = { + .name = RSB_CTRL_NAME, + .of_match_table = sunxi_rsb_of_match_table, +-- +2.35.1 + diff --git a/queue-5.15/bus-sunxi-rsb-support-atomic-transfers.patch b/queue-5.15/bus-sunxi-rsb-support-atomic-transfers.patch new file mode 100644 index 00000000000..573f0106afa --- /dev/null +++ b/queue-5.15/bus-sunxi-rsb-support-atomic-transfers.patch @@ -0,0 +1,92 @@ +From bbfc524e0048be383b0c319f71de0e12e567282f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 19:57:48 -0600 +Subject: bus: sunxi-rsb: Support atomic transfers + +From: Samuel Holland + +[ Upstream commit 077686da0e2162c4ea5ae0df205849c2a7a84479 ] + +When communicating with a PMIC during system poweroff (pm_power_off()), +IRQs are disabled and we are in a RCU read-side critical section, so we +cannot use wait_for_completion_io_timeout(). Instead, poll the status +register for transfer completion. + +Fixes: d787dcdb9c8f ("bus: sunxi-rsb: Add driver for Allwinner Reduced Serial Bus") +Signed-off-by: Samuel Holland +Reviewed-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20221114015749.28490-3-samuel@sholland.org +Signed-off-by: Jernej Skrabec +Signed-off-by: Sasha Levin +--- + drivers/bus/sunxi-rsb.c | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/drivers/bus/sunxi-rsb.c b/drivers/bus/sunxi-rsb.c +index 9c209492b267..20ed77f2b949 100644 +--- a/drivers/bus/sunxi-rsb.c ++++ b/drivers/bus/sunxi-rsb.c +@@ -271,6 +271,9 @@ EXPORT_SYMBOL_GPL(sunxi_rsb_driver_register); + /* common code that starts a transfer */ + static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb) + { ++ u32 int_mask, status; ++ bool timeout; ++ + if (readl(rsb->regs + RSB_CTRL) & RSB_CTRL_START_TRANS) { + dev_dbg(rsb->dev, "RSB transfer still in progress\n"); + return -EBUSY; +@@ -278,13 +281,23 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb) + + reinit_completion(&rsb->complete); + +- writel(RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER, +- rsb->regs + RSB_INTE); ++ int_mask = RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER; ++ writel(int_mask, rsb->regs + RSB_INTE); + writel(RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB, + rsb->regs + RSB_CTRL); + +- if (!wait_for_completion_io_timeout(&rsb->complete, +- msecs_to_jiffies(100))) { ++ if (irqs_disabled()) { ++ timeout = readl_poll_timeout_atomic(rsb->regs + RSB_INTS, ++ status, (status & int_mask), ++ 10, 100000); ++ writel(status, rsb->regs + RSB_INTS); ++ } else { ++ timeout = !wait_for_completion_io_timeout(&rsb->complete, ++ msecs_to_jiffies(100)); ++ status = rsb->status; ++ } ++ ++ if (timeout) { + dev_dbg(rsb->dev, "RSB timeout\n"); + + /* abort the transfer */ +@@ -296,18 +309,18 @@ static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb) + return -ETIMEDOUT; + } + +- if (rsb->status & RSB_INTS_LOAD_BSY) { ++ if (status & RSB_INTS_LOAD_BSY) { + dev_dbg(rsb->dev, "RSB busy\n"); + return -EBUSY; + } + +- if (rsb->status & RSB_INTS_TRANS_ERR) { +- if (rsb->status & RSB_INTS_TRANS_ERR_ACK) { ++ if (status & RSB_INTS_TRANS_ERR) { ++ if (status & RSB_INTS_TRANS_ERR_ACK) { + dev_dbg(rsb->dev, "RSB slave nack\n"); + return -EINVAL; + } + +- if (rsb->status & RSB_INTS_TRANS_ERR_DATA) { ++ if (status & RSB_INTS_TRANS_ERR_DATA) { + dev_dbg(rsb->dev, "RSB transfer data error\n"); + return -EIO; + } +-- +2.35.1 + diff --git a/queue-5.15/dccp-tcp-reset-saddr-on-failure-after-inet6-_hash_co.patch b/queue-5.15/dccp-tcp-reset-saddr-on-failure-after-inet6-_hash_co.patch new file mode 100644 index 00000000000..4f64294befb --- /dev/null +++ b/queue-5.15/dccp-tcp-reset-saddr-on-failure-after-inet6-_hash_co.patch @@ -0,0 +1,113 @@ +From 426789f8f0344909bd7580795539321c2a3fea64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 17:49:11 -0800 +Subject: dccp/tcp: Reset saddr on failure after inet6?_hash_connect(). + +From: Kuniyuki Iwashima + +[ Upstream commit 77934dc6db0d2b111a8f2759e9ad2fb67f5cffa5 ] + +When connect() is called on a socket bound to the wildcard address, +we change the socket's saddr to a local address. If the socket +fails to connect() to the destination, we have to reset the saddr. + +However, when an error occurs after inet_hash6?_connect() in +(dccp|tcp)_v[46]_conect(), we forget to reset saddr and leave +the socket bound to the address. + +From the user's point of view, whether saddr is reset or not varies +with errno. Let's fix this inconsistent behaviour. + +Note that after this patch, the repro [0] will trigger the WARN_ON() +in inet_csk_get_port() again, but this patch is not buggy and rather +fixes a bug papering over the bhash2's bug for which we need another +fix. + +For the record, the repro causes -EADDRNOTAVAIL in inet_hash6_connect() +by this sequence: + + s1 = socket() + s1.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + s1.bind(('127.0.0.1', 10000)) + s1.sendto(b'hello', MSG_FASTOPEN, (('127.0.0.1', 10000))) + # or s1.connect(('127.0.0.1', 10000)) + + s2 = socket() + s2.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) + s2.bind(('0.0.0.0', 10000)) + s2.connect(('127.0.0.1', 10000)) # -EADDRNOTAVAIL + + s2.listen(32) # WARN_ON(inet_csk(sk)->icsk_bind2_hash != tb2); + +[0]: https://syzkaller.appspot.com/bug?extid=015d756bbd1f8b5c8f09 + +Fixes: 3df80d9320bc ("[DCCP]: Introduce DCCPv6") +Fixes: 7c657876b63c ("[DCCP]: Initial implementation") +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Kuniyuki Iwashima +Acked-by: Joanne Koong +Reviewed-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dccp/ipv4.c | 2 ++ + net/dccp/ipv6.c | 2 ++ + net/ipv4/tcp_ipv4.c | 2 ++ + net/ipv6/tcp_ipv6.c | 2 ++ + 4 files changed, 8 insertions(+) + +diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c +index 0ea29270d7e5..5bcfa1e9a941 100644 +--- a/net/dccp/ipv4.c ++++ b/net/dccp/ipv4.c +@@ -137,6 +137,8 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + * This unhashes the socket and releases the local port, if necessary. + */ + dccp_set_state(sk, DCCP_CLOSED); ++ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) ++ inet_reset_saddr(sk); + ip_rt_put(rt); + sk->sk_route_caps = 0; + inet->inet_dport = 0; +diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c +index fa663518fa0e..071620622e1e 100644 +--- a/net/dccp/ipv6.c ++++ b/net/dccp/ipv6.c +@@ -967,6 +967,8 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + + late_failure: + dccp_set_state(sk, DCCP_CLOSED); ++ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) ++ inet_reset_saddr(sk); + __sk_dst_reset(sk); + failure: + inet->inet_dport = 0; +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 42d4af632495..0e1fbad17dbe 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -324,6 +324,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) + * if necessary. + */ + tcp_set_state(sk, TCP_CLOSE); ++ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) ++ inet_reset_saddr(sk); + ip_rt_put(rt); + sk->sk_route_caps = 0; + inet->inet_dport = 0; +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 51f4d330e820..93b3e7c247ce 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -339,6 +339,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, + + late_failure: + tcp_set_state(sk, TCP_CLOSE); ++ if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) ++ inet_reset_saddr(sk); + failure: + inet->inet_dport = 0; + sk->sk_route_caps = 0; +-- +2.35.1 + diff --git a/queue-5.15/dma-buf-fix-racing-conflict-of-dma_heap_add.patch b/queue-5.15/dma-buf-fix-racing-conflict-of-dma_heap_add.patch new file mode 100644 index 00000000000..ec0dcf9661a --- /dev/null +++ b/queue-5.15/dma-buf-fix-racing-conflict-of-dma_heap_add.patch @@ -0,0 +1,94 @@ +From 1d0e7066a80030dcb306d2c4e0fef30aa073d547 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 5 Nov 2022 00:05:36 +0800 +Subject: dma-buf: fix racing conflict of dma_heap_add() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dawei Li + +[ Upstream commit 432e25902b9651622578c6248e549297d03caf66 ] + +Racing conflict could be: +task A task B +list_for_each_entry +strcmp(h->name)) + list_for_each_entry + strcmp(h->name) +kzalloc kzalloc +...... ..... +device_create device_create +list_add + list_add + +The root cause is that task B has no idea about the fact someone +else(A) has inserted heap with same name when it calls list_add, +so a potential collision occurs. + +Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework") +Signed-off-by: Dawei Li +Acked-by: Andrew Davis +Acked-by: Christian König +Signed-off-by: Sumit Semwal +Link: https://patchwork.freedesktop.org/patch/msgid/TYCP286MB2323873BBDF88020781FB986CA3B9@TYCP286MB2323.JPNP286.PROD.OUTLOOK.COM +Signed-off-by: Sasha Levin +--- + drivers/dma-buf/dma-heap.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c +index 8f5848aa144f..59d158873f4c 100644 +--- a/drivers/dma-buf/dma-heap.c ++++ b/drivers/dma-buf/dma-heap.c +@@ -233,18 +233,6 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) + return ERR_PTR(-EINVAL); + } + +- /* check the name is unique */ +- mutex_lock(&heap_list_lock); +- list_for_each_entry(h, &heap_list, list) { +- if (!strcmp(h->name, exp_info->name)) { +- mutex_unlock(&heap_list_lock); +- pr_err("dma_heap: Already registered heap named %s\n", +- exp_info->name); +- return ERR_PTR(-EINVAL); +- } +- } +- mutex_unlock(&heap_list_lock); +- + heap = kzalloc(sizeof(*heap), GFP_KERNEL); + if (!heap) + return ERR_PTR(-ENOMEM); +@@ -283,13 +271,27 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) + err_ret = ERR_CAST(dev_ret); + goto err2; + } +- /* Add heap to the list */ ++ + mutex_lock(&heap_list_lock); ++ /* check the name is unique */ ++ list_for_each_entry(h, &heap_list, list) { ++ if (!strcmp(h->name, exp_info->name)) { ++ mutex_unlock(&heap_list_lock); ++ pr_err("dma_heap: Already registered heap named %s\n", ++ exp_info->name); ++ err_ret = ERR_PTR(-EINVAL); ++ goto err3; ++ } ++ } ++ ++ /* Add heap to the list */ + list_add(&heap->list, &heap_list); + mutex_unlock(&heap_list_lock); + + return heap; + ++err3: ++ device_destroy(dma_heap_class, heap->heap_devt); + err2: + cdev_del(&heap->heap_cdev); + err1: +-- +2.35.1 + diff --git a/queue-5.15/drivers-hv-vmbus-fix-double-free-in-the-error-path-o.patch b/queue-5.15/drivers-hv-vmbus-fix-double-free-in-the-error-path-o.patch new file mode 100644 index 00000000000..85a276af964 --- /dev/null +++ b/queue-5.15/drivers-hv-vmbus-fix-double-free-in-the-error-path-o.patch @@ -0,0 +1,53 @@ +From 657fe66c0e8a6f4cae022985a8a88e87ed646a0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 16:11:34 +0800 +Subject: Drivers: hv: vmbus: fix double free in the error path of + vmbus_add_channel_work() + +From: Yang Yingliang + +[ Upstream commit f92a4b50f0bd7fd52391dc4bb9a309085d278f91 ] + +In the error path of vmbus_device_register(), device_unregister() +is called, which calls vmbus_device_release(). The latter frees +the struct hv_device that was passed in to vmbus_device_register(). +So remove the kfree() in vmbus_add_channel_work() to avoid a double +free. + +Fixes: c2e5df616e1a ("vmbus: add per-channel sysfs info") +Suggested-by: Michael Kelley +Signed-off-by: Yang Yingliang +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20221119081135.1564691-2-yangyingliang@huawei.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + drivers/hv/channel_mgmt.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 07003019263a..d8dc5cc5e3a8 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -531,13 +531,17 @@ static void vmbus_add_channel_work(struct work_struct *work) + * Add the new device to the bus. This will kick off device-driver + * binding which eventually invokes the device driver's AddDevice() + * method. ++ * ++ * If vmbus_device_register() fails, the 'device_obj' is freed in ++ * vmbus_device_release() as called by device_unregister() in the ++ * error path of vmbus_device_register(). In the outside error ++ * path, there's no need to free it. + */ + ret = vmbus_device_register(newchannel->device_obj); + + if (ret != 0) { + pr_err("unable to add child device object (relid %d)\n", + newchannel->offermsg.child_relid); +- kfree(newchannel->device_obj); + goto err_deq_chan; + } + +-- +2.35.1 + diff --git a/queue-5.15/drivers-hv-vmbus-fix-possible-memory-leak-in-vmbus_d.patch b/queue-5.15/drivers-hv-vmbus-fix-possible-memory-leak-in-vmbus_d.patch new file mode 100644 index 00000000000..504a7d473e2 --- /dev/null +++ b/queue-5.15/drivers-hv-vmbus-fix-possible-memory-leak-in-vmbus_d.patch @@ -0,0 +1,41 @@ +From ce7ef71d232ded7c223de2e598f0c11cb49e6ed5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 16:11:35 +0800 +Subject: Drivers: hv: vmbus: fix possible memory leak in + vmbus_device_register() + +From: Yang Yingliang + +[ Upstream commit 25c94b051592c010abe92c85b0485f1faedc83f3 ] + +If device_register() returns error in vmbus_device_register(), +the name allocated by dev_set_name() must be freed. As comment +of device_register() says, it should use put_device() to give +up the reference in the error path. So fix this by calling +put_device(), then the name can be freed in kobject_cleanup(). + +Fixes: 09d50ff8a233 ("Staging: hv: make the Hyper-V virtual bus code build") +Signed-off-by: Yang Yingliang +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20221119081135.1564691-3-yangyingliang@huawei.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + drivers/hv/vmbus_drv.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index ecfc299834e1..b906a3a7941c 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -2109,6 +2109,7 @@ int vmbus_device_register(struct hv_device *child_device_obj) + ret = device_register(&child_device_obj->device); + if (ret) { + pr_err("Unable to register child device\n"); ++ put_device(&child_device_obj->device); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/fs-do-not-update-freeing-inode-i_io_list.patch b/queue-5.15/fs-do-not-update-freeing-inode-i_io_list.patch new file mode 100644 index 00000000000..e692f68cc35 --- /dev/null +++ b/queue-5.15/fs-do-not-update-freeing-inode-i_io_list.patch @@ -0,0 +1,84 @@ +From eb690857b72ef6d06fd76cee6527446266934ba4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 20:20:01 +0000 +Subject: fs: do not update freeing inode i_io_list + +From: Svyatoslav Feldsherov + +[ Upstream commit 4e3c51f4e805291b057d12f5dda5aeb50a538dc4 ] + +After commit cbfecb927f42 ("fs: record I_DIRTY_TIME even if inode +already has I_DIRTY_INODE") writeback_single_inode can push inode with +I_DIRTY_TIME set to b_dirty_time list. In case of freeing inode with +I_DIRTY_TIME set this can happen after deletion of inode from i_io_list +at evict. Stack trace is following. + +evict +fat_evict_inode +fat_truncate_blocks +fat_flush_inodes +writeback_inode +sync_inode_metadata(inode, sync=0) +writeback_single_inode(inode, wbc) <- wbc->sync_mode == WB_SYNC_NONE + +This will lead to use after free in flusher thread. + +Similar issue can be triggered if writeback_single_inode in the +stack trace update inode->i_io_list. Add explicit check to avoid it. + +Fixes: cbfecb927f42 ("fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE") +Reported-by: syzbot+6ba92bd00d5093f7e371@syzkaller.appspotmail.com +Reviewed-by: Jan Kara +Signed-off-by: Svyatoslav Feldsherov +Link: https://lore.kernel.org/r/20221115202001.324188-1-feldsherov@google.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/fs-writeback.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c +index 2a27f0256fa3..f4a5a0c2858a 100644 +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -1739,18 +1739,26 @@ static int writeback_single_inode(struct inode *inode, + wb = inode_to_wb_and_lock_list(inode); + spin_lock(&inode->i_lock); + /* +- * If the inode is now fully clean, then it can be safely removed from +- * its writeback list (if any). Otherwise the flusher threads are +- * responsible for the writeback lists. ++ * If the inode is freeing, its i_io_list shoudn't be updated ++ * as it can be finally deleted at this moment. + */ +- if (!(inode->i_state & I_DIRTY_ALL)) +- inode_cgwb_move_to_attached(inode, wb); +- else if (!(inode->i_state & I_SYNC_QUEUED)) { +- if ((inode->i_state & I_DIRTY)) +- redirty_tail_locked(inode, wb); +- else if (inode->i_state & I_DIRTY_TIME) { +- inode->dirtied_when = jiffies; +- inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); ++ if (!(inode->i_state & I_FREEING)) { ++ /* ++ * If the inode is now fully clean, then it can be safely ++ * removed from its writeback list (if any). Otherwise the ++ * flusher threads are responsible for the writeback lists. ++ */ ++ if (!(inode->i_state & I_DIRTY_ALL)) ++ inode_cgwb_move_to_attached(inode, wb); ++ else if (!(inode->i_state & I_SYNC_QUEUED)) { ++ if ((inode->i_state & I_DIRTY)) ++ redirty_tail_locked(inode, wb); ++ else if (inode->i_state & I_DIRTY_TIME) { ++ inode->dirtied_when = jiffies; ++ inode_io_list_move_locked(inode, ++ wb, ++ &wb->b_dirty_time); ++ } + } + } + +-- +2.35.1 + diff --git a/queue-5.15/iavf-do-not-restart-tx-queues-after-reset-task-failu.patch b/queue-5.15/iavf-do-not-restart-tx-queues-after-reset-task-failu.patch new file mode 100644 index 00000000000..3d0a0e0c339 --- /dev/null +++ b/queue-5.15/iavf-do-not-restart-tx-queues-after-reset-task-failu.patch @@ -0,0 +1,149 @@ +From 68793f1fd45d1ab21eee9bc662311f9fed97c64c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 11:25:02 +0100 +Subject: iavf: Do not restart Tx queues after reset task failure + +From: Ivan Vecera + +[ Upstream commit 08f1c147b7265245d67321585c68a27e990e0c4b ] + +After commit aa626da947e9 ("iavf: Detach device during reset task") +the device is detached during reset task and re-attached at its end. +The problem occurs when reset task fails because Tx queues are +restarted during device re-attach and this leads later to a crash. + +To resolve this issue properly close the net device in cause of +failure in reset task to avoid restarting of tx queues at the end. +Also replace the hacky manipulation with IFF_UP flag by device close +that clears properly both IFF_UP and __LINK_STATE_START flags. +In these case iavf_close() does not do anything because the adapter +state is already __IAVF_DOWN. + +Reproducer: +1) Run some Tx traffic (e.g. iperf3) over iavf interface +2) Set VF trusted / untrusted in loop + +[root@host ~]# cat repro.sh + +PF=enp65s0f0 +IF=${PF}v0 + +ip link set up $IF +ip addr add 192.168.0.2/24 dev $IF +sleep 1 + +iperf3 -c 192.168.0.1 -t 600 --logfile /dev/null & +sleep 2 + +while :; do + ip link set $PF vf 0 trust on + ip link set $PF vf 0 trust off +done +[root@host ~]# ./repro.sh + +Result: +[ 2006.650969] iavf 0000:41:01.0: Failed to init adminq: -53 +[ 2006.675662] ice 0000:41:00.0: VF 0 is now trusted +[ 2006.689997] iavf 0000:41:01.0: Reset task did not complete, VF disabled +[ 2006.696611] iavf 0000:41:01.0: failed to allocate resources during reinit +[ 2006.703209] ice 0000:41:00.0: VF 0 is now untrusted +[ 2006.737011] ice 0000:41:00.0: VF 0 is now trusted +[ 2006.764536] ice 0000:41:00.0: VF 0 is now untrusted +[ 2006.768919] BUG: kernel NULL pointer dereference, address: 0000000000000b4a +[ 2006.776358] #PF: supervisor read access in kernel mode +[ 2006.781488] #PF: error_code(0x0000) - not-present page +[ 2006.786620] PGD 0 P4D 0 +[ 2006.789152] Oops: 0000 [#1] PREEMPT SMP NOPTI +[ 2006.792903] ice 0000:41:00.0: VF 0 is now trusted +[ 2006.793501] CPU: 4 PID: 0 Comm: swapper/4 Kdump: loaded Not tainted 6.1.0-rc3+ #2 +[ 2006.805668] Hardware name: Abacus electric, s.r.o. - servis@abacus.cz Super Server/H12SSW-iN, BIOS 2.4 04/13/2022 +[ 2006.815915] RIP: 0010:iavf_xmit_frame_ring+0x96/0xf70 [iavf] +[ 2006.821028] ice 0000:41:00.0: VF 0 is now untrusted +[ 2006.821572] Code: 48 83 c1 04 48 c1 e1 04 48 01 f9 48 83 c0 10 6b 50 f8 55 c1 ea 14 45 8d 64 14 01 48 39 c8 75 eb 41 83 fc 07 0f 8f e9 08 00 00 <0f> b7 45 4a 0f b7 55 48 41 8d 74 24 05 31 c9 66 39 d0 0f 86 da 00 +[ 2006.845181] RSP: 0018:ffffb253004bc9e8 EFLAGS: 00010293 +[ 2006.850397] RAX: ffff9d154de45b00 RBX: ffff9d15497d52e8 RCX: ffff9d154de45b00 +[ 2006.856327] ice 0000:41:00.0: VF 0 is now trusted +[ 2006.857523] RDX: 0000000000000000 RSI: 00000000000005a8 RDI: ffff9d154de45ac0 +[ 2006.857525] RBP: 0000000000000b00 R08: ffff9d159cb010ac R09: 0000000000000001 +[ 2006.857526] R10: ffff9d154de45940 R11: 0000000000000000 R12: 0000000000000002 +[ 2006.883600] R13: ffff9d1770838dc0 R14: 0000000000000000 R15: ffffffffc07b8380 +[ 2006.885840] ice 0000:41:00.0: VF 0 is now untrusted +[ 2006.890725] FS: 0000000000000000(0000) GS:ffff9d248e900000(0000) knlGS:0000000000000000 +[ 2006.890727] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 2006.909419] CR2: 0000000000000b4a CR3: 0000000c39c10002 CR4: 0000000000770ee0 +[ 2006.916543] PKRU: 55555554 +[ 2006.918254] ice 0000:41:00.0: VF 0 is now trusted +[ 2006.919248] Call Trace: +[ 2006.919250] +[ 2006.919252] dev_hard_start_xmit+0x9e/0x1f0 +[ 2006.932587] sch_direct_xmit+0xa0/0x370 +[ 2006.936424] __dev_queue_xmit+0x7af/0xd00 +[ 2006.940429] ip_finish_output2+0x26c/0x540 +[ 2006.944519] ip_output+0x71/0x110 +[ 2006.947831] ? __ip_finish_output+0x2b0/0x2b0 +[ 2006.952180] __ip_queue_xmit+0x16d/0x400 +[ 2006.952721] ice 0000:41:00.0: VF 0 is now untrusted +[ 2006.956098] __tcp_transmit_skb+0xa96/0xbf0 +[ 2006.965148] __tcp_retransmit_skb+0x174/0x860 +[ 2006.969499] ? cubictcp_cwnd_event+0x40/0x40 +[ 2006.973769] tcp_retransmit_skb+0x14/0xb0 +... + +Fixes: aa626da947e9 ("iavf: Detach device during reset task") +Cc: Jacob Keller +Cc: Patryk Piotrowski +Cc: SlawomirX Laba +Signed-off-by: Ivan Vecera +Reviewed-by: Jacob Keller +Reviewed-by: Leon Romanovsky +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 493d3c407d4f..d6aa1805c55b 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2270,7 +2270,6 @@ static void iavf_disable_vf(struct iavf_adapter *adapter) + iavf_free_queues(adapter); + memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE); + iavf_shutdown_adminq(&adapter->hw); +- adapter->netdev->flags &= ~IFF_UP; + adapter->flags &= ~IAVF_FLAG_RESET_PENDING; + iavf_change_state(adapter, __IAVF_DOWN); + wake_up(&adapter->down_waitqueue); +@@ -2369,6 +2368,11 @@ static void iavf_reset_task(struct work_struct *work) + iavf_disable_vf(adapter); + mutex_unlock(&adapter->client_lock); + mutex_unlock(&adapter->crit_lock); ++ if (netif_running(netdev)) { ++ rtnl_lock(); ++ dev_close(netdev); ++ rtnl_unlock(); ++ } + return; /* Do not attempt to reinit. It's dead, Jim. */ + } + +@@ -2504,6 +2508,16 @@ static void iavf_reset_task(struct work_struct *work) + + mutex_unlock(&adapter->client_lock); + mutex_unlock(&adapter->crit_lock); ++ ++ if (netif_running(netdev)) { ++ /* Close device to ensure that Tx queues will not be started ++ * during netif_device_attach() at the end of the reset task. ++ */ ++ rtnl_lock(); ++ dev_close(netdev); ++ rtnl_unlock(); ++ } ++ + dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n"); + reset_finish: + rtnl_lock(); +-- +2.35.1 + diff --git a/queue-5.15/iavf-fix-a-crash-during-reset-task.patch b/queue-5.15/iavf-fix-a-crash-during-reset-task.patch new file mode 100644 index 00000000000..df3719257e7 --- /dev/null +++ b/queue-5.15/iavf-fix-a-crash-during-reset-task.patch @@ -0,0 +1,95 @@ +From 97b47c33f46d5bba1543bd6e941fe9fc72aa671c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 10:35:34 +0100 +Subject: iavf: Fix a crash during reset task + +From: Ivan Vecera + +[ Upstream commit c678669d6b13b77de3b99b97526aaf23c3088d0a ] + +Recent commit aa626da947e9 ("iavf: Detach device during reset task") +removed netif_tx_stop_all_queues() with an assumption that Tx queues +are already stopped by netif_device_detach() in the beginning of +reset task. This assumption is incorrect because during reset +task a potential link event can start Tx queues again. +Revert this change to fix this issue. + +Reproducer: +1. Run some Tx traffic (e.g. iperf3) over iavf interface +2. Switch MTU of this interface in a loop + +[root@host ~]# cat repro.sh + +IF=enp2s0f0v0 + +iperf3 -c 192.168.0.1 -t 600 --logfile /dev/null & +sleep 2 + +while :; do + for i in 1280 1500 2000 900 ; do + ip link set $IF mtu $i + sleep 2 + done +done +[root@host ~]# ./repro.sh + +Result: +[ 306.199917] iavf 0000:02:02.0 enp2s0f0v0: NIC Link is Up Speed is 40 Gbps Full Duplex +[ 308.205944] iavf 0000:02:02.0 enp2s0f0v0: NIC Link is Up Speed is 40 Gbps Full Duplex +[ 310.103223] BUG: kernel NULL pointer dereference, address: 0000000000000008 +[ 310.110179] #PF: supervisor write access in kernel mode +[ 310.115396] #PF: error_code(0x0002) - not-present page +[ 310.120526] PGD 0 P4D 0 +[ 310.123057] Oops: 0002 [#1] PREEMPT SMP NOPTI +[ 310.127408] CPU: 24 PID: 183 Comm: kworker/u64:9 Kdump: loaded Not tainted 6.1.0-rc3+ #2 +[ 310.135485] Hardware name: Abacus electric, s.r.o. - servis@abacus.cz Super Server/H12SSW-iN, BIOS 2.4 04/13/2022 +[ 310.145728] Workqueue: iavf iavf_reset_task [iavf] +[ 310.150520] RIP: 0010:iavf_xmit_frame_ring+0xd1/0xf70 [iavf] +[ 310.156180] Code: d0 0f 86 da 00 00 00 83 e8 01 0f b7 fa 29 f8 01 c8 39 c6 0f 8f a0 08 00 00 48 8b 45 20 48 8d 14 92 bf 01 00 00 00 4c 8d 3c d0 <49> 89 5f 08 8b 43 70 66 41 89 7f 14 41 89 47 10 f6 83 82 00 00 00 +[ 310.174918] RSP: 0018:ffffbb5f0082caa0 EFLAGS: 00010293 +[ 310.180137] RAX: 0000000000000000 RBX: ffff92345471a6e8 RCX: 0000000000000200 +[ 310.187259] RDX: 0000000000000000 RSI: 000000000000000d RDI: 0000000000000001 +[ 310.194385] RBP: ffff92341d249000 R08: ffff92434987fcac R09: 0000000000000001 +[ 310.201509] R10: 0000000011f683b9 R11: 0000000011f50641 R12: 0000000000000008 +[ 310.208631] R13: ffff923447500000 R14: 0000000000000000 R15: 0000000000000000 +[ 310.215756] FS: 0000000000000000(0000) GS:ffff92434ee00000(0000) knlGS:0000000000000000 +[ 310.223835] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 310.229572] CR2: 0000000000000008 CR3: 0000000fbc210004 CR4: 0000000000770ee0 +[ 310.236696] PKRU: 55555554 +[ 310.239399] Call Trace: +[ 310.241844] +[ 310.243855] ? dst_alloc+0x5b/0xb0 +[ 310.247260] dev_hard_start_xmit+0x9e/0x1f0 +[ 310.251439] sch_direct_xmit+0xa0/0x370 +[ 310.255276] __qdisc_run+0x13e/0x580 +[ 310.258848] __dev_queue_xmit+0x431/0xd00 +[ 310.262851] ? selinux_ip_postroute+0x147/0x3f0 +[ 310.267377] ip_finish_output2+0x26c/0x540 + +Fixes: aa626da947e9 ("iavf: Detach device during reset task") +Cc: Jacob Keller +Cc: Patryk Piotrowski +Cc: SlawomirX Laba +Signed-off-by: Ivan Vecera +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 629ebdfa48b8..493d3c407d4f 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -2381,6 +2381,7 @@ static void iavf_reset_task(struct work_struct *work) + + if (running) { + netif_carrier_off(netdev); ++ netif_tx_stop_all_queues(netdev); + adapter->link_up = false; + iavf_napi_disable_all(adapter); + } +-- +2.35.1 + diff --git a/queue-5.15/iavf-fix-race-condition-between-iavf_shutdown-and-ia.patch b/queue-5.15/iavf-fix-race-condition-between-iavf_shutdown-and-ia.patch new file mode 100644 index 00000000000..85a5868d483 --- /dev/null +++ b/queue-5.15/iavf-fix-race-condition-between-iavf_shutdown-and-ia.patch @@ -0,0 +1,66 @@ +From 4086862343363828675eaae5cc52ec94b86da71d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 14:00:03 +0100 +Subject: iavf: Fix race condition between iavf_shutdown and iavf_remove + +From: Slawomir Laba + +[ Upstream commit a8417330f8a57275ed934293e832982b6d882713 ] + +Fix a deadlock introduced by commit +974578017fc1 ("iavf: Add waiting so the port is initialized in remove") +due to race condition between iavf_shutdown and iavf_remove, where +iavf_remove stucks forever in while loop since iavf_shutdown already +set __IAVF_REMOVE adapter state. + +Fix this by checking if the __IAVF_IN_REMOVE_TASK has already been +set and return if so. + +Fixes: 974578017fc1 ("iavf: Add waiting so the port is initialized in remove") +Signed-off-by: Slawomir Laba +Signed-off-by: Mateusz Palczewski +Tested-by: Marek Szlosek +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index d6aa1805c55b..4b2e99be7ef5 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -4189,23 +4189,21 @@ static int __maybe_unused iavf_resume(struct device *dev_d) + static void iavf_remove(struct pci_dev *pdev) + { + struct iavf_adapter *adapter = iavf_pdev_to_adapter(pdev); +- struct net_device *netdev = adapter->netdev; + struct iavf_fdir_fltr *fdir, *fdirtmp; + struct iavf_vlan_filter *vlf, *vlftmp; ++ struct iavf_cloud_filter *cf, *cftmp; + struct iavf_adv_rss *rss, *rsstmp; + struct iavf_mac_filter *f, *ftmp; +- struct iavf_cloud_filter *cf, *cftmp; +- struct iavf_hw *hw = &adapter->hw; ++ struct net_device *netdev; ++ struct iavf_hw *hw; + int err; + +- /* When reboot/shutdown is in progress no need to do anything +- * as the adapter is already REMOVE state that was set during +- * iavf_shutdown() callback. +- */ +- if (adapter->state == __IAVF_REMOVE) ++ netdev = adapter->netdev; ++ hw = &adapter->hw; ++ ++ if (test_and_set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) + return; + +- set_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section); + /* Wait until port initialization is complete. + * There are flows where register/unregister netdev may race. + */ +-- +2.35.1 + diff --git a/queue-5.15/ipv4-fix-error-return-code-in-fib_table_insert.patch b/queue-5.15/ipv4-fix-error-return-code-in-fib_table_insert.patch new file mode 100644 index 00000000000..7634733eda1 --- /dev/null +++ b/queue-5.15/ipv4-fix-error-return-code-in-fib_table_insert.patch @@ -0,0 +1,40 @@ +From 65bff21f6d4e5a134969c86de522b2cc800a169e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 15:28:38 +0800 +Subject: ipv4: Fix error return code in fib_table_insert() + +From: Ziyang Xuan + +[ Upstream commit 568fe84940ac0e4e0b2cd7751b8b4911f7b9c215 ] + +In fib_table_insert(), if the alias was already inserted, but node not +exist, the error code should be set before return from error handling path. + +Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table") +Signed-off-by: Ziyang Xuan +Link: https://lore.kernel.org/r/20221120072838.2167047-1-william.xuanziyang@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/fib_trie.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c +index 19c6e7b93d3d..52f9f69f57b3 100644 +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1375,8 +1375,10 @@ int fib_table_insert(struct net *net, struct fib_table *tb, + + /* The alias was already inserted, so the node must exist. */ + l = l ? l : fib_find_node(t, &tp, key); +- if (WARN_ON_ONCE(!l)) ++ if (WARN_ON_ONCE(!l)) { ++ err = -ENOENT; + goto out_free_new_fa; ++ } + + if (fib_find_alias(&l->leaf, new_fa->fa_slen, 0, 0, tb->tb_id, true) == + new_fa) { +-- +2.35.1 + diff --git a/queue-5.15/macsec-fix-invalid-error-code-set.patch b/queue-5.15/macsec-fix-invalid-error-code-set.patch new file mode 100644 index 00000000000..8645a53679a --- /dev/null +++ b/queue-5.15/macsec-fix-invalid-error-code-set.patch @@ -0,0 +1,38 @@ +From dd7b3ddd383326e20d3fdd15754085321670d762 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 09:12:49 +0800 +Subject: macsec: Fix invalid error code set + +From: YueHaibing + +[ Upstream commit 7cef6b73fba96abef731a53501924fc3c4a0f947 ] + +'ret' is defined twice in macsec_changelink(), when it is set in macsec_is_offloaded +case, it will be invalid before return. + +Fixes: 3cf3227a21d1 ("net: macsec: hardware offloading infrastructure") +Signed-off-by: YueHaibing +Reviewed-by: Saeed Mahameed +Reviewed-by: Antoine Tenart +Link: https://lore.kernel.org/r/20221118011249.48112-1-yuehaibing@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/macsec.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index f1961d7f9db2..aa9d0dfeda5a 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -3808,7 +3808,6 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[], + if (macsec_is_offloaded(macsec)) { + const struct macsec_ops *ops; + struct macsec_context ctx; +- int ret; + + ops = macsec_get_ops(netdev_priv(dev), &ctx); + if (!ops) { +-- +2.35.1 + diff --git a/queue-5.15/net-dsa-sja1105-disallow-c45-transactions-on-the-bas.patch b/queue-5.15/net-dsa-sja1105-disallow-c45-transactions-on-the-bas.patch new file mode 100644 index 00000000000..a1230c278bc --- /dev/null +++ b/queue-5.15/net-dsa-sja1105-disallow-c45-transactions-on-the-bas.patch @@ -0,0 +1,71 @@ +From ecff6accce6d8d1905404f5838d5b9c54f387c6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 12:06:53 +0200 +Subject: net: dsa: sja1105: disallow C45 transactions on the BASE-TX MDIO bus + +From: Vladimir Oltean + +[ Upstream commit 24deec6b9e4a051635f75777844ffc184644fec9 ] + +You'd think people know that the internal 100BASE-TX PHY on the SJA1110 +responds only to clause 22 MDIO transactions, but they don't :) + +When a clause 45 transaction is attempted, sja1105_base_tx_mdio_read() +and sja1105_base_tx_mdio_write() don't expect "reg" to contain bit 30 +set (MII_ADDR_C45) and pack this value into the SPI transaction buffer. + +But the field in the SPI buffer has a width smaller than 30 bits, so we +see this confusing message from the packing() API rather than a proper +rejection of C45 transactions: + +Call trace: + dump_stack+0x1c/0x38 + sja1105_pack+0xbc/0xc0 [sja1105] + sja1105_xfer+0x114/0x2b0 [sja1105] + sja1105_xfer_u32+0x44/0xf4 [sja1105] + sja1105_base_tx_mdio_read+0x44/0x7c [sja1105] + mdiobus_read+0x44/0x80 + get_phy_c45_ids+0x70/0x234 + get_phy_device+0x68/0x15c + fwnode_mdiobus_register_phy+0x74/0x240 + of_mdiobus_register+0x13c/0x380 + sja1105_mdiobus_register+0x368/0x490 [sja1105] + sja1105_setup+0x94/0x119c [sja1105] +Cannot store 401d2405 inside bits 24-4 (would truncate) + +Fixes: 5a8f09748ee7 ("net: dsa: sja1105: register the MDIO buses for 100base-T1 and 100base-TX") +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/sja1105/sja1105_mdio.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c +index 215dd17ca790..4059fcc8c832 100644 +--- a/drivers/net/dsa/sja1105/sja1105_mdio.c ++++ b/drivers/net/dsa/sja1105/sja1105_mdio.c +@@ -256,6 +256,9 @@ static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg) + u32 tmp; + int rc; + ++ if (reg & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ + rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg, + &tmp, NULL); + if (rc < 0) +@@ -272,6 +275,9 @@ static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg, + const struct sja1105_regs *regs = priv->info->regs; + u32 tmp = val; + ++ if (reg & MII_ADDR_C45) ++ return -EOPNOTSUPP; ++ + return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg, + &tmp, NULL); + } +-- +2.35.1 + diff --git a/queue-5.15/net-enetc-cache-accesses-to-priv-si-hw.patch b/queue-5.15/net-enetc-cache-accesses-to-priv-si-hw.patch new file mode 100644 index 00000000000..e9e64401a46 --- /dev/null +++ b/queue-5.15/net-enetc-cache-accesses-to-priv-si-hw.patch @@ -0,0 +1,377 @@ +From c79253ffb79dbca1713097c6eb42bf14bd2cf7a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 12:52:02 +0300 +Subject: net: enetc: cache accesses to &priv->si->hw + +From: Vladimir Oltean + +[ Upstream commit 715bf2610f1d1adf3d4f9b7b3dd729984ec4270a ] + +The &priv->si->hw construct dereferences 2 pointers and makes lines +longer than they need to be, in turn making the code harder to read. + +Replace &priv->si->hw accesses with a "hw" variable when there are 2 or +more accesses within a function that dereference this. This includes +loops, since &priv->si->hw is a loop invariant. + +Signed-off-by: Vladimir Oltean +Signed-off-by: Jakub Kicinski +Stable-dep-of: 290b5fe096e7 ("net: enetc: preserve TX ring priority across reconfiguration") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 28 +++++---- + drivers/net/ethernet/freescale/enetc/enetc.h | 9 +-- + .../net/ethernet/freescale/enetc/enetc_qos.c | 60 +++++++++---------- + 3 files changed, 49 insertions(+), 48 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 77d765809c1e..0ced688bf9ba 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1831,13 +1831,14 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) + + static void enetc_setup_bdrs(struct enetc_ndev_priv *priv) + { ++ struct enetc_hw *hw = &priv->si->hw; + int i; + + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_setup_txbdr(&priv->si->hw, priv->tx_ring[i]); ++ enetc_setup_txbdr(hw, priv->tx_ring[i]); + + for (i = 0; i < priv->num_rx_rings; i++) +- enetc_setup_rxbdr(&priv->si->hw, priv->rx_ring[i]); ++ enetc_setup_rxbdr(hw, priv->rx_ring[i]); + } + + static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring) +@@ -1870,13 +1871,14 @@ static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) + + static void enetc_clear_bdrs(struct enetc_ndev_priv *priv) + { ++ struct enetc_hw *hw = &priv->si->hw; + int i; + + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_clear_txbdr(&priv->si->hw, priv->tx_ring[i]); ++ enetc_clear_txbdr(hw, priv->tx_ring[i]); + + for (i = 0; i < priv->num_rx_rings; i++) +- enetc_clear_rxbdr(&priv->si->hw, priv->rx_ring[i]); ++ enetc_clear_rxbdr(hw, priv->rx_ring[i]); + + udelay(1); + } +@@ -1884,13 +1886,13 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv) + static int enetc_setup_irqs(struct enetc_ndev_priv *priv) + { + struct pci_dev *pdev = priv->si->pdev; ++ struct enetc_hw *hw = &priv->si->hw; + int i, j, err; + + for (i = 0; i < priv->bdr_int_num; i++) { + int irq = pci_irq_vector(pdev, ENETC_BDR_INT_BASE_IDX + i); + struct enetc_int_vector *v = priv->int_vector[i]; + int entry = ENETC_BDR_INT_BASE_IDX + i; +- struct enetc_hw *hw = &priv->si->hw; + + snprintf(v->name, sizeof(v->name), "%s-rxtx%d", + priv->ndev->name, i); +@@ -1978,13 +1980,14 @@ static void enetc_setup_interrupts(struct enetc_ndev_priv *priv) + + static void enetc_clear_interrupts(struct enetc_ndev_priv *priv) + { ++ struct enetc_hw *hw = &priv->si->hw; + int i; + + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_txbdr_wr(&priv->si->hw, i, ENETC_TBIER, 0); ++ enetc_txbdr_wr(hw, i, ENETC_TBIER, 0); + + for (i = 0; i < priv->num_rx_rings; i++) +- enetc_rxbdr_wr(&priv->si->hw, i, ENETC_RBIER, 0); ++ enetc_rxbdr_wr(hw, i, ENETC_RBIER, 0); + } + + static int enetc_phylink_connect(struct net_device *ndev) +@@ -2151,6 +2154,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct tc_mqprio_qopt *mqprio = type_data; ++ struct enetc_hw *hw = &priv->si->hw; + struct enetc_bdr *tx_ring; + int num_stack_tx_queues; + u8 num_tc; +@@ -2167,7 +2171,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) + /* Reset all ring priorities to 0 */ + for (i = 0; i < priv->num_tx_rings; i++) { + tx_ring = priv->tx_ring[i]; +- enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, 0); ++ enetc_set_bdr_prio(hw, tx_ring->index, 0); + } + + return 0; +@@ -2186,7 +2190,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) + */ + for (i = 0; i < num_tc; i++) { + tx_ring = priv->tx_ring[i]; +- enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, i); ++ enetc_set_bdr_prio(hw, tx_ring->index, i); + } + + /* Reset the number of netdev queues based on the TC count */ +@@ -2296,19 +2300,21 @@ static int enetc_set_rss(struct net_device *ndev, int en) + static void enetc_enable_rxvlan(struct net_device *ndev, bool en) + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); ++ struct enetc_hw *hw = &priv->si->hw; + int i; + + for (i = 0; i < priv->num_rx_rings; i++) +- enetc_bdr_enable_rxvlan(&priv->si->hw, i, en); ++ enetc_bdr_enable_rxvlan(hw, i, en); + } + + static void enetc_enable_txvlan(struct net_device *ndev, bool en) + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); ++ struct enetc_hw *hw = &priv->si->hw; + int i; + + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_bdr_enable_txvlan(&priv->si->hw, i, en); ++ enetc_bdr_enable_txvlan(hw, i, en); + } + + void enetc_set_features(struct net_device *ndev, netdev_features_t features) +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h +index f304cdb854ec..7ec807bd9828 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.h ++++ b/drivers/net/ethernet/freescale/enetc/enetc.h +@@ -423,19 +423,20 @@ int enetc_set_psfp(struct net_device *ndev, bool en); + + static inline void enetc_get_max_cap(struct enetc_ndev_priv *priv) + { ++ struct enetc_hw *hw = &priv->si->hw; + u32 reg; + +- reg = enetc_port_rd(&priv->si->hw, ENETC_PSIDCAPR); ++ reg = enetc_port_rd(hw, ENETC_PSIDCAPR); + priv->psfp_cap.max_streamid = reg & ENETC_PSIDCAPR_MSK; + /* Port stream filter capability */ +- reg = enetc_port_rd(&priv->si->hw, ENETC_PSFCAPR); ++ reg = enetc_port_rd(hw, ENETC_PSFCAPR); + priv->psfp_cap.max_psfp_filter = reg & ENETC_PSFCAPR_MSK; + /* Port stream gate capability */ +- reg = enetc_port_rd(&priv->si->hw, ENETC_PSGCAPR); ++ reg = enetc_port_rd(hw, ENETC_PSGCAPR); + priv->psfp_cap.max_psfp_gate = (reg & ENETC_PSGCAPR_SGIT_MSK); + priv->psfp_cap.max_psfp_gatelist = (reg & ENETC_PSGCAPR_GCL_MSK) >> 16; + /* Port flow meter capability */ +- reg = enetc_port_rd(&priv->si->hw, ENETC_PFMCAPR); ++ reg = enetc_port_rd(hw, ENETC_PFMCAPR); + priv->psfp_cap.max_psfp_meter = reg & ENETC_PFMCAPR_MSK; + } + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +index 9fd9abad34f8..6baf2619a51e 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +@@ -17,8 +17,9 @@ static u16 enetc_get_max_gcl_len(struct enetc_hw *hw) + + void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed) + { ++ struct enetc_hw *hw = &priv->si->hw; + u32 old_speed = priv->speed; +- u32 pspeed; ++ u32 pspeed, tmp; + + if (speed == old_speed) + return; +@@ -39,10 +40,8 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed) + } + + priv->speed = speed; +- enetc_port_wr(&priv->si->hw, ENETC_PMR, +- (enetc_port_rd(&priv->si->hw, ENETC_PMR) +- & (~ENETC_PMR_PSPEED_MASK)) +- | pspeed); ++ tmp = enetc_port_rd(hw, ENETC_PMR); ++ enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed); + } + + #define ENETC_QOS_ALIGN 64 +@@ -50,6 +49,7 @@ static int enetc_setup_taprio(struct net_device *ndev, + struct tc_taprio_qopt_offload *admin_conf) + { + struct enetc_ndev_priv *priv = netdev_priv(ndev); ++ struct enetc_hw *hw = &priv->si->hw; + struct enetc_cbd cbd = {.cmd = 0}; + struct tgs_gcl_conf *gcl_config; + struct tgs_gcl_data *gcl_data; +@@ -62,15 +62,13 @@ static int enetc_setup_taprio(struct net_device *ndev, + int err; + int i; + +- if (admin_conf->num_entries > enetc_get_max_gcl_len(&priv->si->hw)) ++ if (admin_conf->num_entries > enetc_get_max_gcl_len(hw)) + return -EINVAL; + gcl_len = admin_conf->num_entries; + +- tge = enetc_rd(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET); ++ tge = enetc_rd(hw, ENETC_QBV_PTGCR_OFFSET); + if (!admin_conf->enable) { +- enetc_wr(&priv->si->hw, +- ENETC_QBV_PTGCR_OFFSET, +- tge & (~ENETC_QBV_TGE)); ++ enetc_wr(hw, ENETC_QBV_PTGCR_OFFSET, tge & ~ENETC_QBV_TGE); + + priv->active_offloads &= ~ENETC_F_QBV; + +@@ -127,14 +125,11 @@ static int enetc_setup_taprio(struct net_device *ndev, + cbd.cls = BDCR_CMD_PORT_GCL; + cbd.status_flags = 0; + +- enetc_wr(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET, +- tge | ENETC_QBV_TGE); ++ enetc_wr(hw, ENETC_QBV_PTGCR_OFFSET, tge | ENETC_QBV_TGE); + + err = enetc_send_cmd(priv->si, &cbd); + if (err) +- enetc_wr(&priv->si->hw, +- ENETC_QBV_PTGCR_OFFSET, +- tge & (~ENETC_QBV_TGE)); ++ enetc_wr(hw, ENETC_QBV_PTGCR_OFFSET, tge & ~ENETC_QBV_TGE); + + dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN, + tmp, dma); +@@ -149,6 +144,7 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) + { + struct tc_taprio_qopt_offload *taprio = type_data; + struct enetc_ndev_priv *priv = netdev_priv(ndev); ++ struct enetc_hw *hw = &priv->si->hw; + int err; + int i; + +@@ -158,16 +154,14 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) + return -EBUSY; + + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_set_bdr_prio(&priv->si->hw, +- priv->tx_ring[i]->index, ++ enetc_set_bdr_prio(hw, priv->tx_ring[i]->index, + taprio->enable ? i : 0); + + err = enetc_setup_taprio(ndev, taprio); + + if (err) + for (i = 0; i < priv->num_tx_rings; i++) +- enetc_set_bdr_prio(&priv->si->hw, +- priv->tx_ring[i]->index, ++ enetc_set_bdr_prio(hw, priv->tx_ring[i]->index, + taprio->enable ? 0 : i); + + return err; +@@ -189,7 +183,7 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + struct tc_cbs_qopt_offload *cbs = type_data; + u32 port_transmit_rate = priv->speed; + u8 tc_nums = netdev_get_num_tc(ndev); +- struct enetc_si *si = priv->si; ++ struct enetc_hw *hw = &priv->si->hw; + u32 hi_credit_bit, hi_credit_reg; + u32 max_interference_size; + u32 port_frame_max_size; +@@ -210,15 +204,15 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + * lower than this TC have been disabled. + */ + if (tc == prio_top && +- enetc_get_cbs_enable(&si->hw, prio_next)) { ++ enetc_get_cbs_enable(hw, prio_next)) { + dev_err(&ndev->dev, + "Disable TC%d before disable TC%d\n", + prio_next, tc); + return -EINVAL; + } + +- enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), 0); +- enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), 0); ++ enetc_port_wr(hw, ENETC_PTCCBSR1(tc), 0); ++ enetc_port_wr(hw, ENETC_PTCCBSR0(tc), 0); + + return 0; + } +@@ -235,13 +229,13 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + * higher than this TC have been enabled. + */ + if (tc == prio_next) { +- if (!enetc_get_cbs_enable(&si->hw, prio_top)) { ++ if (!enetc_get_cbs_enable(hw, prio_top)) { + dev_err(&ndev->dev, + "Enable TC%d first before enable TC%d\n", + prio_top, prio_next); + return -EINVAL; + } +- bw_sum += enetc_get_cbs_bw(&si->hw, prio_top); ++ bw_sum += enetc_get_cbs_bw(hw, prio_top); + } + + if (bw_sum + bw >= 100) { +@@ -250,7 +244,7 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + return -EINVAL; + } + +- enetc_port_rd(&si->hw, ENETC_PTCMSDUR(tc)); ++ enetc_port_rd(hw, ENETC_PTCMSDUR(tc)); + + /* For top prio TC, the max_interfrence_size is maxSizedFrame. + * +@@ -270,8 +264,8 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + u32 m0, ma, r0, ra; + + m0 = port_frame_max_size * 8; +- ma = enetc_port_rd(&si->hw, ENETC_PTCMSDUR(prio_top)) * 8; +- ra = enetc_get_cbs_bw(&si->hw, prio_top) * ++ ma = enetc_port_rd(hw, ENETC_PTCMSDUR(prio_top)) * 8; ++ ra = enetc_get_cbs_bw(hw, prio_top) * + port_transmit_rate * 10000ULL; + r0 = port_transmit_rate * 1000000ULL; + max_interference_size = m0 + ma + +@@ -291,10 +285,10 @@ int enetc_setup_tc_cbs(struct net_device *ndev, void *type_data) + hi_credit_reg = (u32)div_u64((ENETC_CLK * 100ULL) * hi_credit_bit, + port_transmit_rate * 1000000ULL); + +- enetc_port_wr(&si->hw, ENETC_PTCCBSR1(tc), hi_credit_reg); ++ enetc_port_wr(hw, ENETC_PTCCBSR1(tc), hi_credit_reg); + + /* Set bw register and enable this traffic class */ +- enetc_port_wr(&si->hw, ENETC_PTCCBSR0(tc), bw | ENETC_CBSE); ++ enetc_port_wr(hw, ENETC_PTCCBSR0(tc), bw | ENETC_CBSE); + + return 0; + } +@@ -304,6 +298,7 @@ int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data) + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct tc_etf_qopt_offload *qopt = type_data; + u8 tc_nums = netdev_get_num_tc(ndev); ++ struct enetc_hw *hw = &priv->si->hw; + int tc; + + if (!tc_nums) +@@ -319,12 +314,11 @@ int enetc_setup_tc_txtime(struct net_device *ndev, void *type_data) + return -EBUSY; + + /* TSD and Qbv are mutually exclusive in hardware */ +- if (enetc_rd(&priv->si->hw, ENETC_QBV_PTGCR_OFFSET) & ENETC_QBV_TGE) ++ if (enetc_rd(hw, ENETC_QBV_PTGCR_OFFSET) & ENETC_QBV_TGE) + return -EBUSY; + + priv->tx_ring[tc]->tsd_enable = qopt->enable; +- enetc_port_wr(&priv->si->hw, ENETC_PTCTSDR(tc), +- qopt->enable ? ENETC_TSDE : 0); ++ enetc_port_wr(hw, ENETC_PTCTSDR(tc), qopt->enable ? ENETC_TSDE : 0); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/net-enetc-manage-enetc_f_qbv-in-priv-active_offloads.patch b/queue-5.15/net-enetc-manage-enetc_f_qbv-in-priv-active_offloads.patch new file mode 100644 index 00000000000..4fd71fd841d --- /dev/null +++ b/queue-5.15/net-enetc-manage-enetc_f_qbv-in-priv-active_offloads.patch @@ -0,0 +1,88 @@ +From 80cdf44a5054e76c955e12725d2877615737d753 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 May 2022 19:36:14 +0300 +Subject: net: enetc: manage ENETC_F_QBV in priv->active_offloads only when + enabled + +From: Vladimir Oltean + +[ Upstream commit 32bf8e1f6fb9f6dc334b2b98dffc2e5dcd51e513 ] + +Future work in this driver would like to look at priv->active_offloads & +ENETC_F_QBV to determine whether a tc-taprio qdisc offload was +installed, but this does not produce the intended effect. + +All the other flags in priv->active_offloads are managed dynamically, +except ENETC_F_QBV which is set statically based on the probed SI capability. + +This change makes priv->active_offloads & ENETC_F_QBV really track the +presence of a tc-taprio schedule on the port. + +Some existing users, like the enetc_sched_speed_set() call from +phylink_mac_link_up(), are best kept using the old logic: the tc-taprio +offload does not re-trigger another link mode resolve, so the scheduler +needs to be functional from the get go, as long as Qbv is supported at +all on the port. So to preserve functionality there, look at the static +station interface capability from pf->si->hw_features instead. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Claudiu Manoil +Signed-off-by: Jakub Kicinski +Stable-dep-of: 290b5fe096e7 ("net: enetc: preserve TX ring priority across reconfiguration") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc_pf.c | 6 ++---- + drivers/net/ethernet/freescale/enetc/enetc_qos.c | 6 ++++++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +index 3615357cc60f..5efb079ef25f 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c +@@ -800,9 +800,6 @@ static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, + + ndev->priv_flags |= IFF_UNICAST_FLT; + +- if (si->hw_features & ENETC_SI_F_QBV) +- priv->active_offloads |= ENETC_F_QBV; +- + if (si->hw_features & ENETC_SI_F_PSFP && !enetc_psfp_enable(priv)) { + priv->active_offloads |= ENETC_F_QCI; + ndev->features |= NETIF_F_HW_TC; +@@ -1053,7 +1050,8 @@ static void enetc_pl_mac_link_up(struct phylink_config *config, + int idx; + + priv = netdev_priv(pf->si->ndev); +- if (priv->active_offloads & ENETC_F_QBV) ++ ++ if (pf->si->hw_features & ENETC_SI_F_QBV) + enetc_sched_speed_set(priv, speed); + + if (!phylink_autoneg_inband(mode) && +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +index 6b236e0fd806..9fd9abad34f8 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +@@ -71,6 +71,9 @@ static int enetc_setup_taprio(struct net_device *ndev, + enetc_wr(&priv->si->hw, + ENETC_QBV_PTGCR_OFFSET, + tge & (~ENETC_QBV_TGE)); ++ ++ priv->active_offloads &= ~ENETC_F_QBV; ++ + return 0; + } + +@@ -136,6 +139,9 @@ static int enetc_setup_taprio(struct net_device *ndev, + dma_free_coherent(&priv->si->pdev->dev, data_size + ENETC_QOS_ALIGN, + tmp, dma); + ++ if (!err) ++ priv->active_offloads |= ENETC_F_QBV; ++ + return err; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-enetc-preserve-tx-ring-priority-across-reconfigu.patch b/queue-5.15/net-enetc-preserve-tx-ring-priority-across-reconfigu.patch new file mode 100644 index 00000000000..c51e0080434 --- /dev/null +++ b/queue-5.15/net-enetc-preserve-tx-ring-priority-across-reconfigu.patch @@ -0,0 +1,126 @@ +From 028cad909de915af4d79c430cd335c10dae6e617 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 15:09:36 +0200 +Subject: net: enetc: preserve TX ring priority across reconfiguration + +From: Vladimir Oltean + +[ Upstream commit 290b5fe096e7dd0aad730d1af4f7f2d9fea43e11 ] + +In the blamed commit, a rudimentary reallocation procedure for RX buffer +descriptors was implemented, for the situation when their format changes +between normal (no PTP) and extended (PTP). + +enetc_hwtstamp_set() calls enetc_close() and enetc_open() in a sequence, +and this sequence loses information which was previously configured in +the TX BDR Mode Register, specifically via the enetc_set_bdr_prio() call. +The TX ring priority is configured by tc-mqprio and tc-taprio, and +affects important things for TSN such as the TX time of packets. The +issue manifests itself most visibly by the fact that isochron --txtime +reports premature packet transmissions when PTP is first enabled on an +enetc interface. + +Save the TX ring priority in a new field in struct enetc_bdr (occupies a +2 byte hole on arm64) in order to make this survive a ring reconfiguration. + +Fixes: 434cebabd3a2 ("enetc: Add dynamic allocation of extended Rx BD rings") +Signed-off-by: Vladimir Oltean +Reviewed-by: Alexander Lobakin +Link: https://lore.kernel.org/r/20221122130936.1704151-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 8 ++++--- + drivers/net/ethernet/freescale/enetc/enetc.h | 1 + + .../net/ethernet/freescale/enetc/enetc_qos.c | 21 ++++++++++++------- + 3 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 0ced688bf9ba..222a250fba84 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1768,7 +1768,7 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring) + /* enable Tx ints by setting pkt thr to 1 */ + enetc_txbdr_wr(hw, idx, ENETC_TBICR0, ENETC_TBICR0_ICEN | 0x1); + +- tbmr = ENETC_TBMR_EN; ++ tbmr = ENETC_TBMR_EN | ENETC_TBMR_SET_PRIO(tx_ring->prio); + if (tx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_TX) + tbmr |= ENETC_TBMR_VIH; + +@@ -2171,7 +2171,8 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) + /* Reset all ring priorities to 0 */ + for (i = 0; i < priv->num_tx_rings; i++) { + tx_ring = priv->tx_ring[i]; +- enetc_set_bdr_prio(hw, tx_ring->index, 0); ++ tx_ring->prio = 0; ++ enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio); + } + + return 0; +@@ -2190,7 +2191,8 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) + */ + for (i = 0; i < num_tc; i++) { + tx_ring = priv->tx_ring[i]; +- enetc_set_bdr_prio(hw, tx_ring->index, i); ++ tx_ring->prio = i; ++ enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio); + } + + /* Reset the number of netdev queues based on the TC count */ +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h +index 7ec807bd9828..a3b936375c56 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.h ++++ b/drivers/net/ethernet/freescale/enetc/enetc.h +@@ -91,6 +91,7 @@ struct enetc_bdr { + void __iomem *rcir; + }; + u16 index; ++ u16 prio; + int bd_count; /* # of BDs */ + int next_to_use; + int next_to_clean; +diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +index 6baf2619a51e..ba51fb381f0c 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c +@@ -145,6 +145,7 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) + struct tc_taprio_qopt_offload *taprio = type_data; + struct enetc_ndev_priv *priv = netdev_priv(ndev); + struct enetc_hw *hw = &priv->si->hw; ++ struct enetc_bdr *tx_ring; + int err; + int i; + +@@ -153,16 +154,20 @@ int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) + if (priv->tx_ring[i]->tsd_enable) + return -EBUSY; + +- for (i = 0; i < priv->num_tx_rings; i++) +- enetc_set_bdr_prio(hw, priv->tx_ring[i]->index, +- taprio->enable ? i : 0); ++ for (i = 0; i < priv->num_tx_rings; i++) { ++ tx_ring = priv->tx_ring[i]; ++ tx_ring->prio = taprio->enable ? i : 0; ++ enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio); ++ } + + err = enetc_setup_taprio(ndev, taprio); +- +- if (err) +- for (i = 0; i < priv->num_tx_rings; i++) +- enetc_set_bdr_prio(hw, priv->tx_ring[i]->index, +- taprio->enable ? 0 : i); ++ if (err) { ++ for (i = 0; i < priv->num_tx_rings; i++) { ++ tx_ring = priv->tx_ring[i]; ++ tx_ring->prio = taprio->enable ? 0 : i; ++ enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio); ++ } ++ } + + return err; + } +-- +2.35.1 + diff --git a/queue-5.15/net-ethernet-mtk_eth_soc-fix-error-handling-in-mtk_o.patch b/queue-5.15/net-ethernet-mtk_eth_soc-fix-error-handling-in-mtk_o.patch new file mode 100644 index 00000000000..14bc393baa3 --- /dev/null +++ b/queue-5.15/net-ethernet-mtk_eth_soc-fix-error-handling-in-mtk_o.patch @@ -0,0 +1,42 @@ +From d148404025b5fe07d603ca5fed1bc27db5e92bf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 19:13:56 +0800 +Subject: net: ethernet: mtk_eth_soc: fix error handling in mtk_open() + +From: Liu Jian + +[ Upstream commit f70074140524c59a0935947b06dd6cb6e1ea642d ] + +If mtk_start_dma() fails, invoke phylink_disconnect_phy() to perform +cleanup. phylink_disconnect_phy() contains the put_device action. If +phylink_disconnect_phy is not performed, the Kref of netdev will leak. + +Fixes: b8fc9f30821e ("net: ethernet: mediatek: Add basic PHYLINK support") +Signed-off-by: Liu Jian +Reviewed-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/20221117111356.161547-1-liujian56@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 8601ef26c260..cc6a5b2f24e3 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2327,8 +2327,10 @@ static int mtk_open(struct net_device *dev) + int err; + + err = mtk_start_dma(eth); +- if (err) ++ if (err) { ++ phylink_disconnect_phy(mac->phylink); + return err; ++ } + + if (eth->soc->offload_version && mtk_ppe_start(ð->ppe) == 0) + gdm_config = MTK_GDMA_TO_PPE; +-- +2.35.1 + diff --git a/queue-5.15/net-liquidio-simplify-if-expression.patch b/queue-5.15/net-liquidio-simplify-if-expression.patch new file mode 100644 index 00000000000..49dc3f6c0c8 --- /dev/null +++ b/queue-5.15/net-liquidio-simplify-if-expression.patch @@ -0,0 +1,50 @@ +From f715565f30c8842b1c0c8036cf5f2a338eb5b3bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 19:34:39 +0200 +Subject: net: liquidio: simplify if expression + +From: Leon Romanovsky + +[ Upstream commit 733d4bbf9514890eb53ebe75827bf1fb4fd25ebe ] + +Fix the warning reported by kbuild: + +cocci warnings: (new ones prefixed by >>) +>> drivers/net/ethernet/cavium/liquidio/lio_main.c:1797:54-56: WARNING !A || A && B is equivalent to !A || B + drivers/net/ethernet/cavium/liquidio/lio_main.c:1827:54-56: WARNING !A || A && B is equivalent to !A || B + +Fixes: 8979f428a4af ("net: liquidio: release resources when liquidio driver open failed") +Reported-by: kernel test robot +Signed-off-by: Leon Romanovsky +Reviewed-by: Saeed Mahameed +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cavium/liquidio/lio_main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c +index 7bd97d98afeb..ae68821dd56d 100644 +--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c ++++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c +@@ -1798,7 +1798,7 @@ static int liquidio_open(struct net_device *netdev) + + ifstate_set(lio, LIO_IFSTATE_RUNNING); + +- if (!OCTEON_CN23XX_PF(oct) || (OCTEON_CN23XX_PF(oct) && !oct->msix_on)) { ++ if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) { + ret = setup_tx_poll_fn(netdev); + if (ret) + goto err_poll; +@@ -1828,7 +1828,7 @@ static int liquidio_open(struct net_device *netdev) + return 0; + + err_rx_ctrl: +- if (!OCTEON_CN23XX_PF(oct) || (OCTEON_CN23XX_PF(oct) && !oct->msix_on)) ++ if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) + cleanup_tx_poll_fn(netdev); + err_poll: + if (lio->ptp_clock) { +-- +2.35.1 + diff --git a/queue-5.15/net-mlx4-check-retval-of-mlx4_bitmap_init.patch b/queue-5.15/net-mlx4-check-retval-of-mlx4_bitmap_init.patch new file mode 100644 index 00000000000..24b787c4c77 --- /dev/null +++ b/queue-5.15/net-mlx4-check-retval-of-mlx4_bitmap_init.patch @@ -0,0 +1,43 @@ +From a843add3d4547abe367b4017104d0fe31945a054 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 18:28:06 +0300 +Subject: net/mlx4: Check retval of mlx4_bitmap_init + +From: Peter Kosyh + +[ Upstream commit 594c61ffc77de0a197934aa0f1df9285c68801c6 ] + +If mlx4_bitmap_init fails, mlx4_bitmap_alloc_range will dereference +the NULL pointer (bitmap->table). + +Make sure, that mlx4_bitmap_alloc_range called in no error case. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d57febe1a478 ("net/mlx4: Add A0 hybrid steering") +Reviewed-by: Tariq Toukan +Signed-off-by: Peter Kosyh +Link: https://lore.kernel.org/r/20221117152806.278072-1-pkosyh@yandex.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx4/qp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c +index b149e601f673..48cfaa7eaf50 100644 +--- a/drivers/net/ethernet/mellanox/mlx4/qp.c ++++ b/drivers/net/ethernet/mellanox/mlx4/qp.c +@@ -697,7 +697,8 @@ static int mlx4_create_zones(struct mlx4_dev *dev, + err = mlx4_bitmap_init(*bitmap + k, 1, + MLX4_QP_TABLE_RAW_ETH_SIZE - 1, 0, + 0); +- mlx4_bitmap_alloc_range(*bitmap + k, 1, 1, 0); ++ if (!err) ++ mlx4_bitmap_alloc_range(*bitmap + k, 1, 1, 0); + } + + if (err) +-- +2.35.1 + diff --git a/queue-5.15/net-mlx5-do-not-query-pci-info-while-pci-disabled.patch b/queue-5.15/net-mlx5-do-not-query-pci-info-while-pci-disabled.patch new file mode 100644 index 00000000000..c96a6f123e2 --- /dev/null +++ b/queue-5.15/net-mlx5-do-not-query-pci-info-while-pci-disabled.patch @@ -0,0 +1,60 @@ +From 98d3db4477a1d4102eed01734dd30fee19bbc8ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 09:49:07 +0300 +Subject: net/mlx5: Do not query pci info while pci disabled + +From: Roy Novich + +[ Upstream commit 394164f9d5a3020a7fd719d228386d48d544ec67 ] + +The driver should not interact with PCI while PCI is disabled. Trying to +do so may result in being unable to get vital signs during PCI reset, +driver gets timed out and fails to recover. + +Fixes: fad1783a6d66 ("net/mlx5: Print more info on pci error handlers") +Signed-off-by: Roy Novich +Reviewed-by: Moshe Shemesh +Reviewed-by: Aya Levin +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index d092261e96c3..19c11d33f4b6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -1608,7 +1608,8 @@ static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, + res = state == pci_channel_io_perm_failure ? + PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; + +- mlx5_pci_trace(dev, "Exit, result = %d, %s\n", res, result2str(res)); ++ mlx5_core_info(dev, "%s Device state = %d pci_status: %d. Exit, result = %d, %s\n", ++ __func__, dev->state, dev->pci_status, res, result2str(res)); + return res; + } + +@@ -1647,7 +1648,8 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + int err; + +- mlx5_pci_trace(dev, "Enter\n"); ++ mlx5_core_info(dev, "%s Device state = %d pci_status: %d. Enter\n", ++ __func__, dev->state, dev->pci_status); + + err = mlx5_pci_enable_device(dev); + if (err) { +@@ -1669,7 +1671,8 @@ static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) + + res = PCI_ERS_RESULT_RECOVERED; + out: +- mlx5_pci_trace(dev, "Exit, err = %d, result = %d, %s\n", err, res, result2str(res)); ++ mlx5_core_info(dev, "%s Device state = %d pci_status: %d. Exit, err = %d, result = %d, %s\n", ++ __func__, dev->state, dev->pci_status, err, res, result2str(res)); + return res; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-mlx5-fix-fw-tracer-timestamp-calculation.patch b/queue-5.15/net-mlx5-fix-fw-tracer-timestamp-calculation.patch new file mode 100644 index 00000000000..4de25ca6a15 --- /dev/null +++ b/queue-5.15/net-mlx5-fix-fw-tracer-timestamp-calculation.patch @@ -0,0 +1,38 @@ +From 617956ecb5acc7d6f3872c9b794294542be7e4ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Oct 2022 12:25:59 +0300 +Subject: net/mlx5: Fix FW tracer timestamp calculation + +From: Moshe Shemesh + +[ Upstream commit 61db3d7b99a367416e489ccf764cc5f9b00d62a1 ] + +Fix a bug in calculation of FW tracer timestamp. Decreasing one in the +calculation should effect only bits 52_7 and not effect bits 6_0 of the +timestamp, otherwise bits 6_0 are always set in this calculation. + +Fixes: 70dd6fdb8987 ("net/mlx5: FW tracer, parse traces and kernel tracing support") +Signed-off-by: Moshe Shemesh +Reviewed-by: Feras Daoud +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +index ea46152816f9..326e0b170e36 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +@@ -638,7 +638,7 @@ static void mlx5_tracer_handle_timestamp_trace(struct mlx5_fw_tracer *tracer, + trace_timestamp = (timestamp_event.timestamp & MASK_52_7) | + (str_frmt->timestamp & MASK_6_0); + else +- trace_timestamp = ((timestamp_event.timestamp & MASK_52_7) - 1) | ++ trace_timestamp = ((timestamp_event.timestamp - 1) & MASK_52_7) | + (str_frmt->timestamp & MASK_6_0); + + mlx5_tracer_print_trace(str_frmt, dev, trace_timestamp); +-- +2.35.1 + diff --git a/queue-5.15/net-mlx5-fix-handling-of-entry-refcount-when-command.patch b/queue-5.15/net-mlx5-fix-handling-of-entry-refcount-when-command.patch new file mode 100644 index 00000000000..647eff896dc --- /dev/null +++ b/queue-5.15/net-mlx5-fix-handling-of-entry-refcount-when-command.patch @@ -0,0 +1,62 @@ +From 38d746cf7a968809d386119b373a05cf9f6aafbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 09:07:20 +0200 +Subject: net/mlx5: Fix handling of entry refcount when command is not issued + to FW + +From: Moshe Shemesh + +[ Upstream commit aaf2e65cac7f2e1ae729c2fbc849091df9699f96 ] + +In case command interface is down, or the command is not allowed, driver +did not increment the entry refcount, but might have decrement as part +of forced completion handling. + +Fix that by always increment and decrement the refcount to make it +symmetric for all flows. + +Fixes: 50b2412b7e78 ("net/mlx5: Avoid possible free of command entry while timeout comp handler") +Signed-off-by: Eran Ben Elisha +Signed-off-by: Moshe Shemesh +Reported-by: Jack Wang +Tested-by: Jack Wang +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +index 98ca5d1ed45d..85190f2f4d50 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +@@ -971,6 +971,7 @@ static void cmd_work_handler(struct work_struct *work) + cmd_ent_get(ent); + set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state); + ++ cmd_ent_get(ent); /* for the _real_ FW event on completion */ + /* Skip sending command to fw if internal error */ + if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, ent->op)) { + u8 status = 0; +@@ -984,7 +985,6 @@ static void cmd_work_handler(struct work_struct *work) + return; + } + +- cmd_ent_get(ent); /* for the _real_ FW event on completion */ + /* ring doorbell after the descriptor is valid */ + mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx); + wmb(); +@@ -1598,8 +1598,8 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force + cmd_ent_put(ent); /* timeout work was canceled */ + + if (!forced || /* Real FW completion */ +- pci_channel_offline(dev->pdev) || /* FW is inaccessible */ +- dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) ++ mlx5_cmd_is_down(dev) || /* No real FW completion is expected */ ++ !opcode_allowed(cmd, ent->op)) + cmd_ent_put(ent); + + ent->ts2 = ktime_get_ns(); +-- +2.35.1 + diff --git a/queue-5.15/net-mvpp2-fix-possible-invalid-pointer-dereference.patch b/queue-5.15/net-mvpp2-fix-possible-invalid-pointer-dereference.patch new file mode 100644 index 00000000000..2fa24d6c61c --- /dev/null +++ b/queue-5.15/net-mvpp2-fix-possible-invalid-pointer-dereference.patch @@ -0,0 +1,51 @@ +From b109a97a3aecb18d87f7bf5ea6bc78f0ede24d28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 16:40:32 +0800 +Subject: net: mvpp2: fix possible invalid pointer dereference + +From: Hui Tang + +[ Upstream commit cbe867685386af1f0a2648f5279f6e4c74bfd17f ] + +It will cause invalid pointer dereference to priv->cm3_base behind, +if PTR_ERR(priv->cm3_base) in mvpp2_get_sram(). + +Fixes: e54ad1e01c00 ("net: mvpp2: add CM3 SRAM memory map") +Signed-off-by: Hui Tang +Link: https://lore.kernel.org/r/20221117084032.101144-1-tanghui20@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index ae586f8895fc..524913c28f3b 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -7356,6 +7356,7 @@ static int mvpp2_get_sram(struct platform_device *pdev, + struct mvpp2 *priv) + { + struct resource *res; ++ void __iomem *base; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (!res) { +@@ -7366,9 +7367,12 @@ static int mvpp2_get_sram(struct platform_device *pdev, + return 0; + } + +- priv->cm3_base = devm_ioremap_resource(&pdev->dev, res); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + +- return PTR_ERR_OR_ZERO(priv->cm3_base); ++ priv->cm3_base = base; ++ return 0; + } + + static int mvpp2_probe(struct platform_device *pdev) +-- +2.35.1 + diff --git a/queue-5.15/net-pch_gbe-fix-pci-device-refcount-leak-while-modul.patch b/queue-5.15/net-pch_gbe-fix-pci-device-refcount-leak-while-modul.patch new file mode 100644 index 00000000000..466badad959 --- /dev/null +++ b/queue-5.15/net-pch_gbe-fix-pci-device-refcount-leak-while-modul.patch @@ -0,0 +1,60 @@ +From 469c377b03120a0f8239969eba0550ab2e2df2ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 21:51:48 +0800 +Subject: net: pch_gbe: fix pci device refcount leak while module exiting + +From: Yang Yingliang + +[ Upstream commit 5619537284f1017e9f6c7500b02b859b3830a06d ] + +As comment of pci_get_domain_bus_and_slot() says, it returns +a pci device with refcount increment, when finish using it, +the caller must decrement the reference count by calling +pci_dev_put(). + +In pch_gbe_probe(), pci_get_domain_bus_and_slot() is called, +so in error path in probe() and remove() function, pci_dev_put() +should be called to avoid refcount leak. Compile tested only. + +Fixes: 1a0bdadb4e36 ("net/pch_gbe: supports eg20t ptp clock") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221117135148.301014-1-yangyingliang@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +index 5a42ef6ca762..d555b4cc6049 100644 +--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c ++++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +@@ -2465,6 +2465,7 @@ static void pch_gbe_remove(struct pci_dev *pdev) + unregister_netdev(netdev); + + pch_gbe_phy_hw_reset(&adapter->hw); ++ pci_dev_put(adapter->ptp_pdev); + + free_netdev(netdev); + } +@@ -2540,7 +2541,7 @@ static int pch_gbe_probe(struct pci_dev *pdev, + /* setup the private structure */ + ret = pch_gbe_sw_init(adapter); + if (ret) +- goto err_free_netdev; ++ goto err_put_dev; + + /* Initialize PHY */ + ret = pch_gbe_init_phy(adapter); +@@ -2598,6 +2599,8 @@ static int pch_gbe_probe(struct pci_dev *pdev, + + err_free_adapter: + pch_gbe_phy_hw_reset(&adapter->hw); ++err_put_dev: ++ pci_dev_put(adapter->ptp_pdev); + err_free_netdev: + free_netdev(netdev); + return ret; +-- +2.35.1 + diff --git a/queue-5.15/net-pch_gbe-fix-potential-memleak-in-pch_gbe_tx_queu.patch b/queue-5.15/net-pch_gbe-fix-potential-memleak-in-pch_gbe_tx_queu.patch new file mode 100644 index 00000000000..af86608feab --- /dev/null +++ b/queue-5.15/net-pch_gbe-fix-potential-memleak-in-pch_gbe_tx_queu.patch @@ -0,0 +1,38 @@ +From 9f3e07dcce2dec69e0b3887c90026e6e6291d07b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 14:55:27 +0800 +Subject: net: pch_gbe: fix potential memleak in pch_gbe_tx_queue() + +From: Wang Hai + +[ Upstream commit 2360f9b8c4e81d242d4cbf99d630a2fffa681fab ] + +In pch_gbe_xmit_frame(), NETDEV_TX_OK will be returned whether +pch_gbe_tx_queue() sends data successfully or not, so pch_gbe_tx_queue() +needs to free skb before returning. But pch_gbe_tx_queue() returns without +freeing skb in case of dma_map_single() fails. Add dev_kfree_skb_any() +to fix it. + +Fixes: 77555ee72282 ("net: Add Gigabit Ethernet driver of Topcliff PCH") +Signed-off-by: Wang Hai +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +index ec3e558f890e..5a42ef6ca762 100644 +--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c ++++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +@@ -1148,6 +1148,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter, + buffer_info->dma = 0; + buffer_info->time_stamp = 0; + tx_ring->next_to_use = ring_num; ++ dev_kfree_skb_any(skb); + return; + } + buffer_info->mapped = true; +-- +2.35.1 + diff --git a/queue-5.15/net-qla3xxx-fix-potential-memleak-in-ql3xxx_send.patch b/queue-5.15/net-qla3xxx-fix-potential-memleak-in-ql3xxx_send.patch new file mode 100644 index 00000000000..c8637d1d78d --- /dev/null +++ b/queue-5.15/net-qla3xxx-fix-potential-memleak-in-ql3xxx_send.patch @@ -0,0 +1,36 @@ +From dd456ac301e2cff4e1defc529f0bf3a25824a528 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 16:50:38 +0800 +Subject: net/qla3xxx: fix potential memleak in ql3xxx_send() + +From: Zhang Changzhong + +[ Upstream commit 62a7311fb96c61d281da9852dbee4712fc8c3277 ] + +The ql3xxx_send() returns NETDEV_TX_OK without freeing skb in error +handling case, add dev_kfree_skb_any() to fix it. + +Fixes: bd36b0ac5d06 ("qla3xxx: Add support for Qlogic 4032 chip.") +Signed-off-by: Zhang Changzhong +Link: https://lore.kernel.org/r/1668675039-21138-1-git-send-email-zhangchangzhong@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qla3xxx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index 40d14d80f6f1..29837e533cee 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -2469,6 +2469,7 @@ static netdev_tx_t ql3xxx_send(struct sk_buff *skb, + skb_shinfo(skb)->nr_frags); + if (tx_cb->seg_count == -1) { + netdev_err(ndev, "%s: invalid segment count!\n", __func__); ++ dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-sched-allow-act_ct-to-be-built-without-nf_nat.patch b/queue-5.15/net-sched-allow-act_ct-to-be-built-without-nf_nat.patch new file mode 100644 index 00000000000..71b58c0c9dc --- /dev/null +++ b/queue-5.15/net-sched-allow-act_ct-to-be-built-without-nf_nat.patch @@ -0,0 +1,40 @@ +From d77d2d9f438e47554d1f9d0d3bac30fc268c5bc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 16:33:03 -0500 +Subject: net: sched: allow act_ct to be built without NF_NAT + +From: Xin Long + +[ Upstream commit 8427fd100c7b7793650e212a81e42f1cf124613d ] + +In commit f11fe1dae1c4 ("net/sched: Make NET_ACT_CT depends on NF_NAT"), +it fixed the build failure when NF_NAT is m and NET_ACT_CT is y by +adding depends on NF_NAT for NET_ACT_CT. However, it would also cause +NET_ACT_CT cannot be built without NF_NAT, which is not expected. This +patch fixes it by changing to use "(!NF_NAT || NF_NAT)" as the depend. + +Fixes: f11fe1dae1c4 ("net/sched: Make NET_ACT_CT depends on NF_NAT") +Signed-off-by: Xin Long +Link: https://lore.kernel.org/r/b6386f28d1ba34721795fb776a91cbdabb203447.1668807183.git.lucien.xin@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/sched/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sched/Kconfig b/net/sched/Kconfig +index 1e8ab4749c6c..4662a6ce8a7e 100644 +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -976,7 +976,7 @@ config NET_ACT_TUNNEL_KEY + + config NET_ACT_CT + tristate "connection tracking tc action" +- depends on NET_CLS_ACT && NF_CONNTRACK && NF_NAT && NF_FLOW_TABLE ++ depends on NET_CLS_ACT && NF_CONNTRACK && (!NF_NAT || NF_NAT) && NF_FLOW_TABLE + help + Say Y here to allow sending the packets to conntrack module. + +-- +2.35.1 + diff --git a/queue-5.15/net-sparx5-fix-error-handling-in-sparx5_port_open.patch b/queue-5.15/net-sparx5-fix-error-handling-in-sparx5_port_open.patch new file mode 100644 index 00000000000..ccc5a090938 --- /dev/null +++ b/queue-5.15/net-sparx5-fix-error-handling-in-sparx5_port_open.patch @@ -0,0 +1,63 @@ +From 807bd6d4e9320881f3fb4e347e6955b8e46fdd9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 20:59:18 +0800 +Subject: net: sparx5: fix error handling in sparx5_port_open() + +From: Liu Jian + +[ Upstream commit 4305fe232b8aa59af3761adc9fe6b6aa40913960 ] + +If phylink_of_phy_connect() fails, the port should be disabled. +If sparx5_serdes_set()/phy_power_on() fails, the port should be +disabled and the phylink should be stopped and disconnected. + +Fixes: 946e7fd5053a ("net: sparx5: add port module support") +Fixes: f3cad2611a77 ("net: sparx5: add hostmode with phylink support") +Signed-off-by: Liu Jian +Tested-by: Bjarni Jonasson +Reviewed-by: Steen Hegelund +Link: https://lore.kernel.org/r/20221117125918.203997-1-liujian56@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/microchip/sparx5/sparx5_netdev.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +index cb68eaaac881..5c7b21ce64ed 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +@@ -83,7 +83,7 @@ static int sparx5_port_open(struct net_device *ndev) + err = phylink_of_phy_connect(port->phylink, port->of_node, 0); + if (err) { + netdev_err(ndev, "Could not attach to PHY\n"); +- return err; ++ goto err_connect; + } + + phylink_start(port->phylink); +@@ -95,10 +95,20 @@ static int sparx5_port_open(struct net_device *ndev) + err = sparx5_serdes_set(port->sparx5, port, &port->conf); + else + err = phy_power_on(port->serdes); +- if (err) ++ if (err) { + netdev_err(ndev, "%s failed\n", __func__); ++ goto out_power; ++ } + } + ++ return 0; ++ ++out_power: ++ phylink_stop(port->phylink); ++ phylink_disconnect_phy(port->phylink); ++err_connect: ++ sparx5_port_enable(port, false); ++ + return err; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-thunderx-fix-the-acpi-memory-leak.patch b/queue-5.15/net-thunderx-fix-the-acpi-memory-leak.patch new file mode 100644 index 00000000000..14bd2474dce --- /dev/null +++ b/queue-5.15/net-thunderx-fix-the-acpi-memory-leak.patch @@ -0,0 +1,41 @@ +From 6923fb8e03fc899ba9d067cff3c6ce6d3f1ba15d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 16:22:36 +0800 +Subject: net: thunderx: Fix the ACPI memory leak + +From: Yu Liao + +[ Upstream commit 661e5ebbafd26d9d2e3c749f5cf591e55c7364f5 ] + +The ACPI buffer memory (string.pointer) should be freed as the buffer is +not used after returning from bgx_acpi_match_id(), free it to prevent +memory leak. + +Fixes: 46b903a01c05 ("net, thunder, bgx: Add support to get MAC address from ACPI.") +Signed-off-by: Yu Liao +Link: https://lore.kernel.org/r/20221123082237.1220521-1-liaoyu15@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +index c36fed9c3d73..daaffae1a89f 100644 +--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c ++++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +@@ -1435,8 +1435,10 @@ static acpi_status bgx_acpi_match_id(acpi_handle handle, u32 lvl, + return AE_OK; + } + +- if (strncmp(string.pointer, bgx_sel, 4)) ++ if (strncmp(string.pointer, bgx_sel, 4)) { ++ kfree(string.pointer); + return AE_OK; ++ } + + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + bgx_acpi_register_phy, NULL, bgx, NULL); +-- +2.35.1 + diff --git a/queue-5.15/net-wwan-iosm-use-acpi_free-but-not-kfree-in-ipc_pci.patch b/queue-5.15/net-wwan-iosm-use-acpi_free-but-not-kfree-in-ipc_pci.patch new file mode 100644 index 00000000000..89cbe8ea8b8 --- /dev/null +++ b/queue-5.15/net-wwan-iosm-use-acpi_free-but-not-kfree-in-ipc_pci.patch @@ -0,0 +1,39 @@ +From 67a3468b4259b8ebf1fc51e9cc41497fdd599977 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 14:24:47 +0800 +Subject: net: wwan: iosm: use ACPI_FREE() but not kfree() in + ipc_pcie_read_bios_cfg() + +From: Wang ShaoBo + +[ Upstream commit e541dd7763fc34aec2f93f652a396cc2e7b92d8d ] + +acpi_evaluate_dsm() should be coupled with ACPI_FREE() to free the ACPI +memory, because we need to track the allocation of acpi_object when +ACPI_DBG_TRACK_ALLOCATIONS enabled, so use ACPI_FREE() instead of kfree(). + +Fixes: d38a648d2d6c ("net: wwan: iosm: fix memory leak in ipc_pcie_read_bios_cfg") +Signed-off-by: Wang ShaoBo +Link: https://lore.kernel.org/r/20221118062447.2324881-1-bobo.shaobowang@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/iosm/iosm_ipc_pcie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c +index 01df23835be0..8b4222b137d1 100644 +--- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c +@@ -249,7 +249,7 @@ static enum ipc_pcie_sleep_state ipc_pcie_read_bios_cfg(struct device *dev) + if (object->integer.value == 3) + sleep_state = IPC_PCIE_D3L2; + +- kfree(object); ++ ACPI_FREE(object); + + default_ret: + return sleep_state; +-- +2.35.1 + diff --git a/queue-5.15/netfilter-conntrack-fix-data-races-around-ct-mark.patch b/queue-5.15/netfilter-conntrack-fix-data-races-around-ct-mark.patch new file mode 100644 index 00000000000..aa4aa5b492d --- /dev/null +++ b/queue-5.15/netfilter-conntrack-fix-data-races-around-ct-mark.patch @@ -0,0 +1,369 @@ +From d654971326aa400343bc5bf1b2897b9460a02efa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 12:39:07 -0700 +Subject: netfilter: conntrack: Fix data-races around ct mark + +From: Daniel Xu + +[ Upstream commit 52d1aa8b8249ff477aaa38b6f74a8ced780d079c ] + +nf_conn:mark can be read from and written to in parallel. Use +READ_ONCE()/WRITE_ONCE() for reads and writes to prevent unwanted +compiler optimizations. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Daniel Xu +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/core/flow_dissector.c | 2 +- + net/ipv4/netfilter/ipt_CLUSTERIP.c | 4 ++-- + net/netfilter/nf_conntrack_core.c | 2 +- + net/netfilter/nf_conntrack_netlink.c | 24 ++++++++++++++---------- + net/netfilter/nf_conntrack_standalone.c | 2 +- + net/netfilter/nft_ct.c | 6 +++--- + net/netfilter/xt_connmark.c | 18 ++++++++++-------- + net/openvswitch/conntrack.c | 8 ++++---- + net/sched/act_connmark.c | 4 ++-- + net/sched/act_ct.c | 8 ++++---- + net/sched/act_ctinfo.c | 6 +++--- + 11 files changed, 45 insertions(+), 39 deletions(-) + +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index 1c34e2266578..1d230f041386 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -270,7 +270,7 @@ skb_flow_dissect_ct(const struct sk_buff *skb, + key->ct_zone = ct->zone.id; + #endif + #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) +- key->ct_mark = ct->mark; ++ key->ct_mark = READ_ONCE(ct->mark); + #endif + + cl = nf_ct_labels_find(ct); +diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c +index b518f20c9a24..34737b1d6526 100644 +--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c ++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c +@@ -435,7 +435,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) + + switch (ctinfo) { + case IP_CT_NEW: +- ct->mark = hash; ++ WRITE_ONCE(ct->mark, hash); + break; + case IP_CT_RELATED: + case IP_CT_RELATED_REPLY: +@@ -452,7 +452,7 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par) + #ifdef DEBUG + nf_ct_dump_tuple_ip(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + #endif +- pr_debug("hash=%u ct_hash=%u ", hash, ct->mark); ++ pr_debug("hash=%u ct_hash=%u ", hash, READ_ONCE(ct->mark)); + if (!clusterip_responsible(cipinfo->config, hash)) { + pr_debug("not responsible\n"); + return NF_DROP; +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 9da5ee6c50cd..43ea8cfd374b 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -1735,7 +1735,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +- ct->mark = exp->master->mark; ++ ct->mark = READ_ONCE(exp->master->mark); + #endif + #ifdef CONFIG_NF_CONNTRACK_SECMARK + ct->secmark = exp->master->secmark; +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index ef0a78aa9ba9..1727a4c4764f 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -322,9 +322,9 @@ ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +-static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct) ++static int ctnetlink_dump_mark(struct sk_buff *skb, u32 mark) + { +- if (nla_put_be32(skb, CTA_MARK, htonl(ct->mark))) ++ if (nla_put_be32(skb, CTA_MARK, htonl(mark))) + goto nla_put_failure; + return 0; + +@@ -537,7 +537,7 @@ static int ctnetlink_dump_extinfo(struct sk_buff *skb, + static int ctnetlink_dump_info(struct sk_buff *skb, struct nf_conn *ct) + { + if (ctnetlink_dump_status(skb, ct) < 0 || +- ctnetlink_dump_mark(skb, ct) < 0 || ++ ctnetlink_dump_mark(skb, READ_ONCE(ct->mark)) < 0 || + ctnetlink_dump_secctx(skb, ct) < 0 || + ctnetlink_dump_id(skb, ct) < 0 || + ctnetlink_dump_use(skb, ct) < 0 || +@@ -716,6 +716,7 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item) + struct sk_buff *skb; + unsigned int type; + unsigned int flags = 0, group; ++ u32 mark; + int err; + + if (events & (1 << IPCT_DESTROY)) { +@@ -820,8 +821,9 @@ ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item) + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +- if ((events & (1 << IPCT_MARK) || ct->mark) +- && ctnetlink_dump_mark(skb, ct) < 0) ++ mark = READ_ONCE(ct->mark); ++ if ((events & (1 << IPCT_MARK) || mark) && ++ ctnetlink_dump_mark(skb, mark) < 0) + goto nla_put_failure; + #endif + nlmsg_end(skb, nlh); +@@ -1148,7 +1150,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data) + } + + #ifdef CONFIG_NF_CONNTRACK_MARK +- if ((ct->mark & filter->mark.mask) != filter->mark.val) ++ if ((READ_ONCE(ct->mark) & filter->mark.mask) != filter->mark.val) + goto ignore_entry; + #endif + status = (u32)READ_ONCE(ct->status); +@@ -2016,9 +2018,9 @@ static void ctnetlink_change_mark(struct nf_conn *ct, + mask = ~ntohl(nla_get_be32(cda[CTA_MARK_MASK])); + + mark = ntohl(nla_get_be32(cda[CTA_MARK])); +- newmark = (ct->mark & mask) ^ mark; +- if (newmark != ct->mark) +- ct->mark = newmark; ++ newmark = (READ_ONCE(ct->mark) & mask) ^ mark; ++ if (newmark != READ_ONCE(ct->mark)) ++ WRITE_ONCE(ct->mark, newmark); + } + #endif + +@@ -2690,6 +2692,7 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) + { + const struct nf_conntrack_zone *zone; + struct nlattr *nest_parms; ++ u32 mark; + + zone = nf_ct_zone(ct); + +@@ -2751,7 +2754,8 @@ static int __ctnetlink_glue_build(struct sk_buff *skb, struct nf_conn *ct) + goto nla_put_failure; + + #ifdef CONFIG_NF_CONNTRACK_MARK +- if (ct->mark && ctnetlink_dump_mark(skb, ct) < 0) ++ mark = READ_ONCE(ct->mark); ++ if (mark && ctnetlink_dump_mark(skb, mark) < 0) + goto nla_put_failure; + #endif + if (ctnetlink_dump_labels(skb, ct) < 0) +diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c +index 55aa55b252b2..4d85368203e0 100644 +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -363,7 +363,7 @@ static int ct_seq_show(struct seq_file *s, void *v) + goto release; + + #if defined(CONFIG_NF_CONNTRACK_MARK) +- seq_printf(s, "mark=%u ", ct->mark); ++ seq_printf(s, "mark=%u ", READ_ONCE(ct->mark)); + #endif + + ct_show_secctx(s, ct); +diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c +index 9c7472af9e4a..bd468e955a21 100644 +--- a/net/netfilter/nft_ct.c ++++ b/net/netfilter/nft_ct.c +@@ -97,7 +97,7 @@ static void nft_ct_get_eval(const struct nft_expr *expr, + return; + #ifdef CONFIG_NF_CONNTRACK_MARK + case NFT_CT_MARK: +- *dest = ct->mark; ++ *dest = READ_ONCE(ct->mark); + return; + #endif + #ifdef CONFIG_NF_CONNTRACK_SECMARK +@@ -296,8 +296,8 @@ static void nft_ct_set_eval(const struct nft_expr *expr, + switch (priv->key) { + #ifdef CONFIG_NF_CONNTRACK_MARK + case NFT_CT_MARK: +- if (ct->mark != value) { +- ct->mark = value; ++ if (READ_ONCE(ct->mark) != value) { ++ WRITE_ONCE(ct->mark, value); + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; +diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c +index e5ebc0810675..ad3c033db64e 100644 +--- a/net/netfilter/xt_connmark.c ++++ b/net/netfilter/xt_connmark.c +@@ -30,6 +30,7 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) + u_int32_t new_targetmark; + struct nf_conn *ct; + u_int32_t newmark; ++ u_int32_t oldmark; + + ct = nf_ct_get(skb, &ctinfo); + if (ct == NULL) +@@ -37,14 +38,15 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) + + switch (info->mode) { + case XT_CONNMARK_SET: +- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; ++ oldmark = READ_ONCE(ct->mark); ++ newmark = (oldmark & ~info->ctmask) ^ info->ctmark; + if (info->shift_dir == D_SHIFT_RIGHT) + newmark >>= info->shift_bits; + else + newmark <<= info->shift_bits; + +- if (ct->mark != newmark) { +- ct->mark = newmark; ++ if (READ_ONCE(ct->mark) != newmark) { ++ WRITE_ONCE(ct->mark, newmark); + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; +@@ -55,15 +57,15 @@ connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) + else + new_targetmark <<= info->shift_bits; + +- newmark = (ct->mark & ~info->ctmask) ^ ++ newmark = (READ_ONCE(ct->mark) & ~info->ctmask) ^ + new_targetmark; +- if (ct->mark != newmark) { +- ct->mark = newmark; ++ if (READ_ONCE(ct->mark) != newmark) { ++ WRITE_ONCE(ct->mark, newmark); + nf_conntrack_event_cache(IPCT_MARK, ct); + } + break; + case XT_CONNMARK_RESTORE: +- new_targetmark = (ct->mark & info->ctmask); ++ new_targetmark = (READ_ONCE(ct->mark) & info->ctmask); + if (info->shift_dir == D_SHIFT_RIGHT) + new_targetmark >>= info->shift_bits; + else +@@ -126,7 +128,7 @@ connmark_mt(const struct sk_buff *skb, struct xt_action_param *par) + if (ct == NULL) + return false; + +- return ((ct->mark & info->mask) == info->mark) ^ info->invert; ++ return ((READ_ONCE(ct->mark) & info->mask) == info->mark) ^ info->invert; + } + + static int connmark_mt_check(const struct xt_mtchk_param *par) +diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c +index dc86f03309c1..7106ce231a2d 100644 +--- a/net/openvswitch/conntrack.c ++++ b/net/openvswitch/conntrack.c +@@ -150,7 +150,7 @@ static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo) + static u32 ovs_ct_get_mark(const struct nf_conn *ct) + { + #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) +- return ct ? ct->mark : 0; ++ return ct ? READ_ONCE(ct->mark) : 0; + #else + return 0; + #endif +@@ -338,9 +338,9 @@ static int ovs_ct_set_mark(struct nf_conn *ct, struct sw_flow_key *key, + #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) + u32 new_mark; + +- new_mark = ct_mark | (ct->mark & ~(mask)); +- if (ct->mark != new_mark) { +- ct->mark = new_mark; ++ new_mark = ct_mark | (READ_ONCE(ct->mark) & ~(mask)); ++ if (READ_ONCE(ct->mark) != new_mark) { ++ WRITE_ONCE(ct->mark, new_mark); + if (nf_ct_is_confirmed(ct)) + nf_conntrack_event_cache(IPCT_MARK, ct); + key->ct.mark = new_mark; +diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c +index 94e78ac7a748..032ef927d0eb 100644 +--- a/net/sched/act_connmark.c ++++ b/net/sched/act_connmark.c +@@ -62,7 +62,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + + c = nf_ct_get(skb, &ctinfo); + if (c) { +- skb->mark = c->mark; ++ skb->mark = READ_ONCE(c->mark); + /* using overlimits stats to count how many packets marked */ + ca->tcf_qstats.overlimits++; + goto out; +@@ -82,7 +82,7 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a, + c = nf_ct_tuplehash_to_ctrack(thash); + /* using overlimits stats to count how many packets marked */ + ca->tcf_qstats.overlimits++; +- skb->mark = c->mark; ++ skb->mark = READ_ONCE(c->mark); + nf_ct_put(c); + + out: +diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c +index d85fdefe5730..81a2d6cbfb44 100644 +--- a/net/sched/act_ct.c ++++ b/net/sched/act_ct.c +@@ -177,7 +177,7 @@ static void tcf_ct_flow_table_add_action_meta(struct nf_conn *ct, + entry = tcf_ct_flow_table_flow_action_get_next(action); + entry->id = FLOW_ACTION_CT_METADATA; + #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) +- entry->ct_metadata.mark = ct->mark; ++ entry->ct_metadata.mark = READ_ONCE(ct->mark); + #endif + ctinfo = dir == IP_CT_DIR_ORIGINAL ? IP_CT_ESTABLISHED : + IP_CT_ESTABLISHED_REPLY; +@@ -856,9 +856,9 @@ static void tcf_ct_act_set_mark(struct nf_conn *ct, u32 mark, u32 mask) + if (!mask) + return; + +- new_mark = mark | (ct->mark & ~(mask)); +- if (ct->mark != new_mark) { +- ct->mark = new_mark; ++ new_mark = mark | (READ_ONCE(ct->mark) & ~(mask)); ++ if (READ_ONCE(ct->mark) != new_mark) { ++ WRITE_ONCE(ct->mark, new_mark); + if (nf_ct_is_confirmed(ct)) + nf_conntrack_event_cache(IPCT_MARK, ct); + } +diff --git a/net/sched/act_ctinfo.c b/net/sched/act_ctinfo.c +index 549374a2d008..2d75fe1223ac 100644 +--- a/net/sched/act_ctinfo.c ++++ b/net/sched/act_ctinfo.c +@@ -33,7 +33,7 @@ static void tcf_ctinfo_dscp_set(struct nf_conn *ct, struct tcf_ctinfo *ca, + { + u8 dscp, newdscp; + +- newdscp = (((ct->mark & cp->dscpmask) >> cp->dscpmaskshift) << 2) & ++ newdscp = (((READ_ONCE(ct->mark) & cp->dscpmask) >> cp->dscpmaskshift) << 2) & + ~INET_ECN_MASK; + + switch (proto) { +@@ -73,7 +73,7 @@ static void tcf_ctinfo_cpmark_set(struct nf_conn *ct, struct tcf_ctinfo *ca, + struct sk_buff *skb) + { + ca->stats_cpmark_set++; +- skb->mark = ct->mark & cp->cpmarkmask; ++ skb->mark = READ_ONCE(ct->mark) & cp->cpmarkmask; + } + + static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a, +@@ -131,7 +131,7 @@ static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a, + } + + if (cp->mode & CTINFO_MODE_DSCP) +- if (!cp->dscpstatemask || (ct->mark & cp->dscpstatemask)) ++ if (!cp->dscpstatemask || (READ_ONCE(ct->mark) & cp->dscpstatemask)) + tcf_ctinfo_dscp_set(ct, ca, cp, skb, wlen, proto); + + if (cp->mode & CTINFO_MODE_CPMARK) +-- +2.35.1 + diff --git a/queue-5.15/netfilter-flowtable_offload-add-missing-locking.patch b/queue-5.15/netfilter-flowtable_offload-add-missing-locking.patch new file mode 100644 index 00000000000..3a358ae77fe --- /dev/null +++ b/queue-5.15/netfilter-flowtable_offload-add-missing-locking.patch @@ -0,0 +1,55 @@ +From d5174f7eb29e644df140ed132a5aef57cd0de5ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 19:26:15 +0100 +Subject: netfilter: flowtable_offload: add missing locking + +From: Felix Fietkau + +[ Upstream commit bcd9e3c1656d0f7dd9743598c65c3ae24efb38d0 ] + +nf_flow_table_block_setup and the driver TC_SETUP_FT call can modify the flow +block cb list while they are being traversed elsewhere, causing a crash. +Add a write lock around the calls to protect readers + +Fixes: c29f74e0df7a ("netfilter: nf_flow_table: hardware offload support") +Reported-by: Chad Monroe +Signed-off-by: Felix Fietkau +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_flow_table_offload.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c +index c4559fae8acd..66c9a6c2b9cf 100644 +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -1074,6 +1074,7 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable, + struct flow_block_cb *block_cb, *next; + int err = 0; + ++ down_write(&flowtable->flow_block_lock); + switch (cmd) { + case FLOW_BLOCK_BIND: + list_splice(&bo->cb_list, &flowtable->flow_block.cb_list); +@@ -1088,6 +1089,7 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable, + WARN_ON_ONCE(1); + err = -EOPNOTSUPP; + } ++ up_write(&flowtable->flow_block_lock); + + return err; + } +@@ -1144,7 +1146,9 @@ static int nf_flow_table_offload_cmd(struct flow_block_offload *bo, + + nf_flow_table_block_offload_init(bo, dev_net(dev), cmd, flowtable, + extack); ++ down_write(&flowtable->flow_block_lock); + err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, bo); ++ up_write(&flowtable->flow_block_lock); + if (err < 0) + return err; + +-- +2.35.1 + diff --git a/queue-5.15/netfilter-ipset-regression-in-ip_set_hash_ip.c.patch b/queue-5.15/netfilter-ipset-regression-in-ip_set_hash_ip.c.patch new file mode 100644 index 00000000000..8154b89272f --- /dev/null +++ b/queue-5.15/netfilter-ipset-regression-in-ip_set_hash_ip.c.patch @@ -0,0 +1,66 @@ +From 13b4749663f26566077703e2ce56ae0e9e9ddc32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 14:26:50 -0400 +Subject: netfilter: ipset: regression in ip_set_hash_ip.c + +From: Vishwanath Pai + +[ Upstream commit c7aa1a76d4a0a3c401025b60c401412bbb60f8c6 ] + +This patch introduced a regression: commit 48596a8ddc46 ("netfilter: +ipset: Fix adding an IPv4 range containing more than 2^31 addresses") + +The variable e.ip is passed to adtfn() function which finally adds the +ip address to the set. The patch above refactored the for loop and moved +e.ip = htonl(ip) to the end of the for loop. + +What this means is that if the value of "ip" changes between the first +assignement of e.ip and the forloop, then e.ip is pointing to a +different ip address than "ip". + +Test case: +$ ipset create jdtest_tmp hash:ip family inet hashsize 2048 maxelem 100000 +$ ipset add jdtest_tmp 10.0.1.1/31 +ipset v6.21.1: Element cannot be added to the set: it's already added + +The value of ip gets updated inside the "else if (tb[IPSET_ATTR_CIDR])" +block but e.ip is still pointing to the old value. + +Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses") +Reviewed-by: Joshua Hunt +Signed-off-by: Vishwanath Pai +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/ipset/ip_set_hash_ip.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c +index dd30c03d5a23..75d556d71652 100644 +--- a/net/netfilter/ipset/ip_set_hash_ip.c ++++ b/net/netfilter/ipset/ip_set_hash_ip.c +@@ -151,18 +151,16 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], + if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE) + return -ERANGE; + +- if (retried) { ++ if (retried) + ip = ntohl(h->next.ip); +- e.ip = htonl(ip); +- } + for (; ip <= ip_to;) { ++ e.ip = htonl(ip); + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) + return ret; + + ip += hosts; +- e.ip = htonl(ip); +- if (e.ip == 0) ++ if (ip == 0) + return 0; + + ret = 0; +-- +2.35.1 + diff --git a/queue-5.15/netfilter-ipset-restore-allowing-64-clashing-element.patch b/queue-5.15/netfilter-ipset-restore-allowing-64-clashing-element.patch new file mode 100644 index 00000000000..2a149de115a --- /dev/null +++ b/queue-5.15/netfilter-ipset-restore-allowing-64-clashing-element.patch @@ -0,0 +1,39 @@ +From c21cad70826ab7b049804662017e97dc7ad26c8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 20:18:58 +0100 +Subject: netfilter: ipset: restore allowing 64 clashing elements in + hash:net,iface + +From: Jozsef Kadlecsik + +[ Upstream commit 6a66ce44a51bdfc47721f0c591137df2d4b21247 ] + +The commit 510841da1fcc ("netfilter: ipset: enforce documented limit to +prevent allocating huge memory") was too strict and prevented to add up to +64 clashing elements to a hash:net,iface type of set. This patch fixes the +issue and now the type behaves as documented. + +Fixes: 510841da1fcc ("netfilter: ipset: enforce documented limit to prevent allocating huge memory") +Signed-off-by: Jozsef Kadlecsik +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/ipset/ip_set_hash_gen.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h +index 3adc291d9ce1..7499192af586 100644 +--- a/net/netfilter/ipset/ip_set_hash_gen.h ++++ b/net/netfilter/ipset/ip_set_hash_gen.h +@@ -916,7 +916,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, + #ifdef IP_SET_HASH_WITH_MULTI + if (h->bucketsize >= AHASH_MAX_TUNED) + goto set_full; +- else if (h->bucketsize < multi) ++ else if (h->bucketsize <= multi) + h->bucketsize += AHASH_INIT_SIZE; + #endif + if (n->size >= AHASH_MAX(h)) { +-- +2.35.1 + diff --git a/queue-5.15/netfilter-nf_tables-do-not-set-up-extensions-for-end.patch b/queue-5.15/netfilter-nf_tables-do-not-set-up-extensions-for-end.patch new file mode 100644 index 00000000000..9b537c2b805 --- /dev/null +++ b/queue-5.15/netfilter-nf_tables-do-not-set-up-extensions-for-end.patch @@ -0,0 +1,54 @@ +From 9fb84728dc1f8e883de6fc77e13edcebea42bc9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 11:31:54 +0100 +Subject: netfilter: nf_tables: do not set up extensions for end interval + +From: Pablo Neira Ayuso + +[ Upstream commit 33c7aba0b4ffd6d7cdab862a034eb582a5120a38 ] + +Elements with an end interval flag set on do not store extensions. The +global set definition is currently setting on the timeout and stateful +expression for end interval elements. + +This leads to skipping end interval elements from the set->ops->walk() +path as the expired check bogusly reports true. + +Moreover, do not set up stateful expressions for elements with end +interval flag set on since this is never used. + +Fixes: 65038428b2c6 ("netfilter: nf_tables: allow to specify stateful expression in set definition") +Fixes: 8d8540c4f5e0 ("netfilter: nft_set_rbtree: add timeout support") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 227f03db7ee1..3fac57d66dda 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5813,7 +5813,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + &timeout); + if (err) + return err; +- } else if (set->flags & NFT_SET_TIMEOUT) { ++ } else if (set->flags & NFT_SET_TIMEOUT && ++ !(flags & NFT_SET_ELEM_INTERVAL_END)) { + timeout = set->timeout; + } + +@@ -5879,7 +5880,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + err = -EOPNOTSUPP; + goto err_set_elem_expr; + } +- } else if (set->num_exprs > 0) { ++ } else if (set->num_exprs > 0 && ++ !(flags & NFT_SET_ELEM_INTERVAL_END)) { + err = nft_set_elem_expr_clone(ctx, set, expr_array); + if (err < 0) + goto err_set_elem_expr_clone; +-- +2.35.1 + diff --git a/queue-5.15/nfc-nci-fix-memory-leak-in-nci_rx_data_packet.patch b/queue-5.15/nfc-nci-fix-memory-leak-in-nci_rx_data_packet.patch new file mode 100644 index 00000000000..5b90934fedc --- /dev/null +++ b/queue-5.15/nfc-nci-fix-memory-leak-in-nci_rx_data_packet.patch @@ -0,0 +1,61 @@ +From 0ac2d62a6a9a07799d75533959f60974f08b64db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 16:24:19 +0800 +Subject: NFC: nci: fix memory leak in nci_rx_data_packet() + +From: Liu Shixin + +[ Upstream commit 53270fb0fd77fe786d8c07a0793981d797836b93 ] + +Syzbot reported a memory leak about skb: + +unreferenced object 0xffff88810e144e00 (size 240): + comm "syz-executor284", pid 3701, jiffies 4294952403 (age 12.620s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [] __alloc_skb+0x1f9/0x270 net/core/skbuff.c:497 + [] alloc_skb include/linux/skbuff.h:1267 [inline] + [] virtual_ncidev_write+0x24/0xe0 drivers/nfc/virtual_ncidev.c:116 + [] do_loop_readv_writev fs/read_write.c:759 [inline] + [] do_loop_readv_writev fs/read_write.c:743 [inline] + [] do_iter_write+0x253/0x300 fs/read_write.c:863 + [] vfs_writev+0xdd/0x240 fs/read_write.c:934 + [] do_writev+0xa6/0x1c0 fs/read_write.c:977 + [] do_syscall_x64 arch/x86/entry/common.c:50 [inline] + [] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 + [] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +In nci_rx_data_packet(), if we don't get a valid conn_info, we will return +directly but forget to release the skb. + +Reported-by: syzbot+cdb9a427d1bc08815104@syzkaller.appspotmail.com +Fixes: 4aeee6871e8c ("NFC: nci: Add dynamic logical connections support") +Signed-off-by: Liu Shixin +Link: https://lore.kernel.org/r/20221118082419.239475-1-liushixin2@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/nfc/nci/data.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c +index aa5e712adf07..3d36ea5701f0 100644 +--- a/net/nfc/nci/data.c ++++ b/net/nfc/nci/data.c +@@ -279,8 +279,10 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) + nci_plen(skb->data)); + + conn_info = nci_get_conn_info_by_conn_id(ndev, nci_conn_id(skb->data)); +- if (!conn_info) ++ if (!conn_info) { ++ kfree_skb(skb); + return; ++ } + + /* strip the nci data header */ + skb_pull(skb, NCI_DATA_HDR_SIZE); +-- +2.35.1 + diff --git a/queue-5.15/nfc-nci-fix-race-with-opening-and-closing.patch b/queue-5.15/nfc-nci-fix-race-with-opening-and-closing.patch new file mode 100644 index 00000000000..7c179435738 --- /dev/null +++ b/queue-5.15/nfc-nci-fix-race-with-opening-and-closing.patch @@ -0,0 +1,42 @@ +From c30287092d935aaf1f04e2bae9ea5173be0b323b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 21:02:49 +0800 +Subject: nfc/nci: fix race with opening and closing + +From: Lin Ma + +[ Upstream commit 0ad6bded175e829c2ca261529c9dce39a32a042d ] + +Previously we leverage NCI_UNREG and the lock inside nci_close_device to +prevent the race condition between opening a device and closing a +device. However, it still has problem because a failed opening command +will erase the NCI_UNREG flag and allow another opening command to +bypass the status checking. + +This fix corrects that by making sure the NCI_UNREG is held. + +Reported-by: syzbot+43475bf3cfbd6e41f5b7@syzkaller.appspotmail.com +Fixes: 48b71a9e66c2 ("NFC: add NCI_UNREG flag to eliminate the race") +Signed-off-by: Lin Ma +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/nfc/nci/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c +index 189c9f428a3c..7b6cf9a44aea 100644 +--- a/net/nfc/nci/core.c ++++ b/net/nfc/nci/core.c +@@ -542,7 +542,7 @@ static int nci_open_device(struct nci_dev *ndev) + skb_queue_purge(&ndev->tx_q); + + ndev->ops->close(ndev); +- ndev->flags = 0; ++ ndev->flags &= BIT(NCI_UNREG); + } + + done: +-- +2.35.1 + diff --git a/queue-5.15/nfc-st-nci-fix-incorrect-sizing-calculations-in-evt_.patch b/queue-5.15/nfc-st-nci-fix-incorrect-sizing-calculations-in-evt_.patch new file mode 100644 index 00000000000..06fbae99577 --- /dev/null +++ b/queue-5.15/nfc-st-nci-fix-incorrect-sizing-calculations-in-evt_.patch @@ -0,0 +1,115 @@ +From 53307be2bb90185e4a573fb1a45becd78c9d32ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 18:42:46 -0600 +Subject: nfc: st-nci: fix incorrect sizing calculations in EVT_TRANSACTION + +From: Martin Faltesek + +[ Upstream commit 0254f31a7df3bb3b90c2d9dd2d4052f7b95eb287 ] + +The transaction buffer is allocated by using the size of the packet buf, +and subtracting two which seems intended to remove the two tags which are +not present in the target structure. This calculation leads to under +counting memory because of differences between the packet contents and the +target structure. The aid_len field is a u8 in the packet, but a u32 in +the structure, resulting in at least 3 bytes always being under counted. +Further, the aid data is a variable length field in the packet, but fixed +in the structure, so if this field is less than the max, the difference is +added to the under counting. + +To fix, perform validation checks progressively to safely reach the +next field, to determine the size of both buffers and verify both tags. +Once all validation checks pass, allocate the buffer and copy the data. +This eliminates freeing memory on the error path, as validation checks are +moved ahead of memory allocation. + +Reported-by: Denis Efremov +Reviewed-by: Guenter Roeck +Fixes: 5d1ceb7f5e56 ("NFC: st21nfcb: Add HCI transaction event support") +Signed-off-by: Martin Faltesek +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/st-nci/se.c | 51 +++++++++++++++++++++++++++++------------ + 1 file changed, 36 insertions(+), 15 deletions(-) + +diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c +index a915cad909b4..04a2cea6d6b6 100644 +--- a/drivers/nfc/st-nci/se.c ++++ b/drivers/nfc/st-nci/se.c +@@ -312,6 +312,8 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, + int r = 0; + struct device *dev = &ndev->nfc_dev->dev; + struct nfc_evt_transaction *transaction; ++ u32 aid_len; ++ u8 params_len; + + pr_debug("connectivity gate event: %x\n", event); + +@@ -325,28 +327,47 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, + * Description Tag Length + * AID 81 5 to 16 + * PARAMETERS 82 0 to 255 ++ * ++ * The key differences are aid storage length is variably sized ++ * in the packet, but fixed in nfc_evt_transaction, and that ++ * the aid_len is u8 in the packet, but u32 in the structure, ++ * and the tags in the packet are not included in ++ * nfc_evt_transaction. ++ * ++ * size(b): 1 1 5-16 1 1 0-255 ++ * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4 ++ * mem name: aid_tag(M) aid_len aid params_tag(M) params_len params ++ * example: 0x81 5-16 X 0x82 0-255 X + */ +- if (skb->len < NFC_MIN_AID_LENGTH + 2 || +- skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) ++ if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) + return -EPROTO; + +- transaction = devm_kzalloc(dev, skb->len - 2, GFP_KERNEL); +- if (!transaction) +- return -ENOMEM; ++ aid_len = skb->data[1]; + +- transaction->aid_len = skb->data[1]; +- memcpy(transaction->aid, &skb->data[2], transaction->aid_len); ++ if (skb->len < aid_len + 4 || ++ aid_len > sizeof(transaction->aid)) ++ return -EPROTO; + +- /* Check next byte is PARAMETERS tag (82) */ +- if (skb->data[transaction->aid_len + 2] != +- NFC_EVT_TRANSACTION_PARAMS_TAG) { +- devm_kfree(dev, transaction); ++ params_len = skb->data[aid_len + 3]; ++ ++ /* Verify PARAMETERS tag is (82), and final check that there is ++ * enough space in the packet to read everything. ++ */ ++ if (skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG || ++ skb->len < aid_len + 4 + params_len) + return -EPROTO; +- } + +- transaction->params_len = skb->data[transaction->aid_len + 3]; +- memcpy(transaction->params, skb->data + +- transaction->aid_len + 4, transaction->params_len); ++ transaction = devm_kzalloc(dev, sizeof(*transaction) + ++ params_len, GFP_KERNEL); ++ if (!transaction) ++ return -ENOMEM; ++ ++ transaction->aid_len = aid_len; ++ transaction->params_len = params_len; ++ ++ memcpy(transaction->aid, &skb->data[2], aid_len); ++ memcpy(transaction->params, &skb->data[aid_len + 4], ++ params_len); + + r = nfc_se_transaction(ndev->nfc_dev, host, transaction); + break; +-- +2.35.1 + diff --git a/queue-5.15/nfc-st-nci-fix-incorrect-validating-logic-in-evt_tra.patch b/queue-5.15/nfc-st-nci-fix-incorrect-validating-logic-in-evt_tra.patch new file mode 100644 index 00000000000..f93971ed1e5 --- /dev/null +++ b/queue-5.15/nfc-st-nci-fix-incorrect-validating-logic-in-evt_tra.patch @@ -0,0 +1,41 @@ +From 0dd703d5509e7ef52542392ab3a91d8adf5c6fce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 18:42:44 -0600 +Subject: nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION + +From: Martin Faltesek + +[ Upstream commit c60c152230828825c06e62a8f1ce956d4b659266 ] + +The first validation check for EVT_TRANSACTION has two different checks +tied together with logical AND. One is a check for minimum packet length, +and the other is for a valid aid_tag. If either condition is true (fails), +then an error should be triggered. The fix is to change && to ||. + +Reported-by: Denis Efremov +Reviewed-by: Guenter Roeck +Fixes: 5d1ceb7f5e56 ("NFC: st21nfcb: Add HCI transaction event support") +Signed-off-by: Martin Faltesek +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/st-nci/se.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c +index 5fd89f72969d..522b7a128f4c 100644 +--- a/drivers/nfc/st-nci/se.c ++++ b/drivers/nfc/st-nci/se.c +@@ -326,7 +326,7 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, + * AID 81 5 to 16 + * PARAMETERS 82 0 to 255 + */ +- if (skb->len < NFC_MIN_AID_LENGTH + 2 && ++ if (skb->len < NFC_MIN_AID_LENGTH + 2 || + skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) + return -EPROTO; + +-- +2.35.1 + diff --git a/queue-5.15/nfc-st-nci-fix-memory-leaks-in-evt_transaction.patch b/queue-5.15/nfc-st-nci-fix-memory-leaks-in-evt_transaction.patch new file mode 100644 index 00000000000..626f0c3be01 --- /dev/null +++ b/queue-5.15/nfc-st-nci-fix-memory-leaks-in-evt_transaction.patch @@ -0,0 +1,42 @@ +From 02705914dc27328bcdf4bbaf61d99efa4b081543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 18:42:45 -0600 +Subject: nfc: st-nci: fix memory leaks in EVT_TRANSACTION + +From: Martin Faltesek + +[ Upstream commit 440f2ae9c9f06e26f5dcea697a53717fc61a318c ] + +Error path does not free previously allocated memory. Add devm_kfree() to +the failure path. + +Reported-by: Denis Efremov +Reviewed-by: Guenter Roeck +Fixes: 5d1ceb7f5e56 ("NFC: st21nfcb: Add HCI transaction event support") +Signed-off-by: Martin Faltesek +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/st-nci/se.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c +index 522b7a128f4c..a915cad909b4 100644 +--- a/drivers/nfc/st-nci/se.c ++++ b/drivers/nfc/st-nci/se.c +@@ -339,8 +339,10 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, + + /* Check next byte is PARAMETERS tag (82) */ + if (skb->data[transaction->aid_len + 2] != +- NFC_EVT_TRANSACTION_PARAMS_TAG) ++ NFC_EVT_TRANSACTION_PARAMS_TAG) { ++ devm_kfree(dev, transaction); + return -EPROTO; ++ } + + transaction->params_len = skb->data[transaction->aid_len + 3]; + memcpy(transaction->params, skb->data + +-- +2.35.1 + diff --git a/queue-5.15/nfp-add-port-from-netdev-validation-for-eeprom-acces.patch b/queue-5.15/nfp-add-port-from-netdev-validation-for-eeprom-acces.patch new file mode 100644 index 00000000000..543aa1643da --- /dev/null +++ b/queue-5.15/nfp-add-port-from-netdev-validation-for-eeprom-acces.patch @@ -0,0 +1,45 @@ +From d8d5691b92ccfecf093adabd64d87681078cb554 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 16:37:44 +0100 +Subject: nfp: add port from netdev validation for EEPROM access + +From: Jaco Coetzee + +[ Upstream commit 0873016d46f6dfafd1bdf4d9b935b3331b226f7c ] + +Setting of the port flag `NFP_PORT_CHANGED`, introduced +to ensure the correct reading of EEPROM data, causes a +fatal kernel NULL pointer dereference in cases where +the target netdev type cannot be determined. + +Add validation of port struct pointer before attempting +to set the `NFP_PORT_CHANGED` flag. Return that operation +is not supported if the netdev type cannot be determined. + +Fixes: 4ae97cae07e1 ("nfp: ethtool: fix the display error of `ethtool -m DEVNAME`") +Signed-off-by: Jaco Coetzee +Reviewed-by: Louis Peens +Signed-off-by: Simon Horman +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +index 865865adfefc..d295942968f3 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c ++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +@@ -1219,6 +1219,9 @@ nfp_port_get_module_info(struct net_device *netdev, + u8 data; + + port = nfp_port_from_netdev(netdev); ++ if (!port) ++ return -EOPNOTSUPP; ++ + /* update port state to get latest interface */ + set_bit(NFP_PORT_CHANGED, &port->flags); + eth_port = nfp_port_get_eth_port(port); +-- +2.35.1 + diff --git a/queue-5.15/nfp-fill-splittable-of-devlink_port_attrs-correctly.patch b/queue-5.15/nfp-fill-splittable-of-devlink_port_attrs-correctly.patch new file mode 100644 index 00000000000..0c66b138b50 --- /dev/null +++ b/queue-5.15/nfp-fill-splittable-of-devlink_port_attrs-correctly.patch @@ -0,0 +1,48 @@ +From 4b6cffa538bd826edb837a3806a945fc5f13eca4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 16:37:43 +0100 +Subject: nfp: fill splittable of devlink_port_attrs correctly +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Diana Wang + +[ Upstream commit 4abd9600b9d15d3d92a9ac25cf200422a4c415ee ] + +The error is reflected in that it shows wrong splittable status of +port when executing "devlink port show". +The reason which leads the error is that the assigned operation of +splittable is just a simple negation operation of split and it does +not consider port lanes quantity. A splittable port should have +several lanes that can be split(lanes quantity > 1). +If without the judgement, it will show wrong message for some +firmware, such as 2x25G, 2x10G. + +Fixes: a0f49b548652 ("devlink: Add a new devlink port split ability attribute and pass to netlink") +Signed-off-by: Diana Wang +Reviewed-by: Louis Peens +Reviewed-by: Niklas Söderlund +Signed-off-by: Simon Horman +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfp_devlink.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +index bea978df7713..1647b6b180cc 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c ++++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +@@ -363,7 +363,7 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) + return ret; + + attrs.split = eth_port.is_split; +- attrs.splittable = !attrs.split; ++ attrs.splittable = eth_port.port_lanes > 1 && !attrs.split; + attrs.lanes = eth_port.port_lanes; + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; + attrs.phys.port_number = eth_port.label_port; +-- +2.35.1 + diff --git a/queue-5.15/octeontx2-af-debugsfs-fix-pci-device-refcount-leak.patch b/queue-5.15/octeontx2-af-debugsfs-fix-pci-device-refcount-leak.patch new file mode 100644 index 00000000000..dccec8bf99c --- /dev/null +++ b/queue-5.15/octeontx2-af-debugsfs-fix-pci-device-refcount-leak.patch @@ -0,0 +1,52 @@ +From 82db153d019f27b880c7b6ee767f02ac18328072 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 20:46:58 +0800 +Subject: octeontx2-af: debugsfs: fix pci device refcount leak + +From: Yang Yingliang + +[ Upstream commit d66608803aa2ffb9e475623343f69996305771ae ] + +As comment of pci_get_domain_bus_and_slot() says, it returns +a pci device with refcount increment, when finish using it, +the caller must decrement the reference count by calling +pci_dev_put(). + +So before returning from rvu_dbg_rvu_pf_cgx_map_display() or +cgx_print_dmac_flt(), pci_dev_put() is called to avoid refcount +leak. + +Fixes: dbc52debf95f ("octeontx2-af: Debugfs support for DMAC filters") +Fixes: e2fb37303865 ("octeontx2-af: Display CGX, NIX and PF map in debugfs.") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221117124658.162409-1-yangyingliang@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +index f001579569a2..66d34699f160 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +@@ -441,6 +441,8 @@ static int rvu_dbg_rvu_pf_cgx_map_display(struct seq_file *filp, void *unused) + sprintf(lmac, "LMAC%d", lmac_id); + seq_printf(filp, "%s\t0x%x\t\tNIX%d\t\t%s\t%s\n", + dev_name(&pdev->dev), pcifunc, blkid, cgx, lmac); ++ ++ pci_dev_put(pdev); + } + return 0; + } +@@ -2127,6 +2129,7 @@ static int cgx_print_dmac_flt(struct seq_file *s, int lmac_id) + } + } + ++ pci_dev_put(pdev); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/octeontx2-af-fix-reference-count-issue-in-rvu_sdp_in.patch b/queue-5.15/octeontx2-af-fix-reference-count-issue-in-rvu_sdp_in.patch new file mode 100644 index 00000000000..ba58e58040a --- /dev/null +++ b/queue-5.15/octeontx2-af-fix-reference-count-issue-in-rvu_sdp_in.patch @@ -0,0 +1,55 @@ +From 3d169094414408eee1c53546df1043467339b0ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 14:59:19 +0800 +Subject: octeontx2-af: Fix reference count issue in rvu_sdp_init() + +From: Xiongfeng Wang + +[ Upstream commit ad17c2a3f11b0f6b122e7842d8f7d9a5fcc7ac63 ] + +pci_get_device() will decrease the reference count for the *from* +parameter. So we don't need to call put_device() to decrease the +reference. Let's remove the put_device() in the loop and only decrease +the reference count of the returned 'pdev' for the last loop because it +will not be passed to pci_get_device() as input parameter. We don't need +to check if 'pdev' is NULL because it is already checked inside +pci_dev_put(). Also add pci_dev_put() for the error path. + +Fixes: fe1939bb2340 ("octeontx2-af: Add SDP interface support") +Signed-off-by: Xiongfeng Wang +Reviewed-by: Saeed Mahameed +Link: https://lore.kernel.org/r/20221123065919.31499-1-wangxiongfeng2@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c +index b04fb226f708..ae50d56258ec 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c +@@ -62,15 +62,18 @@ int rvu_sdp_init(struct rvu *rvu) + pfvf->sdp_info = devm_kzalloc(rvu->dev, + sizeof(struct sdp_node_info), + GFP_KERNEL); +- if (!pfvf->sdp_info) ++ if (!pfvf->sdp_info) { ++ pci_dev_put(pdev); + return -ENOMEM; ++ } + + dev_info(rvu->dev, "SDP PF number:%d\n", sdp_pf_num[i]); + +- put_device(&pdev->dev); + i++; + } + ++ pci_dev_put(pdev); ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/octeontx2-pf-add-check-for-devm_kcalloc.patch b/queue-5.15/octeontx2-pf-add-check-for-devm_kcalloc.patch new file mode 100644 index 00000000000..e1840398ece --- /dev/null +++ b/queue-5.15/octeontx2-pf-add-check-for-devm_kcalloc.patch @@ -0,0 +1,39 @@ +From 7bb183f667ecd9c0ab2e5ba85d53f0f2f2efec87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 13:54:49 +0800 +Subject: octeontx2-pf: Add check for devm_kcalloc + +From: Jiasheng Jiang + +[ Upstream commit cd07eadd5147ffdae11b6fd28b77a3872f2a2484 ] + +As the devm_kcalloc may return NULL pointer, +it should be better to add check for the return +value, as same as the others. + +Fixes: e8e095b3b370 ("octeontx2-af: cn10k: Bandwidth profiles config support") +Signed-off-by: Jiasheng Jiang +Reviewed-by: Maciej Fijalkowski +Link: https://lore.kernel.org/r/20221122055449.31247-1-jiasheng@iscas.ac.cn +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +index 603361c94786..09892703cfd4 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +@@ -4832,6 +4832,8 @@ static int nix_setup_ipolicers(struct rvu *rvu, + ipolicer->ref_count = devm_kcalloc(rvu->dev, + ipolicer->band_prof.max, + sizeof(u16), GFP_KERNEL); ++ if (!ipolicer->ref_count) ++ return -ENOMEM; + } + + /* Set policer timeunit to 2us ie (19 + 1) * 100 nsec = 2us */ +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-kobject-release-warning-and-memor.patch b/queue-5.15/regulator-core-fix-kobject-release-warning-and-memor.patch new file mode 100644 index 00000000000..6bb0cdefeb5 --- /dev/null +++ b/queue-5.15/regulator-core-fix-kobject-release-warning-and-memor.patch @@ -0,0 +1,75 @@ +From c5e5cd76b2f3244b38e02cb2a682f30202b31a39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 15:43:39 +0800 +Subject: regulator: core: fix kobject release warning and memory leak in + regulator_register() + +From: Zeng Heng + +[ Upstream commit 5f4b204b6b8153923d5be8002c5f7082985d153f ] + +Here is a warning report about lack of registered release() +from kobject lib: + +Device '(null)' does not have a release() function, it is broken and must be fixed. +WARNING: CPU: 0 PID: 48430 at drivers/base/core.c:2332 device_release+0x104/0x120 +Call Trace: + kobject_put+0xdc/0x180 + put_device+0x1b/0x30 + regulator_register+0x651/0x1170 + devm_regulator_register+0x4f/0xb0 + +When regulator_register() returns fail and directly goto `clean` symbol, +rdev->dev has not registered release() function yet (which is registered +by regulator_class in the following), so rdev needs to be freed manually. +If rdev->dev.of_node is not NULL, which means the of_node has gotten by +regulator_of_get_init_data(), it needs to call of_node_put() to avoid +refcount leak. + +Otherwise, only calling put_device() would lead memory leak of rdev +in further: + +unreferenced object 0xffff88810d0b1000 (size 2048): + comm "107-i2c-rtq6752", pid 48430, jiffies 4342258431 (age 1341.780s) + backtrace: + kmalloc_trace+0x22/0x110 + regulator_register+0x184/0x1170 + devm_regulator_register+0x4f/0xb0 + +When regulator_register() returns fail and goto `wash` symbol, +rdev->dev has registered release() function, so directly call +put_device() to cleanup everything. + +Fixes: d3c731564e09 ("regulator: plug of_node leak in regulator_register()'s error path") +Signed-off-by: Zeng Heng +Link: https://lore.kernel.org/r/20221116074339.1024240-1-zengheng4@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index aa4d78b02483..fd61c5c54a07 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -5549,11 +5549,15 @@ regulator_register(const struct regulator_desc *regulator_desc, + mutex_lock(®ulator_list_mutex); + regulator_ena_gpio_free(rdev); + mutex_unlock(®ulator_list_mutex); ++ put_device(&rdev->dev); ++ rdev = NULL; + clean: + if (dangling_of_gpiod) + gpiod_put(config->ena_gpiod); ++ if (rdev && rdev->dev.of_node) ++ of_node_put(rdev->dev.of_node); ++ kfree(rdev); + kfree(config); +- put_device(&rdev->dev); + rinse: + if (dangling_cfg_gpiod) + gpiod_put(cfg->ena_gpiod); +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-uaf-in-destroy_regulator.patch b/queue-5.15/regulator-core-fix-uaf-in-destroy_regulator.patch new file mode 100644 index 00000000000..8fed65a8b03 --- /dev/null +++ b/queue-5.15/regulator-core-fix-uaf-in-destroy_regulator.patch @@ -0,0 +1,132 @@ +From edf7bb7cec279dbd5c9fb35fd9fd93a5c5304d9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 11:37:06 +0800 +Subject: regulator: core: fix UAF in destroy_regulator() + +From: Yang Yingliang + +[ Upstream commit 1f386d6894d0f1b7de8ef640c41622ddd698e7ab ] + +I got a UAF report as following: + +================================================================== +BUG: KASAN: use-after-free in __lock_acquire+0x935/0x2060 +Read of size 8 at addr ffff88810e838220 by task python3/268 +Call Trace: + + dump_stack_lvl+0x67/0x83 + print_report+0x178/0x4b0 + kasan_report+0x90/0x190 + __lock_acquire+0x935/0x2060 + lock_acquire+0x156/0x400 + _raw_spin_lock+0x2a/0x40 + lockref_get+0x11/0x30 + simple_recursive_removal+0x41/0x440 + debugfs_remove.part.12+0x32/0x50 + debugfs_remove+0x29/0x30 + _regulator_put.cold.54+0x3e/0x27f + regulator_put+0x1f/0x30 + release_nodes+0x6a/0xa0 + devres_release_all+0xf8/0x150 + +Allocated by task 37: + kasan_save_stack+0x1c/0x40 + kasan_set_track+0x21/0x30 + __kasan_slab_alloc+0x5d/0x70 + slab_post_alloc_hook+0x62/0x510 + kmem_cache_alloc_lru+0x222/0x5a0 + __d_alloc+0x31/0x440 + d_alloc+0x30/0xf0 + d_alloc_parallel+0xc4/0xd20 + __lookup_slow+0x15e/0x2f0 + lookup_one_len+0x13a/0x150 + start_creating+0xea/0x190 + debugfs_create_dir+0x1e/0x210 + create_regulator+0x254/0x4e0 + _regulator_get+0x2a1/0x467 + _devm_regulator_get+0x5a/0xb0 + regulator_virtual_probe+0xb9/0x1a0 + +Freed by task 30: + kasan_save_stack+0x1c/0x40 + kasan_set_track+0x21/0x30 + kasan_save_free_info+0x2a/0x50 + __kasan_slab_free+0x102/0x190 + kmem_cache_free+0xf6/0x600 + rcu_core+0x54c/0x12b0 + __do_softirq+0xf2/0x5e3 + +Last potentially related work creation: + kasan_save_stack+0x1c/0x40 + __kasan_record_aux_stack+0x98/0xb0 + call_rcu+0x42/0x700 + dentry_free+0x6c/0xd0 + __dentry_kill+0x23b/0x2d0 + dput.part.31+0x431/0x780 + simple_recursive_removal+0xa9/0x440 + debugfs_remove.part.12+0x32/0x50 + debugfs_remove+0x29/0x30 + regulator_unregister+0xe3/0x230 + release_nodes+0x6a/0xa0 + +================================================================== + +Here is how happened: + +processor A processor B +regulator_register() + rdev_init_debugfs() + rdev->debugfs = debugfs_create_dir() + devm_regulator_get() + rdev = regulator_dev_lookup() + create_regulator(rdev) + // using rdev->debugfs as parent + debugfs_create_dir(rdev->debugfs) + +mfd_remove_devices_fn() + release_nodes() + regulator_unregister() + // free rdev->debugfs + debugfs_remove_recursive(rdev->debugfs) + release_nodes() + destroy_regulator() + debugfs_remove_recursive() <- causes UAF + +In devm_regulator_get(), after getting rdev, the refcount +is get, so fix this by moving debugfs_remove_recursive() +to regulator_dev_release(), then it can be proctected by +the refcount, the 'rdev->debugfs' can not be freed until +the refcount is 0. + +Fixes: 5de705194e98 ("regulator: Add basic per consumer debugfs") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221116033706.3595812-1-yangyingliang@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index fd61c5c54a07..221ae807b379 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -5071,6 +5071,7 @@ static void regulator_dev_release(struct device *dev) + { + struct regulator_dev *rdev = dev_get_drvdata(dev); + ++ debugfs_remove_recursive(rdev->debugfs); + kfree(rdev->constraints); + of_node_put(rdev->dev.of_node); + kfree(rdev); +@@ -5586,7 +5587,6 @@ void regulator_unregister(struct regulator_dev *rdev) + + mutex_lock(®ulator_list_mutex); + +- debugfs_remove_recursive(rdev->debugfs); + WARN_ON(rdev->open_count); + regulator_remove_coupling(rdev); + unset_regulator_supplies(rdev); +-- +2.35.1 + diff --git a/queue-5.15/regulator-twl6030-re-add-twl6032_subclass.patch b/queue-5.15/regulator-twl6030-re-add-twl6032_subclass.patch new file mode 100644 index 00000000000..32703617bdf --- /dev/null +++ b/queue-5.15/regulator-twl6030-re-add-twl6032_subclass.patch @@ -0,0 +1,47 @@ +From 21d20a7d7dbec9f9b0682e4dbab4484c2f1dc608 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 23:12:07 +0100 +Subject: regulator: twl6030: re-add TWL6032_SUBCLASS + +From: Andreas Kemnade + +[ Upstream commit 3d6c982b26db94cc21bc9f7784f63e8286b7be62 ] + +In former times, info->feature was populated via the parent driver +by pdata/regulator_init_data->driver_data for all regulators when +USB_PRODUCT_ID_LSB indicates a TWL6032. +Today, the information is not set, so re-add it at the regulator +definitions. + +Fixes: 25d82337705e2 ("regulator: twl: make driver DT only") +Signed-off-by: Andreas Kemnade +Link: https://lore.kernel.org/r/20221120221208.3093727-2-andreas@kemnade.info +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/twl6030-regulator.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c +index 430265c404d6..7c7e3648ea4b 100644 +--- a/drivers/regulator/twl6030-regulator.c ++++ b/drivers/regulator/twl6030-regulator.c +@@ -530,6 +530,7 @@ static const struct twlreg_info TWL6030_INFO_##label = { \ + #define TWL6032_ADJUSTABLE_LDO(label, offset) \ + static const struct twlreg_info TWL6032_INFO_##label = { \ + .base = offset, \ ++ .features = TWL6032_SUBCLASS, \ + .desc = { \ + .name = #label, \ + .id = TWL6032_REG_##label, \ +@@ -562,6 +563,7 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \ + #define TWL6032_ADJUSTABLE_SMPS(label, offset) \ + static const struct twlreg_info TWLSMPS_INFO_##label = { \ + .base = offset, \ ++ .features = TWL6032_SUBCLASS, \ + .desc = { \ + .name = #label, \ + .id = TWL6032_REG_##label, \ +-- +2.35.1 + diff --git a/queue-5.15/rxrpc-allow-list-of-in-use-local-udp-endpoints-to-be.patch b/queue-5.15/rxrpc-allow-list-of-in-use-local-udp-endpoints-to-be.patch new file mode 100644 index 00000000000..f97f2f62e21 --- /dev/null +++ b/queue-5.15/rxrpc-allow-list-of-in-use-local-udp-endpoints-to-be.patch @@ -0,0 +1,256 @@ +From 43b2978d26918174bcf61e14185cf1ccdffecc76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 21 May 2022 08:45:15 +0100 +Subject: rxrpc: Allow list of in-use local UDP endpoints to be viewed in /proc + +From: David Howells + +[ Upstream commit 33912c2639ad76660988c8ca97e4d18fca89b668 ] + +Allow the list of in-use local UDP endpoints in the current network +namespace to be viewed in /proc. + +To aid with this, the endpoint list is converted to an hlist and RCU-safe +manipulation is used so that the list can be read with only the RCU +read lock held. + +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Signed-off-by: David S. Miller +Stable-dep-of: 3bcd6c7eaa53 ("rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]") +Signed-off-by: Sasha Levin +--- + net/rxrpc/ar-internal.h | 5 +-- + net/rxrpc/local_object.c | 37 +++++++++++---------- + net/rxrpc/net_ns.c | 5 ++- + net/rxrpc/proc.c | 69 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 94 insertions(+), 22 deletions(-) + +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index f2e3fb77a02d..38dd63169aac 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -88,7 +88,7 @@ struct rxrpc_net { + struct work_struct client_conn_reaper; + struct timer_list client_conn_reap_timer; + +- struct list_head local_endpoints; ++ struct hlist_head local_endpoints; + struct mutex local_mutex; /* Lock for ->local_endpoints */ + + DECLARE_HASHTABLE (peer_hash, 10); +@@ -281,7 +281,7 @@ struct rxrpc_local { + atomic_t active_users; /* Number of users of the local endpoint */ + atomic_t usage; /* Number of references to the structure */ + struct rxrpc_net *rxnet; /* The network ns in which this resides */ +- struct list_head link; ++ struct hlist_node link; + struct socket *socket; /* my UDP socket */ + struct work_struct processor; + struct rxrpc_sock __rcu *service; /* Service(s) listening on this endpoint */ +@@ -1016,6 +1016,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *); + extern const struct seq_operations rxrpc_call_seq_ops; + extern const struct seq_operations rxrpc_connection_seq_ops; + extern const struct seq_operations rxrpc_peer_seq_ops; ++extern const struct seq_operations rxrpc_local_seq_ops; + + /* + * recvmsg.c +diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c +index 1d15940f61d7..0cbbbbcf490e 100644 +--- a/net/rxrpc/local_object.c ++++ b/net/rxrpc/local_object.c +@@ -82,7 +82,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, + atomic_set(&local->usage, 1); + atomic_set(&local->active_users, 1); + local->rxnet = rxnet; +- INIT_LIST_HEAD(&local->link); ++ INIT_HLIST_NODE(&local->link); + INIT_WORK(&local->processor, rxrpc_local_processor); + init_rwsem(&local->defrag_sem); + skb_queue_head_init(&local->reject_queue); +@@ -181,7 +181,7 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, + { + struct rxrpc_local *local; + struct rxrpc_net *rxnet = rxrpc_net(net); +- struct list_head *cursor; ++ struct hlist_node *cursor; + const char *age; + long diff; + int ret; +@@ -191,16 +191,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, + + mutex_lock(&rxnet->local_mutex); + +- for (cursor = rxnet->local_endpoints.next; +- cursor != &rxnet->local_endpoints; +- cursor = cursor->next) { +- local = list_entry(cursor, struct rxrpc_local, link); ++ hlist_for_each(cursor, &rxnet->local_endpoints) { ++ local = hlist_entry(cursor, struct rxrpc_local, link); + + diff = rxrpc_local_cmp_key(local, srx); +- if (diff < 0) ++ if (diff != 0) + continue; +- if (diff > 0) +- break; + + /* Services aren't allowed to share transport sockets, so + * reject that here. It is possible that the object is dying - +@@ -212,9 +208,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, + goto addr_in_use; + } + +- /* Found a match. We replace a dying object. Attempting to +- * bind the transport socket may still fail if we're attempting +- * to use a local address that the dying object is still using. ++ /* Found a match. We want to replace a dying object. ++ * Attempting to bind the transport socket may still fail if ++ * we're attempting to use a local address that the dying ++ * object is still using. + */ + if (!rxrpc_use_local(local)) + break; +@@ -231,10 +228,12 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, + if (ret < 0) + goto sock_error; + +- if (cursor != &rxnet->local_endpoints) +- list_replace_init(cursor, &local->link); +- else +- list_add_tail(&local->link, cursor); ++ if (cursor) { ++ hlist_replace_rcu(cursor, &local->link); ++ cursor->pprev = NULL; ++ } else { ++ hlist_add_head_rcu(&local->link, &rxnet->local_endpoints); ++ } + age = "new"; + + found: +@@ -375,7 +374,7 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local) + local->dead = true; + + mutex_lock(&rxnet->local_mutex); +- list_del_init(&local->link); ++ hlist_del_init_rcu(&local->link); + mutex_unlock(&rxnet->local_mutex); + + rxrpc_clean_up_local_conns(local); +@@ -462,9 +461,9 @@ void rxrpc_destroy_all_locals(struct rxrpc_net *rxnet) + + flush_workqueue(rxrpc_workqueue); + +- if (!list_empty(&rxnet->local_endpoints)) { ++ if (!hlist_empty(&rxnet->local_endpoints)) { + mutex_lock(&rxnet->local_mutex); +- list_for_each_entry(local, &rxnet->local_endpoints, link) { ++ hlist_for_each_entry(local, &rxnet->local_endpoints, link) { + pr_err("AF_RXRPC: Leaked local %p {%d}\n", + local, atomic_read(&local->usage)); + } +diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c +index e4d6d432515b..bb4c25d6df64 100644 +--- a/net/rxrpc/net_ns.c ++++ b/net/rxrpc/net_ns.c +@@ -72,7 +72,7 @@ static __net_init int rxrpc_init_net(struct net *net) + timer_setup(&rxnet->client_conn_reap_timer, + rxrpc_client_conn_reap_timeout, 0); + +- INIT_LIST_HEAD(&rxnet->local_endpoints); ++ INIT_HLIST_HEAD(&rxnet->local_endpoints); + mutex_init(&rxnet->local_mutex); + + hash_init(rxnet->peer_hash); +@@ -98,6 +98,9 @@ static __net_init int rxrpc_init_net(struct net *net) + proc_create_net("peers", 0444, rxnet->proc_net, + &rxrpc_peer_seq_ops, + sizeof(struct seq_net_private)); ++ proc_create_net("locals", 0444, rxnet->proc_net, ++ &rxrpc_local_seq_ops, ++ sizeof(struct seq_net_private)); + return 0; + + err_proc: +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 5a67955cc00f..7d007a66eba5 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -328,3 +328,72 @@ const struct seq_operations rxrpc_peer_seq_ops = { + .stop = rxrpc_peer_seq_stop, + .show = rxrpc_peer_seq_show, + }; ++ ++/* ++ * Generate a list of extant virtual local endpoints in /proc/net/rxrpc/locals ++ */ ++static int rxrpc_local_seq_show(struct seq_file *seq, void *v) ++{ ++ struct rxrpc_local *local; ++ char lbuff[50]; ++ ++ if (v == SEQ_START_TOKEN) { ++ seq_puts(seq, ++ "Proto Local " ++ " Use Act\n"); ++ return 0; ++ } ++ ++ local = hlist_entry(v, struct rxrpc_local, link); ++ ++ sprintf(lbuff, "%pISpc", &local->srx.transport); ++ ++ seq_printf(seq, ++ "UDP %-47.47s %3u %3u\n", ++ lbuff, ++ atomic_read(&local->usage), ++ atomic_read(&local->active_users)); ++ ++ return 0; ++} ++ ++static void *rxrpc_local_seq_start(struct seq_file *seq, loff_t *_pos) ++ __acquires(rcu) ++{ ++ struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); ++ unsigned int n; ++ ++ rcu_read_lock(); ++ ++ if (*_pos >= UINT_MAX) ++ return NULL; ++ ++ n = *_pos; ++ if (n == 0) ++ return SEQ_START_TOKEN; ++ ++ return seq_hlist_start_rcu(&rxnet->local_endpoints, n - 1); ++} ++ ++static void *rxrpc_local_seq_next(struct seq_file *seq, void *v, loff_t *_pos) ++{ ++ struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); ++ ++ if (*_pos >= UINT_MAX) ++ return NULL; ++ ++ return seq_hlist_next_rcu(v, &rxnet->local_endpoints, _pos); ++} ++ ++static void rxrpc_local_seq_stop(struct seq_file *seq, void *v) ++ __releases(rcu) ++{ ++ rcu_read_unlock(); ++} ++ ++const struct seq_operations rxrpc_local_seq_ops = { ++ .start = rxrpc_local_seq_start, ++ .next = rxrpc_local_seq_next, ++ .stop = rxrpc_local_seq_stop, ++ .show = rxrpc_local_seq_show, ++}; +-- +2.35.1 + diff --git a/queue-5.15/rxrpc-fix-race-between-conn-bundle-lookup-and-bundle.patch b/queue-5.15/rxrpc-fix-race-between-conn-bundle-lookup-and-bundle.patch new file mode 100644 index 00000000000..5904ef5722b --- /dev/null +++ b/queue-5.15/rxrpc-fix-race-between-conn-bundle-lookup-and-bundle.patch @@ -0,0 +1,173 @@ +From 5a9d3fa4412612b3a24698c7270748c5767cf745 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 14:02:28 +0000 +Subject: rxrpc: Fix race between conn bundle lookup and bundle removal + [ZDI-CAN-15975] + +From: David Howells + +[ Upstream commit 3bcd6c7eaa53b56c3f584da46a1f7652e759d0e5 ] + +After rxrpc_unbundle_conn() has removed a connection from a bundle, it +checks to see if there are any conns with available channels and, if not, +removes and attempts to destroy the bundle. + +Whilst it does check after grabbing client_bundles_lock that there are no +connections attached, this races with rxrpc_look_up_bundle() retrieving the +bundle, but not attaching a connection for the connection to be attached +later. + +There is therefore a window in which the bundle can get destroyed before we +manage to attach a new connection to it. + +Fix this by adding an "active" counter to struct rxrpc_bundle: + + (1) rxrpc_connect_call() obtains an active count by prepping/looking up a + bundle and ditches it before returning. + + (2) If, during rxrpc_connect_call(), a connection is added to the bundle, + this obtains an active count, which is held until the connection is + discarded. + + (3) rxrpc_deactivate_bundle() is created to drop an active count on a + bundle and destroy it when the active count reaches 0. The active + count is checked inside client_bundles_lock() to prevent a race with + rxrpc_look_up_bundle(). + + (4) rxrpc_unbundle_conn() then calls rxrpc_deactivate_bundle(). + +Fixes: 245500d853e9 ("rxrpc: Rewrite the client connection manager") +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-15975 +Signed-off-by: David Howells +Tested-by: zdi-disclosures@trendmicro.com +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rxrpc/ar-internal.h | 1 + + net/rxrpc/conn_client.c | 38 +++++++++++++++++++++++--------------- + 2 files changed, 24 insertions(+), 15 deletions(-) + +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index 62c70709d798..e0123efa2a62 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -399,6 +399,7 @@ enum rxrpc_conn_proto_state { + struct rxrpc_bundle { + struct rxrpc_conn_parameters params; + refcount_t ref; ++ atomic_t active; /* Number of active users */ + unsigned int debug_id; + bool try_upgrade; /* True if the bundle is attempting upgrade */ + bool alloc_conn; /* True if someone's getting a conn */ +diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c +index 3c9eeb5b750c..bdb335cb2d05 100644 +--- a/net/rxrpc/conn_client.c ++++ b/net/rxrpc/conn_client.c +@@ -40,6 +40,8 @@ __read_mostly unsigned long rxrpc_conn_idle_client_fast_expiry = 2 * HZ; + DEFINE_IDR(rxrpc_client_conn_ids); + static DEFINE_SPINLOCK(rxrpc_conn_id_lock); + ++static void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle); ++ + /* + * Get a connection ID and epoch for a client connection from the global pool. + * The connection struct pointer is then recorded in the idr radix tree. The +@@ -123,6 +125,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp, + bundle->params = *cp; + rxrpc_get_peer(bundle->params.peer); + refcount_set(&bundle->ref, 1); ++ atomic_set(&bundle->active, 1); + spin_lock_init(&bundle->channel_lock); + INIT_LIST_HEAD(&bundle->waiting_calls); + } +@@ -149,7 +152,7 @@ void rxrpc_put_bundle(struct rxrpc_bundle *bundle) + + dead = __refcount_dec_and_test(&bundle->ref, &r); + +- _debug("PUT B=%x %d", d, r); ++ _debug("PUT B=%x %d", d, r - 1); + if (dead) + rxrpc_free_bundle(bundle); + } +@@ -338,6 +341,7 @@ static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *c + rxrpc_free_bundle(candidate); + found_bundle: + rxrpc_get_bundle(bundle); ++ atomic_inc(&bundle->active); + spin_unlock(&local->client_bundles_lock); + _leave(" = %u [found]", bundle->debug_id); + return bundle; +@@ -435,6 +439,7 @@ static void rxrpc_add_conn_to_bundle(struct rxrpc_bundle *bundle, gfp_t gfp) + if (old) + trace_rxrpc_client(old, -1, rxrpc_client_replace); + candidate->bundle_shift = shift; ++ atomic_inc(&bundle->active); + bundle->conns[i] = candidate; + for (j = 0; j < RXRPC_MAXCALLS; j++) + set_bit(shift + j, &bundle->avail_chans); +@@ -725,6 +730,7 @@ int rxrpc_connect_call(struct rxrpc_sock *rx, + smp_rmb(); + + out_put_bundle: ++ rxrpc_deactivate_bundle(bundle); + rxrpc_put_bundle(bundle); + out: + _leave(" = %d", ret); +@@ -900,9 +906,8 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call + static void rxrpc_unbundle_conn(struct rxrpc_connection *conn) + { + struct rxrpc_bundle *bundle = conn->bundle; +- struct rxrpc_local *local = bundle->params.local; + unsigned int bindex; +- bool need_drop = false, need_put = false; ++ bool need_drop = false; + int i; + + _enter("C=%x", conn->debug_id); +@@ -921,15 +926,22 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn) + } + spin_unlock(&bundle->channel_lock); + +- /* If there are no more connections, remove the bundle */ +- if (!bundle->avail_chans) { +- _debug("maybe unbundle"); +- spin_lock(&local->client_bundles_lock); ++ if (need_drop) { ++ rxrpc_deactivate_bundle(bundle); ++ rxrpc_put_connection(conn); ++ } ++} + +- for (i = 0; i < ARRAY_SIZE(bundle->conns); i++) +- if (bundle->conns[i]) +- break; +- if (i == ARRAY_SIZE(bundle->conns) && !bundle->params.exclusive) { ++/* ++ * Drop the active count on a bundle. ++ */ ++static void rxrpc_deactivate_bundle(struct rxrpc_bundle *bundle) ++{ ++ struct rxrpc_local *local = bundle->params.local; ++ bool need_put = false; ++ ++ if (atomic_dec_and_lock(&bundle->active, &local->client_bundles_lock)) { ++ if (!bundle->params.exclusive) { + _debug("erase bundle"); + rb_erase(&bundle->local_node, &local->client_bundles); + need_put = true; +@@ -939,10 +951,6 @@ static void rxrpc_unbundle_conn(struct rxrpc_connection *conn) + if (need_put) + rxrpc_put_bundle(bundle); + } +- +- if (need_drop) +- rxrpc_put_connection(conn); +- _leave(""); + } + + /* +-- +2.35.1 + diff --git a/queue-5.15/rxrpc-use-refcount_t-rather-than-atomic_t.patch b/queue-5.15/rxrpc-use-refcount_t-rather-than-atomic_t.patch new file mode 100644 index 00000000000..b63131f6480 --- /dev/null +++ b/queue-5.15/rxrpc-use-refcount_t-rather-than-atomic_t.patch @@ -0,0 +1,864 @@ +From 52810344f776ff77fc3b17f9ef57071c00d54613 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 21 May 2022 08:45:22 +0100 +Subject: rxrpc: Use refcount_t rather than atomic_t + +From: David Howells + +[ Upstream commit a05754295e01f006a651eec759c5dbe682ef6cef ] + +Move to using refcount_t rather than atomic_t for refcounts in rxrpc. + +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Signed-off-by: David S. Miller +Stable-dep-of: 3bcd6c7eaa53 ("rxrpc: Fix race between conn bundle lookup and bundle removal [ZDI-CAN-15975]") +Signed-off-by: Sasha Levin +--- + include/trace/events/rxrpc.h | 2 +- + net/rxrpc/af_rxrpc.c | 2 +- + net/rxrpc/ar-internal.h | 18 ++++--------- + net/rxrpc/call_accept.c | 4 +-- + net/rxrpc/call_object.c | 44 ++++++++++++++++---------------- + net/rxrpc/conn_client.c | 30 +++++++++++----------- + net/rxrpc/conn_object.c | 49 ++++++++++++++++++------------------ + net/rxrpc/conn_service.c | 8 +++--- + net/rxrpc/input.c | 4 +-- + net/rxrpc/local_object.c | 31 ++++++++++++----------- + net/rxrpc/peer_object.c | 40 +++++++++++++++-------------- + net/rxrpc/proc.c | 8 +++--- + net/rxrpc/skbuff.c | 1 - + 13 files changed, 119 insertions(+), 122 deletions(-) + +diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h +index 1c714336b863..221856f2d295 100644 +--- a/include/trace/events/rxrpc.h ++++ b/include/trace/events/rxrpc.h +@@ -583,7 +583,7 @@ TRACE_EVENT(rxrpc_client, + TP_fast_assign( + __entry->conn = conn ? conn->debug_id : 0; + __entry->channel = channel; +- __entry->usage = conn ? atomic_read(&conn->usage) : -2; ++ __entry->usage = conn ? refcount_read(&conn->ref) : -2; + __entry->op = op; + __entry->cid = conn ? conn->proto.cid : 0; + ), +diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c +index 2b5f89713e36..ceba28e9dce6 100644 +--- a/net/rxrpc/af_rxrpc.c ++++ b/net/rxrpc/af_rxrpc.c +@@ -351,7 +351,7 @@ static void rxrpc_dummy_notify_rx(struct sock *sk, struct rxrpc_call *rxcall, + */ + void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call) + { +- _enter("%d{%d}", call->debug_id, atomic_read(&call->usage)); ++ _enter("%d{%d}", call->debug_id, refcount_read(&call->ref)); + + mutex_lock(&call->user_mutex); + rxrpc_release_call(rxrpc_sk(sock->sk), call); +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index 38dd63169aac..62c70709d798 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -15,14 +15,6 @@ + #include + #include "protocol.h" + +-#if 0 +-#define CHECK_SLAB_OKAY(X) \ +- BUG_ON(atomic_read((X)) >> (sizeof(atomic_t) - 2) == \ +- (POISON_FREE << 8 | POISON_FREE)) +-#else +-#define CHECK_SLAB_OKAY(X) do {} while (0) +-#endif +- + #define FCRYPT_BSIZE 8 + struct rxrpc_crypt { + union { +@@ -279,7 +271,7 @@ struct rxrpc_security { + struct rxrpc_local { + struct rcu_head rcu; + atomic_t active_users; /* Number of users of the local endpoint */ +- atomic_t usage; /* Number of references to the structure */ ++ refcount_t ref; /* Number of references to the structure */ + struct rxrpc_net *rxnet; /* The network ns in which this resides */ + struct hlist_node link; + struct socket *socket; /* my UDP socket */ +@@ -304,7 +296,7 @@ struct rxrpc_local { + */ + struct rxrpc_peer { + struct rcu_head rcu; /* This must be first */ +- atomic_t usage; ++ refcount_t ref; + unsigned long hash_key; + struct hlist_node hash_link; + struct rxrpc_local *local; +@@ -406,7 +398,7 @@ enum rxrpc_conn_proto_state { + */ + struct rxrpc_bundle { + struct rxrpc_conn_parameters params; +- atomic_t usage; ++ refcount_t ref; + unsigned int debug_id; + bool try_upgrade; /* True if the bundle is attempting upgrade */ + bool alloc_conn; /* True if someone's getting a conn */ +@@ -427,7 +419,7 @@ struct rxrpc_connection { + struct rxrpc_conn_proto proto; + struct rxrpc_conn_parameters params; + +- atomic_t usage; ++ refcount_t ref; + struct rcu_head rcu; + struct list_head cache_link; + +@@ -609,7 +601,7 @@ struct rxrpc_call { + int error; /* Local error incurred */ + enum rxrpc_call_state state; /* current state of call */ + enum rxrpc_call_completion completion; /* Call completion condition */ +- atomic_t usage; ++ refcount_t ref; + u16 service_id; /* service ID */ + u8 security_ix; /* Security type */ + enum rxrpc_interruptibility interruptibility; /* At what point call may be interrupted */ +diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c +index 8b24ffbc72ef..99e10eea3732 100644 +--- a/net/rxrpc/call_accept.c ++++ b/net/rxrpc/call_accept.c +@@ -91,7 +91,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, + (head + 1) & (size - 1)); + + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service, +- atomic_read(&conn->usage), here); ++ refcount_read(&conn->ref), here); + } + + /* Now it gets complicated, because calls get registered with the +@@ -104,7 +104,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, + call->state = RXRPC_CALL_SERVER_PREALLOC; + + trace_rxrpc_call(call->debug_id, rxrpc_call_new_service, +- atomic_read(&call->usage), ++ refcount_read(&call->ref), + here, (const void *)user_call_ID); + + write_lock(&rx->call_lock); +diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c +index d674d90e7031..6401cdf7a624 100644 +--- a/net/rxrpc/call_object.c ++++ b/net/rxrpc/call_object.c +@@ -112,7 +112,7 @@ struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *rx, + found_extant_call: + rxrpc_get_call(call, rxrpc_call_got); + read_unlock(&rx->call_lock); +- _leave(" = %p [%d]", call, atomic_read(&call->usage)); ++ _leave(" = %p [%d]", call, refcount_read(&call->ref)); + return call; + } + +@@ -160,7 +160,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp, + spin_lock_init(&call->notify_lock); + spin_lock_init(&call->input_lock); + rwlock_init(&call->state_lock); +- atomic_set(&call->usage, 1); ++ refcount_set(&call->ref, 1); + call->debug_id = debug_id; + call->tx_total_len = -1; + call->next_rx_timo = 20 * HZ; +@@ -301,7 +301,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, + call->interruptibility = p->interruptibility; + call->tx_total_len = p->tx_total_len; + trace_rxrpc_call(call->debug_id, rxrpc_call_new_client, +- atomic_read(&call->usage), ++ refcount_read(&call->ref), + here, (const void *)p->user_call_ID); + if (p->kernel) + __set_bit(RXRPC_CALL_KERNEL, &call->flags); +@@ -354,7 +354,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, + goto error_attached_to_socket; + + trace_rxrpc_call(call->debug_id, rxrpc_call_connected, +- atomic_read(&call->usage), here, NULL); ++ refcount_read(&call->ref), here, NULL); + + rxrpc_start_call_timer(call); + +@@ -374,7 +374,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, + __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, + RX_CALL_DEAD, -EEXIST); + trace_rxrpc_call(call->debug_id, rxrpc_call_error, +- atomic_read(&call->usage), here, ERR_PTR(-EEXIST)); ++ refcount_read(&call->ref), here, ERR_PTR(-EEXIST)); + rxrpc_release_call(rx, call); + mutex_unlock(&call->user_mutex); + rxrpc_put_call(call, rxrpc_call_put); +@@ -388,7 +388,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, + */ + error_attached_to_socket: + trace_rxrpc_call(call->debug_id, rxrpc_call_error, +- atomic_read(&call->usage), here, ERR_PTR(ret)); ++ refcount_read(&call->ref), here, ERR_PTR(ret)); + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); + __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, + RX_CALL_DEAD, ret); +@@ -444,8 +444,9 @@ void rxrpc_incoming_call(struct rxrpc_sock *rx, + bool rxrpc_queue_call(struct rxrpc_call *call) + { + const void *here = __builtin_return_address(0); +- int n = atomic_fetch_add_unless(&call->usage, 1, 0); +- if (n == 0) ++ int n; ++ ++ if (!__refcount_inc_not_zero(&call->ref, &n)) + return false; + if (rxrpc_queue_work(&call->processor)) + trace_rxrpc_call(call->debug_id, rxrpc_call_queued, n + 1, +@@ -461,7 +462,7 @@ bool rxrpc_queue_call(struct rxrpc_call *call) + bool __rxrpc_queue_call(struct rxrpc_call *call) + { + const void *here = __builtin_return_address(0); +- int n = atomic_read(&call->usage); ++ int n = refcount_read(&call->ref); + ASSERTCMP(n, >=, 1); + if (rxrpc_queue_work(&call->processor)) + trace_rxrpc_call(call->debug_id, rxrpc_call_queued_ref, n, +@@ -478,7 +479,7 @@ void rxrpc_see_call(struct rxrpc_call *call) + { + const void *here = __builtin_return_address(0); + if (call) { +- int n = atomic_read(&call->usage); ++ int n = refcount_read(&call->ref); + + trace_rxrpc_call(call->debug_id, rxrpc_call_seen, n, + here, NULL); +@@ -488,11 +489,11 @@ void rxrpc_see_call(struct rxrpc_call *call) + bool rxrpc_try_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) + { + const void *here = __builtin_return_address(0); +- int n = atomic_fetch_add_unless(&call->usage, 1, 0); ++ int n; + +- if (n == 0) ++ if (!__refcount_inc_not_zero(&call->ref, &n)) + return false; +- trace_rxrpc_call(call->debug_id, op, n, here, NULL); ++ trace_rxrpc_call(call->debug_id, op, n + 1, here, NULL); + return true; + } + +@@ -502,9 +503,10 @@ bool rxrpc_try_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) + void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) + { + const void *here = __builtin_return_address(0); +- int n = atomic_inc_return(&call->usage); ++ int n; + +- trace_rxrpc_call(call->debug_id, op, n, here, NULL); ++ __refcount_inc(&call->ref, &n); ++ trace_rxrpc_call(call->debug_id, op, n + 1, here, NULL); + } + + /* +@@ -529,10 +531,10 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) + struct rxrpc_connection *conn = call->conn; + bool put = false; + +- _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); ++ _enter("{%d,%d}", call->debug_id, refcount_read(&call->ref)); + + trace_rxrpc_call(call->debug_id, rxrpc_call_release, +- atomic_read(&call->usage), ++ refcount_read(&call->ref), + here, (const void *)call->flags); + + ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); +@@ -621,14 +623,14 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) + struct rxrpc_net *rxnet = call->rxnet; + const void *here = __builtin_return_address(0); + unsigned int debug_id = call->debug_id; ++ bool dead; + int n; + + ASSERT(call != NULL); + +- n = atomic_dec_return(&call->usage); ++ dead = __refcount_dec_and_test(&call->ref, &n); + trace_rxrpc_call(debug_id, op, n, here, NULL); +- ASSERTCMP(n, >=, 0); +- if (n == 0) { ++ if (dead) { + _debug("call %d dead", call->debug_id); + ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); + +@@ -718,7 +720,7 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet) + list_del_init(&call->link); + + pr_err("Call %p still in use (%d,%s,%lx,%lx)!\n", +- call, atomic_read(&call->usage), ++ call, refcount_read(&call->ref), + rxrpc_call_states[call->state], + call->flags, call->events); + +diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c +index 8120138dac01..3c9eeb5b750c 100644 +--- a/net/rxrpc/conn_client.c ++++ b/net/rxrpc/conn_client.c +@@ -102,7 +102,7 @@ void rxrpc_destroy_client_conn_ids(void) + if (!idr_is_empty(&rxrpc_client_conn_ids)) { + idr_for_each_entry(&rxrpc_client_conn_ids, conn, id) { + pr_err("AF_RXRPC: Leaked client conn %p {%d}\n", +- conn, atomic_read(&conn->usage)); ++ conn, refcount_read(&conn->ref)); + } + BUG(); + } +@@ -122,7 +122,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp, + if (bundle) { + bundle->params = *cp; + rxrpc_get_peer(bundle->params.peer); +- atomic_set(&bundle->usage, 1); ++ refcount_set(&bundle->ref, 1); + spin_lock_init(&bundle->channel_lock); + INIT_LIST_HEAD(&bundle->waiting_calls); + } +@@ -131,7 +131,7 @@ static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_conn_parameters *cp, + + struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle) + { +- atomic_inc(&bundle->usage); ++ refcount_inc(&bundle->ref); + return bundle; + } + +@@ -144,10 +144,13 @@ static void rxrpc_free_bundle(struct rxrpc_bundle *bundle) + void rxrpc_put_bundle(struct rxrpc_bundle *bundle) + { + unsigned int d = bundle->debug_id; +- unsigned int u = atomic_dec_return(&bundle->usage); ++ bool dead; ++ int r; + +- _debug("PUT B=%x %u", d, u); +- if (u == 0) ++ dead = __refcount_dec_and_test(&bundle->ref, &r); ++ ++ _debug("PUT B=%x %d", d, r); ++ if (dead) + rxrpc_free_bundle(bundle); + } + +@@ -169,7 +172,7 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp) + return ERR_PTR(-ENOMEM); + } + +- atomic_set(&conn->usage, 1); ++ refcount_set(&conn->ref, 1); + conn->bundle = bundle; + conn->params = bundle->params; + conn->out_clientflag = RXRPC_CLIENT_INITIATED; +@@ -195,7 +198,7 @@ rxrpc_alloc_client_connection(struct rxrpc_bundle *bundle, gfp_t gfp) + key_get(conn->params.key); + + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_client, +- atomic_read(&conn->usage), ++ refcount_read(&conn->ref), + __builtin_return_address(0)); + + atomic_inc(&rxnet->nr_client_conns); +@@ -966,14 +969,13 @@ void rxrpc_put_client_conn(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id = conn->debug_id; +- int n; ++ bool dead; ++ int r; + +- n = atomic_dec_return(&conn->usage); +- trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, n, here); +- if (n <= 0) { +- ASSERTCMP(n, >=, 0); ++ dead = __refcount_dec_and_test(&conn->ref, &r); ++ trace_rxrpc_conn(debug_id, rxrpc_conn_put_client, r - 1, here); ++ if (dead) + rxrpc_kill_client_conn(conn); +- } + } + + /* +diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c +index 660cd9b1a465..22089e37e97f 100644 +--- a/net/rxrpc/conn_object.c ++++ b/net/rxrpc/conn_object.c +@@ -104,7 +104,7 @@ struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local, + goto not_found; + *_peer = peer; + conn = rxrpc_find_service_conn_rcu(peer, skb); +- if (!conn || atomic_read(&conn->usage) == 0) ++ if (!conn || refcount_read(&conn->ref) == 0) + goto not_found; + _leave(" = %p", conn); + return conn; +@@ -114,7 +114,7 @@ struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local, + */ + conn = idr_find(&rxrpc_client_conn_ids, + sp->hdr.cid >> RXRPC_CIDSHIFT); +- if (!conn || atomic_read(&conn->usage) == 0) { ++ if (!conn || refcount_read(&conn->ref) == 0) { + _debug("no conn"); + goto not_found; + } +@@ -263,11 +263,12 @@ void rxrpc_kill_connection(struct rxrpc_connection *conn) + bool rxrpc_queue_conn(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); +- int n = atomic_fetch_add_unless(&conn->usage, 1, 0); +- if (n == 0) ++ int r; ++ ++ if (!__refcount_inc_not_zero(&conn->ref, &r)) + return false; + if (rxrpc_queue_work(&conn->processor)) +- trace_rxrpc_conn(conn->debug_id, rxrpc_conn_queued, n + 1, here); ++ trace_rxrpc_conn(conn->debug_id, rxrpc_conn_queued, r + 1, here); + else + rxrpc_put_connection(conn); + return true; +@@ -280,7 +281,7 @@ void rxrpc_see_connection(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); + if (conn) { +- int n = atomic_read(&conn->usage); ++ int n = refcount_read(&conn->ref); + + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_seen, n, here); + } +@@ -292,9 +293,10 @@ void rxrpc_see_connection(struct rxrpc_connection *conn) + struct rxrpc_connection *rxrpc_get_connection(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); +- int n = atomic_inc_return(&conn->usage); ++ int r; + +- trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here); ++ __refcount_inc(&conn->ref, &r); ++ trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, r, here); + return conn; + } + +@@ -305,11 +307,11 @@ struct rxrpc_connection * + rxrpc_get_connection_maybe(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); ++ int r; + + if (conn) { +- int n = atomic_fetch_add_unless(&conn->usage, 1, 0); +- if (n > 0) +- trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n + 1, here); ++ if (__refcount_inc_not_zero(&conn->ref, &r)) ++ trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, r + 1, here); + else + conn = NULL; + } +@@ -333,12 +335,11 @@ void rxrpc_put_service_conn(struct rxrpc_connection *conn) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id = conn->debug_id; +- int n; ++ int r; + +- n = atomic_dec_return(&conn->usage); +- trace_rxrpc_conn(debug_id, rxrpc_conn_put_service, n, here); +- ASSERTCMP(n, >=, 0); +- if (n == 1) ++ __refcount_dec(&conn->ref, &r); ++ trace_rxrpc_conn(debug_id, rxrpc_conn_put_service, r - 1, here); ++ if (r - 1 == 1) + rxrpc_set_service_reap_timer(conn->params.local->rxnet, + jiffies + rxrpc_connection_expiry); + } +@@ -351,9 +352,9 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu) + struct rxrpc_connection *conn = + container_of(rcu, struct rxrpc_connection, rcu); + +- _enter("{%d,u=%d}", conn->debug_id, atomic_read(&conn->usage)); ++ _enter("{%d,u=%d}", conn->debug_id, refcount_read(&conn->ref)); + +- ASSERTCMP(atomic_read(&conn->usage), ==, 0); ++ ASSERTCMP(refcount_read(&conn->ref), ==, 0); + + _net("DESTROY CONN %d", conn->debug_id); + +@@ -392,8 +393,8 @@ void rxrpc_service_connection_reaper(struct work_struct *work) + + write_lock(&rxnet->conn_lock); + list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) { +- ASSERTCMP(atomic_read(&conn->usage), >, 0); +- if (likely(atomic_read(&conn->usage) > 1)) ++ ASSERTCMP(refcount_read(&conn->ref), >, 0); ++ if (likely(refcount_read(&conn->ref) > 1)) + continue; + if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) + continue; +@@ -405,7 +406,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) + expire_at = idle_timestamp + rxrpc_closed_conn_expiry * HZ; + + _debug("reap CONN %d { u=%d,t=%ld }", +- conn->debug_id, atomic_read(&conn->usage), ++ conn->debug_id, refcount_read(&conn->ref), + (long)expire_at - (long)now); + + if (time_before(now, expire_at)) { +@@ -418,7 +419,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) + /* The usage count sits at 1 whilst the object is unused on the + * list; we reduce that to 0 to make the object unavailable. + */ +- if (atomic_cmpxchg(&conn->usage, 1, 0) != 1) ++ if (!refcount_dec_if_one(&conn->ref)) + continue; + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_reap_service, 0, NULL); + +@@ -442,7 +443,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) + link); + list_del_init(&conn->link); + +- ASSERTCMP(atomic_read(&conn->usage), ==, 0); ++ ASSERTCMP(refcount_read(&conn->ref), ==, 0); + rxrpc_kill_connection(conn); + } + +@@ -470,7 +471,7 @@ void rxrpc_destroy_all_connections(struct rxrpc_net *rxnet) + write_lock(&rxnet->conn_lock); + list_for_each_entry_safe(conn, _p, &rxnet->service_conns, link) { + pr_err("AF_RXRPC: Leaked conn %p {%d}\n", +- conn, atomic_read(&conn->usage)); ++ conn, refcount_read(&conn->ref)); + leak = true; + } + write_unlock(&rxnet->conn_lock); +diff --git a/net/rxrpc/conn_service.c b/net/rxrpc/conn_service.c +index e1966dfc9152..6e6aa02c6f9e 100644 +--- a/net/rxrpc/conn_service.c ++++ b/net/rxrpc/conn_service.c +@@ -9,7 +9,7 @@ + #include "ar-internal.h" + + static struct rxrpc_bundle rxrpc_service_dummy_bundle = { +- .usage = ATOMIC_INIT(1), ++ .ref = REFCOUNT_INIT(1), + .debug_id = UINT_MAX, + .channel_lock = __SPIN_LOCK_UNLOCKED(&rxrpc_service_dummy_bundle.channel_lock), + }; +@@ -99,7 +99,7 @@ static void rxrpc_publish_service_conn(struct rxrpc_peer *peer, + return; + + found_extant_conn: +- if (atomic_read(&cursor->usage) == 0) ++ if (refcount_read(&cursor->ref) == 0) + goto replace_old_connection; + write_sequnlock_bh(&peer->service_conn_lock); + /* We should not be able to get here. rxrpc_incoming_connection() is +@@ -132,7 +132,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn + * the rxrpc_connections list. + */ + conn->state = RXRPC_CONN_SERVICE_PREALLOC; +- atomic_set(&conn->usage, 2); ++ refcount_set(&conn->ref, 2); + conn->bundle = rxrpc_get_bundle(&rxrpc_service_dummy_bundle); + + atomic_inc(&rxnet->nr_conns); +@@ -142,7 +142,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn + write_unlock(&rxnet->conn_lock); + + trace_rxrpc_conn(conn->debug_id, rxrpc_conn_new_service, +- atomic_read(&conn->usage), ++ refcount_read(&conn->ref), + __builtin_return_address(0)); + } + +diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c +index 3521ebd0ee41..721d847ba92b 100644 +--- a/net/rxrpc/input.c ++++ b/net/rxrpc/input.c +@@ -1190,8 +1190,6 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local, + */ + static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) + { +- CHECK_SLAB_OKAY(&local->usage); +- + if (rxrpc_get_local_maybe(local)) { + skb_queue_tail(&local->reject_queue, skb); + rxrpc_queue_local(local); +@@ -1449,7 +1447,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) + } + } + +- if (!call || atomic_read(&call->usage) == 0) { ++ if (!call || refcount_read(&call->ref) == 0) { + if (rxrpc_to_client(sp) || + sp->hdr.type != RXRPC_PACKET_TYPE_DATA) + goto bad_message; +diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c +index 0cbbbbcf490e..38ea98ff426b 100644 +--- a/net/rxrpc/local_object.c ++++ b/net/rxrpc/local_object.c +@@ -79,7 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, + + local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL); + if (local) { +- atomic_set(&local->usage, 1); ++ refcount_set(&local->ref, 1); + atomic_set(&local->active_users, 1); + local->rxnet = rxnet; + INIT_HLIST_NODE(&local->link); +@@ -266,10 +266,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, + struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local) + { + const void *here = __builtin_return_address(0); +- int n; ++ int r; + +- n = atomic_inc_return(&local->usage); +- trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here); ++ __refcount_inc(&local->ref, &r); ++ trace_rxrpc_local(local->debug_id, rxrpc_local_got, r + 1, here); + return local; + } + +@@ -279,12 +279,12 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local) + struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local) + { + const void *here = __builtin_return_address(0); ++ int r; + + if (local) { +- int n = atomic_fetch_add_unless(&local->usage, 1, 0); +- if (n > 0) ++ if (__refcount_inc_not_zero(&local->ref, &r)) + trace_rxrpc_local(local->debug_id, rxrpc_local_got, +- n + 1, here); ++ r + 1, here); + else + local = NULL; + } +@@ -298,10 +298,10 @@ void rxrpc_queue_local(struct rxrpc_local *local) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id = local->debug_id; +- int n = atomic_read(&local->usage); ++ int r = refcount_read(&local->ref); + + if (rxrpc_queue_work(&local->processor)) +- trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here); ++ trace_rxrpc_local(debug_id, rxrpc_local_queued, r + 1, here); + else + rxrpc_put_local(local); + } +@@ -313,15 +313,16 @@ void rxrpc_put_local(struct rxrpc_local *local) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id; +- int n; ++ bool dead; ++ int r; + + if (local) { + debug_id = local->debug_id; + +- n = atomic_dec_return(&local->usage); +- trace_rxrpc_local(debug_id, rxrpc_local_put, n, here); ++ dead = __refcount_dec_and_test(&local->ref, &r); ++ trace_rxrpc_local(debug_id, rxrpc_local_put, r, here); + +- if (n == 0) ++ if (dead) + call_rcu(&local->rcu, rxrpc_local_rcu); + } + } +@@ -409,7 +410,7 @@ static void rxrpc_local_processor(struct work_struct *work) + return; + + trace_rxrpc_local(local->debug_id, rxrpc_local_processing, +- atomic_read(&local->usage), NULL); ++ refcount_read(&local->ref), NULL); + + do { + again = false; +@@ -465,7 +466,7 @@ void rxrpc_destroy_all_locals(struct rxrpc_net *rxnet) + mutex_lock(&rxnet->local_mutex); + hlist_for_each_entry(local, &rxnet->local_endpoints, link) { + pr_err("AF_RXRPC: Leaked local %p {%d}\n", +- local, atomic_read(&local->usage)); ++ local, refcount_read(&local->ref)); + } + mutex_unlock(&rxnet->local_mutex); + BUG(); +diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c +index 0298fe2ad6d3..26d2ae9baaf2 100644 +--- a/net/rxrpc/peer_object.c ++++ b/net/rxrpc/peer_object.c +@@ -121,7 +121,7 @@ static struct rxrpc_peer *__rxrpc_lookup_peer_rcu( + + hash_for_each_possible_rcu(rxnet->peer_hash, peer, hash_link, hash_key) { + if (rxrpc_peer_cmp_key(peer, local, srx, hash_key) == 0 && +- atomic_read(&peer->usage) > 0) ++ refcount_read(&peer->ref) > 0) + return peer; + } + +@@ -140,7 +140,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *local, + peer = __rxrpc_lookup_peer_rcu(local, srx, hash_key); + if (peer) { + _net("PEER %d {%pISp}", peer->debug_id, &peer->srx.transport); +- _leave(" = %p {u=%d}", peer, atomic_read(&peer->usage)); ++ _leave(" = %p {u=%d}", peer, refcount_read(&peer->ref)); + } + return peer; + } +@@ -216,7 +216,7 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp) + + peer = kzalloc(sizeof(struct rxrpc_peer), gfp); + if (peer) { +- atomic_set(&peer->usage, 1); ++ refcount_set(&peer->ref, 1); + peer->local = rxrpc_get_local(local); + INIT_HLIST_HEAD(&peer->error_targets); + peer->service_conns = RB_ROOT; +@@ -378,7 +378,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx, + + _net("PEER %d {%pISp}", peer->debug_id, &peer->srx.transport); + +- _leave(" = %p {u=%d}", peer, atomic_read(&peer->usage)); ++ _leave(" = %p {u=%d}", peer, refcount_read(&peer->ref)); + return peer; + } + +@@ -388,10 +388,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx, + struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer) + { + const void *here = __builtin_return_address(0); +- int n; ++ int r; + +- n = atomic_inc_return(&peer->usage); +- trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n, here); ++ __refcount_inc(&peer->ref, &r); ++ trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, r + 1, here); + return peer; + } + +@@ -401,11 +401,11 @@ struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer) + struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *peer) + { + const void *here = __builtin_return_address(0); ++ int r; + + if (peer) { +- int n = atomic_fetch_add_unless(&peer->usage, 1, 0); +- if (n > 0) +- trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, n + 1, here); ++ if (__refcount_inc_not_zero(&peer->ref, &r)) ++ trace_rxrpc_peer(peer->debug_id, rxrpc_peer_got, r + 1, here); + else + peer = NULL; + } +@@ -436,13 +436,14 @@ void rxrpc_put_peer(struct rxrpc_peer *peer) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id; +- int n; ++ bool dead; ++ int r; + + if (peer) { + debug_id = peer->debug_id; +- n = atomic_dec_return(&peer->usage); +- trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here); +- if (n == 0) ++ dead = __refcount_dec_and_test(&peer->ref, &r); ++ trace_rxrpc_peer(debug_id, rxrpc_peer_put, r - 1, here); ++ if (dead) + __rxrpc_put_peer(peer); + } + } +@@ -455,11 +456,12 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer) + { + const void *here = __builtin_return_address(0); + unsigned int debug_id = peer->debug_id; +- int n; ++ bool dead; ++ int r; + +- n = atomic_dec_return(&peer->usage); +- trace_rxrpc_peer(debug_id, rxrpc_peer_put, n, here); +- if (n == 0) { ++ dead = __refcount_dec_and_test(&peer->ref, &r); ++ trace_rxrpc_peer(debug_id, rxrpc_peer_put, r - 1, here); ++ if (dead) { + hash_del_rcu(&peer->hash_link); + list_del_init(&peer->keepalive_link); + rxrpc_free_peer(peer); +@@ -481,7 +483,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet) + hlist_for_each_entry(peer, &rxnet->peer_hash[i], hash_link) { + pr_err("Leaked peer %u {%u} %pISp\n", + peer->debug_id, +- atomic_read(&peer->usage), ++ refcount_read(&peer->ref), + &peer->srx.transport); + } + } +diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c +index 7d007a66eba5..245418943e01 100644 +--- a/net/rxrpc/proc.c ++++ b/net/rxrpc/proc.c +@@ -101,7 +101,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) + call->cid, + call->call_id, + rxrpc_is_service_call(call) ? "Svc" : "Clt", +- atomic_read(&call->usage), ++ refcount_read(&call->ref), + rxrpc_call_states[call->state], + call->abort_code, + call->debug_id, +@@ -183,7 +183,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) + conn->service_id, + conn->proto.cid, + rxrpc_conn_is_service(conn) ? "Svc" : "Clt", +- atomic_read(&conn->usage), ++ refcount_read(&conn->ref), + rxrpc_conn_states[conn->state], + key_serial(conn->params.key), + atomic_read(&conn->serial), +@@ -233,7 +233,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) + " %3u %5u %6llus %8u %8u\n", + lbuff, + rbuff, +- atomic_read(&peer->usage), ++ refcount_read(&peer->ref), + peer->cong_cwnd, + peer->mtu, + now - peer->last_tx_at, +@@ -351,7 +351,7 @@ static int rxrpc_local_seq_show(struct seq_file *seq, void *v) + seq_printf(seq, + "UDP %-47.47s %3u %3u\n", + lbuff, +- atomic_read(&local->usage), ++ refcount_read(&local->ref), + atomic_read(&local->active_users)); + + return 0; +diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c +index 0348d2bf6f7d..580a5acffee7 100644 +--- a/net/rxrpc/skbuff.c ++++ b/net/rxrpc/skbuff.c +@@ -71,7 +71,6 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) + const void *here = __builtin_return_address(0); + if (skb) { + int n; +- CHECK_SLAB_OKAY(&skb->users); + n = atomic_dec_return(select_skb_count(skb)); + trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, + rxrpc_skb(skb)->rx_flags, here); +-- +2.35.1 + diff --git a/queue-5.15/s390-crashdump-fix-tod-programmable-field-size.patch b/queue-5.15/s390-crashdump-fix-tod-programmable-field-size.patch new file mode 100644 index 00000000000..8d68250a856 --- /dev/null +++ b/queue-5.15/s390-crashdump-fix-tod-programmable-field-size.patch @@ -0,0 +1,61 @@ +From 2a5bfbc1f57cc735571a635a409f4b2c5de762ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 13:05:39 +0100 +Subject: s390/crashdump: fix TOD programmable field size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Heiko Carstens + +[ Upstream commit f44e07a8afdd713ddc1a8832c39372fe5dd86895 ] + +The size of the TOD programmable field was incorrectly increased from +four to eight bytes with commit 1a2c5840acf9 ("s390/dump: cleanup CPU +save area handling"). +This leads to an elf notes section NT_S390_TODPREG which has a size of +eight instead of four bytes in case of kdump, however even worse is +that the contents is incorrect: it is supposed to contain only the +contents of the TOD programmable field, but in fact contains a mix of +the TOD programmable field (32 bit upper bits) and parts of the CPU +timer register (lower 32 bits). + +Fix this by simply changing the size of the todpreg field within the +save area structure. This will implicitly also fix the size of the +corresponding elf notes sections. + +This also gets rid of this compile time warning: + +in function ‘fortify_memcpy_chk’, + inlined from ‘save_area_add_regs’ at arch/s390/kernel/crash_dump.c:99:2: +./include/linux/fortify-string.h:413:25: error: call to ‘__read_overflow2_field’ + declared with attribute warning: detected read beyond size of field + (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning] + 413 | __read_overflow2_field(q_size_field, size); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Fixes: 1a2c5840acf9 ("s390/dump: cleanup CPU save area handling") +Reviewed-by: Christian Borntraeger +Signed-off-by: Heiko Carstens +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + arch/s390/kernel/crash_dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c +index f17ad2daab07..8722bd07c607 100644 +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -44,7 +44,7 @@ struct save_area { + u64 fprs[16]; + u32 fpc; + u32 prefix; +- u64 todpreg; ++ u32 todpreg; + u64 timer; + u64 todcmp; + u64 vxrs_low[16]; +-- +2.35.1 + diff --git a/queue-5.15/s390-dasd-fix-no-record-found-for-raw_track_access.patch b/queue-5.15/s390-dasd-fix-no-record-found-for-raw_track_access.patch new file mode 100644 index 00000000000..7163e5bff63 --- /dev/null +++ b/queue-5.15/s390-dasd-fix-no-record-found-for-raw_track_access.patch @@ -0,0 +1,75 @@ +From a6b30514704c966d0335f42c8b89413b556f051b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 17:07:18 +0100 +Subject: s390/dasd: fix no record found for raw_track_access + +From: Stefan Haberland + +[ Upstream commit 590ce6d96d6a224b470a3862c33a483d5022bfdb ] + +For DASD devices in raw_track_access mode only full track images are +read and written. +For this purpose it is not necessary to do search operation in the +locate record extended function. The documentation even states that +this might fail if the searched record is not found on a track. + +Currently the driver sets a value of 1 in the search field for the first +record after record zero. This is the default for disks not in +raw_track_access mode but record 1 might be missing on a completely +empty track. + +There has not been any problem with this on IBM storage servers but it +might lead to errors with DASD devices on other vendors storage servers. + +Fix this by setting the search field to 0. Record zero is always available +even on a completely empty track. + +Fixes: e4dbb0f2b5dd ("[S390] dasd: Add support for raw ECKD access.") +Signed-off-by: Stefan Haberland +Reviewed-by: Jan Hoeppner +Link: https://lore.kernel.org/r/20221123160719.3002694-4-sth@linux.ibm.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/s390/block/dasd_eckd.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c +index ff7b7d470e96..57dfc92aa756 100644 +--- a/drivers/s390/block/dasd_eckd.c ++++ b/drivers/s390/block/dasd_eckd.c +@@ -4696,7 +4696,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, + struct dasd_device *basedev; + struct req_iterator iter; + struct dasd_ccw_req *cqr; +- unsigned int first_offs; + unsigned int trkcount; + unsigned long *idaws; + unsigned int size; +@@ -4730,7 +4729,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, + last_trk = (blk_rq_pos(req) + blk_rq_sectors(req) - 1) / + DASD_RAW_SECTORS_PER_TRACK; + trkcount = last_trk - first_trk + 1; +- first_offs = 0; + + if (rq_data_dir(req) == READ) + cmd = DASD_ECKD_CCW_READ_TRACK; +@@ -4774,13 +4772,13 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev, + + if (use_prefix) { + prefix_LRE(ccw++, data, first_trk, last_trk, cmd, basedev, +- startdev, 1, first_offs + 1, trkcount, 0, 0); ++ startdev, 1, 0, trkcount, 0, 0); + } else { + define_extent(ccw++, data, first_trk, last_trk, cmd, basedev, 0); + ccw[-1].flags |= CCW_FLAG_CC; + + data += sizeof(struct DE_eckd_data); +- locate_record_ext(ccw++, data, first_trk, first_offs + 1, ++ locate_record_ext(ccw++, data, first_trk, 0, + trkcount, cmd, basedev, 0, 0); + } + +-- +2.35.1 + diff --git a/queue-5.15/scsi-storvsc-fix-handling-of-srb_status-and-capacity.patch b/queue-5.15/scsi-storvsc-fix-handling-of-srb_status-and-capacity.patch new file mode 100644 index 00000000000..745d487581f --- /dev/null +++ b/queue-5.15/scsi-storvsc-fix-handling-of-srb_status-and-capacity.patch @@ -0,0 +1,148 @@ +From 7da41f2dd3fe0029c0a6411c8fe63390be4b92f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 10:48:42 -0800 +Subject: scsi: storvsc: Fix handling of srb_status and capacity change events + +From: Michael Kelley + +[ Upstream commit b8a5376c321b4669f7ffabc708fd30c3970f3084 ] + +Current handling of the srb_status is incorrect. Commit 52e1b3b3daa9 +("scsi: storvsc: Correctly handle multiple flags in srb_status") +is based on srb_status being a set of flags, when in fact only the +2 high order bits are flags and the remaining 6 bits are an integer +status. Because the integer values of interest mostly look like flags, +the code actually works when treated that way. + +But in the interest of correctness going forward, fix this by treating +the low 6 bits of srb_status as an integer status code. Add handling +for SRB_STATUS_INVALID_REQUEST, which was the original intent of commit +52e1b3b3daa9. Furthermore, treat the ERROR, ABORTED, and INVALID_REQUEST +srb status codes as essentially equivalent for the cases we care about. +There's no harm in doing so, and it isn't always clear which status code +current or older versions of Hyper-V report for particular conditions. + +Treating the srb status codes as equivalent has the additional benefit +of ensuring that capacity change events result in an immediate rescan +so that the new size is known to Linux. Existing code checks SCSI +sense data for capacity change events when the srb status is ABORTED. +But capacity change events are also being observed when Hyper-V reports +the srb status as ERROR. Without the immediate rescan, the new size +isn't known until something else causes a rescan (such as running +fdisk to expand a partition), and in the meantime, tools such as "lsblk" +continue to report the old size. + +Fixes: 52e1b3b3daa9 ("scsi: storvsc: Correctly handle multiple flags in srb_status") +Reported-by: Juan Tian +Signed-off-by: Michael Kelley +Link: https://lore.kernel.org/r/1668019722-1983-1-git-send-email-mikelley@microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + drivers/scsi/storvsc_drv.c | 69 +++++++++++++++++++------------------- + 1 file changed, 34 insertions(+), 35 deletions(-) + +diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c +index 3d03e1ca5820..6110dfd903f7 100644 +--- a/drivers/scsi/storvsc_drv.c ++++ b/drivers/scsi/storvsc_drv.c +@@ -344,16 +344,21 @@ enum storvsc_request_type { + }; + + /* +- * SRB status codes and masks; a subset of the codes used here. ++ * SRB status codes and masks. In the 8-bit field, the two high order bits ++ * are flags, while the remaining 6 bits are an integer status code. The ++ * definitions here include only the subset of the integer status codes that ++ * are tested for in this driver. + */ +- + #define SRB_STATUS_AUTOSENSE_VALID 0x80 + #define SRB_STATUS_QUEUE_FROZEN 0x40 +-#define SRB_STATUS_INVALID_LUN 0x20 +-#define SRB_STATUS_SUCCESS 0x01 +-#define SRB_STATUS_ABORTED 0x02 +-#define SRB_STATUS_ERROR 0x04 +-#define SRB_STATUS_DATA_OVERRUN 0x12 ++ ++/* SRB status integer codes */ ++#define SRB_STATUS_SUCCESS 0x01 ++#define SRB_STATUS_ABORTED 0x02 ++#define SRB_STATUS_ERROR 0x04 ++#define SRB_STATUS_INVALID_REQUEST 0x06 ++#define SRB_STATUS_DATA_OVERRUN 0x12 ++#define SRB_STATUS_INVALID_LUN 0x20 + + #define SRB_STATUS(status) \ + (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) +@@ -1032,38 +1037,25 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, + void (*process_err_fn)(struct work_struct *work); + struct hv_host_device *host_dev = shost_priv(host); + +- /* +- * In some situations, Hyper-V sets multiple bits in the +- * srb_status, such as ABORTED and ERROR. So process them +- * individually, with the most specific bits first. +- */ +- +- if (vm_srb->srb_status & SRB_STATUS_INVALID_LUN) { +- set_host_byte(scmnd, DID_NO_CONNECT); +- process_err_fn = storvsc_remove_lun; +- goto do_work; +- } ++ switch (SRB_STATUS(vm_srb->srb_status)) { ++ case SRB_STATUS_ERROR: ++ case SRB_STATUS_ABORTED: ++ case SRB_STATUS_INVALID_REQUEST: ++ if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) { ++ /* Check for capacity change */ ++ if ((asc == 0x2a) && (ascq == 0x9)) { ++ process_err_fn = storvsc_device_scan; ++ /* Retry the I/O that triggered this. */ ++ set_host_byte(scmnd, DID_REQUEUE); ++ goto do_work; ++ } + +- if (vm_srb->srb_status & SRB_STATUS_ABORTED) { +- if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && +- /* Capacity data has changed */ +- (asc == 0x2a) && (ascq == 0x9)) { +- process_err_fn = storvsc_device_scan; + /* +- * Retry the I/O that triggered this. ++ * Otherwise, let upper layer deal with the ++ * error when sense message is present + */ +- set_host_byte(scmnd, DID_REQUEUE); +- goto do_work; +- } +- } +- +- if (vm_srb->srb_status & SRB_STATUS_ERROR) { +- /* +- * Let upper layer deal with error when +- * sense message is present. +- */ +- if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) + return; ++ } + + /* + * If there is an error; offline the device since all +@@ -1086,6 +1078,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, + default: + set_host_byte(scmnd, DID_ERROR); + } ++ return; ++ ++ case SRB_STATUS_INVALID_LUN: ++ set_host_byte(scmnd, DID_NO_CONNECT); ++ process_err_fn = storvsc_remove_lun; ++ goto do_work; ++ + } + return; + +-- +2.35.1 + diff --git a/queue-5.15/selftests-mptcp-fix-mibit-vs-mbit-mix-up.patch b/queue-5.15/selftests-mptcp-fix-mibit-vs-mbit-mix-up.patch new file mode 100644 index 00000000000..c15890391c2 --- /dev/null +++ b/queue-5.15/selftests-mptcp-fix-mibit-vs-mbit-mix-up.patch @@ -0,0 +1,52 @@ +From c5c85137406754ef5dc63dc0d4f884bd4607d443 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 14:10:46 -0800 +Subject: selftests: mptcp: fix mibit vs mbit mix up + +From: Matthieu Baerts + +[ Upstream commit 3de88b95c4d436d78afc0266a0bed76c35ddeb62 ] + +The estimated time was supposing the rate was expressed in mibit +(bit * 1024^2) but it is in mbit (bit * 1000^2). + +This makes the threshold higher but in a more realistic way to avoid +false positives reported by CI instances. + +Before this patch, the thresholds were at 7561/4005ms and now they are +at 7906/4178ms. + +While at it, also fix a typo in the linked comment, spotted by Mat. + +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/310 +Fixes: 1a418cb8e888 ("mptcp: simult flow self-tests") +Suggested-by: Paolo Abeni +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts +Signed-off-by: Mat Martineau +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/mptcp/simult_flows.sh | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index f441ff7904fc..7df4900dfaf7 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -235,9 +235,10 @@ run_test() + tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1 + tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2 + +- # time is measured in ms, account for transfer size, affegated link speed ++ # time is measured in ms, account for transfer size, aggregated link speed + # and header overhead (10%) +- local time=$((size * 8 * 1000 * 10 / (( $rate1 + $rate2) * 1024 *1024 * 9) )) ++ # ms byte -> bit 10% mbit -> kbit -> bit 10% ++ local time=$((1000 * size * 8 * 10 / ((rate1 + rate2) * 1000 * 1000 * 9) )) + + # mptcp_connect will do some sleeps to allow the mp_join handshake + # completion (see mptcp_connect): 200ms on each side, add some slack +-- +2.35.1 + diff --git a/queue-5.15/selftests-mptcp-more-stable-simult_flows-tests.patch b/queue-5.15/selftests-mptcp-more-stable-simult_flows-tests.patch new file mode 100644 index 00000000000..81b2ba1f70e --- /dev/null +++ b/queue-5.15/selftests-mptcp-more-stable-simult_flows-tests.patch @@ -0,0 +1,325 @@ +From efb651ce6f2679cae1fe3c98ac5ec267e1218779 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Oct 2021 16:55:59 -0700 +Subject: selftests: mptcp: more stable simult_flows tests + +From: Paolo Abeni + +[ Upstream commit b6ab64b074f29b42ff272793806efc913f7cc742 ] + +Currently the simult_flows.sh self-tests are not very stable, +especially when running on slow VMs. + +The tests measure runtime for transfers on multiple subflows +and check that the time is near the theoretical maximum. + +The current test infra introduces a bit of jitter in test +runtime, due to multiple explicit delays. Additionally the +runtime is measured by the shell script wrapper. On a slow +VM, the script overhead is measurable and subject to relevant +jitter. + +One solution to make the test more stable would be adding more +slack to the expected time; that could possibly hide real +regressions. Instead move the measurement inside the command +doing the transfer, and drop most unneeded sleeps. + +Reviewed-by: Matthieu Baerts +Signed-off-by: Paolo Abeni +Signed-off-by: Mat Martineau +Signed-off-by: David S. Miller +Stable-dep-of: 3de88b95c4d4 ("selftests: mptcp: fix mibit vs mbit mix up") +Signed-off-by: Sasha Levin +--- + .../selftests/net/mptcp/mptcp_connect.c | 72 +++++++++++++++---- + .../selftests/net/mptcp/simult_flows.sh | 36 ++++------ + 2 files changed, 72 insertions(+), 36 deletions(-) + +diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c +index 89c4753c2760..95e81d557b08 100644 +--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c ++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -64,6 +65,7 @@ static int cfg_sndbuf; + static int cfg_rcvbuf; + static bool cfg_join; + static bool cfg_remove; ++static unsigned int cfg_time; + static unsigned int cfg_do_w; + static int cfg_wait; + static uint32_t cfg_mark; +@@ -78,9 +80,10 @@ static struct cfg_cmsg_types cfg_cmsg_types; + static void die_usage(void) + { + fprintf(stderr, "Usage: mptcp_connect [-6] [-u] [-s MPTCP|TCP] [-p port] [-m mode]" +- "[-l] [-w sec] connect_address\n"); ++ "[-l] [-w sec] [-t num] [-T num] connect_address\n"); + fprintf(stderr, "\t-6 use ipv6\n"); + fprintf(stderr, "\t-t num -- set poll timeout to num\n"); ++ fprintf(stderr, "\t-T num -- set expected runtime to num ms\n"); + fprintf(stderr, "\t-S num -- set SO_SNDBUF to num\n"); + fprintf(stderr, "\t-R num -- set SO_RCVBUF to num\n"); + fprintf(stderr, "\t-p num -- use port num\n"); +@@ -448,7 +451,7 @@ static void set_nonblock(int fd) + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + } + +-static int copyfd_io_poll(int infd, int peerfd, int outfd) ++static int copyfd_io_poll(int infd, int peerfd, int outfd, bool *in_closed_after_out) + { + struct pollfd fds = { + .fd = peerfd, +@@ -487,9 +490,11 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd) + */ + fds.events &= ~POLLIN; + +- if ((fds.events & POLLOUT) == 0) ++ if ((fds.events & POLLOUT) == 0) { ++ *in_closed_after_out = true; + /* and nothing more to send */ + break; ++ } + + /* Else, still have data to transmit */ + } else if (len < 0) { +@@ -547,7 +552,7 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd) + } + + /* leave some time for late join/announce */ +- if (cfg_join || cfg_remove) ++ if (cfg_remove) + usleep(cfg_wait); + + close(peerfd); +@@ -646,7 +651,7 @@ static int do_sendfile(int infd, int outfd, unsigned int count) + } + + static int copyfd_io_mmap(int infd, int peerfd, int outfd, +- unsigned int size) ++ unsigned int size, bool *in_closed_after_out) + { + int err; + +@@ -664,13 +669,14 @@ static int copyfd_io_mmap(int infd, int peerfd, int outfd, + shutdown(peerfd, SHUT_WR); + + err = do_recvfile(peerfd, outfd); ++ *in_closed_after_out = true; + } + + return err; + } + + static int copyfd_io_sendfile(int infd, int peerfd, int outfd, +- unsigned int size) ++ unsigned int size, bool *in_closed_after_out) + { + int err; + +@@ -685,6 +691,7 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd, + if (err) + return err; + err = do_recvfile(peerfd, outfd); ++ *in_closed_after_out = true; + } + + return err; +@@ -692,27 +699,62 @@ static int copyfd_io_sendfile(int infd, int peerfd, int outfd, + + static int copyfd_io(int infd, int peerfd, int outfd) + { ++ bool in_closed_after_out = false; ++ struct timespec start, end; + int file_size; ++ int ret; ++ ++ if (cfg_time && (clock_gettime(CLOCK_MONOTONIC, &start) < 0)) ++ xerror("can not fetch start time %d", errno); + + switch (cfg_mode) { + case CFG_MODE_POLL: +- return copyfd_io_poll(infd, peerfd, outfd); ++ ret = copyfd_io_poll(infd, peerfd, outfd, &in_closed_after_out); ++ break; ++ + case CFG_MODE_MMAP: + file_size = get_infd_size(infd); + if (file_size < 0) + return file_size; +- return copyfd_io_mmap(infd, peerfd, outfd, file_size); ++ ret = copyfd_io_mmap(infd, peerfd, outfd, file_size, &in_closed_after_out); ++ break; ++ + case CFG_MODE_SENDFILE: + file_size = get_infd_size(infd); + if (file_size < 0) + return file_size; +- return copyfd_io_sendfile(infd, peerfd, outfd, file_size); ++ ret = copyfd_io_sendfile(infd, peerfd, outfd, file_size, &in_closed_after_out); ++ break; ++ ++ default: ++ fprintf(stderr, "Invalid mode %d\n", cfg_mode); ++ ++ die_usage(); ++ return 1; + } + +- fprintf(stderr, "Invalid mode %d\n", cfg_mode); ++ if (ret) ++ return ret; + +- die_usage(); +- return 1; ++ if (cfg_time) { ++ unsigned int delta_ms; ++ ++ if (clock_gettime(CLOCK_MONOTONIC, &end) < 0) ++ xerror("can not fetch end time %d", errno); ++ delta_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000; ++ if (delta_ms > cfg_time) { ++ xerror("transfer slower than expected! runtime %d ms, expected %d ms", ++ delta_ms, cfg_time); ++ } ++ ++ /* show the runtime only if this end shutdown(wr) before receiving the EOF, ++ * (that is, if this end got the longer runtime) ++ */ ++ if (in_closed_after_out) ++ fprintf(stderr, "%d", delta_ms); ++ } ++ ++ return 0; + } + + static void check_sockaddr(int pf, struct sockaddr_storage *ss, +@@ -1005,12 +1047,11 @@ static void parse_opts(int argc, char **argv) + { + int c; + +- while ((c = getopt(argc, argv, "6jr:lp:s:hut:m:S:R:w:M:P:c:")) != -1) { ++ while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:")) != -1) { + switch (c) { + case 'j': + cfg_join = true; + cfg_mode = CFG_MODE_POLL; +- cfg_wait = 400000; + break; + case 'r': + cfg_remove = true; +@@ -1043,6 +1084,9 @@ static void parse_opts(int argc, char **argv) + if (poll_timeout <= 0) + poll_timeout = -1; + break; ++ case 'T': ++ cfg_time = atoi(optarg); ++ break; + case 'm': + cfg_mode = parse_mode(optarg); + break; +diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh +index 910d8126af8f..f441ff7904fc 100755 +--- a/tools/testing/selftests/net/mptcp/simult_flows.sh ++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh +@@ -51,7 +51,7 @@ setup() + sout=$(mktemp) + cout=$(mktemp) + capout=$(mktemp) +- size=$((2048 * 4096)) ++ size=$((2 * 2048 * 4096)) + dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1 + dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1 + +@@ -161,17 +161,15 @@ do_transfer() + + timeout ${timeout_test} \ + ip netns exec ${ns3} \ +- ./mptcp_connect -jt ${timeout_poll} -l -p $port \ ++ ./mptcp_connect -jt ${timeout_poll} -l -p $port -T $time \ + 0.0.0.0 < "$sin" > "$sout" & + local spid=$! + + wait_local_port_listen "${ns3}" "${port}" + +- local start +- start=$(date +%s%3N) + timeout ${timeout_test} \ + ip netns exec ${ns1} \ +- ./mptcp_connect -jt ${timeout_poll} -p $port \ ++ ./mptcp_connect -jt ${timeout_poll} -p $port -T $time \ + 10.0.3.3 < "$cin" > "$cout" & + local cpid=$! + +@@ -180,27 +178,20 @@ do_transfer() + wait $spid + local rets=$? + +- local stop +- stop=$(date +%s%3N) +- + if $capture; then + sleep 1 + kill ${cappid_listener} + kill ${cappid_connector} + fi + +- local duration +- duration=$((stop-start)) +- + cmp $sin $cout > /dev/null 2>&1 + local cmps=$? + cmp $cin $sout > /dev/null 2>&1 + local cmpc=$? + +- printf "%16s" "$duration max $max_time " ++ printf "%-16s" " max $max_time " + if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \ +- [ $cmpc -eq 0 ] && [ $cmps -eq 0 ] && \ +- [ $duration -lt $max_time ]; then ++ [ $cmpc -eq 0 ] && [ $cmps -eq 0 ]; then + echo "[ OK ]" + cat "$capout" + return 0 +@@ -244,23 +235,24 @@ run_test() + tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1 + tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2 + +- # time is measure in ms +- local time=$((size * 8 * 1000 / (( $rate1 + $rate2) * 1024 *1024) )) ++ # time is measured in ms, account for transfer size, affegated link speed ++ # and header overhead (10%) ++ local time=$((size * 8 * 1000 * 10 / (( $rate1 + $rate2) * 1024 *1024 * 9) )) + + # mptcp_connect will do some sleeps to allow the mp_join handshake +- # completion +- time=$((time + 1350)) ++ # completion (see mptcp_connect): 200ms on each side, add some slack ++ time=$((time + 450)) + +- printf "%-50s" "$msg" +- do_transfer $small $large $((time * 11 / 10)) ++ printf "%-60s" "$msg" ++ do_transfer $small $large $time + lret=$? + if [ $lret -ne 0 ]; then + ret=$lret + [ $bail -eq 0 ] || exit $ret + fi + +- printf "%-50s" "$msg - reverse direction" +- do_transfer $large $small $((time * 11 / 10)) ++ printf "%-60s" "$msg - reverse direction" ++ do_transfer $large $small $time + lret=$? + if [ $lret -ne 0 ]; then + ret=$lret +-- +2.35.1 + diff --git a/queue-5.15/series b/queue-5.15/series index cf245bc364a..1ebee440fcf 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -52,3 +52,82 @@ revert-drm-amdgpu-revert-drm-amdgpu-getting-fan-spee.patch alsa-usb-audio-add-quirk-to-fix-hamedal-c20-disconne.patch risc-v-vdso-do-not-add-missing-symbols-to-version-se.patch mips-pic32-treat-port-as-signed-integer.patch +xfrm-fix-disable_policy-on-ipv4-early-demux.patch +xfrm-replay-fix-esn-wrap-around-for-gso.patch +af_key-fix-send_acquire-race-with-pfkey_register.patch +arm-dts-am335x-pcm-953-define-fixed-regulators-in-ro.patch +asoc-hdac_hda-fix-hda-pcm-buffer-overflow-issue.patch +asoc-sgtl5000-reset-the-chip_clk_ctrl-reg-on-remove.patch +asoc-soc-pcm-don-t-zero-tdm-masks-in-__soc_pcm_open.patch +x86-hyperv-restore-vp-assist-page-after-cpu-offlinin.patch +scsi-storvsc-fix-handling-of-srb_status-and-capacity.patch +asoc-max98373-add-checks-for-devm_kcalloc.patch +regulator-core-fix-kobject-release-warning-and-memor.patch +spi-dw-dma-decrease-reference-count-in-dw_spi_dma_in.patch +regulator-core-fix-uaf-in-destroy_regulator.patch +bus-sunxi-rsb-remove-the-shutdown-callback.patch +bus-sunxi-rsb-support-atomic-transfers.patch +tee-optee-fix-possible-memory-leak-in-optee_register.patch +arm-dts-at91-sam9g20ek-enable-udc-vbus-gpio-pinctrl.patch +selftests-mptcp-more-stable-simult_flows-tests.patch +selftests-mptcp-fix-mibit-vs-mbit-mix-up.patch +net-liquidio-simplify-if-expression.patch +rxrpc-allow-list-of-in-use-local-udp-endpoints-to-be.patch +rxrpc-use-refcount_t-rather-than-atomic_t.patch +rxrpc-fix-race-between-conn-bundle-lookup-and-bundle.patch +net-dsa-sja1105-disallow-c45-transactions-on-the-bas.patch +nfc-nci-fix-race-with-opening-and-closing.patch +net-pch_gbe-fix-potential-memleak-in-pch_gbe_tx_queu.patch +9p-fd-fix-issue-of-list_del-corruption-in-p9_fd_canc.patch +netfilter-conntrack-fix-data-races-around-ct-mark.patch +netfilter-nf_tables-do-not-set-up-extensions-for-end.patch +iavf-fix-a-crash-during-reset-task.patch +iavf-do-not-restart-tx-queues-after-reset-task-failu.patch +iavf-fix-race-condition-between-iavf_shutdown-and-ia.patch +arm-mxs-fix-memory-leak-in-mxs_machine_init.patch +arm-dts-imx6q-prti6q-fix-ref-tcxo-clock-frequency-pr.patch +net-ethernet-mtk_eth_soc-fix-error-handling-in-mtk_o.patch +net-mlx4-check-retval-of-mlx4_bitmap_init.patch +net-mvpp2-fix-possible-invalid-pointer-dereference.patch +net-qla3xxx-fix-potential-memleak-in-ql3xxx_send.patch +octeontx2-af-debugsfs-fix-pci-device-refcount-leak.patch +net-pch_gbe-fix-pci-device-refcount-leak-while-modul.patch +nfp-fill-splittable-of-devlink_port_attrs-correctly.patch +nfp-add-port-from-netdev-validation-for-eeprom-acces.patch +macsec-fix-invalid-error-code-set.patch +drivers-hv-vmbus-fix-double-free-in-the-error-path-o.patch +drivers-hv-vmbus-fix-possible-memory-leak-in-vmbus_d.patch +netfilter-ipset-regression-in-ip_set_hash_ip.c.patch +net-mlx5-do-not-query-pci-info-while-pci-disabled.patch +net-mlx5-fix-fw-tracer-timestamp-calculation.patch +net-mlx5-fix-handling-of-entry-refcount-when-command.patch +tipc-set-con-sock-in-tipc_conn_alloc.patch +tipc-add-an-extra-conn_get-in-tipc_conn_alloc.patch +tipc-check-skb_linearize-return-value-in-tipc_disc_r.patch +xfrm-fix-oops-in-__xfrm_state_delete.patch +xfrm-fix-ignored-return-value-in-xfrm6_init.patch +net-wwan-iosm-use-acpi_free-but-not-kfree-in-ipc_pci.patch +sfc-fix-potential-memleak-in-__ef100_hard_start_xmit.patch +net-sparx5-fix-error-handling-in-sparx5_port_open.patch +net-sched-allow-act_ct-to-be-built-without-nf_nat.patch +nfc-nci-fix-memory-leak-in-nci_rx_data_packet.patch +regulator-twl6030-re-add-twl6032_subclass.patch +bnx2x-fix-pci-device-refcount-leak-in-bnx2x_vf_is_pc.patch +dma-buf-fix-racing-conflict-of-dma_heap_add.patch +netfilter-ipset-restore-allowing-64-clashing-element.patch +netfilter-flowtable_offload-add-missing-locking.patch +fs-do-not-update-freeing-inode-i_io_list.patch +dccp-tcp-reset-saddr-on-failure-after-inet6-_hash_co.patch +ipv4-fix-error-return-code-in-fib_table_insert.patch +arcnet-fix-potential-memory-leak-in-com20020_probe.patch +s390-dasd-fix-no-record-found-for-raw_track_access.patch +nfc-st-nci-fix-incorrect-validating-logic-in-evt_tra.patch +nfc-st-nci-fix-memory-leaks-in-evt_transaction.patch +nfc-st-nci-fix-incorrect-sizing-calculations-in-evt_.patch +net-enetc-manage-enetc_f_qbv-in-priv-active_offloads.patch +net-enetc-cache-accesses-to-priv-si-hw.patch +net-enetc-preserve-tx-ring-priority-across-reconfigu.patch +octeontx2-pf-add-check-for-devm_kcalloc.patch +octeontx2-af-fix-reference-count-issue-in-rvu_sdp_in.patch +net-thunderx-fix-the-acpi-memory-leak.patch +s390-crashdump-fix-tod-programmable-field-size.patch diff --git a/queue-5.15/sfc-fix-potential-memleak-in-__ef100_hard_start_xmit.patch b/queue-5.15/sfc-fix-potential-memleak-in-__ef100_hard_start_xmit.patch new file mode 100644 index 00000000000..d1735f72777 --- /dev/null +++ b/queue-5.15/sfc-fix-potential-memleak-in-__ef100_hard_start_xmit.patch @@ -0,0 +1,38 @@ +From 941b61821495965348d512b8a4289c391b3a234b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:50:09 +0800 +Subject: sfc: fix potential memleak in __ef100_hard_start_xmit() + +From: Zhang Changzhong + +[ Upstream commit aad98abd5cb8133507f22654f56bcb443aaa2d89 ] + +The __ef100_hard_start_xmit() returns NETDEV_TX_OK without freeing skb +in error handling case, add dev_kfree_skb_any() to fix it. + +Fixes: 51b35a454efd ("sfc: skeleton EF100 PF driver") +Signed-off-by: Zhang Changzhong +Acked-by: Martin Habets +Reviewed-by: Leon Romanovsky +Link: https://lore.kernel.org/r/1668671409-10909-1-git-send-email-zhangchangzhong@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/sfc/ef100_netdev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c +index 67fe44db6b61..63a44ee763be 100644 +--- a/drivers/net/ethernet/sfc/ef100_netdev.c ++++ b/drivers/net/ethernet/sfc/ef100_netdev.c +@@ -200,6 +200,7 @@ static netdev_tx_t ef100_hard_start_xmit(struct sk_buff *skb, + skb->len, skb->data_len, channel->channel); + if (!efx->n_channels || !efx->n_tx_channels || !channel) { + netif_stop_queue(net_dev); ++ dev_kfree_skb_any(skb); + goto err; + } + +-- +2.35.1 + diff --git a/queue-5.15/spi-dw-dma-decrease-reference-count-in-dw_spi_dma_in.patch b/queue-5.15/spi-dw-dma-decrease-reference-count-in-dw_spi_dma_in.patch new file mode 100644 index 00000000000..1c5cfcbeb49 --- /dev/null +++ b/queue-5.15/spi-dw-dma-decrease-reference-count-in-dw_spi_dma_in.patch @@ -0,0 +1,47 @@ +From bcfca3135a1642496a31e9dfd7c4b8b01c10459f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 17:32:04 +0800 +Subject: spi: dw-dma: decrease reference count in dw_spi_dma_init_mfld() + +From: Xiongfeng Wang + +[ Upstream commit 804313b64e412a81b0b3389a10e7622452004aa6 ] + +pci_get_device() will increase the reference count for the returned +pci_dev. Since 'dma_dev' is only used to filter the channel in +dw_spi_dma_chan_filer() after using it we need to call pci_dev_put() to +decrease the reference count. Also add pci_dev_put() for the error case. + +Fixes: 7063c0d942a1 ("spi/dw_spi: add DMA support") +Signed-off-by: Xiongfeng Wang +Acked-by: Serge Semin +Link: https://lore.kernel.org/r/20221116093204.46700-1-wangxiongfeng2@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-dw-dma.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c +index a09831c62192..32ac8f9068e8 100644 +--- a/drivers/spi/spi-dw-dma.c ++++ b/drivers/spi/spi-dw-dma.c +@@ -127,12 +127,15 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) + + dw_spi_dma_sg_burst_init(dws); + ++ pci_dev_put(dma_dev); ++ + return 0; + + free_rxchan: + dma_release_channel(dws->rxchan); + dws->rxchan = NULL; + err_exit: ++ pci_dev_put(dma_dev); + return -EBUSY; + } + +-- +2.35.1 + diff --git a/queue-5.15/tee-optee-fix-possible-memory-leak-in-optee_register.patch b/queue-5.15/tee-optee-fix-possible-memory-leak-in-optee_register.patch new file mode 100644 index 00000000000..f058511e603 --- /dev/null +++ b/queue-5.15/tee-optee-fix-possible-memory-leak-in-optee_register.patch @@ -0,0 +1,41 @@ +From 24d4421c33a61571f1fb5225436e6ac5ee32448d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 22:01:24 +0800 +Subject: tee: optee: fix possible memory leak in optee_register_device() + +From: Yang Yingliang + +[ Upstream commit cce616e012c215d65c15e5d1afa73182dea49389 ] + +If device_register() returns error in optee_register_device(), +the name allocated by dev_set_name() need be freed. As comment +of device_register() says, it should use put_device() to give +up the reference in the error path. So fix this by calling +put_device(), then the name can be freed in kobject_cleanup(), +and optee_device is freed in optee_release_device(). + +Fixes: c3fa24af9244 ("tee: optee: add TEE bus device enumeration support") +Signed-off-by: Yang Yingliang +Reviewed-by: Sumit Garg +Signed-off-by: Jens Wiklander +Signed-off-by: Sasha Levin +--- + drivers/tee/optee/device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c +index 128a2d2a50a1..a74d82e230e3 100644 +--- a/drivers/tee/optee/device.c ++++ b/drivers/tee/optee/device.c +@@ -80,7 +80,7 @@ static int optee_register_device(const uuid_t *device_uuid) + rc = device_register(&optee_device->dev); + if (rc) { + pr_err("device registration failed, err: %d\n", rc); +- kfree(optee_device); ++ put_device(&optee_device->dev); + } + + return rc; +-- +2.35.1 + diff --git a/queue-5.15/tipc-add-an-extra-conn_get-in-tipc_conn_alloc.patch b/queue-5.15/tipc-add-an-extra-conn_get-in-tipc_conn_alloc.patch new file mode 100644 index 00000000000..247e4ee323d --- /dev/null +++ b/queue-5.15/tipc-add-an-extra-conn_get-in-tipc_conn_alloc.patch @@ -0,0 +1,84 @@ +From 69fc839dc2f7a2df5965b66ce565bcf1999239ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 16:45:01 -0500 +Subject: tipc: add an extra conn_get in tipc_conn_alloc + +From: Xin Long + +[ Upstream commit a7b42969d63f47320853a802efd879fbdc4e010e ] + +One extra conn_get() is needed in tipc_conn_alloc(), as after +tipc_conn_alloc() is called, tipc_conn_close() may free this +con before deferencing it in tipc_topsrv_accept(): + + tipc_conn_alloc(); + newsk = newsock->sk; + <---- tipc_conn_close(); + write_lock_bh(&sk->sk_callback_lock); + newsk->sk_data_ready = tipc_conn_data_ready; + +Then an uaf issue can be triggered: + + BUG: KASAN: use-after-free in tipc_topsrv_accept+0x1e7/0x370 [tipc] + Call Trace: + + dump_stack_lvl+0x33/0x46 + print_report+0x178/0x4b0 + kasan_report+0x8c/0x100 + kasan_check_range+0x179/0x1e0 + tipc_topsrv_accept+0x1e7/0x370 [tipc] + process_one_work+0x6a3/0x1030 + worker_thread+0x8a/0xdf0 + +This patch fixes it by holding it in tipc_conn_alloc(), then after +all accessing in tipc_topsrv_accept() releasing it. Note when does +this in tipc_topsrv_kern_subscr(), as tipc_conn_rcv_sub() returns +0 or -1 only, we don't need to check for "> 0". + +Fixes: c5fa7b3cf3cb ("tipc: introduce new TIPC server infrastructure") +Signed-off-by: Xin Long +Acked-by: Jon Maloy +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/topsrv.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c +index b0f9aa521670..e3b427a70398 100644 +--- a/net/tipc/topsrv.c ++++ b/net/tipc/topsrv.c +@@ -206,6 +206,7 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *s + set_bit(CF_CONNECTED, &con->flags); + con->server = s; + con->sock = sock; ++ conn_get(con); + spin_unlock_bh(&s->idr_lock); + + return con; +@@ -484,6 +485,7 @@ static void tipc_topsrv_accept(struct work_struct *work) + + /* Wake up receive process in case of 'SYN+' message */ + newsk->sk_data_ready(newsk); ++ conn_put(con); + } + } + +@@ -583,10 +585,11 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower, + + *conid = con->conid; + rc = tipc_conn_rcv_sub(tipc_topsrv(net), con, &sub); +- if (rc >= 0) +- return true; ++ if (rc) ++ conn_put(con); ++ + conn_put(con); +- return false; ++ return !rc; + } + + void tipc_topsrv_kern_unsubscr(struct net *net, int conid) +-- +2.35.1 + diff --git a/queue-5.15/tipc-check-skb_linearize-return-value-in-tipc_disc_r.patch b/queue-5.15/tipc-check-skb_linearize-return-value-in-tipc_disc_r.patch new file mode 100644 index 00000000000..d8ff6babd5d --- /dev/null +++ b/queue-5.15/tipc-check-skb_linearize-return-value-in-tipc_disc_r.patch @@ -0,0 +1,41 @@ +From ead71705b8b955516c7e7bdff573e11ae0c9a6d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 15:28:32 +0800 +Subject: tipc: check skb_linearize() return value in tipc_disc_rcv() + +From: YueHaibing + +[ Upstream commit cd0f6421162201e4b22ce757a1966729323185eb ] + +If skb_linearize() fails in tipc_disc_rcv(), we need to free the skb instead of +handle it. + +Fixes: 25b0b9c4e835 ("tipc: handle collisions of 32-bit node address hash values") +Signed-off-by: YueHaibing +Acked-by: Jon Maloy +Link: https://lore.kernel.org/r/20221119072832.7896-1-yuehaibing@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/discover.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/discover.c b/net/tipc/discover.c +index e8630707901e..e8dcdf267c0c 100644 +--- a/net/tipc/discover.c ++++ b/net/tipc/discover.c +@@ -211,7 +211,10 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb, + u32 self; + int err; + +- skb_linearize(skb); ++ if (skb_linearize(skb)) { ++ kfree_skb(skb); ++ return; ++ } + hdr = buf_msg(skb); + + if (caps & TIPC_NODE_ID128) +-- +2.35.1 + diff --git a/queue-5.15/tipc-set-con-sock-in-tipc_conn_alloc.patch b/queue-5.15/tipc-set-con-sock-in-tipc_conn_alloc.patch new file mode 100644 index 00000000000..87a6233b539 --- /dev/null +++ b/queue-5.15/tipc-set-con-sock-in-tipc_conn_alloc.patch @@ -0,0 +1,106 @@ +From 4d92303386e21963a475c27877b0616959694aa3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 16:45:00 -0500 +Subject: tipc: set con sock in tipc_conn_alloc + +From: Xin Long + +[ Upstream commit 0e5d56c64afcd6fd2d132ea972605b66f8a7d3c4 ] + +A crash was reported by Wei Chen: + + BUG: kernel NULL pointer dereference, address: 0000000000000018 + RIP: 0010:tipc_conn_close+0x12/0x100 + Call Trace: + tipc_topsrv_exit_net+0x139/0x320 + ops_exit_list.isra.9+0x49/0x80 + cleanup_net+0x31a/0x540 + process_one_work+0x3fa/0x9f0 + worker_thread+0x42/0x5c0 + +It was caused by !con->sock in tipc_conn_close(). In tipc_topsrv_accept(), +con is allocated in conn_idr then its sock is set: + + con = tipc_conn_alloc(); + ... <----[1] + con->sock = newsock; + +If tipc_conn_close() is called in anytime of [1], the null-pointer-def +is triggered by con->sock->sk due to con->sock is not yet set. + +This patch fixes it by moving the con->sock setting to tipc_conn_alloc() +under s->idr_lock. So that con->sock can never be NULL when getting the +con from s->conn_idr. It will be also safer to move con->server and flag +CF_CONNECTED setting under s->idr_lock, as they should all be set before +tipc_conn_alloc() is called. + +Fixes: c5fa7b3cf3cb ("tipc: introduce new TIPC server infrastructure") +Reported-by: Wei Chen +Signed-off-by: Xin Long +Acked-by: Jon Maloy +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/topsrv.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c +index d92ec92f0b71..b0f9aa521670 100644 +--- a/net/tipc/topsrv.c ++++ b/net/tipc/topsrv.c +@@ -176,7 +176,7 @@ static void tipc_conn_close(struct tipc_conn *con) + conn_put(con); + } + +-static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) ++static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *sock) + { + struct tipc_conn *con; + int ret; +@@ -202,10 +202,11 @@ static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) + } + con->conid = ret; + s->idr_in_use++; +- spin_unlock_bh(&s->idr_lock); + + set_bit(CF_CONNECTED, &con->flags); + con->server = s; ++ con->sock = sock; ++ spin_unlock_bh(&s->idr_lock); + + return con; + } +@@ -467,7 +468,7 @@ static void tipc_topsrv_accept(struct work_struct *work) + ret = kernel_accept(lsock, &newsock, O_NONBLOCK); + if (ret < 0) + return; +- con = tipc_conn_alloc(srv); ++ con = tipc_conn_alloc(srv, newsock); + if (IS_ERR(con)) { + ret = PTR_ERR(con); + sock_release(newsock); +@@ -479,7 +480,6 @@ static void tipc_topsrv_accept(struct work_struct *work) + newsk->sk_data_ready = tipc_conn_data_ready; + newsk->sk_write_space = tipc_conn_write_space; + newsk->sk_user_data = con; +- con->sock = newsock; + write_unlock_bh(&newsk->sk_callback_lock); + + /* Wake up receive process in case of 'SYN+' message */ +@@ -577,12 +577,11 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type, u32 lower, + sub.filter = filter; + *(u64 *)&sub.usr_handle = (u64)port; + +- con = tipc_conn_alloc(tipc_topsrv(net)); ++ con = tipc_conn_alloc(tipc_topsrv(net), NULL); + if (IS_ERR(con)) + return false; + + *conid = con->conid; +- con->sock = NULL; + rc = tipc_conn_rcv_sub(tipc_topsrv(net), con, &sub); + if (rc >= 0) + return true; +-- +2.35.1 + diff --git a/queue-5.15/x86-hyperv-restore-vp-assist-page-after-cpu-offlinin.patch b/queue-5.15/x86-hyperv-restore-vp-assist-page-after-cpu-offlinin.patch new file mode 100644 index 00000000000..b0768e75b38 --- /dev/null +++ b/queue-5.15/x86-hyperv-restore-vp-assist-page-after-cpu-offlinin.patch @@ -0,0 +1,125 @@ +From 4f0eed21277bf72409b7aded09ec62d672549d9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 20:06:01 +0100 +Subject: x86/hyperv: Restore VP assist page after cpu offlining/onlining + +From: Vitaly Kuznetsov + +[ Upstream commit ee6815416380bc069b7dcbdff0682d4c53617527 ] + +Commit e5d9b714fe40 ("x86/hyperv: fix root partition faults when writing +to VP assist page MSR") moved 'wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE)' under +'if (*hvp)' condition. This works for root partition as hv_cpu_die() +does memunmap() and sets 'hv_vp_assist_page[cpu]' to NULL but breaks +non-root partitions as hv_cpu_die() doesn't free 'hv_vp_assist_page[cpu]' +for them. This causes VP assist page to remain unset after CPU +offline/online cycle: + +$ rdmsr -p 24 0x40000073 + 10212f001 +$ echo 0 > /sys/devices/system/cpu/cpu24/online +$ echo 1 > /sys/devices/system/cpu/cpu24/online +$ rdmsr -p 24 0x40000073 + 0 + +Fix the issue by always writing to HV_X64_MSR_VP_ASSIST_PAGE in +hv_cpu_init(). Note, checking 'if (!*hvp)', for root partition is +pointless as hv_cpu_die() always sets 'hv_vp_assist_page[cpu]' to +NULL (and it's also NULL initially). + +Note: the fact that 'hv_vp_assist_page[cpu]' is reset to NULL may +present a (potential) issue for KVM. While Hyper-V uses +CPUHP_AP_ONLINE_DYN stage in CPU hotplug, KVM uses CPUHP_AP_KVM_STARTING +which comes earlier in CPU teardown sequence. It is theoretically +possible that Enlightened VMCS is still in use. It is unclear if the +issue is real and if using KVM with Hyper-V root partition is even +possible. + +While on it, drop the unneeded smp_processor_id() call from hv_cpu_init(). + +Fixes: e5d9b714fe40 ("x86/hyperv: fix root partition faults when writing to VP assist page MSR") +Signed-off-by: Vitaly Kuznetsov +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20221103190601.399343-1-vkuznets@redhat.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + arch/x86/hyperv/hv_init.c | 54 +++++++++++++++++++-------------------- + 1 file changed, 26 insertions(+), 28 deletions(-) + +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +index b6d48ca5b0f1..762f10cdfb7a 100644 +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -45,7 +45,7 @@ EXPORT_SYMBOL_GPL(hv_vp_assist_page); + static int hv_cpu_init(unsigned int cpu) + { + union hv_vp_assist_msr_contents msr = { 0 }; +- struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()]; ++ struct hv_vp_assist_page **hvp = &hv_vp_assist_page[cpu]; + int ret; + + ret = hv_common_cpu_init(cpu); +@@ -55,34 +55,32 @@ static int hv_cpu_init(unsigned int cpu) + if (!hv_vp_assist_page) + return 0; + +- if (!*hvp) { +- if (hv_root_partition) { +- /* +- * For root partition we get the hypervisor provided VP assist +- * page, instead of allocating a new page. +- */ +- rdmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64); +- *hvp = memremap(msr.pfn << +- HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT, +- PAGE_SIZE, MEMREMAP_WB); +- } else { +- /* +- * The VP assist page is an "overlay" page (see Hyper-V TLFS's +- * Section 5.2.1 "GPA Overlay Pages"). Here it must be zeroed +- * out to make sure we always write the EOI MSR in +- * hv_apic_eoi_write() *after* the EOI optimization is disabled +- * in hv_cpu_die(), otherwise a CPU may not be stopped in the +- * case of CPU offlining and the VM will hang. +- */ ++ if (hv_root_partition) { ++ /* ++ * For root partition we get the hypervisor provided VP assist ++ * page, instead of allocating a new page. ++ */ ++ rdmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64); ++ *hvp = memremap(msr.pfn << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT, ++ PAGE_SIZE, MEMREMAP_WB); ++ } else { ++ /* ++ * The VP assist page is an "overlay" page (see Hyper-V TLFS's ++ * Section 5.2.1 "GPA Overlay Pages"). Here it must be zeroed ++ * out to make sure we always write the EOI MSR in ++ * hv_apic_eoi_write() *after* the EOI optimization is disabled ++ * in hv_cpu_die(), otherwise a CPU may not be stopped in the ++ * case of CPU offlining and the VM will hang. ++ */ ++ if (!*hvp) + *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO); +- if (*hvp) +- msr.pfn = vmalloc_to_pfn(*hvp); +- } +- WARN_ON(!(*hvp)); +- if (*hvp) { +- msr.enable = 1; +- wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64); +- } ++ if (*hvp) ++ msr.pfn = vmalloc_to_pfn(*hvp); ++ ++ } ++ if (!WARN_ON(!(*hvp))) { ++ msr.enable = 1; ++ wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64); + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/xfrm-fix-disable_policy-on-ipv4-early-demux.patch b/queue-5.15/xfrm-fix-disable_policy-on-ipv4-early-demux.patch new file mode 100644 index 00000000000..ba860387b69 --- /dev/null +++ b/queue-5.15/xfrm-fix-disable_policy-on-ipv4-early-demux.patch @@ -0,0 +1,54 @@ +From 3c1f8ce26a7fd2951da47105171ba4d224fb8dc8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Oct 2022 22:16:43 +0300 +Subject: xfrm: fix "disable_policy" on ipv4 early demux + +From: Eyal Birger + +[ Upstream commit 3a5913183aa1b14148c723bda030e6102ad73008 ] + +The commit in the "Fixes" tag tried to avoid a case where policy check +is ignored due to dst caching in next hops. + +However, when the traffic is locally consumed, the dst may be cached +in a local TCP or UDP socket as part of early demux. In this case the +"disable_policy" flag is not checked as ip_route_input_noref() was only +called before caching, and thus, packets after the initial packet in a +flow will be dropped if not matching policies. + +Fix by checking the "disable_policy" flag also when a valid dst is +already available. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216557 +Reported-by: Monil Patel +Fixes: e6175a2ed1f1 ("xfrm: fix "disable_policy" flag use when arriving from different devices") +Signed-off-by: Eyal Birger + +---- + +v2: use dev instead of skb->dev +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_input.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c +index 459d7e630cb0..124bf8fdf924 100644 +--- a/net/ipv4/ip_input.c ++++ b/net/ipv4/ip_input.c +@@ -364,6 +364,11 @@ static int ip_rcv_finish_core(struct net *net, struct sock *sk, + iph->tos, dev); + if (unlikely(err)) + goto drop_error; ++ } else { ++ struct in_device *in_dev = __in_dev_get_rcu(dev); ++ ++ if (in_dev && IN_DEV_ORCONF(in_dev, NOPOLICY)) ++ IPCB(skb)->flags |= IPSKB_NOPOLICY; + } + + #ifdef CONFIG_IP_ROUTE_CLASSID +-- +2.35.1 + diff --git a/queue-5.15/xfrm-fix-ignored-return-value-in-xfrm6_init.patch b/queue-5.15/xfrm-fix-ignored-return-value-in-xfrm6_init.patch new file mode 100644 index 00000000000..cf267e6903c --- /dev/null +++ b/queue-5.15/xfrm-fix-ignored-return-value-in-xfrm6_init.patch @@ -0,0 +1,59 @@ +From 78245d75b21394601f4f54a3496776503da10948 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 17:07:13 +0800 +Subject: xfrm: Fix ignored return value in xfrm6_init() + +From: Chen Zhongjin + +[ Upstream commit 40781bfb836eda57d19c0baa37c7e72590e05fdc ] + +When IPv6 module initializing in xfrm6_init(), register_pernet_subsys() +is possible to fail but its return value is ignored. + +If IPv6 initialization fails later and xfrm6_fini() is called, +removing uninitialized list in xfrm6_net_ops will cause null-ptr-deref: + +KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] +CPU: 1 PID: 330 Comm: insmod +RIP: 0010:unregister_pernet_operations+0xc9/0x450 +Call Trace: + + unregister_pernet_subsys+0x31/0x3e + xfrm6_fini+0x16/0x30 [ipv6] + ip6_route_init+0xcd/0x128 [ipv6] + inet6_init+0x29c/0x602 [ipv6] + ... + +Fix it by catching the error return value of register_pernet_subsys(). + +Fixes: 8d068875caca ("xfrm: make gc_thresh configurable in all namespaces") +Signed-off-by: Chen Zhongjin +Reviewed-by: Leon Romanovsky +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv6/xfrm6_policy.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index af7a4b8b1e9c..247296e3294b 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -289,9 +289,13 @@ int __init xfrm6_init(void) + if (ret) + goto out_state; + +- register_pernet_subsys(&xfrm6_net_ops); ++ ret = register_pernet_subsys(&xfrm6_net_ops); ++ if (ret) ++ goto out_protocol; + out: + return ret; ++out_protocol: ++ xfrm6_protocol_fini(); + out_state: + xfrm6_state_fini(); + out_policy: +-- +2.35.1 + diff --git a/queue-5.15/xfrm-fix-oops-in-__xfrm_state_delete.patch b/queue-5.15/xfrm-fix-oops-in-__xfrm_state_delete.patch new file mode 100644 index 00000000000..9f407cffe10 --- /dev/null +++ b/queue-5.15/xfrm-fix-oops-in-__xfrm_state_delete.patch @@ -0,0 +1,119 @@ +From e7cc851a408e4ba2a9f90da7148db57a81ba17a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 11:18:48 +0100 +Subject: xfrm: Fix oops in __xfrm_state_delete() + +From: Thomas Jarosch + +[ Upstream commit b97df039a68b2f3e848e238df5d5d06343ea497b ] + +Kernel 5.14 added a new "byseq" index to speed +up xfrm_state lookups by sequence number in commit +fe9f1d8779cb ("xfrm: add state hashtable keyed by seq") + +While the patch was thorough, the function pfkey_send_new_mapping() +in net/af_key.c also modifies x->km.seq and never added +the current xfrm_state to the "byseq" index. + +This leads to the following kernel Ooops: + BUG: kernel NULL pointer dereference, address: 0000000000000000 + .. + RIP: 0010:__xfrm_state_delete+0xc9/0x1c0 + .. + Call Trace: + + xfrm_state_delete+0x1e/0x40 + xfrm_del_sa+0xb0/0x110 [xfrm_user] + xfrm_user_rcv_msg+0x12d/0x270 [xfrm_user] + ? remove_entity_load_avg+0x8a/0xa0 + ? copy_to_user_state_extra+0x580/0x580 [xfrm_user] + netlink_rcv_skb+0x51/0x100 + xfrm_netlink_rcv+0x30/0x50 [xfrm_user] + netlink_unicast+0x1a6/0x270 + netlink_sendmsg+0x22a/0x480 + __sys_sendto+0x1a6/0x1c0 + ? __audit_syscall_entry+0xd8/0x130 + ? __audit_syscall_exit+0x249/0x2b0 + __x64_sys_sendto+0x23/0x30 + do_syscall_64+0x3a/0x90 + entry_SYSCALL_64_after_hwframe+0x61/0xcb + +Exact location of the crash in __xfrm_state_delete(): + if (x->km.seq) + hlist_del_rcu(&x->byseq); + +The hlist_node "byseq" was never populated. + +The bug only triggers if a new NAT traversal mapping (changed IP or port) +is detected in esp_input_done2() / esp6_input_done2(), which in turn +indirectly calls pfkey_send_new_mapping() *if* the kernel is compiled +with CONFIG_NET_KEY and "af_key" is active. + +The PF_KEYv2 message SADB_X_NAT_T_NEW_MAPPING is not part of RFC 2367. +Various implementations have been examined how they handle +the "sadb_msg_seq" header field: + +- racoon (Android): does not process SADB_X_NAT_T_NEW_MAPPING +- strongswan: does not care about sadb_msg_seq +- openswan: does not care about sadb_msg_seq + +There is no standard how PF_KEYv2 sadb_msg_seq should be populated +for SADB_X_NAT_T_NEW_MAPPING and it's not used in popular +implementations either. Herbert Xu suggested we should just +use the current km.seq value as is. This fixes the root cause +of the oops since we no longer modify km.seq itself. + +The update of "km.seq" looks like a copy'n'paste error +from pfkey_send_acquire(). SADB_ACQUIRE must indeed assign a unique km.seq +number according to RFC 2367. It has been verified that code paths +involving pfkey_send_acquire() don't cause the same Oops. + +PF_KEYv2 SADB_X_NAT_T_NEW_MAPPING support was originally added here: + https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git + + commit cbc3488685b20e7b2a98ad387a1a816aada569d8 + Author: Derek Atkins + AuthorDate: Wed Apr 2 13:21:02 2003 -0800 + + [IPSEC]: Implement UDP Encapsulation framework. + + In particular, implement ESPinUDP encapsulation for IPsec + Nat Traversal. + +A note on triggering the bug: I was not able to trigger it using VMs. +There is one VPN using a high latency link on our production VPN server +that triggered it like once a day though. + +Link: https://github.com/strongswan/strongswan/issues/992 +Link: https://lore.kernel.org/netdev/00959f33ee52c4b3b0084d42c430418e502db554.1652340703.git.antony.antony@secunet.com/T/ +Link: https://lore.kernel.org/netdev/20221027142455.3975224-1-chenzhihao@meizu.com/T/ + +Fixes: fe9f1d8779cb ("xfrm: add state hashtable keyed by seq") +Reported-by: Roth Mark +Reported-by: Zhihao Chen +Tested-by: Roth Mark +Signed-off-by: Thomas Jarosch +Acked-by: Antony Antony +Acked-by: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/key/af_key.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/key/af_key.c b/net/key/af_key.c +index a654bd4bc437..1d6ae1df3886 100644 +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -3394,7 +3394,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, + hdr->sadb_msg_len = size / sizeof(uint64_t); + hdr->sadb_msg_errno = 0; + hdr->sadb_msg_reserved = 0; +- hdr->sadb_msg_seq = x->km.seq = get_acqseq(); ++ hdr->sadb_msg_seq = x->km.seq; + hdr->sadb_msg_pid = 0; + + /* SA */ +-- +2.35.1 + diff --git a/queue-5.15/xfrm-replay-fix-esn-wrap-around-for-gso.patch b/queue-5.15/xfrm-replay-fix-esn-wrap-around-for-gso.patch new file mode 100644 index 00000000000..4edbb8084f8 --- /dev/null +++ b/queue-5.15/xfrm-replay-fix-esn-wrap-around-for-gso.patch @@ -0,0 +1,103 @@ +From 39f79cd8e5445597ef17d1f95bdf89f1ab2ad2a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 08:34:47 +0200 +Subject: xfrm: replay: Fix ESN wrap around for GSO + +From: Christian Langrock + +[ Upstream commit 4b549ccce941798703f159b227aa28c716aa78fa ] + +When using GSO it can happen that the wrong seq_hi is used for the last +packets before the wrap around. This can lead to double usage of a +sequence number. To avoid this, we should serialize this last GSO +packet. + +Fixes: d7dbefc45cf5 ("xfrm: Add xfrm_replay_overflow functions for offloading") +Co-developed-by: Steffen Klassert +Signed-off-by: Christian Langrock +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4_offload.c | 3 +++ + net/ipv6/esp6_offload.c | 3 +++ + net/xfrm/xfrm_device.c | 15 ++++++++++++++- + net/xfrm/xfrm_replay.c | 2 +- + 4 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c +index dad5d29a6a8d..2ddba1e2cf22 100644 +--- a/net/ipv4/esp4_offload.c ++++ b/net/ipv4/esp4_offload.c +@@ -311,6 +311,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_ + xo->seq.low += skb_shinfo(skb)->gso_segs; + } + ++ if (xo->seq.low < seq) ++ xo->seq.hi++; ++ + esp.seqno = cpu_to_be64(seq + ((u64)xo->seq.hi << 32)); + + ip_hdr(skb)->tot_len = htons(skb->len); +diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c +index 302170882382..4cc19acfc369 100644 +--- a/net/ipv6/esp6_offload.c ++++ b/net/ipv6/esp6_offload.c +@@ -343,6 +343,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features + xo->seq.low += skb_shinfo(skb)->gso_segs; + } + ++ if (xo->seq.low < seq) ++ xo->seq.hi++; ++ + esp.seqno = cpu_to_be64(xo->seq.low + ((u64)xo->seq.hi << 32)); + + len = skb->len - sizeof(struct ipv6hdr); +diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c +index c255aac6b816..8b8e957a69c3 100644 +--- a/net/xfrm/xfrm_device.c ++++ b/net/xfrm/xfrm_device.c +@@ -97,6 +97,18 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb) + } + } + ++static inline bool xmit_xfrm_check_overflow(struct sk_buff *skb) ++{ ++ struct xfrm_offload *xo = xfrm_offload(skb); ++ __u32 seq = xo->seq.low; ++ ++ seq += skb_shinfo(skb)->gso_segs; ++ if (unlikely(seq < xo->seq.low)) ++ return true; ++ ++ return false; ++} ++ + struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again) + { + int err; +@@ -134,7 +146,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur + return skb; + } + +- if (skb_is_gso(skb) && unlikely(x->xso.dev != dev)) { ++ if (skb_is_gso(skb) && (unlikely(x->xso.dev != dev) || ++ unlikely(xmit_xfrm_check_overflow(skb)))) { + struct sk_buff *segs; + + /* Packet got rerouted, fixup features and segment it. */ +diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c +index 9277d81b344c..49dd788859d8 100644 +--- a/net/xfrm/xfrm_replay.c ++++ b/net/xfrm/xfrm_replay.c +@@ -714,7 +714,7 @@ static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff + oseq += skb_shinfo(skb)->gso_segs; + } + +- if (unlikely(oseq < replay_esn->oseq)) { ++ if (unlikely(xo->seq.low < replay_esn->oseq)) { + XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi; + xo->seq.hi = oseq_hi; + replay_esn->oseq_hi = oseq_hi; +-- +2.35.1 +