5.15.148-rc1 review
Subsystems (3)
Greg Kroah-Hartman
maintainerPATCH 324/374 perf env: Avoid recursively taking env->bpf_progs.lock
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit 9c51f8788b5d4e9f46afbcf563255cfd355690b3 ]
Add variants of perf_env__insert_bpf_prog_info(), perf_env__insert_btf() and perf_env__find_btf prefixed with __ to indicate the env->bpf_progs.lock is assumed held.
Call these variants when the lock is held to avoid recursively taking it and potentially having a thread deadlock with itself.
--- tools/perf/util/bpf-event.c | 8 +++--- tools/perf/util/bpf-event.h | 12 ++++----- tools/perf/util/env.c | 50 ++++++++++++++++++++++++------------- tools/perf/util/env.h | 4 +++ tools/perf/util/header.c | 8 +++--- 5 files changed, 50 insertions(+), 32 deletions(-)
tools/perf/util/bpf-event.c +4 -4
@@ -554,9 +554,9 @@ int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env)return evlist__add_sb_event (evlist, &attr, bpf_event__sb_cb, env); } -void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, -struct perf_env *env, -FILE *fp) +void __bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, +struct perf_env *env, +FILE *fp) {__u32 *prog_lens = (__u32 *)(uintptr_t )(info->jited_func_lens);__u64 *prog_addrs = (__u64 *)(uintptr_t )(info->jited_ksyms);
@@ -572,7 +572,7 @@ void bpf_event__print_bpf_prog_info(struct bpf_prog_info *info,if (info->btf_id) {struct btf_node *node; - node =perf_env__find_btf (env, info->btf_id); + node =__perf_env__find_btf (env, info->btf_id);if (node) btf =btf__new ((__u8 *)(node->data), node->data_size);
tools/perf/util/bpf-event.h +6 -6
@@ -34,9 +34,9 @@ struct btf_node {int machine__process_bpf (struct machine *machine,union perf_event *event,struct perf_sample *sample);int evlist__add_bpf_sb_event (struct evlist *evlist,struct perf_env *env); -void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, -struct perf_env *env, -FILE *fp); +void __bpf_event__print_bpf_prog_info (struct bpf_prog_info *info, +struct perf_env *env, +FILE *fp);#else static inline int machine__process_bpf(struct machine *machine __maybe_unused, union perf_event *event __maybe_unused,
@@ -51,9 +51,9 @@ static inline int evlist__add_bpf_sb_event(struct evlist *evlist __maybe_unused,return 0 ; } -static inline void bpf_event__print_bpf_prog_info (struct bpf_prog_info *info__maybe_unused , -struct perf_env *env__maybe_unused , -FILE *fp__maybe_unused ) +static inline void __bpf_event__print_bpf_prog_info (struct bpf_prog_info *info__maybe_unused , +struct perf_env *env__maybe_unused , +FILE *fp__maybe_unused ) { }
tools/perf/util/env.c +32 -18
112 lines not on this page · raw message
tools/perf/util/env.h +4 -0
@@ -163,12 +163,16 @@ const char *perf_env__raw_arch(struct perf_env *env);int perf_env__nr_cpus_avail (struct perf_env *env);void perf_env__init (struct perf_env *env); +void __perf_env__insert_bpf_prog_info (struct perf_env *env, +struct bpf_prog_info_node *info_node);void perf_env__insert_bpf_prog_info (struct perf_env *env,struct bpf_prog_info_node *info_node);struct bpf_prog_info_node *perf_env__find_bpf_prog_info (struct perf_env *env,__u32 prog_id);bool perf_env__insert_btf (struct perf_env *env,struct btf_node *btf_node); +bool __perf_env__insert_btf (struct perf_env *env,struct btf_node *btf_node);struct btf_node *perf_env__find_btf (struct perf_env *env,__u32 btf_id); +struct btf_node *__perf_env__find_btf (struct perf_env *env,__u32 btf_id);int perf_env__numa_node (struct perf_env *env,int cpu);#endif /* __PERF_ENV_H */
tools/perf/util/header.c +4 -4
@@ -1735,8 +1735,8 @@ static void print_bpf_prog_info(struct feat_fd *ff, FILE *fp) node = rb_entry(next, struct bpf_prog_info_node, rb_node); next =rb_next (&node->rb_node); -bpf_event__print_bpf_prog_info (&node->info_linear->info, - env, fp); +__bpf_event__print_bpf_prog_info (&node->info_linear->info, + env, fp); }up_read (&env->bpf_progs.lock);
@@ -3073,7 +3073,7 @@ static int process_bpf_prog_info(struct feat_fd *ff, void *data __maybe_unused)/* after reading from file, translate offset to address */ bpf_program__bpil_offs_to_addr (info_linear); info_node->info_linear = info_linear; -perf_env__insert_bpf_prog_info (env, info_node); +__perf_env__insert_bpf_prog_info (env, info_node); }up_write (&env->bpf_progs.lock);
@@ -3120,7 +3120,7 @@ static int process_bpf_btf(struct feat_fd *ff, void *data __maybe_unused)if (__do_read (ff, node->data, data_size)) goto out; -perf_env__insert_btf (env, node); +__perf_env__insert_btf (env, node); node =NULL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 325/374 apparmor: avoid crash when parsed profile name is empty
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
[ Upstream commit 55a8210c9e7d21ff2644809699765796d4bfb200 ]
When processing a packed profile in unpack_profile() described like
"profile :ns::samba-dcerpcd /usr/lib*/samba/{,samba/}samba-dcerpcd {...}"
a string ":samba-dcerpcd" is unpacked as a fully-qualified name and then passed to aa_splitn_fqname().
aa_splitn_fqname() treats ":samba-dcerpcd" as only containing a namespace. Thus it returns NULL for tmpname, meanwhile tmpns is non-NULL. Later aa_alloc_profile() crashes as the new profile name is NULL now.
general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 6 PID: 1657 Comm: apparmor_parser Not tainted 6.7.0-rc2-dirty #16 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 RIP: 0010:strlen+0x1e/0xa0 Call Trace: <TASK> ? strlen+0x1e/0xa0 aa_policy_init+0x1bb/0x230 aa_alloc_profile+0xb1/0x480 unpack_profile+0x3bc/0x4960 aa_unpack+0x309/0x15e0 aa_replace_profiles+0x213/0x33c0 policy_update+0x261/0x370 profile_replace+0x20e/0x2a0 vfs_write+0x2af/0xe00 ksys_write+0x126/0x250 do_syscall_64+0x46/0xf0 entry_SYSCALL_64_after_hwframe+0x6e/0x76 </TASK> ---[ end trace 0000000000000000 ]--- RIP: 0010:strlen+0x1e/0xa0
It seems such behaviour of aa_splitn_fqname() is expected and checked in other places where it is called (e.g. aa_remove_profiles). Well, there is an explicit comment "a ns name without a following profile is allowed" inside.
AFAICS, nothing can prevent unpacked "name" to be in form like ":samba-dcerpcd" - it is passed from userspace.
Deny the whole profile set replacement in such case and inform user with EPROTO and an explaining message.
Found by Linux Verification Center (linuxtesting.org).
--- security/apparmor/policy_unpack.c | 4 ++++ 1 file changed, 4 insertions(+)
security/apparmor/policy_unpack.c +4 -0
@@ -696,6 +696,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) tmpname =aa_splitn_fqname (name,strlen (name), &tmpns, &ns_len);if (tmpns) { +if (!tmpname) { + info ="empty profile name" ; + goto fail; + } *ns_name =kstrndup (tmpns, ns_len,GFP_KERNEL );if (!*ns_name) { info ="out of memory" ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 326/374 usb: xhci-mtk: fix a short packet issue of gen1 isoc-in transfer
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chunfeng Yun <[email protected]>
[ Upstream commit 017dbfc05c31284150819890b4cc86a699cbdb71 ]
For Gen1 isoc-in transfer, host still send out unexpected ACK after device finish the burst with a short packet, this will cause an exception on the connected device, such as, a usb 4k camera.
It can be fixed by setting rxfifo depth less than 4k bytes, prefer to use 3k here, the side-effect is that may cause performance drop about 10%, including bulk transfer.
--- drivers/usb/host/xhci-mtk.c | 40 +++++++++++++++++++++++++++++++++++-- drivers/usb/host/xhci-mtk.h | 2 ++ 2 files changed, 40 insertions(+), 2 deletions(-)
drivers/usb/host/xhci-mtk.c +38 -2
@@ -7,6 +7,7 @@* Chunfeng Yun <[email protected]> */ +#include <linux/bitfield.h> #include <linux/dma-mapping.h> #include <linux/iopoll.h> #include <linux/kernel.h>
@@ -72,6 +73,9 @@#define FRMCNT_LEV1_RANG (0x12b << 8)#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8) +#define HSCH_CFG1 0x960 +#define SCH3_RXFIFO_DEPTH_MASK GENMASK(21, 20) +#define SS_GEN2_EOF_CFG 0x990#define SSG2EOF_OFFSET 0x3c
@@ -100,6 +104,8 @@#define SSC_IP_SLEEP_EN BIT(4)#define SSC_SPM_INT_EN BIT(1) +#define SCH_FIFO_TO_KB (x) ((x) >> 10) +enum ssusb_uwk_vers {SSUSB_UWK_V1 =1 ,SSUSB_UWK_V2 ,
@@ -147,6 +153,35 @@ static void xhci_mtk_set_frame_interval(struct xhci_hcd_mtk *mtk)writel (value, hcd->regs +SS_GEN2_EOF_CFG ); } +/* +* workaround: usb3.2 gen1 isoc rx hw issue +* host send out unexpected ACK afer device fininsh a burst transfer with +* a short packet. +*/ +static void xhci_mtk_rxfifo_depth_set (struct xhci_hcd_mtk *mtk) +{ +struct usb_hcd *hcd = mtk->hcd; +u32 value; + +if (!mtk->rxfifo_depth) +return ; + + value =readl (hcd->regs +HSCH_CFG1 ); + value &= ~SCH3_RXFIFO_DEPTH_MASK ; + value |=FIELD_PREP (SCH3_RXFIFO_DEPTH_MASK , +SCH_FIFO_TO_KB (mtk->rxfifo_depth) -1 ); +writel (value, hcd->regs +HSCH_CFG1 ); +} + +static void xhci_mtk_init_quirk (struct xhci_hcd_mtk *mtk) +{ +/* workaround only for mt8195 */ +xhci_mtk_set_frame_interval (mtk); + +/* workaround for SoCs using SSUSB about before IPM v1.6.0 */ +xhci_mtk_rxfifo_depth_set (mtk); +} +static int xhci_mtk_host_enable (struct xhci_hcd_mtk *mtk) {struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
@@ -429,8 +464,7 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)if (ret)return ret; -/* workaround only for mt8195 */ -xhci_mtk_set_frame_interval (mtk); +xhci_mtk_init_quirk (mtk); } ret =xhci_gen_setup (hcd, xhci_mtk_quirks);
@@ -517,6 +551,8 @@ static int xhci_mtk_probe(struct platform_device *pdev)of_property_read_u32 (node,"mediatek,u2p-dis-msk" , &mtk->u2p_dis_msk); +of_property_read_u32 (node,"rx-fifo-depth" , &mtk->rxfifo_depth); + ret =usb_wakeup_of_property_parse (mtk, node);if (ret) {dev_err (dev,"failed to parse uwk property\n" );
drivers/usb/host/xhci-mtk.h +2 -0
@@ -161,6 +161,8 @@ struct xhci_hcd_mtk {struct regmap *uwk;u32 uwk_reg_base;u32 uwk_vers; +/* quirk */ +u32 rxfifo_depth; };static inline struct xhci_hcd_mtk *hcd_to_mtk (struct usb_hcd *hcd)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 327/374 serial: imx: Correct clock error message in function probe()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Niedermaier <[email protected]>
[ Upstream commit 3e189470cad27d41a3a9dc02649f965b7ed1c90f ]
Correct the clock error message by changing the clock name.
--- drivers/tty/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/imx.c +1 -1
@@ -2318,7 +2318,7 @@ static int imx_uart_probe(struct platform_device *pdev)/* For register access, we only need to enable the ipg clock. */ ret =clk_prepare_enable (sport->clk_ipg);if (ret) { -dev_err (&pdev->dev,"failed to enable per clk: %d\n" , ret); +dev_err (&pdev->dev,"failed to enable ipg clk: %d\n" , ret);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 328/374 nvmet: re-fix tracing strncpy() warning
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 4ee7ffeb4ce50c80bc4504db6f39b25a2df6bcf4 ]
An earlier patch had tried to address a warning about a string copy with missing zero termination:
drivers/nvme/target/trace.h:52:3: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation]
The new version causes a different warning with some compiler versions, notably gcc-9 and gcc-10, and also misses the zero padding that was apparently done intentionally in the original code:
drivers/nvme/target/trace.h:56:2: error: 'strncpy' specified bound depends on the length of the source argument [-Werror=stringop-overflow=]
Change it to use strscpy_pad() with the original length, which will give a properly padded and zero-terminated string as well as avoiding the warning.
--- drivers/nvme/target/trace.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/nvme/target/trace.h +1 -2
@@ -53,8 +53,7 @@ static inline void __assign_req_name(char *name, struct nvmet_req *req) return; } -strncpy (name, req->ns->device_path, -min_t (size_t,DISK_NAME_LEN ,strlen (req->ns->device_path))); +strscpy_pad (name, req->ns->device_path,DISK_NAME_LEN ); }#endif
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 329/374 nvmet-tcp: Fix the H2C expected PDU len calculation
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maurizio Lombardi <[email protected]>
[ Upstream commit 9a1abc24850eb759e36a2f8869161c3b7254c904 ]
The nvmet_tcp_handle_h2c_data_pdu() function should take into consideration the possibility that the header digest and/or the data digests are enabled when calculating the expected PDU length, before comparing it to the value stored in cmd->pdu_len.
--- drivers/nvme/target/tcp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/nvme/target/tcp.c +7 -3
@@ -931,7 +931,7 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue) {struct nvme_tcp_data_pdu *data = &queue->pdu.data;struct nvmet_tcp_cmd *cmd; -unsigned int plen; +unsigned int exp_data_len;if (likely (queue->nr_cmds)) {if (unlikely (data->ttag >= queue->nr_cmds)) {
@@ -954,9 +954,13 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue)return -EPROTO ; } - plen =le32_to_cpu (data->hdr.plen); + exp_data_len =le32_to_cpu (data->hdr.plen) - +nvmet_tcp_hdgst_len (queue) - +nvmet_tcp_ddgst_len (queue) - +sizeof (*data); + cmd->pdu_len =le32_to_cpu (data->data_length); -if (unlikely (cmd->pdu_len != (plen -sizeof (*data)) || +if (unlikely (cmd->pdu_len != exp_data_len || cmd->pdu_len ==0 || cmd->pdu_len >NVMET_TCP_MAXH2CDATA )) {pr_err ("H2CData PDU len %u is invalid\n" , cmd->pdu_len);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 330/374 PCI: keystone: Fix race condition when initializing PHYs
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddharth Vadapalli <[email protected]>
[ Upstream commit c12ca110c613a81cb0f0099019c839d078cd0f38 ]
The PCI driver invokes the PHY APIs using the ks_pcie_enable_phy() function. The PHY in this case is the Serdes. It is possible that the PCI instance is configured for two lane operation across two different Serdes instances, using one lane of each Serdes.
In such a configuration, if the reference clock for one Serdes is provided by the other Serdes, it results in a race condition. After the Serdes providing the reference clock is initialized by the PCI driver by invoking its PHY APIs, it is not guaranteed that this Serdes remains powered on long enough for the PHY APIs based initialization of the dependent Serdes. In such cases, the PLL of the dependent Serdes fails to lock due to the absence of the reference clock from the former Serdes which has been powered off by the PM Core.
Fix this by obtaining reference to the PHYs before invoking the PHY initialization APIs and releasing reference after the initialization is complete.
--- drivers/pci/controller/dwc/pci-keystone.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/pci/controller/dwc/pci-keystone.c +9 -0
@@ -1200,7 +1200,16 @@ static int ks_pcie_probe(struct platform_device *pdev) goto err_link; } +/* Obtain references to the PHYs */ +for (i =0 ; i < num_lanes; i++) +phy_pm_runtime_get_sync (ks_pcie->phy[i]); + ret =ks_pcie_enable_phy (ks_pcie); + +/* Release references to the PHYs */ +for (i =0 ; i < num_lanes; i++) +phy_pm_runtime_put_sync (ks_pcie->phy[i]); +if (ret) {dev_err (dev,"failed to enable phy\n" ); goto err_link;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 331/374 s390/pci: fix max size calculation in zpci_memcpy_toio()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Schnelle <[email protected]>
[ Upstream commit 80df7d6af7f6d229b34cf237b2cc9024c07111cd ]
The zpci_get_max_write_size() helper is used to determine the maximum size a PCI store or load can use at a given __iomem address.
For the PCI block store the following restrictions apply:
1. The dst + len must not cross a 4K boundary in the (pseudo-)MMIO space
2. len must not exceed ZPCI_MAX_WRITE_SIZE
3. len must be a multiple of 8 bytes
4. The src address must be double word (8 byte) aligned
5. The dst address must be double word (8 byte) aligned
Otherwise only a normal PCI store which takes its src value from a register can be used. For these PCI store restriction 1 still applies. Similarly 1 also applies to PCI loads.
It turns out zpci_max_write_size() instead implements stricter conditions which prevents PCI block stores from being used where they can and should be used. In particular instead of conditions 4 and 5 it wrongly enforces both dst and src to be size aligned. This indirectly covers condition 1 but also prevents many legal PCI block stores.
On top of the functional shortcomings the zpci_get_max_write_size() is misnamed as it is used for both read and write size calculations. Rename it to zpci_get_max_io_size() and implement the listed conditions explicitly.
--- arch/s390/include/asm/pci_io.h | 32 ++++++++++++++++++-------------- arch/s390/pci/pci_mmio.c | 12 ++++++------ 2 files changed, 24 insertions(+), 20 deletions(-)
arch/s390/include/asm/pci_io.h +18 -14
@@ -11,6 +11,8 @@/* I/O size constraints */ #define ZPCI_MAX_READ_SIZE 8#define ZPCI_MAX_WRITE_SIZE 128 +#define ZPCI_BOUNDARY_SIZE (1 << 12) +#define ZPCI_BOUNDARY_MASK (ZPCI_BOUNDARY_SIZE - 1)/* I/O Map */ #define ZPCI_IOMAP_SHIFT 48
@@ -125,16 +127,18 @@ static inline int zpci_read_single(void *dst, const volatile void __iomem *src,int zpci_write_block (volatile void __iomem *dst,const void *src,unsigned long len); -static inline u8 zpci_get_max_write_size (u64 src,u64 dst,int len,int max) +static inline int zpci_get_max_io_size (u64 src,u64 dst,int len,int max) { -int count = len > max ? max : len, size =1 ; +int offset = dst &ZPCI_BOUNDARY_MASK ; +int size; -while (!(src &0x1 ) && !(dst &0x1 ) && ((size <<1 ) <= count)) { - dst = dst >>1 ; - src = src >>1 ; - size = size <<1 ; - } -return size; + size =min3 (len,ZPCI_BOUNDARY_SIZE - offset, max); +if (IS_ALIGNED (src,8 ) &&IS_ALIGNED (dst,8 ) &&IS_ALIGNED (size,8 )) +return size; + +if (size >=8 ) +return 8 ; +return rounddown_pow_of_two (size); } static inline int zpci_memcpy_fromio(void *dst,
@@ -144,9 +148,9 @@ static inline int zpci_memcpy_fromio(void *dst,int size, rc =0 ;while (n >0 ) { - size =zpci_get_max_write_size ((u64 __force ) src, - (u64 ) dst, n, -ZPCI_MAX_READ_SIZE ); + size =zpci_get_max_io_size ((u64 __force ) src, + (u64 ) dst, n, +ZPCI_MAX_READ_SIZE ); rc =zpci_read_single (dst, src, size);if (rc)break ;
@@ -166,9 +170,9 @@ static inline int zpci_memcpy_toio(volatile void __iomem *dst,return -EINVAL ;while (n >0 ) { - size =zpci_get_max_write_size ((u64 __force ) dst, - (u64 ) src, n, -ZPCI_MAX_WRITE_SIZE ); + size =zpci_get_max_io_size ((u64 __force ) dst, + (u64 ) src, n, +ZPCI_MAX_WRITE_SIZE );if (size >8 )/* main path */ rc =zpci_write_block (dst, src, size);else
arch/s390/pci/pci_mmio.c +6 -6
@@ -96,9 +96,9 @@ static inline int __memcpy_toio_inuser(void __iomem *dst,return -EINVAL ;while (n >0 ) { - size =zpci_get_max_write_size ((u64 __force ) dst, - (u64 __force ) src, n, -ZPCI_MAX_WRITE_SIZE ); + size =zpci_get_max_io_size ((u64 __force ) dst, + (u64 __force ) src, n, +ZPCI_MAX_WRITE_SIZE );if (size >8 )/* main path */ rc =__pcistb_mio_inuser (dst, src, size, &status);else
@@ -241,9 +241,9 @@ static inline int __memcpy_fromio_inuser(void __user *dst,u8 status;while (n >0 ) { - size =zpci_get_max_write_size ((u64 __force ) src, - (u64 __force ) dst, n, -ZPCI_MAX_READ_SIZE ); + size =zpci_get_max_io_size ((u64 __force ) src, + (u64 __force ) dst, n, +ZPCI_MAX_READ_SIZE ); rc =__pcilg_mio_inuser (dst, src, size, &status);if (rc)break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 332/374 net: qualcomm: rmnet: fix global oob in rmnet_policy
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lin Ma <[email protected]>
[ Upstream commit b33fb5b801c6db408b774a68e7c8722796b59ecc ]
The variable rmnet_link_ops assign a *bigger* maxtype which leads to a global out-of-bounds read when parsing the netlink attributes. See bug trace below:
==================================================================
BUG: KASAN: global-out-of-bounds in validate_nla lib/nlattr.c:386 [inline]
BUG: KASAN: global-out-of-bounds in __nla_validate_parse+0x24af/0x2750 lib/nlattr.c:600
Read of size 1 at addr ffffffff92c438d0 by task syz-executor.6/84207
CPU: 0 PID: 84207 Comm: syz-executor.6 Tainted: G N 6.1.0 #3
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x8b/0xb3 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:284 [inline]
print_report+0x172/0x475 mm/kasan/report.c:395
kasan_report+0xbb/0x1c0 mm/kasan/report.c:495
validate_nla lib/nlattr.c:386 [inline]
__nla_validate_parse+0x24af/0x2750 lib/nlattr.c:600
__nla_parse+0x3e/0x50 lib/nlattr.c:697
nla_parse_nested_deprecated include/net/netlink.h:1248 [inline]
__rtnl_newlink+0x50a/0x1880 net/core/rtnetlink.c:3485
rtnl_newlink+0x64/0xa0 net/core/rtnetlink.c:3594
rtnetlink_rcv_msg+0x43c/0xd70 net/core/rtnetlink.c:6091
netlink_rcv_skb+0x14f/0x410 net/netlink/af_netlink.c:2540
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x54e/0x800 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x930/0xe50 net/netlink/af_netlink.c:1921
sock_sendmsg_nosec net/socket.c:714 [inline]
sock_sendmsg+0x154/0x190 net/socket.c:734
____sys_sendmsg+0x6df/0x840 net/socket.c:2482
___sys_sendmsg+0x110/0x1b0 net/socket.c:2536
__sys_sendmsg+0xf3/0x1c0 net/socket.c:2565
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x3b/0x90 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fdcf2072359
Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 19 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fdcf13e3168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00007fdcf219ff80 RCX: 00007fdcf2072359
RDX: 0000000000000000 RSI: 0000000020000200 RDI: 0000000000000003
RBP: 00007fdcf20bd493 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fffbb8d7bdf R14: 00007fdcf13e3300 R15: 0000000000022000
</TASK>
The buggy address belongs to the variable:
rmnet_policy+0x30/0xe0
The buggy address belongs to the physical page:
page:0000000065bdeb3c refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x155243
flags: 0x200000000001000(reserved|node=0|zone=2)
raw: 0200000000001000 ffffea00055490c8 ffffea00055490c8 0000000000000000
raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffffffff92c43780: f9 f9 f9 f9 00 00 00 02 f9 f9 f9 f9 00 00 00 07
ffffffff92c43800: f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9 06 f9 f9 f9
>ffffffff92c43880: f9 f9 f9 f9 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
^
ffffffff92c43900: 00 00 00 00 00 00 00 00 07 f9 f9 f9 f9 f9 f9 f9
ffffffff92c43980: 00 00 00 07 f9 f9 f9 f9 00 00 00 05 f9 f9 f9 f9According to the comment of nla_parse_nested_deprecated, the maxtype should be len(destination array) - 1. Hence use IFLA_RMNET_MAX here.
--- drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +1 -1
@@ -391,7 +391,7 @@ static int rmnet_fill_info(struct sk_buff *skb, const struct net_device *dev)struct rtnl_link_ops rmnet_link_ops__read_mostly = { .kind ="rmnet" , - .maxtype = __IFLA_RMNET_MAX, + .maxtype =IFLA_RMNET_MAX , .priv_size =sizeof (struct rmnet_priv ), .setup = rmnet_vnd_setup, .validate = rmnet_rtnl_validate,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 333/374 net: ethernet: ti: am65-cpsw: Fix max mtu to fit ethernet frames
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanjuán García, Jorge <[email protected]>
[ Upstream commit 64e47d8afb5ca533b27efc006405e5bcae2c4a7b ]
The value of AM65_CPSW_MAX_PACKET_SIZE represents the maximum length of a received frame. This value is written to the register AM65_CPSW_PORT_REG_RX_MAXLEN.
The maximum MTU configured on the network device should then leave some room for the ethernet headers and frame check. Otherwise, if the network interface is configured to its maximum mtu possible, the frames will be larger than AM65_CPSW_MAX_PACKET_SIZE and will get dropped as oversized.
The switch supports ethernet frame sizes between 64 and 2024 bytes (including VLAN) as stated in the technical reference manual, so define AM65_CPSW_MAX_PACKET_SIZE with that maximum size.
--- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/ethernet/ti/am65-cpsw-nuss.c +3 -2
@@ -53,7 +53,7 @@#define AM65_CPSW_MAX_PORTS 8#define AM65_CPSW_MIN_PACKET_SIZE VLAN_ETH_ZLEN -#define AM65_CPSW_MAX_PACKET_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) +#define AM65_CPSW_MAX_PACKET_SIZE 2024#define AM65_CPSW_REG_CTL 0x004#define AM65_CPSW_REG_STAT_PORT_EN 0x014
@@ -1985,7 +1985,8 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)eth_hw_addr_set (port->ndev, port->slave.mac_addr); port->ndev->min_mtu =AM65_CPSW_MIN_PACKET_SIZE ; - port->ndev->max_mtu =AM65_CPSW_MAX_PACKET_SIZE ; + port->ndev->max_mtu =AM65_CPSW_MAX_PACKET_SIZE - + (VLAN_ETH_HLEN +ETH_FCS_LEN ); port->ndev->hw_features =NETIF_F_SG |NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 334/374 net: phy: micrel: populate .soft_reset for KSZ9131
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea <[email protected]>
[ Upstream commit e398822c4751017fe401f57409488f5948d12fb5 ]
The RZ/G3S SMARC Module has 2 KSZ9131 PHYs. In this setup, the KSZ9131 PHY is used with the ravb Ethernet driver. It has been discovered that when bringing the Ethernet interface down/up continuously, e.g., with the following sh script:
$ while :; do ifconfig eth0 down; ifconfig eth0 up; done
the link speed and duplex are wrong after interrupting the bring down/up operation even though the Ethernet interface is up. To recover from this state the following configuration sequence is necessary (executed manually):
$ ifconfig eth0 down $ ifconfig eth0 up
The behavior has been identified also on the Microchip SAMA7G5-EK board which runs the macb driver and uses the same PHY.
The order of PHY-related operations in ravb_open() is as follows:ravb_open() ->
ravb_phy_start() ->
ravb_phy_init() ->
of_phy_connect() ->
phy_connect_direct() ->
phy_attach_direct() ->
phy_init_hw() ->
phydev->drv->soft_reset()
phydev->drv->config_init()
phydev->drv->config_intr()
phy_resume()
kszphy_resume()The order of PHY-related operations in ravb_close is as follows:ravb_close() ->
phy_stop() ->
phy_suspend() ->
kszphy_suspend() ->
genphy_suspend()
// set BMCR_PDOWN bit in MII_BMCRIn genphy_suspend() setting the BMCR_PDWN bit in MII_BMCR switches the PHY to Software Power-Down (SPD) mode (according to the KSZ9131 datasheet). Thus, when opening the interface after it has been previously closed (via ravb_close()), the phydev->drv->config_init() and phydev->drv->config_intr() reach the KSZ9131 PHY driver via the ksz9131_config_init() and kszphy_config_intr() functions.
KSZ9131 specifies that the MII management interface remains operational during SPD (Software Power-Down), but (according to manual):
- Only access to the standard registers (0 through 31) is supported.
- Access to MMD address spaces other than MMD address space 1 is possible if the spd_clock_gate_override bit is set.
- Access to MMD address space 1 is not possible.
The spd_clock_gate_override bit is not used in the KSZ9131 driver.
ksz9131_config_init() configures RGMII delay, pad skews and LEDs by accessesing MMD registers other than those in address space 1.
The datasheet for the KSZ9131 does not specify what happens if registers from an unsupported address space are accessed while the PHY is in SPD.
To fix the issue the .soft_reset method has been instantiated for KSZ9131, too. This resets the PHY to the default state before doing any configurations to it, thus switching it out of SPD.
--- drivers/net/phy/micrel.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/phy/micrel.c +1 -0
@@ -1728,6 +1728,7 @@ static struct phy_driver ksphy_driver[] = {/* PHY_GBIT_FEATURES */ .driver_data = &ksz9021_type, .probe = kszphy_probe, + .soft_reset = genphy_soft_reset, .config_init = ksz9131_config_init, .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 335/374 mptcp: mptcp_parse_option() fix for MPTCPOPT_MP_JOIN
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 89e23277f9c16df6f9f9c1a1a07f8f132339c15c ]
mptcp_parse_option() currently sets OPTIONS_MPTCP_MPJ, for the three possible cases handled for MPTCPOPT_MP_JOIN option.
OPTIONS_MPTCP_MPJ is the combination of three flags:
- OPTION_MPTCP_MPJ_SYN
- OPTION_MPTCP_MPJ_SYNACK
- OPTION_MPTCP_MPJ_ACK
This is a problem, because backup, join_id, token, nonce and/or hmac fields could be left uninitialized in some cases.
Distinguish the three cases, as following patches will need this step.
--- net/mptcp/options.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/mptcp/options.c +3 -3
@@ -118,8 +118,8 @@ static void mptcp_parse_option(const struct sk_buff *skb,break ;case MPTCPOPT_MP_JOIN : - mp_opt->suboptions |=OPTIONS_MPTCP_MPJ ;if (opsize ==TCPOLEN_MPTCP_MPJ_SYN ) { + mp_opt->suboptions |=OPTION_MPTCP_MPJ_SYN ; mp_opt->backup = *ptr++ &MPTCPOPT_BACKUP ; mp_opt->join_id = *ptr++; mp_opt->token =get_unaligned_be32 (ptr);
@@ -130,6 +130,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, mp_opt->backup, mp_opt->join_id, mp_opt->token, mp_opt->nonce); }else if (opsize ==TCPOLEN_MPTCP_MPJ_SYNACK ) { + mp_opt->suboptions |=OPTION_MPTCP_MPJ_SYNACK ; mp_opt->backup = *ptr++ &MPTCPOPT_BACKUP ; mp_opt->join_id = *ptr++; mp_opt->thmac =get_unaligned_be64 (ptr);
@@ -140,11 +141,10 @@ static void mptcp_parse_option(const struct sk_buff *skb, mp_opt->backup, mp_opt->join_id, mp_opt->thmac, mp_opt->nonce); }else if (opsize ==TCPOLEN_MPTCP_MPJ_ACK ) { + mp_opt->suboptions |=OPTION_MPTCP_MPJ_ACK ; ptr +=2 ;memcpy (mp_opt->hmac, ptr,MPTCPOPT_HMAC_LEN );pr_debug ("MP_JOIN hmac" ); - }else { - mp_opt->suboptions &= ~OPTIONS_MPTCP_MPJ ; }break ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 336/374 mptcp: drop unused sk in mptcp_get_options
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geliang Tang <[email protected]>
[ Upstream commit 0799e21b5a76d9f14d8a8f024d0b6b9847ad1a03 ]
The parameter 'sk' became useless since the code using it was dropped from mptcp_get_options() in the commit 8d548ea1dd15 ("mptcp: do not set unconditionally csum_reqd on incoming opt"). Let's drop it.
Stable-dep-of: c1665273bdc7 ("mptcp: strict validation before using mp_opt->hmac")
--- net/mptcp/options.c | 5 ++--- net/mptcp/protocol.h | 3 +-- net/mptcp/subflow.c | 10 +++++----- 3 files changed, 8 insertions(+), 10 deletions(-)
net/mptcp/options.c +2 -3
@@ -354,8 +354,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, } } -void mptcp_get_options (const struct sock *sk, -const struct sk_buff *skb, +void mptcp_get_options (const struct sk_buff *skb,struct mptcp_options_received *mp_opt) {const struct tcphdr *th =tcp_hdr (skb);
@@ -1091,7 +1090,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)return true; } -mptcp_get_options (sk, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt);/* The subflow can be in close state only if check_fully_established() * just sent a reset. If so, tell the caller to ignore the current packet.
net/mptcp/protocol.h +1 -2
@@ -636,8 +636,7 @@ int __init mptcp_proto_v6_init(void);struct sock *mptcp_sk_clone (const struct sock *sk,const struct mptcp_options_received *mp_opt,struct request_sock *req); -void mptcp_get_options (const struct sock *sk, -const struct sk_buff *skb, +void mptcp_get_options (const struct sk_buff *skb,struct mptcp_options_received *mp_opt);void mptcp_finish_connect (struct sock *sk);
net/mptcp/subflow.c +5 -5
@@ -152,7 +152,7 @@ static int subflow_check_req(struct request_sock *req,return -EINVAL ;#endif -mptcp_get_options (sk_listener, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt); opt_mp_capable = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPC ); opt_mp_join = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ );
@@ -249,7 +249,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,int err;subflow_init_req (req, sk_listener); -mptcp_get_options (sk_listener, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt); opt_mp_capable = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPC ); opt_mp_join = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ );
@@ -407,7 +407,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) subflow->ssn_offset =TCP_SKB_CB (skb)->seq;pr_debug ("subflow=%p synack seq=%x" , subflow, subflow->ssn_offset); -mptcp_get_options (sk, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt);if (subflow->request_mptcp) {if (!(mp_opt.suboptions &OPTIONS_MPTCP_MPC )) { MPTCP_INC_STATS(sock_net(sk),
@@ -687,7 +687,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,* reordered MPC will cause fallback, but we don't have other * options. */ -mptcp_get_options (sk, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt);if (!(mp_opt.suboptions &OPTIONS_MPTCP_MPC )) { fallback = true; goto create_child;
@@ -697,7 +697,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,if (!new_msk) fallback = true; }else if (subflow_req->mp_join) { -mptcp_get_options (sk, skb, &mp_opt); +mptcp_get_options (skb, &mp_opt);if (!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ ) || !subflow_hmac_valid (req, &mp_opt) || !mptcp_can_accept_new_subflow (subflow_req->msk)) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 337/374 mptcp: strict validation before using mp_opt->hmac
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit c1665273bdc7c201766c65e561c06711f2e050dc ]
mp_opt->hmac contains uninitialized data unless OPTION_MPTCP_MPJ_ACK was set in mptcp_parse_option().
We must refine the condition before we call subflow_hmac_valid().
--- net/mptcp/subflow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/subflow.c +1 -1
@@ -698,7 +698,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, fallback = true; }else if (subflow_req->mp_join) {mptcp_get_options (skb, &mp_opt); -if (!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ ) || +if (!(mp_opt.suboptions &OPTION_MPTCP_MPJ_ACK ) || !subflow_hmac_valid (req, &mp_opt) || !mptcp_can_accept_new_subflow (subflow_req->msk)) {SUBFLOW_REQ_INC_STATS (req,MPTCP_MIB_JOINACKMAC );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 338/374 mptcp: use OPTION_MPTCP_MPJ_SYNACK in subflow_finish_connect()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit be1d9d9d38da922bd4beeec5b6dd821ff5a1dfeb ]
subflow_finish_connect() uses four fields (backup, join_id, thmac, none) that may contain garbage unless OPTION_MPTCP_MPJ_SYNACK has been set in mptcp_parse_option()
--- net/mptcp/subflow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/subflow.c +1 -1
@@ -432,7 +432,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) }else if (subflow->request_join) {u8 hmac[SHA256_DIGEST_SIZE ]; -if (!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ )) { +if (!(mp_opt.suboptions &OPTION_MPTCP_MPJ_SYNACK )) { subflow->reset_reason =MPTCP_RST_EMPTCP ; goto do_reset; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 339/374 mptcp: use OPTION_MPTCP_MPJ_SYN in subflow_check_req()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 66ff70df1a919a066942844bb095d6fcb748d78d ]
syzbot reported that subflow_check_req() was using uninitialized data in subflow_check_req() [1]
This is because mp_opt.token is only set when OPTION_MPTCP_MPJ_SYN is also set.
While we are are it, fix mptcp_subflow_init_cookie_req() to test for OPTION_MPTCP_MPJ_ACK.
[1]
BUG: KMSAN: uninit-value in subflow_token_join_request net/mptcp/subflow.c:91 [inline] BUG: KMSAN: uninit-value in subflow_check_req+0x1028/0x15d0 net/mptcp/subflow.c:209 subflow_token_join_request net/mptcp/subflow.c:91 [inline] subflow_check_req+0x1028/0x15d0 net/mptcp/subflow.c:209 subflow_v6_route_req+0x269/0x410 net/mptcp/subflow.c:367 tcp_conn_request+0x153a/0x4240 net/ipv4/tcp_input.c:7164 subflow_v6_conn_request+0x3ee/0x510 tcp_rcv_state_process+0x2e1/0x4ac0 net/ipv4/tcp_input.c:6659 tcp_v6_do_rcv+0x11bf/0x1fe0 net/ipv6/tcp_ipv6.c:1669 tcp_v6_rcv+0x480b/0x4fb0 net/ipv6/tcp_ipv6.c:1900 ip6_protocol_deliver_rcu+0xda6/0x2a60 net/ipv6/ip6_input.c:438 ip6_input_finish net/ipv6/ip6_input.c:483 [inline] NF_HOOK include/linux/netfilter.h:314 [inline] ip6_input+0x15d/0x430 net/ipv6/ip6_input.c:492 dst_input include/net/dst.h:461 [inline] ip6_rcv_finish+0x5db/0x870 net/ipv6/ip6_input.c:79 NF_HOOK include/linux/netfilter.h:314 [inline] ipv6_rcv+0xda/0x390 net/ipv6/ip6_input.c:310 __netif_receive_skb_one_core net/core/dev.c:5532 [inline] __netif_receive_skb+0x1a6/0x5a0 net/core/dev.c:5646 netif_receive_skb_internal net/core/dev.c:5732 [inline] netif_receive_skb+0x58/0x660 net/core/dev.c:5791 tun_rx_batched+0x3ee/0x980 drivers/net/tun.c:1555 tun_get_user+0x53af/0x66d0 drivers/net/tun.c:2002 tun_chr_write_iter+0x3af/0x5d0 drivers/net/tun.c:2048 call_write_iter include/linux/fs.h:2020 [inline] new_sync_write fs/read_write.c:491 [inline] vfs_write+0x8ef/0x1490 fs/read_write.c:584 ksys_write+0x20f/0x4c0 fs/read_write.c:637 __do_sys_write fs/read_write.c:649 [inline] __se_sys_write fs/read_write.c:646 [inline] __x64_sys_write+0x93/0xd0 fs/read_write.c:646 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x44/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x63/0x6b
Local variable mp_opt created at:
subflow_check_req+0x6d/0x15d0 net/mptcp/subflow.c:145 subflow_v6_route_req+0x269/0x410 net/mptcp/subflow.c:367 CPU: 1 PID: 5924 Comm: syz-executor.3 Not tainted 6.7.0-rc8-syzkaller-00055-g5eff55d725a4 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/17/2023
--- net/mptcp/subflow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/mptcp/subflow.c +2 -2
@@ -155,7 +155,7 @@ static int subflow_check_req(struct request_sock *req,mptcp_get_options (skb, &mp_opt); opt_mp_capable = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPC ); - opt_mp_join = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ ); + opt_mp_join = !!(mp_opt.suboptions &OPTION_MPTCP_MPJ_SYN );if (opt_mp_capable) {SUBFLOW_REQ_INC_STATS (req,MPTCP_MIB_MPCAPABLEPASSIVE );
@@ -252,7 +252,7 @@ int mptcp_subflow_init_cookie_req(struct request_sock *req,mptcp_get_options (skb, &mp_opt); opt_mp_capable = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPC ); - opt_mp_join = !!(mp_opt.suboptions &OPTIONS_MPTCP_MPJ ); + opt_mp_join = !!(mp_opt.suboptions &OPTION_MPTCP_MPJ_ACK );if (opt_mp_capable && opt_mp_join)return -EINVAL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 340/374 net: ravb: Fix dma_addr_t truncation in error case
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikita Yushchenko <[email protected]>
[ Upstream commit e327b2372bc0f18c30433ac40be07741b59231c5 ]
In ravb_start_xmit(), ravb driver uses u32 variable to store result of dma_map_single() call. Since ravb hardware has 32-bit address fields in descriptors, this works properly when mapping is successful - it is platform's job to provide mapping addresses that fit into hardware limitations.
However, in failure case dma_map_single() returns DMA_MAPPING_ERROR constant that is 64-bit when dma_addr_t is 64-bit. Storing this constant in u32 leads to truncation, and further call to dma_mapping_error() fails to notice the error.
Fix that by storing result of dma_map_single() in a dma_addr_t variable.
--- drivers/net/ethernet/renesas/ravb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/renesas/ravb_main.c +1 -1
@@ -1567,7 +1567,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)struct ravb_tstamp_skb *ts_skb;struct ravb_tx_desc *desc;unsigned long flags; -u32 dma_addr; +dma_addr_t dma_addr;void *buffer;u32 entry;u32 len;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 341/374 net: stmmac: ethtool: Fixed calltrace caused by unbalanced disable_irq_wake calls
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qiang Ma <[email protected]>
[ Upstream commit a23aa04042187cbde16f470b49d4ad60d32e9206 ]
We found the following dmesg calltrace when testing the GMAC NIC notebook:
[9.448656] ------------[ cut here ]------------ [9.448658] Unbalanced IRQ 43 wake disable [9.448673] WARNING: CPU: 3 PID: 1083 at kernel/irq/manage.c:688 irq_set_irq_wake+0xe0/0x128 [9.448717] CPU: 3 PID: 1083 Comm: ethtool Tainted: G O 4.19 #1 [9.448773] ... [9.448774] Call Trace: [9.448781] [<9000000000209b5c>] show_stack+0x34/0x140 [9.448788] [<9000000000d52700>] dump_stack+0x98/0xd0 [9.448794] [<9000000000228610>] __warn+0xa8/0x120 [9.448797] [<9000000000d2fb60>] report_bug+0x98/0x130 [9.448800] [<900000000020a418>] do_bp+0x248/0x2f0 [9.448805] [<90000000002035f4>] handle_bp_int+0x4c/0x78 [9.448808] [<900000000029ea40>] irq_set_irq_wake+0xe0/0x128 [9.448813] [<9000000000a96a7c>] stmmac_set_wol+0x134/0x150 [9.448819] [<9000000000be6ed0>] dev_ethtool+0x1368/0x2440 [9.448824] [<9000000000c08350>] dev_ioctl+0x1f8/0x3e0 [9.448827] [<9000000000bb2a34>] sock_ioctl+0x2a4/0x450 [9.448832] [<900000000046f044>] do_vfs_ioctl+0xa4/0x738 [9.448834] [<900000000046f778>] ksys_ioctl+0xa0/0xe8 [9.448837] [<900000000046f7d8>] sys_ioctl+0x18/0x28 [9.448840] [<9000000000211ab4>] syscall_common+0x20/0x34 [9.448842] ---[ end trace 40c18d9aec863c3e ]---
Multiple disable_irq_wake() calls will keep decreasing the IRQ wake_depth, When wake_depth is 0, calling disable_irq_wake() again, will report the above calltrace.
Due to the need to appear in pairs, we cannot call disable_irq_wake() without calling enable_irq_wake(). Fix this by making sure there are no unbalanced disable_irq_wake() calls.
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 10 ++++++++-- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 1 + 3 files changed, 10 insertions(+), 2 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -0
@@ -241,6 +241,7 @@ struct stmmac_priv {u32 msg_enable;int wolopts;int wol_irq; +bool wol_irq_disabled;int clk_csr;struct timer_list eee_ctrl_timer;int lpi_irq;
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +8 -2
@@ -758,10 +758,16 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)if (wol->wolopts) {pr_info ("stmmac: wakeup enable\n" );device_set_wakeup_enable (priv->device,1 ); -enable_irq_wake (priv->wol_irq); +/* Avoid unbalanced enable_irq_wake calls */ +if (priv->wol_irq_disabled) +enable_irq_wake (priv->wol_irq); + priv->wol_irq_disabled = false; }else {device_set_wakeup_enable (priv->device,0 ); -disable_irq_wake (priv->wol_irq); +/* Avoid unbalanced disable_irq_wake calls */ +if (!priv->wol_irq_disabled) +disable_irq_wake (priv->wol_irq); + priv->wol_irq_disabled = true; }mutex_lock (&priv->lock);
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +1 -0
@@ -3506,6 +3506,7 @@ static int stmmac_request_irq_multi_msi(struct net_device *dev)/* Request the Wake IRQ in case of another line * is used for WoL */ + priv->wol_irq_disabled = true;if (priv->wol_irq >0 && priv->wol_irq != dev->irq) { int_name = priv->int_name_wol;sprintf (int_name,"%s:%s" , dev->name,"wol" );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 342/374 bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Sun <[email protected]>
[ Upstream commit 22c7fa171a02d310e3a3f6ed46a698ca8a0060ed ]
For PTR_TO_FLOW_KEYS, check_flow_keys_access() only uses fixed off for validation. However, variable offset ptr alu is not prohibited for this ptr kind. So the variable offset is not checked.
The following prog is accepted:
func#0 @0
0: R1=ctx() R10=fp0
0: (bf) r6 = r1 ; R1=ctx() R6_w=ctx() 1: (79) r7 = *(u64 *)(r6 +144) ; R6_w=ctx() R7_w=flow_keys() 2: (b7) r8 = 1024 ; R8_w=1024 3: (37) r8 /= 1 ; R8_w=scalar() 4: (57) r8 &= 1024 ; R8_w=scalar(smin=smin32=0,
smax=umax=smax32=umax32=1024,var_off=(0x0; 0x400))
5: (0f) r7 += r8
mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
mark_precise: frame0: regs=r8 stack= before 4: (57) r8 &= 1024
mark_precise: frame0: regs=r8 stack= before 3: (37) r8 /= 1
mark_precise: frame0: regs=r8 stack= before 2: (b7) r8 = 1024 6: R7_w=flow_keys(smin=smin32=0,smax=umax=smax32=umax32=1024,var_off =(0x0; 0x400)) R8_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=1024, var_off=(0x0; 0x400))
6: (79) r0 = *(u64 *)(r7 +0) ; R0_w=scalar()
7: (95) exit
This prog loads flow_keys to r7, and adds the variable offset r8 to r7, and finally causes out-of-bounds access:
BUG: unable to handle page fault for address: ffffc90014c80038 [...] Call Trace: <TASK> bpf_dispatcher_nop_func include/linux/bpf.h:1231 [inline] __bpf_prog_run include/linux/filter.h:651 [inline] bpf_prog_run include/linux/filter.h:658 [inline] bpf_prog_run_pin_on_cpu include/linux/filter.h:675 [inline] bpf_flow_dissect+0x15f/0x350 net/core/flow_dissector.c:991 bpf_prog_test_run_flow_dissector+0x39d/0x620 net/bpf/test_run.c:1359 bpf_prog_test_run kernel/bpf/syscall.c:4107 [inline] __sys_bpf+0xf8f/0x4560 kernel/bpf/syscall.c:5475 __do_sys_bpf kernel/bpf/syscall.c:5561 [inline] __se_sys_bpf kernel/bpf/syscall.c:5559 [inline] __x64_sys_bpf+0x73/0xb0 kernel/bpf/syscall.c:5559 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0x3f/0x110 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x63/0x6b
Fix this by rejecting ptr alu with variable offset on flow_keys. Applying the patch rejects the program with "R7 pointer arithmetic on flow_keys prohibited".
--- kernel/bpf/verifier.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/bpf/verifier.c +4 -0
@@ -7295,6 +7295,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, }switch (base_type (ptr_reg->type)) { +case PTR_TO_FLOW_KEYS : +if (known) +break ; + fallthrough;case CONST_PTR_TO_MAP :/* smin_val represents the known value */ if (known && smin_val ==0 && opcode ==BPF_ADD )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 343/374 net: dsa: vsc73xx: Add null pointer check to vsc73xx_gpio_probe
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kunwu Chan <[email protected]>
[ Upstream commit 776dac5a662774f07a876b650ba578d0a62d20db ]
devm_kasprintf() returns a pointer to dynamically allocated memory which can be NULL upon failure.
--- drivers/net/dsa/vitesse-vsc73xx-core.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/dsa/vitesse-vsc73xx-core.c +2 -0
@@ -1119,6 +1119,8 @@ static int vsc73xx_gpio_probe(struct vsc73xx *vsc) vsc->gc.label =devm_kasprintf (vsc->dev,GFP_KERNEL ,"VSC%04x" , vsc->chipid); +if (!vsc->gc.label) +return -ENOMEM ; vsc->gc.ngpio =4 ; vsc->gc.owner =THIS_MODULE ; vsc->gc.parent = vsc->dev;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 344/374 netfilter: nf_tables: reject invalid set policy
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 0617c3de9b4026b87be12b0cb5c35f42c7c66fcb ]
Report -EINVAL in case userspace provides a unsupported set backend policy.
--- net/netfilter/nf_tables_api.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +9 -1
@@ -4683,8 +4683,16 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, } desc.policy =NFT_SET_POL_PERFORMANCE ; -if (nla[NFTA_SET_POLICY ] !=NULL ) +if (nla[NFTA_SET_POLICY ] !=NULL ) { desc.policy =ntohl (nla_get_be32 (nla[NFTA_SET_POLICY ])); +switch (desc.policy) { +case NFT_SET_POL_PERFORMANCE : +case NFT_SET_POL_MEMORY : +break ; +default : +return -EOPNOTSUPP ; + } + }if (nla[NFTA_SET_DESC ] !=NULL ) { err =nf_tables_set_desc_parse (&desc, nla[NFTA_SET_DESC ]);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 345/374 netfilter: nft_connlimit: move stateful fields out of expression data
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 37f319f37d9005693dff085bb72852eeebc803ef ]
In preparation for the rule blob representation.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nft_connlimit.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)
net/netfilter/nft_connlimit.c +18 -8
@@ -14,7 +14,7 @@#include <net/netfilter/nf_conntrack_zones.h> struct nft_connlimit { -struct nf_conncount_list list; +struct nf_conncount_list *list;u32 limit;bool invert; };
@@ -43,12 +43,12 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,return ; } -if (nf_conncount_add (nft_net (pkt), &priv->list, tuple_ptr, zone)) { +if (nf_conncount_add (nft_net (pkt), priv->list, tuple_ptr, zone)) { regs->verdict.code =NF_DROP ;return ; } - count = priv->list.count; + count = priv->list->count;if ((count > priv->limit) ^ priv->invert) { regs->verdict.code =NFT_BREAK ;
@@ -76,7 +76,11 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx, invert = true; } -nf_conncount_list_init (&priv->list); + priv->list =kmalloc (sizeof (*priv->list),GFP_KERNEL ); +if (!priv->list) +return -ENOMEM ; + +nf_conncount_list_init (priv->list); priv->limit = limit; priv->invert = invert;
@@ -87,7 +91,8 @@ static void nft_connlimit_do_destroy(const struct nft_ctx *ctx, struct nft_connlimit *priv) {nf_ct_netns_put (ctx->net, ctx->family); -nf_conncount_cache_free (&priv->list); +nf_conncount_cache_free (priv->list); +kfree (priv->list); } static int nft_connlimit_do_dump(struct sk_buff *skb,
@@ -200,7 +205,11 @@ static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src)struct nft_connlimit *priv_dst =nft_expr_priv (dst);struct nft_connlimit *priv_src =nft_expr_priv (src); -nf_conncount_list_init (&priv_dst->list); + priv_dst->list =kmalloc (sizeof (*priv_dst->list),GFP_ATOMIC ); +if (priv_dst->list) +return -ENOMEM ; + +nf_conncount_list_init (priv_dst->list); priv_dst->limit = priv_src->limit; priv_dst->invert = priv_src->invert;
@@ -212,7 +221,8 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx, {struct nft_connlimit *priv =nft_expr_priv (expr); -nf_conncount_cache_free (&priv->list); +nf_conncount_cache_free (priv->list); +kfree (priv->list); }static bool nft_connlimit_gc (struct net *net,const struct nft_expr *expr)
@@ -221,7 +231,7 @@ static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)bool ret;local_bh_disable (); - ret =nf_conncount_gc_list (net, &priv->list); + ret =nf_conncount_gc_list (net, priv->list);local_bh_enable ();return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 346/374 netfilter: nft_last: move stateful fields out of expression data
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 33a24de37e814572491bcb35f42c0de74ad67586 ]
In preparation for the rule blob representation.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nft_last.c | 69 +++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 18 deletions(-)
net/netfilter/nft_last.c +51 -18
@@ -8,9 +8,13 @@#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> +struct nft_last { +unsigned long jiffies; +unsigned int set; +}; +struct nft_last_priv { -unsigned long last_jiffies; -unsigned int last_set; +struct nft_last *last; };static const struct nla_policy nft_last_policy[NFTA_LAST_MAX +1 ] = {
@@ -22,47 +26,55 @@ static int nft_last_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) {struct nft_last_priv *priv =nft_expr_priv (expr); +struct nft_last *last;u64 last_jiffies; -u32 last_set =0 ;int err; -if (tb[NFTA_LAST_SET ]) { - last_set =ntohl (nla_get_be32 (tb[NFTA_LAST_SET ])); -if (last_set ==1 ) - priv->last_set =1 ; - } + last =kzalloc (sizeof (*last),GFP_KERNEL ); +if (!last) +return -ENOMEM ; + +if (tb[NFTA_LAST_SET ]) + last->set =ntohl (nla_get_be32 (tb[NFTA_LAST_SET ])); -if (last_set && tb[NFTA_LAST_MSECS ]) { +if (last->set && tb[NFTA_LAST_MSECS ]) { err =nf_msecs_to_jiffies64 (tb[NFTA_LAST_MSECS ], &last_jiffies);if (err <0 ) -return err; + goto err; - priv->last_jiffies = jiffies - (unsigned long )last_jiffies; + last->jiffies = jiffies - (unsigned long )last_jiffies; } + priv->last = last;return 0 ; +err: +kfree (last); + +return err; }static void nft_last_eval (const struct nft_expr *expr,struct nft_regs *regs,const struct nft_pktinfo *pkt) {struct nft_last_priv *priv =nft_expr_priv (expr); +struct nft_last *last = priv->last; -if (READ_ONCE (priv->last_jiffies) != jiffies) -WRITE_ONCE (priv->last_jiffies, jiffies); -if (READ_ONCE (priv->last_set) ==0 ) -WRITE_ONCE (priv->last_set,1 ); +if (READ_ONCE (last->jiffies) != jiffies) +WRITE_ONCE (last->jiffies, jiffies); +if (READ_ONCE (last->set) ==0 ) +WRITE_ONCE (last->set,1 ); }static int nft_last_dump (struct sk_buff *skb,const struct nft_expr *expr) {struct nft_last_priv *priv =nft_expr_priv (expr); -unsigned long last_jiffies =READ_ONCE (priv->last_jiffies); -u32 last_set =READ_ONCE (priv->last_set); +struct nft_last *last = priv->last; +unsigned long last_jiffies =READ_ONCE (last->jiffies); +u32 last_set =READ_ONCE (last->set);__be64 msecs;if (time_before (jiffies, last_jiffies)) { -WRITE_ONCE (priv->last_set,0 ); +WRITE_ONCE (last->set,0 ); last_set =0 ; }
@@ -81,11 +93,32 @@ static int nft_last_dump(struct sk_buff *skb, const struct nft_expr *expr)return -1 ; } +static void nft_last_destroy (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_last_priv *priv =nft_expr_priv (expr); + +kfree (priv->last); +} + +static int nft_last_clone (struct nft_expr *dst,const struct nft_expr *src) +{ +struct nft_last_priv *priv_dst =nft_expr_priv (dst); + + priv_dst->last =kzalloc (sizeof (*priv_dst->last),GFP_ATOMIC ); +if (priv_dst->last) +return -ENOMEM ; + +return 0 ; +} +static const struct nft_expr_ops nft_last_ops = { .type = &nft_last_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_last_priv )), .eval = nft_last_eval, .init = nft_last_init, + .destroy = nft_last_destroy, + .clone = nft_last_clone, .dump = nft_last_dump, };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 347/374 netfilter: nft_quota: move stateful fields out of expression data
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit ed0a0c60f0e50fa52853620672af97edde3d3a03 ]
In preparation for the rule blob representation.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nft_quota.c | 52 +++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-)
net/netfilter/nft_quota.c +47 -5
@@ -15,13 +15,13 @@struct nft_quota {atomic64_t quota;unsigned long flags; -atomic64_t consumed; +atomic64_t *consumed; };static inline bool nft_overquota (struct nft_quota *priv,const struct sk_buff *skb) { -return atomic64_add_return (skb->len, &priv->consumed) >= +return atomic64_add_return (skb->len, priv->consumed) >=atomic64_read (&priv->quota); }
@@ -90,13 +90,23 @@ static int nft_quota_do_init(const struct nlattr * const tb[],return -EOPNOTSUPP ; } + priv->consumed =kmalloc (sizeof (*priv->consumed),GFP_KERNEL ); +if (!priv->consumed) +return -ENOMEM ; +atomic64_set (&priv->quota, quota); priv->flags = flags; -atomic64_set (&priv->consumed, consumed); +atomic64_set (priv->consumed, consumed);return 0 ; } +static void nft_quota_do_destroy (const struct nft_ctx *ctx, +struct nft_quota *priv) +{ +kfree (priv->consumed); +} +static int nft_quota_obj_init (const struct nft_ctx *ctx,const struct nlattr *const tb[],struct nft_object *obj)
@@ -128,7 +138,7 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,* that we see, don't go over the quota boundary in what we send to * userspace. */ - consumed =atomic64_read (&priv->consumed); + consumed =atomic64_read (priv->consumed); quota =atomic64_read (&priv->quota);if (consumed >= quota) { consumed_cap = quota;
@@ -145,7 +155,7 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv, goto nla_put_failure;if (reset) { -atomic64_sub (consumed, &priv->consumed); +atomic64_sub (consumed, priv->consumed);clear_bit (NFT_QUOTA_DEPLETED_BIT , &priv->flags); }return 0 ;
@@ -162,11 +172,20 @@ static int nft_quota_obj_dump(struct sk_buff *skb, struct nft_object *obj,return nft_quota_do_dump (skb, priv, reset); } +static void nft_quota_obj_destroy (const struct nft_ctx *ctx, +struct nft_object *obj) +{ +struct nft_quota *priv =nft_obj_data (obj); + +return nft_quota_do_destroy (ctx, priv); +} +static struct nft_object_type nft_quota_obj_type;static const struct nft_object_ops nft_quota_obj_ops = { .type = &nft_quota_obj_type, .size =sizeof (struct nft_quota ), .init = nft_quota_obj_init, + .destroy = nft_quota_obj_destroy, .eval = nft_quota_obj_eval, .dump = nft_quota_obj_dump, .update = nft_quota_obj_update,
@@ -205,12 +224,35 @@ static int nft_quota_dump(struct sk_buff *skb, const struct nft_expr *expr)return nft_quota_do_dump (skb, priv, false); } +static void nft_quota_destroy (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_quota *priv =nft_expr_priv (expr); + +return nft_quota_do_destroy (ctx, priv); +} + +static int nft_quota_clone (struct nft_expr *dst,const struct nft_expr *src) +{ +struct nft_quota *priv_dst =nft_expr_priv (dst); + + priv_dst->consumed =kmalloc (sizeof (*priv_dst->consumed),GFP_ATOMIC ); +if (priv_dst->consumed) +return -ENOMEM ; + +atomic64_set (priv_dst->consumed,0 ); + +return 0 ; +} +static struct nft_expr_type nft_quota_type;static const struct nft_expr_ops nft_quota_ops = { .type = &nft_quota_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_quota )), .eval = nft_quota_eval, .init = nft_quota_init, + .destroy = nft_quota_destroy, + .clone = nft_quota_clone, .dump = nft_quota_dump, };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 348/374 netfilter: nft_limit: rename stateful structure
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 369b6cb5d391750fc01ce951c2500281d2975705 ]
Quoted 1 line
From struct
nft_limittonft_limit_priv.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nft_limit.c | 104 +++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 52 deletions(-)
net/netfilter/nft_limit.c +52 -52
@@ -14,7 +14,7 @@#include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h> -struct nft_limit { +struct nft_limit_priv {spinlock_t lock;u64 last;u64 tokens;
@@ -25,33 +25,33 @@ struct nft_limit {bool invert; }; -static inline bool nft_limit_eval (struct nft_limit *limit,u64 cost) +static inline bool nft_limit_eval (struct nft_limit_priv *priv,u64 cost) {u64 now, tokens;s64 delta; -spin_lock_bh (&limit->lock); +spin_lock_bh (&priv->lock); now =ktime_get_ns (); - tokens = limit->tokens + now - limit->last; -if (tokens > limit->tokens_max) - tokens = limit->tokens_max; + tokens = priv->tokens + now - priv->last; +if (tokens > priv->tokens_max) + tokens = priv->tokens_max; - limit->last = now; + priv->last = now; delta = tokens - cost;if (delta >=0 ) { - limit->tokens = delta; -spin_unlock_bh (&limit->lock); -return limit->invert; + priv->tokens = delta; +spin_unlock_bh (&priv->lock); +return priv->invert; } - limit->tokens = tokens; -spin_unlock_bh (&limit->lock); -return !limit->invert; + priv->tokens = tokens; +spin_unlock_bh (&priv->lock); +return !priv->invert; }/* Use same default as in iptables. */ #define NFT_LIMIT_PKT_BURST_DEFAULT 5 -static int nft_limit_init (struct nft_limit *limit, +static int nft_limit_init (struct nft_limit_priv *priv,const struct nlattr *const tb[],bool pkts) {u64 unit, tokens;
@@ -60,58 +60,58 @@ static int nft_limit_init(struct nft_limit *limit, tb[NFTA_LIMIT_UNIT] == NULL)return -EINVAL ; - limit->rate =be64_to_cpu (nla_get_be64 (tb[NFTA_LIMIT_RATE ])); + priv->rate =be64_to_cpu (nla_get_be64 (tb[NFTA_LIMIT_RATE ])); unit =be64_to_cpu (nla_get_be64 (tb[NFTA_LIMIT_UNIT ])); - limit->nsecs = unit *NSEC_PER_SEC ; -if (limit->rate ==0 || limit->nsecs < unit) + priv->nsecs = unit *NSEC_PER_SEC ; +if (priv->rate ==0 || priv->nsecs < unit)return -EOVERFLOW ;if (tb[NFTA_LIMIT_BURST ]) - limit->burst =ntohl (nla_get_be32 (tb[NFTA_LIMIT_BURST ])); + priv->burst =ntohl (nla_get_be32 (tb[NFTA_LIMIT_BURST ])); -if (pkts && limit->burst ==0 ) - limit->burst =NFT_LIMIT_PKT_BURST_DEFAULT ; +if (pkts && priv->burst ==0 ) + priv->burst =NFT_LIMIT_PKT_BURST_DEFAULT ; -if (limit->rate + limit->burst < limit->rate) +if (priv->rate + priv->burst < priv->rate)return -EOVERFLOW ;if (pkts) { - tokens =div64_u64 (limit->nsecs, limit->rate) * limit->burst; + tokens =div64_u64 (priv->nsecs, priv->rate) * priv->burst; }else {/* The token bucket size limits the number of tokens can be * accumulated. tokens_max specifies the bucket size. * tokens_max = unit * (rate + burst) / rate. */ - tokens =div64_u64 (limit->nsecs * (limit->rate + limit->burst), - limit->rate); + tokens =div64_u64 (priv->nsecs * (priv->rate + priv->burst), + priv->rate); } - limit->tokens = tokens; - limit->tokens_max = limit->tokens; + priv->tokens = tokens; + priv->tokens_max = priv->tokens;if (tb[NFTA_LIMIT_FLAGS ]) {u32 flags =ntohl (nla_get_be32 (tb[NFTA_LIMIT_FLAGS ]));if (flags &NFT_LIMIT_F_INV ) - limit->invert = true; + priv->invert = true; } - limit->last =ktime_get_ns (); -spin_lock_init (&limit->lock); + priv->last =ktime_get_ns (); +spin_lock_init (&priv->lock);return 0 ; } -static int nft_limit_dump (struct sk_buff *skb,const struct nft_limit *limit, +static int nft_limit_dump (struct sk_buff *skb,const struct nft_limit_priv *priv,enum nft_limit_type type) { -u32 flags = limit->invert ?NFT_LIMIT_F_INV :0 ; -u64 secs =div_u64 (limit->nsecs,NSEC_PER_SEC ); +u32 flags = priv->invert ?NFT_LIMIT_F_INV :0 ; +u64 secs =div_u64 (priv->nsecs,NSEC_PER_SEC ); -if (nla_put_be64 (skb,NFTA_LIMIT_RATE ,cpu_to_be64 (limit->rate), +if (nla_put_be64 (skb,NFTA_LIMIT_RATE ,cpu_to_be64 (priv->rate),NFTA_LIMIT_PAD ) ||nla_put_be64 (skb,NFTA_LIMIT_UNIT ,cpu_to_be64 (secs),NFTA_LIMIT_PAD ) || -nla_put_be32 (skb,NFTA_LIMIT_BURST ,htonl (limit->burst)) || +nla_put_be32 (skb,NFTA_LIMIT_BURST ,htonl (priv->burst)) ||nla_put_be32 (skb,NFTA_LIMIT_TYPE ,htonl (type)) ||nla_put_be32 (skb,NFTA_LIMIT_FLAGS ,htonl (flags))) goto nla_put_failure;
@@ -121,8 +121,8 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit *limit,return -1 ; } -struct nft_limit_pkts { -struct nft_limit limit; +struct nft_limit_priv_pkts { +struct nft_limit_priv limit;u64 cost; };
@@ -130,7 +130,7 @@ static void nft_limit_pkts_eval(const struct nft_expr *expr,struct nft_regs *regs, const struct nft_pktinfo *pkt) { - struct nft_limit_pkts *priv = nft_expr_priv(expr); + struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);if (nft_limit_eval (&priv->limit, priv->cost)) regs->verdict.code =NFT_BREAK ;
@@ -148,7 +148,7 @@ static int nft_limit_pkts_init(const struct nft_ctx *ctx,const struct nft_expr *expr, const struct nlattr * const tb[]) { - struct nft_limit_pkts *priv = nft_expr_priv(expr); + struct nft_limit_priv_pkts *priv = nft_expr_priv(expr);int err; err =nft_limit_init (&priv->limit, tb, true);
@@ -161,7 +161,7 @@ static int nft_limit_pkts_init(const struct nft_ctx *ctx,static int nft_limit_pkts_dump (struct sk_buff *skb,const struct nft_expr *expr) { -const struct nft_limit_pkts *priv =nft_expr_priv (expr); +const struct nft_limit_priv_pkts *priv =nft_expr_priv (expr);return nft_limit_dump (skb, &priv->limit,NFT_LIMIT_PKTS ); }
@@ -169,7 +169,7 @@ static int nft_limit_pkts_dump(struct sk_buff *skb, const struct nft_expr *expr)static struct nft_expr_type nft_limit_type;static const struct nft_expr_ops nft_limit_pkts_ops = { .type = &nft_limit_type, - .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_pkts )), + .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv_pkts )), .eval = nft_limit_pkts_eval, .init = nft_limit_pkts_init, .dump = nft_limit_pkts_dump,
@@ -179,7 +179,7 @@ static void nft_limit_bytes_eval(const struct nft_expr *expr,struct nft_regs *regs, const struct nft_pktinfo *pkt) { - struct nft_limit *priv = nft_expr_priv(expr); + struct nft_limit_priv *priv = nft_expr_priv(expr);u64 cost =div64_u64 (priv->nsecs * pkt->skb->len, priv->rate);if (nft_limit_eval (priv, cost))
@@ -190,7 +190,7 @@ static int nft_limit_bytes_init(const struct nft_ctx *ctx,const struct nft_expr *expr, const struct nlattr * const tb[]) { - struct nft_limit *priv = nft_expr_priv(expr); + struct nft_limit_priv *priv = nft_expr_priv(expr);return nft_limit_init (priv, tb, false); }
@@ -198,14 +198,14 @@ static int nft_limit_bytes_init(const struct nft_ctx *ctx,static int nft_limit_bytes_dump (struct sk_buff *skb,const struct nft_expr *expr) { -const struct nft_limit *priv =nft_expr_priv (expr); +const struct nft_limit_priv *priv =nft_expr_priv (expr);return nft_limit_dump (skb, priv,NFT_LIMIT_PKT_BYTES ); }static const struct nft_expr_ops nft_limit_bytes_ops = { .type = &nft_limit_type, - .size =NFT_EXPR_SIZE (sizeof (struct nft_limit )), + .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv )), .eval = nft_limit_bytes_eval, .init = nft_limit_bytes_init, .dump = nft_limit_bytes_dump,
@@ -240,7 +240,7 @@ static void nft_limit_obj_pkts_eval(struct nft_object *obj,struct nft_regs *regs, const struct nft_pktinfo *pkt) { - struct nft_limit_pkts *priv = nft_obj_data(obj); + struct nft_limit_priv_pkts *priv = nft_obj_data(obj);if (nft_limit_eval (&priv->limit, priv->cost)) regs->verdict.code =NFT_BREAK ;
@@ -250,7 +250,7 @@ static int nft_limit_obj_pkts_init(const struct nft_ctx *ctx,const struct nlattr *const tb[], struct nft_object *obj) { - struct nft_limit_pkts *priv = nft_obj_data(obj); + struct nft_limit_priv_pkts *priv = nft_obj_data(obj);int err; err =nft_limit_init (&priv->limit, tb, true);
@@ -265,7 +265,7 @@ static int nft_limit_obj_pkts_dump(struct sk_buff *skb, struct nft_object *obj, bool reset) { -const struct nft_limit_pkts *priv =nft_obj_data (obj); +const struct nft_limit_priv_pkts *priv =nft_obj_data (obj);return nft_limit_dump (skb, &priv->limit,NFT_LIMIT_PKTS ); }
@@ -273,7 +273,7 @@ static int nft_limit_obj_pkts_dump(struct sk_buff *skb,static struct nft_object_type nft_limit_obj_type;static const struct nft_object_ops nft_limit_obj_pkts_ops = { .type = &nft_limit_obj_type, - .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_pkts )), + .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv_pkts )), .init = nft_limit_obj_pkts_init, .eval = nft_limit_obj_pkts_eval, .dump = nft_limit_obj_pkts_dump,
@@ -283,7 +283,7 @@ static void nft_limit_obj_bytes_eval(struct nft_object *obj,struct nft_regs *regs, const struct nft_pktinfo *pkt) { - struct nft_limit *priv = nft_obj_data(obj); + struct nft_limit_priv *priv = nft_obj_data(obj);u64 cost =div64_u64 (priv->nsecs * pkt->skb->len, priv->rate);if (nft_limit_eval (priv, cost))
@@ -294,7 +294,7 @@ static int nft_limit_obj_bytes_init(const struct nft_ctx *ctx,const struct nlattr *const tb[], struct nft_object *obj) { - struct nft_limit *priv = nft_obj_data(obj); + struct nft_limit_priv *priv = nft_obj_data(obj);return nft_limit_init (priv, tb, false); }
@@ -303,7 +303,7 @@ static int nft_limit_obj_bytes_dump(struct sk_buff *skb, struct nft_object *obj, bool reset) { -const struct nft_limit *priv =nft_obj_data (obj); +const struct nft_limit_priv *priv =nft_obj_data (obj);return nft_limit_dump (skb, priv,NFT_LIMIT_PKT_BYTES ); }
@@ -311,7 +311,7 @@ static int nft_limit_obj_bytes_dump(struct sk_buff *skb,static struct nft_object_type nft_limit_obj_type;static const struct nft_object_ops nft_limit_obj_bytes_ops = { .type = &nft_limit_obj_type, - .size =sizeof (struct nft_limit ), + .size =sizeof (struct nft_limit_priv ), .init = nft_limit_obj_bytes_init, .eval = nft_limit_obj_bytes_eval, .dump = nft_limit_obj_bytes_dump,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 349/374 netfilter: nft_limit: move stateful fields out of expression data
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 3b9e2ea6c11bff72ac1d607f6b954e7666b47409 ]
In preparation for the rule blob representation.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nft_limit.c | 94 ++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 12 deletions(-)
net/netfilter/nft_limit.c +82 -12
@@ -14,10 +14,14 @@#include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h> -struct nft_limit_priv { +struct nft_limit {spinlock_t lock;u64 last;u64 tokens; +}; + +struct nft_limit_priv { +struct nft_limit *limit;u64 tokens_max;u64 rate;u64 nsecs;
@@ -30,21 +34,21 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)u64 now, tokens;s64 delta; -spin_lock_bh (&priv->lock); +spin_lock_bh (&priv->limit->lock); now =ktime_get_ns (); - tokens = priv->tokens + now - priv->last; + tokens = priv->limit->tokens + now - priv->limit->last;if (tokens > priv->tokens_max) tokens = priv->tokens_max; - priv->last = now; + priv->limit->last = now; delta = tokens - cost;if (delta >=0 ) { - priv->tokens = delta; -spin_unlock_bh (&priv->lock); + priv->limit->tokens = delta; +spin_unlock_bh (&priv->limit->lock);return priv->invert; } - priv->tokens = tokens; -spin_unlock_bh (&priv->lock); + priv->limit->tokens = tokens; +spin_unlock_bh (&priv->limit->lock);return !priv->invert; }
@@ -86,8 +90,12 @@ static int nft_limit_init(struct nft_limit_priv *priv, priv->rate); } - priv->tokens = tokens; - priv->tokens_max = priv->tokens; + priv->limit =kmalloc (sizeof (*priv->limit),GFP_KERNEL ); +if (!priv->limit) +return -ENOMEM ; + + priv->limit->tokens = tokens; + priv->tokens_max = priv->limit->tokens;if (tb[NFTA_LIMIT_FLAGS ]) {u32 flags =ntohl (nla_get_be32 (tb[NFTA_LIMIT_FLAGS ]));
@@ -95,8 +103,8 @@ static int nft_limit_init(struct nft_limit_priv *priv,if (flags &NFT_LIMIT_F_INV ) priv->invert = true; } - priv->last =ktime_get_ns (); -spin_lock_init (&priv->lock); + priv->limit->last =ktime_get_ns (); +spin_lock_init (&priv->limit->lock);return 0 ; }
@@ -121,6 +129,32 @@ static int nft_limit_dump(struct sk_buff *skb, const struct nft_limit_priv *privreturn -1 ; } +static void nft_limit_destroy (const struct nft_ctx *ctx, +const struct nft_limit_priv *priv) +{ +kfree (priv->limit); +} + +static int nft_limit_clone (struct nft_limit_priv *priv_dst, +const struct nft_limit_priv *priv_src) +{ + priv_dst->tokens_max = priv_src->tokens_max; + priv_dst->rate = priv_src->rate; + priv_dst->nsecs = priv_src->nsecs; + priv_dst->burst = priv_src->burst; + priv_dst->invert = priv_src->invert; + + priv_dst->limit =kmalloc (sizeof (*priv_dst->limit),GFP_ATOMIC ); +if (priv_dst->limit) +return -ENOMEM ; + +spin_lock_init (&priv_dst->limit->lock); + priv_dst->limit->tokens = priv_src->tokens_max; + priv_dst->limit->last =ktime_get_ns (); + +return 0 ; +} +struct nft_limit_priv_pkts {struct nft_limit_priv limit;u64 cost;
@@ -166,12 +200,30 @@ static int nft_limit_pkts_dump(struct sk_buff *skb, const struct nft_expr *expr)return nft_limit_dump (skb, &priv->limit,NFT_LIMIT_PKTS ); } +static void nft_limit_pkts_destroy (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +const struct nft_limit_priv_pkts *priv =nft_expr_priv (expr); + +nft_limit_destroy (ctx, &priv->limit); +} + +static int nft_limit_pkts_clone (struct nft_expr *dst,const struct nft_expr *src) +{ +struct nft_limit_priv_pkts *priv_dst =nft_expr_priv (dst); +struct nft_limit_priv_pkts *priv_src =nft_expr_priv (src); + +return nft_limit_clone (&priv_dst->limit, &priv_src->limit); +} +static struct nft_expr_type nft_limit_type;static const struct nft_expr_ops nft_limit_pkts_ops = { .type = &nft_limit_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv_pkts )), .eval = nft_limit_pkts_eval, .init = nft_limit_pkts_init, + .destroy = nft_limit_pkts_destroy, + .clone = nft_limit_pkts_clone, .dump = nft_limit_pkts_dump, };
@@ -203,12 +255,30 @@ static int nft_limit_bytes_dump(struct sk_buff *skb,return nft_limit_dump (skb, priv,NFT_LIMIT_PKT_BYTES ); } +static void nft_limit_bytes_destroy (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +const struct nft_limit_priv *priv =nft_expr_priv (expr); + +nft_limit_destroy (ctx, priv); +} + +static int nft_limit_bytes_clone (struct nft_expr *dst,const struct nft_expr *src) +{ +struct nft_limit_priv *priv_dst =nft_expr_priv (dst); +struct nft_limit_priv *priv_src =nft_expr_priv (src); + +return nft_limit_clone (priv_dst, priv_src); +} +static const struct nft_expr_ops nft_limit_bytes_ops = { .type = &nft_limit_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv )), .eval = nft_limit_bytes_eval, .init = nft_limit_bytes_init, .dump = nft_limit_bytes_dump, + .clone = nft_limit_bytes_clone, + .destroy = nft_limit_bytes_destroy, }; static const struct nft_expr_ops *
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 350/374 netfilter: nf_tables: memcg accounting for dynamically allocated objects
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasily Averin <[email protected]>
[ Upstream commit 42193ffd79bd3acd91bd947e53f3548a3661d0a1 ]
nft_*.c files whose NFT_EXPR_STATEFUL flag is set on need to use __GFP_ACCOUNT flag for objects that are dynamically allocated from the packet path.
Such objects are allocated inside nft_expr_ops->init() callbacks executed in task context while processing netlink messages.
In addition, this patch adds accounting to nft_set_elem_expr_clone() used for the same purposes.
Stable-dep-of: 91a139cee120 ("netfilter: nft_limit: do not ignore unsupported flags")
--- net/netfilter/nf_tables_api.c | 2 +- net/netfilter/nft_connlimit.c | 2 +- net/netfilter/nft_counter.c | 2 +- net/netfilter/nft_last.c | 2 +- net/netfilter/nft_limit.c | 2 +- net/netfilter/nft_quota.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
net/netfilter/nf_tables_api.c +1 -1
@@ -5896,7 +5896,7 @@ int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,int err, i, k;for (i =0 ; i < set->num_exprs; i++) { - expr =kzalloc (set->exprs[i]->ops->size,GFP_KERNEL ); + expr =kzalloc (set->exprs[i]->ops->size,GFP_KERNEL_ACCOUNT );if (!expr) goto err_expr;
net/netfilter/nft_connlimit.c +1 -1
@@ -76,7 +76,7 @@ static int nft_connlimit_do_init(const struct nft_ctx *ctx, invert = true; } - priv->list =kmalloc (sizeof (*priv->list),GFP_KERNEL ); + priv->list =kmalloc (sizeof (*priv->list),GFP_KERNEL_ACCOUNT );if (!priv->list)return -ENOMEM ;
net/netfilter/nft_counter.c +1 -1
@@ -61,7 +61,7 @@ static int nft_counter_do_init(const struct nlattr * const tb[],struct nft_counter __percpu *cpu_stats;struct nft_counter *this_cpu; - cpu_stats = alloc_percpu(struct nft_counter); + cpu_stats = alloc_percpu_gfp(struct nft_counter, GFP_KERNEL_ACCOUNT);if (cpu_stats ==NULL )return -ENOMEM ;
net/netfilter/nft_last.c +1 -1
@@ -30,7 +30,7 @@ static int nft_last_init(const struct nft_ctx *ctx, const struct nft_expr *expr,u64 last_jiffies;int err; - last =kzalloc (sizeof (*last),GFP_KERNEL ); + last =kzalloc (sizeof (*last),GFP_KERNEL_ACCOUNT );if (!last)return -ENOMEM ;
net/netfilter/nft_limit.c +1 -1
@@ -90,7 +90,7 @@ static int nft_limit_init(struct nft_limit_priv *priv, priv->rate); } - priv->limit =kmalloc (sizeof (*priv->limit),GFP_KERNEL ); + priv->limit =kmalloc (sizeof (*priv->limit),GFP_KERNEL_ACCOUNT );if (!priv->limit)return -ENOMEM ;
net/netfilter/nft_quota.c +1 -1
@@ -90,7 +90,7 @@ static int nft_quota_do_init(const struct nlattr * const tb[],return -EOPNOTSUPP ; } - priv->consumed =kmalloc (sizeof (*priv->consumed),GFP_KERNEL ); + priv->consumed =kmalloc (sizeof (*priv->consumed),GFP_KERNEL_ACCOUNT );if (!priv->consumed)return -ENOMEM ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 351/374 netfilter: nft_limit: do not ignore unsupported flags
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 91a139cee1202a4599a380810d93c69b5bac6197 ]
Bail out if userspace provides unsupported flags, otherwise future extensions to the limit expression will be silently ignored by the kernel.
--- net/netfilter/nft_limit.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
net/netfilter/nft_limit.c +12 -7
@@ -58,6 +58,7 @@ static inline bool nft_limit_eval(struct nft_limit_priv *priv, u64 cost)static int nft_limit_init (struct nft_limit_priv *priv,const struct nlattr *const tb[],bool pkts) { +bool invert = false;u64 unit, tokens; if (tb[NFTA_LIMIT_RATE] == NULL ||
@@ -90,19 +91,23 @@ static int nft_limit_init(struct nft_limit_priv *priv, priv->rate); } +if (tb[NFTA_LIMIT_FLAGS ]) { +u32 flags =ntohl (nla_get_be32 (tb[NFTA_LIMIT_FLAGS ])); + +if (flags & ~NFT_LIMIT_F_INV ) +return -EOPNOTSUPP ; + +if (flags &NFT_LIMIT_F_INV ) + invert = true; + } + priv->limit =kmalloc (sizeof (*priv->limit),GFP_KERNEL_ACCOUNT );if (!priv->limit)return -ENOMEM ; priv->limit->tokens = tokens; priv->tokens_max = priv->limit->tokens; - -if (tb[NFTA_LIMIT_FLAGS ]) { -u32 flags =ntohl (nla_get_be32 (tb[NFTA_LIMIT_FLAGS ])); - -if (flags &NFT_LIMIT_F_INV ) - priv->invert = true; - } + priv->invert = invert; priv->limit->last =ktime_get_ns ();spin_lock_init (&priv->limit->lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 352/374 netfilter: nf_tables: do not allow mismatch field size and set key length
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 3ce67e3793f48c1b9635beb9bb71116ca1e51b58 ]
The set description provides the size of each field in the set whose sum should not mismatch the set key length, bail out otherwise.
I did not manage to crash nft_set_pipapo with mismatch fields and set key length so far, but this is UB which must be disallowed.
--- net/netfilter/nf_tables_api.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +5 -1
@@ -4453,8 +4453,8 @@ static int nft_set_desc_concat_parse(const struct nlattr *attr,static int nft_set_desc_concat (struct nft_set_desc *desc,const struct nlattr *nla) { +u32 num_regs =0 , key_num_regs =0 ;struct nlattr *attr; -u32 num_regs =0 ;int rem, err, i;nla_for_each_nested (attr, nla, rem) {
@@ -4469,6 +4469,10 @@ static int nft_set_desc_concat(struct nft_set_desc *desc,for (i =0 ; i < desc->field_count; i++) num_regs +=DIV_ROUND_UP (desc->field_len[i],sizeof (u32)); + key_num_regs =DIV_ROUND_UP (desc->klen,sizeof (u32)); +if (key_num_regs != num_regs) +return -EINVAL ; +if (num_regs >NFT_REG32_COUNT )return -E2BIG ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 353/374 netfilter: nf_tables: skip dead set elements in netlink dump
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 6b1ca88e4bb63673dc9f9c7f23c899f22c3cb17a ]
Delete from packet path relies on the garbage collector to purge elements with NFT_SET_ELEM_DEAD_BIT on.
Skip these dead elements from nf_tables_dump_setelem() path, I very rarely see tests/shell/testcases/maps/typeof_maps_add_delete reports [DUMP FAILED] showing a mismatch in the expected output with an element that should not be there.
If the netlink dump happens before GC worker run, it might show dead elements in the ruleset listing.
nft_rhash_get() already skips dead elements in nft_rhash_cmp(), therefore, it already does not show the element when getting a single element via netlink control plane.
--- net/netfilter/nf_tables_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +1 -1
@@ -5348,7 +5348,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,const struct nft_set_ext *ext =nft_set_elem_ext (set, elem->priv);struct nft_set_dump_args *args; -if (nft_set_elem_expired (ext)) +if (nft_set_elem_expired (ext) ||nft_set_elem_is_dead (ext))return 0 ; args = container_of(iter, struct nft_set_dump_args, iter);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 354/374 netfilter: nf_tables: reject NFT_SET_CONCAT with not field length description
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 113661e07460a6604aacc8ae1b23695a89e7d4b3 ]
It is still possible to set on the NFT_SET_CONCAT flag by specifying a set size and no field description, report EINVAL in such case.
--- net/netfilter/nf_tables_api.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +5 -1
@@ -4703,8 +4703,12 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,if (err <0 )return err; -if (desc.field_count >1 && !(flags &NFT_SET_CONCAT )) +if (desc.field_count >1 ) { +if (!(flags &NFT_SET_CONCAT )) +return -EINVAL ; + }else if (flags &NFT_SET_CONCAT ) {return -EINVAL ; + } }else if (flags &NFT_SET_CONCAT ) {return -EINVAL ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 355/374 ipvs: avoid stat macros calls from preemptible context
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
[ Upstream commit d6938c1c76c64f42363d0d1f051e1b4641c2ad40 ]
Inside decrement_ttl() upon discovering that the packet ttl has exceeded, __IP_INC_STATS and __IP6_INC_STATS macros can be called from preemptible context having the following backtrace:
check_preemption_disabled: 48 callbacks suppressed
BUG: using __this_cpu_add() in preemptible [00000000] code: curl/1177 caller is decrement_ttl+0x217/0x830 CPU: 5 PID: 1177 Comm: curl Not tainted 6.7.0+ #34 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0xbd/0xe0 check_preemption_disabled+0xd1/0xe0 decrement_ttl+0x217/0x830 __ip_vs_get_out_rt+0x4e0/0x1ef0 ip_vs_nat_xmit+0x205/0xcd0 ip_vs_in_hook+0x9b1/0x26a0 nf_hook_slow+0xc2/0x210 nf_hook+0x1fb/0x770 __ip_local_out+0x33b/0x640 ip_local_out+0x2a/0x490 __ip_queue_xmit+0x990/0x1d10 __tcp_transmit_skb+0x288b/0x3d10 tcp_connect+0x3466/0x5180 tcp_v4_connect+0x1535/0x1bb0 __inet_stream_connect+0x40d/0x1040 inet_stream_connect+0x57/0xa0 __sys_connect_file+0x162/0x1a0 __sys_connect+0x137/0x160 __x64_sys_connect+0x72/0xb0 do_syscall_64+0x6f/0x140 entry_SYSCALL_64_after_hwframe+0x6e/0x76 RIP: 0033:0x7fe6dbbc34e0
Use the corresponding preemption-aware variants: IP_INC_STATS and IP6_INC_STATS.
Found by Linux Verification Center (linuxtesting.org).
--- net/netfilter/ipvs/ip_vs_xmit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/ipvs/ip_vs_xmit.c +2 -2
@@ -271,7 +271,7 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs, skb->dev = dst->dev;icmpv6_send (skb,ICMPV6_TIME_EXCEED ,ICMPV6_EXC_HOPLIMIT ,0 ); -__IP6_INC_STATS (net, idev,IPSTATS_MIB_INHDRERRORS ); +IP6_INC_STATS (net, idev,IPSTATS_MIB_INHDRERRORS );return false; }
@@ -286,7 +286,7 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs, {if (ip_hdr (skb)->ttl <=1 ) {/* Tell the sender its packet died... */ -__IP_INC_STATS (net,IPSTATS_MIB_INHDRERRORS ); +IP_INC_STATS (net,IPSTATS_MIB_INHDRERRORS );icmp_send (skb,ICMP_TIME_EXCEEDED ,ICMP_EXC_TTL ,0 );return false; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 356/374 kdb: Fix a potential buffer overflow in kdb_local()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 4f41d30cd6dc865c3cbc1a852372321eba6d4e4c ]
When appending "[defcmd]" to 'kdb_prompt_str', the size of the string already in the buffer should be taken into account.
An option could be to switch from strncat() to strlcat() which does the correct test to avoid such an overflow.
However, this actually looks as dead code, because 'defcmd_in_progress' can't be true here.
See a more detailed explanation at [1].
[1]: https://lore.kernel.org/all/CAD=FV=WSh7wKN7Yp-3wWiDgX4E3isQ8uh0LCzTmd1v9Cg9j+nQ@mail.gmail.com/
--- kernel/debug/kdb/kdb_main.c | 2 -- 1 file changed, 2 deletions(-)
kernel/debug/kdb/kdb_main.c +0 -2
@@ -1350,8 +1350,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,/* PROMPT can only be set if we have MEM_READ permission. */ snprintf (kdb_prompt_str,CMD_BUFLEN ,kdbgetenv ("PROMPT" ),raw_smp_processor_id ()); -if (defcmd_in_progress) -strncat (kdb_prompt_str,"[defcmd]" ,CMD_BUFLEN );/* * Fetch command from keyboard
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 357/374 ethtool: netlink: Add missing ethnl_ops_begin/complete
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ludvig Pärsson <[email protected]>
[ Upstream commit f1172f3ee3a98754d95b968968920a7d03fdebcc ]
Accessing an ethernet device that is powered off or clock gated might cause the CPU to hang. Add ethnl_ops_begin/complete in ethnl_set_features() to protect against this.
--- net/ethtool/features.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/ethtool/features.c +7 -2
@@ -235,17 +235,20 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info) dev = req_info.dev;rtnl_lock (); + ret =ethnl_ops_begin (dev); +if (ret <0 ) + goto out_rtnl;ethnl_features_to_bitmap (old_active, dev->features);ethnl_features_to_bitmap (old_wanted, dev->wanted_features); ret =ethnl_parse_bitset (req_wanted, req_mask,NETDEV_FEATURE_COUNT , tb[ETHTOOL_A_FEATURES_WANTED ], netdev_features_strings, info->extack);if (ret <0 ) - goto out_rtnl; + goto out_ops;if (ethnl_bitmap_to_features (req_mask) & ~NETIF_F_ETHTOOL_BITS ) {GENL_SET_ERR_MSG (info,"attempt to change non-ethtool features" ); ret = -EINVAL ; - goto out_rtnl; + goto out_ops; }/* set req_wanted bits not in req_mask from old_wanted */
@@ -282,6 +285,8 @@ int ethnl_set_features(struct sk_buff *skb, struct genl_info *info)if (mod)netdev_features_change (dev); +out_ops: +ethnl_ops_complete (dev); out_rtnl:rtnl_unlock ();dev_put (dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 358/374 mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Cohen <[email protected]>
[ Upstream commit 6d6eeabcfaba2fcadf5443b575789ea606f9de83 ]
Lately, a bug was found when many TC filters are added - at some point, several bugs are printed to dmesg [1] and the switch is crashed with segmentation fault.
The issue starts when gen_pool_free() fails because of unexpected behavior - a try to free memory which is already freed, this leads to BUG() call which crashes the switch and makes many other bugs.
Trying to track down the unexpected behavior led to a bug in eRP code. The function mlxsw_sp_acl_erp_table_alloc() gets a pointer to the allocated index, sets the value and returns an error code. When gen_pool_alloc() fails it returns address 0, we track it and return -ENOBUFS outside, BUT the call for gen_pool_alloc() already override the index in erp_table structure. This is a problem when such allocation is done as part of table expansion. This is not a new table, which will not be used in case of allocation failure. We try to expand eRP table and override the current index (non-zero) with zero. Then, it leads to an unexpected behavior when address 0 is freed twice. Note that address 0 is valid in erp_table->base_index and indeed other tables use it.
gen_pool_alloc() fails in case that there is no space left in the pre-allocated pool, in our case, the pool is limited to ACL_MAX_ERPT_BANK_SIZE, which is read from hardware. When more than max erp entries are required, we exceed the limit and return an error, this error leads to "Failed to migrate vregion" print.
Fix this by changing erp_table->base_index only in case of a successful allocation.
Add a test case for such a scenario. Without this fix it causes segmentation fault:
$ TESTS="max_erp_entries_test" ./tc_flower.sh ./tc_flower.sh: line 988: 1560 Segmentation fault tc filter del dev $h2 ingress chain $i protocol ip pref $i handle $j flower &>/dev/null
[1]:
kernel BUG at lib/genalloc.c:508!
invalid opcode: 0000 [#1] PREEMPT SMP
CPU: 6 PID: 3531 Comm: tc Not tainted 6.7.0-rc5-custom-ga6893f479f5e #1 Hardware name: Mellanox Technologies Ltd. MSN4700/VMOD0010, BIOS 5.11 07/12/2021 RIP: 0010:gen_pool_free_owner+0xc9/0xe0 ... Call Trace: <TASK> __mlxsw_sp_acl_erp_table_other_dec+0x70/0xa0 [mlxsw_spectrum] mlxsw_sp_acl_erp_mask_destroy+0xf5/0x110 [mlxsw_spectrum] objagg_obj_root_destroy+0x18/0x80 [objagg] objagg_obj_destroy+0x12c/0x130 [objagg] mlxsw_sp_acl_erp_mask_put+0x37/0x50 [mlxsw_spectrum] mlxsw_sp_acl_ctcam_region_entry_remove+0x74/0xa0 [mlxsw_spectrum] mlxsw_sp_acl_ctcam_entry_del+0x1e/0x40 [mlxsw_spectrum] mlxsw_sp_acl_tcam_ventry_del+0x78/0xd0 [mlxsw_spectrum] mlxsw_sp_flower_destroy+0x4d/0x70 [mlxsw_spectrum] mlxsw_sp_flow_block_cb+0x73/0xb0 [mlxsw_spectrum] tc_setup_cb_destroy+0xc1/0x180 fl_hw_destroy_filter+0x94/0xc0 [cls_flower] __fl_delete+0x1ac/0x1c0 [cls_flower] fl_destroy+0xc2/0x150 [cls_flower] tcf_proto_destroy+0x1a/0xa0
...mlxsw_spectrum3 0000:07:00.0: Failed to migrate vregion mlxsw_spectrum3 0000:07:00.0: Failed to migrate vregion
--- .../mellanox/mlxsw/spectrum_acl_erp.c | 8 +-- .../drivers/net/mlxsw/spectrum-2/tc_flower.sh | 52 ++++++++++++++++++- 2 files changed, 56 insertions(+), 4 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c +5 -3
@@ -301,6 +301,7 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core, unsigned long *p_index) {unsigned int num_rows, entry_size; +unsigned long index;/* We only allow allocations of entire rows */ if (num_erps % erp_core->num_erp_banks !=0 )
@@ -309,10 +310,11 @@ mlxsw_sp_acl_erp_table_alloc(struct mlxsw_sp_acl_erp_core *erp_core, entry_size = erp_core->erpt_entries_size[region_type]; num_rows = num_erps / erp_core->num_erp_banks; - *p_index =gen_pool_alloc (erp_core->erp_tables, num_rows * entry_size); -if (*p_index ==0 ) + index =gen_pool_alloc (erp_core->erp_tables, num_rows * entry_size); +if (!index)return -ENOBUFS ; - *p_index -=MLXSW_SP_ACL_ERP_GENALLOC_OFFSET ; + + *p_index = index -MLXSW_SP_ACL_ERP_GENALLOC_OFFSET ;return 0 ; }
tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh +51 -1
64 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 359/374 mlxsw: spectrum: Use bitmap_zalloc() when applicable
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 2c087dfcc9d5e7e8557d217f01f58ba42d1ddbf1 ]
Use 'bitmap_zalloc()' to simplify code, improve the semantic and avoid some open-coded arithmetic in allocator arguments.
Also change the corresponding 'kfree()' into 'bitmap_free()' to keep consistency.
Stable-dep-of: 483ae90d8f97 ("mlxsw: spectrum_acl_tcam: Fix stack corruption")
--- .../ethernet/mellanox/mlxsw/spectrum_acl_atcam.c | 8 +++----- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 15 ++++++--------- .../net/ethernet/mellanox/mlxsw/spectrum_cnt.c | 9 +++------ .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 11 ++++------- 4 files changed, 16 insertions(+), 27 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c +3 -5
@@ -119,7 +119,6 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion) {struct mlxsw_sp *mlxsw_sp = aregion->region->mlxsw_sp;struct mlxsw_sp_acl_atcam_region_12kb *region_12kb; -size_t alloc_size;u64 max_lkey_id;int err;
@@ -131,8 +130,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion)if (!region_12kb)return -ENOMEM ; - alloc_size =BITS_TO_LONGS (max_lkey_id) *sizeof (unsigned long ); - region_12kb->used_lkey_id =kzalloc (alloc_size,GFP_KERNEL ); + region_12kb->used_lkey_id =bitmap_zalloc (max_lkey_id,GFP_KERNEL );if (!region_12kb->used_lkey_id) { err = -ENOMEM ; goto err_used_lkey_id_alloc;
@@ -149,7 +147,7 @@ mlxsw_sp_acl_atcam_region_12kb_init(struct mlxsw_sp_acl_atcam_region *aregion)return 0 ; err_rhashtable_init: -kfree (region_12kb->used_lkey_id); +bitmap_free (region_12kb->used_lkey_id); err_used_lkey_id_alloc:kfree (region_12kb);return err;
@@ -161,7 +159,7 @@ mlxsw_sp_acl_atcam_region_12kb_fini(struct mlxsw_sp_acl_atcam_region *aregion)struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv;rhashtable_destroy (®ion_12kb->lkey_ht); -kfree (region_12kb->used_lkey_id); +bitmap_free (region_12kb->used_lkey_id);kfree (region_12kb); }
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +6 -9
@@ -36,7 +36,6 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,u64 max_tcam_regions;u64 max_regions;u64 max_groups; -size_t alloc_size;int err;mutex_init (&tcam->lock);
@@ -52,15 +51,13 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,if (max_tcam_regions < max_regions) max_regions = max_tcam_regions; - alloc_size =sizeof (tcam->used_regions[0 ]) *BITS_TO_LONGS (max_regions); - tcam->used_regions =kzalloc (alloc_size,GFP_KERNEL ); + tcam->used_regions =bitmap_zalloc (max_regions,GFP_KERNEL );if (!tcam->used_regions)return -ENOMEM ; tcam->max_regions = max_regions; max_groups =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_GROUPS ); - alloc_size =sizeof (tcam->used_groups[0 ]) *BITS_TO_LONGS (max_groups); - tcam->used_groups =kzalloc (alloc_size,GFP_KERNEL ); + tcam->used_groups =bitmap_zalloc (max_groups,GFP_KERNEL );if (!tcam->used_groups) { err = -ENOMEM ; goto err_alloc_used_groups;
@@ -76,9 +73,9 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,return 0 ; err_tcam_init: -kfree (tcam->used_groups); +bitmap_free (tcam->used_groups); err_alloc_used_groups: -kfree (tcam->used_regions); +bitmap_free (tcam->used_regions);return err; }
@@ -89,8 +86,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,mutex_destroy (&tcam->lock); ops->fini (mlxsw_sp, tcam->priv); -kfree (tcam->used_groups); -kfree (tcam->used_regions); +bitmap_free (tcam->used_groups); +bitmap_free (tcam->used_regions); } int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.c +3 -6
@@ -122,7 +122,6 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)unsigned int sub_pools_count =ARRAY_SIZE (mlxsw_sp_counter_sub_pools);struct devlink *devlink =priv_to_devlink (mlxsw_sp->core);struct mlxsw_sp_counter_pool *pool; -unsigned int map_size;int err; pool = kzalloc(struct_size(pool, sub_pools, sub_pools_count),
@@ -143,9 +142,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)devlink_resource_occ_get_register (devlink,MLXSW_SP_RESOURCE_COUNTERS , mlxsw_sp_counter_pool_occ_get, pool); - map_size =BITS_TO_LONGS (pool->pool_size) *sizeof (unsigned long ); - - pool->usage =kzalloc (map_size,GFP_KERNEL ); + pool->usage =bitmap_zalloc (pool->pool_size,GFP_KERNEL );if (!pool->usage) { err = -ENOMEM ; goto err_usage_alloc;
@@ -158,7 +155,7 @@ int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)return 0 ; err_sub_pools_init: -kfree (pool->usage); +bitmap_free (pool->usage); err_usage_alloc:devlink_resource_occ_get_unregister (devlink,MLXSW_SP_RESOURCE_COUNTERS );
@@ -176,7 +173,7 @@ void mlxsw_sp_counter_pool_fini(struct mlxsw_sp *mlxsw_sp)WARN_ON (find_first_bit (pool->usage, pool->pool_size) != pool->pool_size);WARN_ON (atomic_read (&pool->active_entries_count)); -kfree (pool->usage); +bitmap_free (pool->usage);devlink_resource_occ_get_unregister (devlink,MLXSW_SP_RESOURCE_COUNTERS );kfree (pool);
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +4 -7
@@ -1635,16 +1635,13 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, u16 fid) {struct mlxsw_sp_mid *mid; -size_t alloc_size; mid =kzalloc (sizeof (*mid),GFP_KERNEL );if (!mid)return NULL ; - alloc_size =sizeof (unsigned long ) * -BITS_TO_LONGS (mlxsw_core_max_ports (mlxsw_sp->core)); - - mid->ports_in_mid =kzalloc (alloc_size,GFP_KERNEL ); + mid->ports_in_mid =bitmap_zalloc (mlxsw_core_max_ports (mlxsw_sp->core), +GFP_KERNEL );if (!mid->ports_in_mid) goto err_ports_in_mid_alloc;
@@ -1663,7 +1660,7 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,return mid; err_write_mdb_entry: -kfree (mid->ports_in_mid); +bitmap_free (mid->ports_in_mid); err_ports_in_mid_alloc:kfree (mid);return NULL ;
@@ -1680,7 +1677,7 @@ static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port, mlxsw_core_max_ports(mlxsw_sp->core))) { err =mlxsw_sp_mc_remove_mdb_entry (mlxsw_sp, mid);list_del (&mid->list); -kfree (mid->ports_in_mid); +bitmap_free (mid->ports_in_mid);kfree (mid); }return err;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 360/374 mlxsw: spectrum_acl_tcam: Add missing mutex_destroy()
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 65823e07b1e4055b6278725fd92f4d7e6f8d53fd ]
Pair mutex_init() with a mutex_destroy() in the error path. Found during code review. No functional changes.
Stable-dep-of: 483ae90d8f97 ("mlxsw: spectrum_acl_tcam: Fix stack corruption")
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +6 -2
@@ -52,8 +52,10 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, max_regions = max_tcam_regions; tcam->used_regions =bitmap_zalloc (max_regions,GFP_KERNEL ); -if (!tcam->used_regions) -return -ENOMEM ; +if (!tcam->used_regions) { + err = -ENOMEM ; + goto err_alloc_used_regions; + } tcam->max_regions = max_regions; max_groups =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_GROUPS );
@@ -76,6 +78,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,bitmap_free (tcam->used_groups); err_alloc_used_groups:bitmap_free (tcam->used_regions); +err_alloc_used_regions: +mutex_destroy (&tcam->lock);return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 361/374 mlxsw: spectrum_acl_tcam: Make fini symmetric to init
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 61fe3b9102ac84ba479ab84d8f5454af2e21e468 ]
Move mutex_destroy() to the end to make the function symmetric with mlxsw_sp_acl_tcam_init(). No functional changes.
Stable-dep-of: 483ae90d8f97 ("mlxsw: spectrum_acl_tcam: Fix stack corruption")
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +1 -1
@@ -88,10 +88,10 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, {const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; -mutex_destroy (&tcam->lock); ops->fini (mlxsw_sp, tcam->priv);bitmap_free (tcam->used_groups);bitmap_free (tcam->used_regions); +mutex_destroy (&tcam->lock); } int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 362/374 mlxsw: spectrum_acl_tcam: Reorder functions to avoid forward declarations
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 194ab9476089bbfc021073214e071a404e375ee6 ]
Move the initialization and de-initialization code further below in order to avoid forward declarations in the next patch. No functional changes.
Stable-dep-of: 483ae90d8f97 ("mlxsw: spectrum_acl_tcam: Fix stack corruption")
--- .../mellanox/mlxsw/spectrum_acl_tcam.c | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +65 -65
@@ -29,71 +29,6 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp)#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000/* ms */ #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100/* number of entries */ -int mlxsw_sp_acl_tcam_init (struct mlxsw_sp *mlxsw_sp, -struct mlxsw_sp_acl_tcam *tcam) -{ -const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; -u64 max_tcam_regions; -u64 max_regions; -u64 max_groups; -int err; - -mutex_init (&tcam->lock); - tcam->vregion_rehash_intrvl = -MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT ; -INIT_LIST_HEAD (&tcam->vregion_list); - - max_tcam_regions =MLXSW_CORE_RES_GET (mlxsw_sp->core, -ACL_MAX_TCAM_REGIONS ); - max_regions =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_REGIONS ); - -/* Use 1:1 mapping between ACL region and TCAM region */ -if (max_tcam_regions < max_regions) - max_regions = max_tcam_regions; - - tcam->used_regions =bitmap_zalloc (max_regions,GFP_KERNEL ); -if (!tcam->used_regions) { - err = -ENOMEM ; - goto err_alloc_used_regions; - } - tcam->max_regions = max_regions; - - max_groups =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_GROUPS ); - tcam->used_groups =bitmap_zalloc (max_groups,GFP_KERNEL ); -if (!tcam->used_groups) { - err = -ENOMEM ; - goto err_alloc_used_groups; - } - tcam->max_groups = max_groups; - tcam->max_group_size =MLXSW_CORE_RES_GET (mlxsw_sp->core, -ACL_MAX_GROUP_SIZE ); - - err = ops->init (mlxsw_sp, tcam->priv, tcam); -if (err) - goto err_tcam_init; - -return 0 ; - -err_tcam_init: -bitmap_free (tcam->used_groups); -err_alloc_used_groups: -bitmap_free (tcam->used_regions); -err_alloc_used_regions: -mutex_destroy (&tcam->lock); -return err; -} - -void mlxsw_sp_acl_tcam_fini (struct mlxsw_sp *mlxsw_sp, -struct mlxsw_sp_acl_tcam *tcam) -{ -const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; - - ops->fini (mlxsw_sp, tcam->priv); -bitmap_free (tcam->used_groups); -bitmap_free (tcam->used_regions); -mutex_destroy (&tcam->lock); -} -int mlxsw_sp_acl_tcam_priority_get (struct mlxsw_sp *mlxsw_sp,struct mlxsw_sp_acl_rule_info *rulei,u32 *priority,bool fillup_priority)
@@ -1546,6 +1481,71 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,mlxsw_sp_acl_tcam_vregion_rehash_end (mlxsw_sp, vregion, ctx); } +int mlxsw_sp_acl_tcam_init (struct mlxsw_sp *mlxsw_sp, +struct mlxsw_sp_acl_tcam *tcam) +{ +const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; +u64 max_tcam_regions; +u64 max_regions; +u64 max_groups; +int err; + +mutex_init (&tcam->lock); + tcam->vregion_rehash_intrvl = +MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT ; +INIT_LIST_HEAD (&tcam->vregion_list); + + max_tcam_regions =MLXSW_CORE_RES_GET (mlxsw_sp->core, +ACL_MAX_TCAM_REGIONS ); + max_regions =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_REGIONS ); + +/* Use 1:1 mapping between ACL region and TCAM region */ +if (max_tcam_regions < max_regions) + max_regions = max_tcam_regions; + + tcam->used_regions =bitmap_zalloc (max_regions,GFP_KERNEL ); +if (!tcam->used_regions) { + err = -ENOMEM ; + goto err_alloc_used_regions; + } + tcam->max_regions = max_regions; + + max_groups =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_GROUPS ); + tcam->used_groups =bitmap_zalloc (max_groups,GFP_KERNEL ); +if (!tcam->used_groups) { + err = -ENOMEM ; + goto err_alloc_used_groups; + } + tcam->max_groups = max_groups; + tcam->max_group_size =MLXSW_CORE_RES_GET (mlxsw_sp->core, +ACL_MAX_GROUP_SIZE ); + + err = ops->init (mlxsw_sp, tcam->priv, tcam); +if (err) + goto err_tcam_init; + +return 0 ; + +err_tcam_init: +bitmap_free (tcam->used_groups); +err_alloc_used_groups: +bitmap_free (tcam->used_regions); +err_alloc_used_regions: +mutex_destroy (&tcam->lock); +return err; +} + +void mlxsw_sp_acl_tcam_fini (struct mlxsw_sp *mlxsw_sp, +struct mlxsw_sp_acl_tcam *tcam) +{ +const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; + + ops->fini (mlxsw_sp, tcam->priv); +bitmap_free (tcam->used_groups); +bitmap_free (tcam->used_regions); +mutex_destroy (&tcam->lock); +} +static const enum mlxsw_afk_element mlxsw_sp_acl_tcam_pattern_ipv4[] = {MLXSW_AFK_ELEMENT_SRC_SYS_PORT ,MLXSW_AFK_ELEMENT_DMAC_32_47 ,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 363/374 mlxsw: spectrum_acl_tcam: Fix stack corruption
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 483ae90d8f976f8339cf81066312e1329f2d3706 ]
When tc filters are first added to a net device, the corresponding local port gets bound to an ACL group in the device. The group contains a list of ACLs. In turn, each ACL points to a different TCAM region where the filters are stored. During forwarding, the ACLs are sequentially evaluated until a match is found.
One reason to place filters in different regions is when they are added with decreasing priorities and in an alternating order so that two consecutive filters can never fit in the same region because of their key usage.
In Spectrum-2 and newer ASICs the firmware started to report that the maximum number of ACLs in a group is more than 16, but the layout of the register that configures ACL groups (PAGT) was not updated to account for that. It is therefore possible to hit stack corruption [1] in the rare case where more than 16 ACLs in a group are required.
Fix by limiting the maximum ACL group size to the minimum between what the firmware reports and the maximum ACLs that fit in the PAGT register.
Add a test case to make sure the machine does not crash when this condition is hit.
[1]
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: mlxsw_sp_acl_tcam_group_update+0x116/0x120 [...] dump_stack_lvl+0x36/0x50 panic+0x305/0x330 __stack_chk_fail+0x15/0x20 mlxsw_sp_acl_tcam_group_update+0x116/0x120 mlxsw_sp_acl_tcam_group_region_attach+0x69/0x110 mlxsw_sp_acl_tcam_vchunk_get+0x492/0xa20 mlxsw_sp_acl_tcam_ventry_add+0x25/0xe0 mlxsw_sp_acl_rule_add+0x47/0x240 mlxsw_sp_flower_replace+0x1a9/0x1d0 tc_setup_cb_add+0xdc/0x1c0 fl_hw_replace_filter+0x146/0x1f0 fl_change+0xc17/0x1360 tc_new_tfilter+0x472/0xb90 rtnetlink_rcv_msg+0x313/0x3b0 netlink_rcv_skb+0x58/0x100 netlink_unicast+0x244/0x390 netlink_sendmsg+0x1e4/0x440 ____sys_sendmsg+0x164/0x260 ___sys_sendmsg+0x9a/0xe0 __sys_sendmsg+0x7a/0xc0 do_syscall_64+0x40/0xe0 entry_SYSCALL_64_after_hwframe+0x63/0x6b
--- .../mellanox/mlxsw/spectrum_acl_tcam.c | 2 + .../drivers/net/mlxsw/spectrum-2/tc_flower.sh | 56 ++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +2 -0
@@ -1519,6 +1519,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, tcam->max_groups = max_groups; tcam->max_group_size =MLXSW_CORE_RES_GET (mlxsw_sp->core,ACL_MAX_GROUP_SIZE ); + tcam->max_group_size = min_t(unsigned int, tcam->max_group_size, +MLXSW_REG_PAGT_ACL_MAX_NUM ); err = ops->init (mlxsw_sp, tcam->priv, tcam);if (err)
tools/testing/selftests/drivers/net/mlxsw/spectrum-2/tc_flower.sh +55 -1
68 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 364/374 selftests: mlxsw: qos_pfc: Adjust the test to support 8 lanes
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Cohen <[email protected]>
[ Upstream commit b34f4de6d30cbaa8fed905a5080b6eace8c84dc7 ]
'qos_pfc' test checks PFC behavior. The idea is to limit the traffic using a shaper somewhere in the flow of the packets. In this area, the buffer is smaller than the buffer at the beginning of the flow, so it fills up until there is no more space left. The test configures there PFC which is supposed to notice that the headroom is filling up and send PFC Xoff to indicate the transmitter to stop sending traffic for the priorities sharing this PG.
The Xon/Xoff threshold is auto-configured and always equal to 2*(MTU rounded up to cell size). Even after sending the PFC Xoff packet, traffic will keep arriving until the transmitter receives and processes the PFC packet. This amount of traffic is known as the PFC delay allowance.
Currently the buffer for the delay traffic is configured as 100KB. The MTU in the test is 10KB, therefore the threshold for Xoff is about 20KB. This allows 80KB extra to be stored in this buffer.
8-lane ports use two buffers among which the configured buffer is split, the Xoff threshold then applies to each buffer in parallel.
The test does not take into account the behavior of 8-lane ports, when the ports are configured to 400Gbps with 8 lanes or 800Gbps with 8 lanes, packets are dropped and the test fails.
Check if the relevant ports use 8 lanes, in such case double the size of the buffer, as the headroom is split half-half.
--- .../selftests/drivers/net/mlxsw/qos_pfc.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
tools/testing/selftests/drivers/net/mlxsw/qos_pfc.sh +17 -1
@@ -121,6 +121,9 @@ h2_destroy() switch_create() { + local lanes_swp4 + local pg1_size + # pools # -----
@@ -230,7 +233,20 @@ switch_create() dcb pfc set dev $swp4 prio-pfc all:off 1:on # PG0 will get autoconfigured to Xoff, give PG1 arbitrarily 100K, which # is (-2*MTU) about 80K of delay provision. - dcb buffer set dev $swp4 buffer-size all:0 1:$_100KB + pg1_size=$_100KB + + setup_wait_dev_with_timeout $swp4 + + lanes_swp4=$(ethtool $swp4 | grep 'Lanes:') + lanes_swp4=${lanes_swp4#*"Lanes: "} + + # 8-lane ports use two buffers among which the configured buffer + # is split, so double the size to get twice (20K + 80K). + if [[ $lanes_swp4 -eq 8 ]]; then + pg1_size=$((pg1_size * 2)) + fi + + dcb buffer set dev $swp4 buffer-size all:0 1:$pg1_size # bridges # -------
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 365/374 ipv6: mcast: fix data-race in ipv6_mc_down / mld_ifc_work
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikita Zhandarovich <[email protected]>
[ Upstream commit 2e7ef287f07c74985f1bf2858bedc62bd9ebf155 ]
idev->mc_ifc_count can be written over without proper locking.
Originally found by syzbot [1], fix this issue by encapsulating calls to mld_ifc_stop_work() (and mld_gq_stop_work() for good measure) with mutex_lock() and mutex_unlock() accordingly as these functions should only be called with mc_lock per their declarations.
[1]
BUG: KCSAN: data-race in ipv6_mc_down / mld_ifc_work
write to 0xffff88813a80c832 of 1 bytes by task 3771 on cpu 0:
mld_ifc_stop_work net/ipv6/mcast.c:1080 [inline] ipv6_mc_down+0x10a/0x280 net/ipv6/mcast.c:2725 addrconf_ifdown+0xe32/0xf10 net/ipv6/addrconf.c:3949 addrconf_notify+0x310/0x980 notifier_call_chain kernel/notifier.c:93 [inline] raw_notifier_call_chain+0x6b/0x1c0 kernel/notifier.c:461 __dev_notify_flags+0x205/0x3d0 dev_change_flags+0xab/0xd0 net/core/dev.c:8685 do_setlink+0x9f6/0x2430 net/core/rtnetlink.c:2916 rtnl_group_changelink net/core/rtnetlink.c:3458 [inline] __rtnl_newlink net/core/rtnetlink.c:3717 [inline] rtnl_newlink+0xbb3/0x1670 net/core/rtnetlink.c:3754 rtnetlink_rcv_msg+0x807/0x8c0 net/core/rtnetlink.c:6558 netlink_rcv_skb+0x126/0x220 net/netlink/af_netlink.c:2545 rtnetlink_rcv+0x1c/0x20 net/core/rtnetlink.c:6576 netlink_unicast_kernel net/netlink/af_netlink.c:1342 [inline] netlink_unicast+0x589/0x650 net/netlink/af_netlink.c:1368 netlink_sendmsg+0x66e/0x770 net/netlink/af_netlink.c:1910 ...
write to 0xffff88813a80c832 of 1 bytes by task 22 on cpu 1:
mld_ifc_work+0x54c/0x7b0 net/ipv6/mcast.c:2653 process_one_work kernel/workqueue.c:2627 [inline] process_scheduled_works+0x5b8/0xa30 kernel/workqueue.c:2700 worker_thread+0x525/0x730 kernel/workqueue.c:2781 ...
--- net/ipv6/mcast.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/mcast.c +4 -0
@@ -2725,8 +2725,12 @@ void ipv6_mc_down(struct inet6_dev *idev)synchronize_net ();mld_query_stop_work (idev);mld_report_stop_work (idev); + +mutex_lock (&idev->mc_lock);mld_ifc_stop_work (idev);mld_gq_stop_work (idev); +mutex_unlock (&idev->mc_lock); +mld_dad_stop_work (idev); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 366/374 i2c: s3c24xx: fix read transfers in polling mode
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 0d9cf23ed55d7ba3ab26d617a3ae507863674c8f ]
To properly handle read transfers in polling mode, no waiting for the ACK state is needed as it will never come. Just wait a bit to ensure start state is on the bus and continue processing next bytes.
--- drivers/i2c/busses/i2c-s3c2410.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/i2c/busses/i2c-s3c2410.c +11 -2
@@ -220,8 +220,17 @@ static bool is_ack(struct s3c24xx_i2c *i2c)int tries;for (tries =50 ; tries; --tries) { -if (readl (i2c->regs +S3C2410_IICCON ) - &S3C2410_IICCON_IRQPEND ) { +unsigned long tmp =readl (i2c->regs +S3C2410_IICCON ); + +if (!(tmp &S3C2410_IICCON_ACKEN )) { +/* +* Wait a bit for the bus to stabilize, +* delay estimated experimentally. +*/ +usleep_range (100 ,200 ); +return true; + } +if (tmp &S3C2410_IICCON_IRQPEND ) {if (!(readl (i2c->regs +S3C2410_IICSTAT ) &S3C2410_IICSTAT_LASTBIT ))return true;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 367/374 i2c: s3c24xx: fix transferring more than one message in polling mode
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Szyprowski <[email protected]>
[ Upstream commit 990489e1042c6c5d6bccf56deca68f8dbeed8180 ]
To properly handle ACK on the bus when transferring more than one message in polling mode, move the polling handling loop from s3c24xx_i2c_message_start() to s3c24xx_i2c_doxfer(). This way i2c_s3c_irq_nextbyte() is always executed till the end, properly acknowledging the IRQ bits and no recursive calls to i2c_s3c_irq_nextbyte() are made.
While touching this, also fix finishing transfers in polling mode by using common code path and always waiting for the bus to become idle and disabled.
--- drivers/i2c/busses/i2c-s3c2410.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-)
drivers/i2c/busses/i2c-s3c2410.c +10 -17
@@ -283,16 +283,6 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, stat |=S3C2410_IICSTAT_START ;writel (stat, i2c->regs +S3C2410_IICSTAT ); - -if (i2c->quirks &QUIRK_POLL ) { -while ((i2c->msg_num !=0 ) &&is_ack (i2c)) { -i2c_s3c_irq_nextbyte (i2c, stat); - stat =readl (i2c->regs +S3C2410_IICSTAT ); - -if (stat &S3C2410_IICSTAT_ARBITR ) -dev_err (i2c->dev,"deal with arbitration loss\n" ); - } - } }static inline void s3c24xx_i2c_stop (struct s3c24xx_i2c *i2c,int ret)
@@ -699,7 +689,7 @@ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)static int s3c24xx_i2c_doxfer (struct s3c24xx_i2c *i2c,struct i2c_msg *msgs,int num) { -unsigned long timeout; +unsigned long timeout =0 ;int ret; ret =s3c24xx_i2c_set_master (i2c);
@@ -719,16 +709,19 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,s3c24xx_i2c_message_start (i2c, msgs);if (i2c->quirks &QUIRK_POLL ) { - ret = i2c->msg_idx; +while ((i2c->msg_num !=0 ) &&is_ack (i2c)) { +unsigned long stat =readl (i2c->regs +S3C2410_IICSTAT ); -if (ret != num) -dev_dbg (i2c->dev,"incomplete xfer (%d)\n" , ret); +i2c_s3c_irq_nextbyte (i2c, stat); - goto out; + stat =readl (i2c->regs +S3C2410_IICSTAT ); +if (stat &S3C2410_IICSTAT_ARBITR ) +dev_err (i2c->dev,"deal with arbitration loss\n" ); + } + }else { + timeout =wait_event_timeout (i2c->wait, i2c->msg_num ==0 ,HZ *5 ); } - timeout =wait_event_timeout (i2c->wait, i2c->msg_num ==0 ,HZ *5 ); - ret = i2c->msg_idx;/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 368/374 block: Remove special-casing of compound pages
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
commit 1b151e2435fc3a9b10c8946c6aebe9f3e1938c55 upstream.
The special casing was originally added in pre-git history; reproducing the commit log here:
Quoted 9 lines
commit
a318a92567d77Author: Andrew Morton <[email protected]> Date: Sun Sep 21 01:42:22 2003 -0700[PATCH] Speed up direct-io hugetlbpage handling
This patch short-circuits all the direct-io page dirtying logic for higher-order pages. Without this, we pointlessly bounce BIOs up to keventd all the time.
In the last twenty years, compound pages have become used for more than just hugetlb. Rewrite these functions to operate on folios instead of pages and remove the special case for hugetlbfs; I don't think it's needed any more (and if it is, we can put it back in as a call to folio_test_hugetlb()).
This was found by inspection; as far as I can tell, this bug can lead to pages used as the destination of a direct I/O read not being marked as dirty. If those pages are then reclaimed by the MM without being dirtied for some other reason, they won't be written out. Then when they're faulted back in, they will not contain the data they should. It'll take a pretty unusual setup to produce this problem with several races all going the wrong way.
This problem predates the folio work; it could for example have been triggered by mmaping a THP in tmpfs and using that as the target of an O_DIRECT read.
--- block/bio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
block/bio.c +3 -4
@@ -1026,7 +1026,7 @@ void bio_release_pages(struct bio *bio,return ;bio_for_each_segment_all (bvec, bio, iter_all) { -if (mark_dirty && !PageCompound (bvec->bv_page)) +if (mark_dirty)set_page_dirty_lock (bvec->bv_page);put_page (bvec->bv_page); }
@@ -1345,8 +1345,7 @@ void bio_set_pages_dirty(struct bio *biostruct bvec_iter_all iter_all;bio_for_each_segment_all (bvec, bio, iter_all) { -if (!PageCompound (bvec->bv_page)) -set_page_dirty_lock (bvec->bv_page); +set_page_dirty_lock (bvec->bv_page); } }
@@ -1394,7 +1393,7 @@ void bio_check_pages_dirty(struct bio *bstruct bvec_iter_all iter_all;bio_for_each_segment_all (bvec, bio, iter_all) { -if (!PageDirty (bvec->bv_page) && !PageCompound (bvec->bv_page)) +if (!PageDirty (bvec->bv_page)) goto defer; }
Greg Kroah-Hartman
maintainerPATCH 369/374 netfilter: nf_tables: typo NULL check in _clone() function
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit 51edb2ff1c6fc27d3fa73f0773a31597ecd8e230 upstream.
This should check for NULL in case memory allocation fails.
--- net/netfilter/nft_connlimit.c | 2 +- net/netfilter/nft_last.c | 2 +- net/netfilter/nft_limit.c | 2 +- net/netfilter/nft_quota.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-)
net/netfilter/nft_connlimit.c +1 -1
@@ -206,7 +206,7 @@ static int nft_connlimit_clone(struct nfstruct nft_connlimit *priv_src =nft_expr_priv (src); priv_dst->list =kmalloc (sizeof (*priv_dst->list),GFP_ATOMIC ); -if (priv_dst->list) +if (!priv_dst->list)return -ENOMEM ;nf_conncount_list_init (priv_dst->list);
net/netfilter/nft_last.c +1 -1
@@ -106,7 +106,7 @@ static int nft_last_clone(struct nft_expstruct nft_last_priv *priv_dst =nft_expr_priv (dst); priv_dst->last =kzalloc (sizeof (*priv_dst->last),GFP_ATOMIC ); -if (priv_dst->last) +if (!priv_dst->last)return -ENOMEM ;return 0 ;
net/netfilter/nft_limit.c +1 -1
@@ -150,7 +150,7 @@ static int nft_limit_clone(struct nft_li priv_dst->invert = priv_src->invert; priv_dst->limit =kmalloc (sizeof (*priv_dst->limit),GFP_ATOMIC ); -if (priv_dst->limit) +if (!priv_dst->limit)return -ENOMEM ;spin_lock_init (&priv_dst->limit->lock);
net/netfilter/nft_quota.c +1 -1
@@ -237,7 +237,7 @@ static int nft_quota_clone(struct nft_exstruct nft_quota *priv_dst =nft_expr_priv (dst); priv_dst->consumed =kmalloc (sizeof (*priv_dst->consumed),GFP_ATOMIC ); -if (priv_dst->consumed) +if (!priv_dst->consumed)return -ENOMEM ;atomic64_set (priv_dst->consumed,0 );
Greg Kroah-Hartman
maintainerPATCH 370/374 netfilter: nft_connlimit: memleak if nf_ct_netns_get() fails
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit 7d70984a1ad4c445dff08edb9aacce8906b6a222 upstream.
Check if nf_ct_netns_get() fails then release the limit object previously allocated via kmalloc().
--- net/netfilter/nft_connlimit.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
net/netfilter/nft_connlimit.c +10 -1
@@ -62,6 +62,7 @@ static int nft_connlimit_do_init(const s {bool invert = false;u32 flags, limit; +int err;if (!tb[NFTA_CONNLIMIT_COUNT ])return -EINVAL ;
@@ -84,7 +85,15 @@ static int nft_connlimit_do_init(const s priv->limit = limit; priv->invert = invert; -return nf_ct_netns_get (ctx->net, ctx->family); + err =nf_ct_netns_get (ctx->net, ctx->family); +if (err <0 ) + goto err_netns; + +return 0 ; +err_netns: +kfree (priv->list); + +return err; } static void nft_connlimit_do_destroy(const struct nft_ctx *ctx,
Greg Kroah-Hartman
maintainerPATCH 371/374 netfilter: nft_limit: fix stateful object memory leak
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 1a58f84ea5df7f026bf92a0009f931bf547fe965 upstream.
We need to provide a destroy callback to release the extra fields.
--- net/netfilter/nft_limit.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
net/netfilter/nft_limit.c +18 -0
@@ -345,11 +345,20 @@ static int nft_limit_obj_pkts_dump(strucreturn nft_limit_dump (skb, &priv->limit,NFT_LIMIT_PKTS ); } +static void nft_limit_obj_pkts_destroy (const struct nft_ctx *ctx, +struct nft_object *obj) +{ +struct nft_limit_priv_pkts *priv =nft_obj_data (obj); + +nft_limit_destroy (ctx, &priv->limit); +} +static struct nft_object_type nft_limit_obj_type;static const struct nft_object_ops nft_limit_obj_pkts_ops = { .type = &nft_limit_obj_type, .size =NFT_EXPR_SIZE (sizeof (struct nft_limit_priv_pkts )), .init = nft_limit_obj_pkts_init, + .destroy = nft_limit_obj_pkts_destroy, .eval = nft_limit_obj_pkts_eval, .dump = nft_limit_obj_pkts_dump, };
@@ -383,11 +392,20 @@ static int nft_limit_obj_bytes_dump(strureturn nft_limit_dump (skb, priv,NFT_LIMIT_PKT_BYTES ); } +static void nft_limit_obj_bytes_destroy (const struct nft_ctx *ctx, +struct nft_object *obj) +{ +struct nft_limit_priv *priv =nft_obj_data (obj); + +nft_limit_destroy (ctx, priv); +} +static struct nft_object_type nft_limit_obj_type;static const struct nft_object_ops nft_limit_obj_bytes_ops = { .type = &nft_limit_obj_type, .size =sizeof (struct nft_limit_priv ), .init = nft_limit_obj_bytes_init, + .destroy = nft_limit_obj_bytes_destroy, .eval = nft_limit_obj_bytes_eval, .dump = nft_limit_obj_bytes_dump, };
Greg Kroah-Hartman
maintainerPATCH 372/374 netfilter: nft_limit: Clone packet limits cost value
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
commit 558254b0b602b8605d7246a10cfeb584b1fcabfc upstream.
When cloning a packet-based limit expression, copy the cost value as well. Otherwise the new limit is not functional anymore.
--- net/netfilter/nft_limit.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nft_limit.c +2 -0
@@ -218,6 +218,8 @@ static int nft_limit_pkts_clone(struct nstruct nft_limit_priv_pkts *priv_dst =nft_expr_priv (dst);struct nft_limit_priv_pkts *priv_src =nft_expr_priv (src); + priv_dst->cost = priv_src->cost; +return nft_limit_clone (&priv_dst->limit, &priv_src->limit); }
Greg Kroah-Hartman
maintainerPATCH 373/374 netfilter: nft_last: copy content when cloning expression
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit 860e874290fb3be08e966c9c8ffc510c5b0f2bd8 upstream.
If the ruleset contains last timestamps, restore them accordingly. Otherwise, listing after restoration shows never used items.
--- net/netfilter/nft_last.c | 4 ++++ 1 file changed, 4 insertions(+)
net/netfilter/nft_last.c +4 -0
@@ -104,11 +104,15 @@ static void nft_last_destroy(const strucstatic int nft_last_clone (struct nft_expr *dst,const struct nft_expr *src) {struct nft_last_priv *priv_dst =nft_expr_priv (dst); +struct nft_last_priv *priv_src =nft_expr_priv (src); priv_dst->last =kzalloc (sizeof (*priv_dst->last),GFP_ATOMIC );if (!priv_dst->last)return -ENOMEM ; + priv_dst->last->set = priv_src->last->set; + priv_dst->last->jiffies = priv_src->last->jiffies; +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 374/374 netfilter: nft_quota: copy content when cloning expression
In reply to Greg Kroah-Hartman5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
commit aabef97a35160461e9c576848ded737558d89055 upstream.
If the ruleset contains consumed quota, restore them accordingly. Otherwise, listing after restoration shows never used items.
Restore the user-defined quota and flags too.
--- net/netfilter/nft_quota.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/netfilter/nft_quota.c +5 -1
@@ -235,12 +235,16 @@ static void nft_quota_destroy(const strustatic int nft_quota_clone (struct nft_expr *dst,const struct nft_expr *src) {struct nft_quota *priv_dst =nft_expr_priv (dst); +struct nft_quota *priv_src =nft_expr_priv (src); + + priv_dst->quota = priv_src->quota; + priv_dst->flags = priv_src->flags; priv_dst->consumed =kmalloc (sizeof (*priv_dst->consumed),GFP_ATOMIC );if (!priv_dst->consumed)return -ENOMEM ; -atomic64_set (priv_dst->consumed,0 ); + *priv_dst->consumed = *priv_src->consumed;return 0 ; }
Jon Hunter
maintainerHi Greg,
Quoted 17 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.148 release. There are 374 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 24 Jan 2024 23:56:49 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.148-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
...
Quoted 2 lines
Douglas Anderson <[email protected]>
r8152: Choose our USB config withchoose_configuration()rather thanprobe()
The above commit is causing a boot regression on the Tegra210 Jetson TX1 board and reverting this commit fixes it. This also happens with linux-6.1.y, linux-6.6.y and linux-6.7.y. I am not seeing this on the mainline.
Test results for stable-v5.15:
10 builds: 10 pass, 0 fail
28 boots: 26 pass, 2 fail
74 tests: 74 pass, 0 failLinux version: 5.15.148-rc1-g59db9667b9d1
Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000,
tegra194-p2972-0000, tegra194-p3509-0000+p3668-0000,
tegra20-ventana, tegra210-p2371-2180,
tegra210-p3450-0000, tegra30-cardhu-a04Boot failures: tegra210-p2371-2180
Looking at the console I am seeing the following panic ...
[ 5.262192] r8152-cfgselector 2-1: reset SuperSpeed USB device number 2 using tegra-xusb [ 5.367566] r8152 2-1:1.0: load rtl8153a-3 v2 02/07/20 successfully [ 5.415902] r8152 2-1:1.0 eth0: v1.12.13 [ 5.423122] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 5.431970] Mem abort info: [ 5.434799] ESR = 0x0000000086000004 [ 5.438596] EC = 0x21: IABT (current EL), IL = 32 bits [ 5.443963] SET = 0, FnV = 0 [ 5.447078] EA = 0, S1PTW = 0 [ 5.450254] FSC = 0x04: level 0 translation fault [ 5.455160] [0000000000000000] user address but active_mm is swapper [ 5.461551] Internal error: Oops: 0000000086000004 [#1] PREEMPT SMP [ 5.467830] Modules linked in: [ 5.470892] CPU: 2 PID: 120 Comm: kworker/2:3 Not tainted 5.15.147-00306-gfca62e959560 #8 [ 5.479075] Hardware name: NVIDIA Jetson TX1 Developer Kit (DT) [ 5.484995] Workqueue: usb_hub_wq hub_event [ 5.489196] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 5.496163] pc : 0x0 [ 5.498354] lr : usb_probe_device+0x34/0xb8 [ 5.502548] sp : ffff80000aad3990 [ 5.505863] x29: ffff80000aad3990 x28: ffff0000825810a8 x27: ffff80000a464958 [ 5.513015] x26: ffff80000a3190f8 x25: ffff80000a34df50 x24: 0000000000000000 [ 5.520163] x23: 0000000000000001 x22: 000000000000001d x21: ffff000082581000 [ 5.527309] x20: ffff80000a34d1d0 x19: ffff80000a34d210 x18: 0000000000000000 [ 5.534456] x17: 313a312d322f312d x16: 322f326273752f62 x15: 0000000000000001 [ 5.541602] x14: 0000000000000002 x13: 00000000000777aa x12: 0000000000000001 [ 5.548746] x11: 0000000000000028 x10: 0000000000000001 x9 : 0000000000000228 [ 5.555892] x8 : 0101010101010101 x7 : 7f7f7f7f7f7f7f7f x6 : 000000000ef0212c [ 5.563038] x5 : 00ffffffffffffff x4 : ffff80000a34ef88 x3 : 0000000000000000 [ 5.570184] x2 : ffffffffffffff00 x1 : 0000000000000000 x0 : ffff000082581000 [ 5.577329] Call trace: [ 5.579777] 0x0 [ 5.581619] really_probe+0xb4/0x2e0 [ 5.585208] __driver_probe_device+0x7c/0x120 [ 5.589570] driver_probe_device+0x40/0x130 [ 5.593757] __device_attach_driver+0x94/0xe0 [ 5.598120] bus_for_each_drv+0x70/0xc8 [ 5.601963] __device_attach+0xfc/0x188 [ 5.605803] device_initial_probe+0x10/0x18 [ 5.609993] bus_probe_device+0x94/0xa0 [ 5.613833] device_add+0x4ac/0x838 [ 5.617326] usb_new_device+0x1e4/0x580 [ 5.621167] hub_event+0x918/0x1350 [ 5.624658] process_one_work+0x1f4/0x4c0 [ 5.628675] worker_thread+0x48/0x470 [ 5.632342] kthread+0x120/0x158 [ 5.635579] ret_from_fork+0x10/0x20 [ 5.639166] Code: bad PC value [ 5.642224] ---[ end trace f266fb655cdbc485 ]---
Jon
Signature · 1 line
nvpublic
Greg Kroah-Hartman
maintainerQuoted 22 lines · Jon Hunter
Hi Greg,
Quoted 17 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.148 release. There are 374 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 24 Jan 2024 23:56:49 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.148-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h
...
Quoted 8 lines
Quoted 2 lines
Douglas Anderson <[email protected]>
r8152: Choose our USB config withchoose_configuration()rather thanprobe()The above commit is causing a boot regression on the Tegra210 Jetson TX1 board and reverting this commit fixes it. This also happens with linux-6.1.y, linux-6.6.y and linux-6.7.y. I am not seeing this on the mainline.
Ok, thanks for letting us know, I was a bit "worried" about these
changes, so I'll back them out and push out new -rc releases. If the
ChromeOS developers want them backported, I'll let them provide a working series.
thanks!
greg k-h
Hi Greg,
Quoted 8 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.15.148 release. There are 374 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 24 Jan 2024 23:56:49 +0000. Anything received after that time might be too late.
No problems seen on x86_64 and aarch64 with our testing.
Thanks,
Harshit
Quoted 10 lines
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.15.148-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.15.y
and the diffstat can be found below.thanks,
greg k-h