6.1.178-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 379/1067 ocfs2/dlm: require a ref for locking_state debugfs open
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit 03ad858ce8064861ea580021976dc19b7aabb549 ]
debug_lockres_open() copies inode->i_private into struct debug_lockres and debug_lockres_release() later drops that pointer with dlm_put(). That only works if open successfully pins the struct dlm_ctxt.
Today open calls dlm_grab(dlm) but ignores its return value. Once the last domain unregister has removed the context from dlm_domains, dlm_grab() returns NULL, yet open still stores the raw pointer and returns success. The later release path is outside the debugfs removal barrier, so it can call dlm_put() after dlm_free_ctxt_mem() has freed the context. KASAN reports this as a slab-use-after-free in dlm_put() called from debug_lockres_release().
Fail the open when dlm_grab() cannot acquire the reference and unwind the seq_file private state before returning. That keeps locking_state from handing out a file descriptor whose release path does not own the dlm_ctxt.
The buggy scenario involves two paths, with each column showing the order within that path:
locking_state debugfs open: last domain unregister:
1. debug_lockres_open() reads 1. dlm_unregister_domain() calls
inode->i_private. dlm_complete_dlm_shutdown().
2. debug_lockres_open() calls 2. shutdown removes the dlm_ctxt from
dlm_grab(dlm) and gets NULL. dlm_domains.
3. open still stores the raw dlm 3. final teardown reaches
pointer in dl->dl_ctxt and dlm_free_ctxt_mem() and frees it.
returns success.
4. debug_lockres_release() later
calls dlm_put(dl->dl_ctxt).
Validation reproduced this kernel report:
KASAN slab-use-after-free in dlm_put+0x82/0x200
RIP: 0033:0x7f4d349bc9e0 The buggy address belongs to the object at ffff888103a3c000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 816 bytes inside of freed 2048-byte region [ffff888103a3c000, ffff888103a3c800) Write of size 4 Call trace: dump_stack_lvl+0x66/0xa0 (?:?) print_report+0xd0/0x630 (?:?) dlm_put+0x82/0x200 (?:?) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x188/0x2f0 (?:?) kasan_report+0xe4/0x120 (?:?) kasan_check_range+0x105/0x1b0 (?:?) debug_lockres_release+0x53/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) dlm_put+0x9/0x200 (?:?) debug_lockres_release+0x5c/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) full_proxy_release+0x67/0x90 (?:?) __fput+0x1df/0x4b0 (?:?) do_raw_spin_lock+0x10f/0x1b0 (?:?) fput_close_sync+0xd2/0x170 (?:?) __x64_sys_close+0x55/0x90 (?:?) do_syscall_64+0x10c/0x640 (arch/x86/entry/syscall_64.c:87) irqentry_exit+0xac/0x6e0 (?:?) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?) Freed by task stack: kasan_save_stack+0x33/0x60 (?:?) kasan_save_track+0x14/0x30 (?:?) kasan_save_free_info+0x3b/0x60 (?:?) __kasan_slab_free+0x5f/0x80 (?:?) kfree+0x30f/0x580 (?:?) dlm_put+0x1ce/0x200 (?:?) dlm_unregister_domain+0xf6/0xb30 (?:?) o2cb_cluster_disconnect+0x6b/0x90 (?:?) ocfs2_cluster_disconnect+0x41/0x70 (?:?) ocfs2_dlm_shutdown+0x1c4/0x220 (?:?) ocfs2_dismount_volume+0x38a/0x550 (?:?) generic_shutdown_super+0xc3/0x220 (?:?) kill_block_super+0x29/0x60 (?:?) deactivate_locked_super+0x66/0xe0 (?:?) cleanup_mnt+0x13d/0x210 (?:?) task_work_run+0xfa/0x170 (?:?) exit_to_user_mode_loop+0xd6/0x430 (?:?) do_syscall_64+0x3cb/0x640 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
--- fs/ocfs2/dlm/dlmdebug.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
fs/ocfs2/dlm/dlmdebug.c +12 -4
@@ -612,6 +612,7 @@ static int debug_lockres_open(struct inode *inode, struct file *file)struct dlm_ctxt *dlm = inode->i_private;struct debug_lockres *dl;void *buf; +int status = -ENOMEM ; buf =kmalloc (PAGE_SIZE ,GFP_KERNEL );if (!buf)
@@ -624,16 +625,23 @@ static int debug_lockres_open(struct inode *inode, struct file *file) dl->dl_len =PAGE_SIZE ; dl->dl_buf = buf; -dlm_grab (dlm); - dl->dl_ctxt = dlm; +/* ->release uses dl_ctxt after open, so it needs a real pin. */ + dl->dl_ctxt =dlm_grab (dlm); +if (!dl->dl_ctxt) { + status = -ENOENT ; + goto bailseq; + }return 0 ; +bailseq: +seq_release_private (inode, file); bailfree:kfree (buf); bail: -mlog_errno (-ENOMEM ); -return -ENOMEM ; +if (status != -ENOENT ) +mlog_errno (status); +return status; }static int debug_lockres_release (struct inode *inode,struct file *file)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 380/1067 ocfs2: fix race between ocfs2_control_install_private() and ocfs2_control_release()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Qi <[email protected]>
[ Upstream commit 57dcfd9049d497c31151787a0696d59f0a98f8e6 ]
Move atomic_inc(&ocfs2_control_opened) and the handshake state update inside ocfs2_control_lock to close a race window where ocfs2_control_release() can observe ocfs2_control_opened dropping to zero (resetting ocfs2_control_this_node and running_proto) while ocfs2_control_install_private() is about to bump the counter and mark the connection valid.
--- fs/ocfs2/stack_user.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
fs/ocfs2/stack_user.c +3 -7
@@ -326,18 +326,14 @@ static int ocfs2_control_install_private(struct file *file) ocfs2_control_this_node = p->op_this_node; running_proto.pv_major = p->op_proto.pv_major; running_proto.pv_minor = p->op_proto.pv_minor; - } - -out_unlock: -mutex_unlock (&ocfs2_control_lock); - -if (!rc && set_p) { -/* We set the global values successfully */ atomic_inc (&ocfs2_control_opened);ocfs2_control_set_handshake_state (file,OCFS2_CONTROL_HANDSHAKE_VALID ); } +out_unlock: +mutex_unlock (&ocfs2_control_lock); +return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 381/1067 netfilter: nfnetlink_osf: fix mss parsing on big-endian architectures
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit a625c94144c9b66d32e1f374f909f38db46161c1 ]
The MSS calculation in nf_osf_match_one() manually shifts bytes to construct a 16-bit value before passing it to ntohs().
This works on little-endian hosts but it does not work on big-endian as the bytes are being always shifted and set in the same way for all architectures.
Use get_unaligned_be16() to fix this on big-endian systems. It also simplifies the code.
--- net/netfilter/nfnetlink_osf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
net/netfilter/nfnetlink_osf.c +1 -5
@@ -95,11 +95,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,switch (*optp) {case OSFOPT_MSS : - mss = optp[3 ]; - mss <<=8 ; - mss |= optp[2 ]; - - mss =ntohs ((__force __be16 )mss); + mss =get_unaligned_be16 (&optp[2 ]);break ;case OSFOPT_TS :break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 382/1067 netfilter: synproxy: protect nf_ct_seqadj_init() with conntrack lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit 9e37388b8070afe73d4ab2d973b28593ed65f3ad ]
nf_ct_seqadj_init() is called without holding the ct lock. This can race with nf_ct_seq_adjust() when a connection is in CLOSE state due to an RST or connection reopening. In addition for SYN_RECV state, concurrent processing of packets can trigger nf_ct_seq_adjust() too. These situations create a read/write data race.
As synproxy is the only user of nf_ct_seqadj_init() at the moment, fix this by holding ct->lock inside nf_ct_seqadj_init() until all is done.
--- net/netfilter/nf_conntrack_seqadj.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nf_conntrack_seqadj.c +2 -0
@@ -17,12 +17,14 @@ int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,if (off ==0 )return 0 ; +spin_lock_bh (&ct->lock);set_bit (IPS_SEQ_ADJUST_BIT , &ct->status); seqadj =nfct_seqadj (ct); this_way = &seqadj->seq[dir]; this_way->offset_before = off; this_way->offset_after = off; +spin_unlock_bh (&ct->lock);return 0 ; }EXPORT_SYMBOL_GPL (nf_ct_seqadj_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 383/1067 netfilter: conntrack: call nf_ct_gre_keymap_destroy() if master helper is pptp
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit b0f02608fbcd607b5131cceb91fc0a035264e61c ]
For GRE flows, validate that the ct master helper (if any) is pptp before calling nf_ct_gre_keymap_destroy(), so the helper data area can be accessed safely. Note that only the pptp helper provides a .destroy callback.
--- net/netfilter/nf_conntrack_core.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
net/netfilter/nf_conntrack_core.c +16 -2
@@ -576,9 +576,23 @@ static void destroy_gre_conntrack(struct nf_conn *ct) {#ifdef CONFIG_NF_CT_PROTO_GRE struct nf_conn *master = ct->master; +struct nf_conn_help *help; + +if (!master) +return ; + + help =nfct_help (master); +if (help) { +struct nf_conntrack_helper *helper; -if (master) -nf_ct_gre_keymap_destroy (master); +rcu_read_lock (); + helper =rcu_dereference (help->helper); +/* Only pptp helper has a destroy callback. */ +if (helper && helper->destroy) +nf_ct_gre_keymap_destroy (master); + +rcu_read_unlock (); + }#endif }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 384/1067 IB/cm: Fix av cm device leak on an error path in cm_init_av_by_path()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 9b2207bc5cdb955bdae34b3eec80f04979e17081 ]
Codex pointed out that cm_init_av_by_path() can call cm_set_av_port() which takes a reference on the cm device, but then can immediately return error if ib_init_ah_attr_from_path() fails.
Since callers like ib_send_cm_req() put the av on the stack this leaks that cm device reference.
Re-order cm_init_av_by_path() so it doesn't touch the av until it has done all its failable work, and then update the av in one shot so it is either left alone or fully init'd.
Sashiko also pointed out that the cm_destroy_av() prior to cm_init_av_by_path() is harmful as it leaves the AV broken in the error case and thus the REJ won't send. Since cm_init_av_by_path() is now atomic it is safe to delete the cm_destroy_av(). On succees the av from cm_init_av_for_response() is cleaned up by cm_init_av_by_path(), on failure the 'goto rejected' guarentees the av is destroyed during ib_destroy_cm_id().
--- drivers/infiniband/core/cm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/infiniband/core/cm.c +8 -5
@@ -514,6 +514,7 @@ static int cm_init_av_by_path(struct sa_path_rec *path,struct rdma_ah_attr new_ah_attr;struct cm_device *cm_dev;struct cm_port *port; +u16 pkey_index;int ret; port =get_cm_port_from_path (path, sgid_attr);
@@ -522,12 +523,10 @@ static int cm_init_av_by_path(struct sa_path_rec *path, cm_dev = port->cm_dev; ret =ib_find_cached_pkey (cm_dev->ib_device, port->port_num, -be16_to_cpu (path->pkey), &av->pkey_index); +be16_to_cpu (path->pkey), &pkey_index);if (ret)return ret; -cm_set_av_port (av, port); -/* * av->ah_attr might be initialized based on wc or during * request processing time which might have reference to sgid_attr.
@@ -542,6 +541,8 @@ static int cm_init_av_by_path(struct sa_path_rec *path,if (ret)return ret; + av->pkey_index = pkey_index; +cm_set_av_port (av, port); av->timeout = path->packet_life_time +1 ;rdma_move_ah_attr (&av->ah_attr, &new_ah_attr);return 0 ;
@@ -2169,8 +2170,10 @@ static int cm_req_handler(struct cm_work *work) cm_id_priv->av.ah_attr.roce.dmac); work->path[0 ].hop_limit = grh->hop_limit; -/* This destroy call is needed to pair with cm_init_av_for_response */ -cm_destroy_av (&cm_id_priv->av); +/* +* cm_init_av_by_path() will internally pair with the above +* cm_init_av_for_response() if it succeeds. +*/ ret =cm_init_av_by_path (&work->path[0 ], gid_attr, &cm_id_priv->av);if (ret) {int err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 385/1067 RDMA/irdma: Fix OOB read during CQ MR registration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 4385ddd654d90245eeb83b3cb539670ab5c85ba4 ]
Sashiko pointed out an unrelated bug during a previous patch:
https://sashiko.dev/#/patchset/20260512183852.614045-1-jmoroni%40google.com
This change fixes the bug by eliminating the cqmr->split field which was not being set properly and instead just checks the CQ resize feature flag directly.
The cqmr->split field essentially tracks whether IRDMA_FEATURE_CQ_RESIZE is set, but it was not being set until CQ creation time, which is _after_ CQ memory registration (the only other place where it is referenced).
As a result, it would always be false during MR registration and would therefore cause irdma_handle_q_mem to populate cqmr->shadow even for GEN_2 HW and beyond:
cqmr->shadow = (dma_addr_t)arr[req->cq_pages];
The issue is that for GEN_2 and beyond, req->cq_pages may be exactly equal to iwmr->page_cnt and therefore equal to the size of arr, which would cause an OOB read by one.
--- drivers/infiniband/hw/irdma/verbs.c | 4 ++-- drivers/infiniband/hw/irdma/verbs.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/infiniband/hw/irdma/verbs.c +2 -2
@@ -2106,7 +2106,6 @@ static int irdma_create_cq(struct ib_cq *ibcq, } cqmr_shadow = &iwpbl_shadow->cq_mr; info.shadow_area_pa = cqmr_shadow->cq_pbl.addr; - cqmr->split = true; }else { info.shadow_area_pa = cqmr->shadow; }
@@ -2480,7 +2479,8 @@ static int irdma_handle_q_mem(struct irdma_device *iwdev,case IRDMA_MEMREG_TYPE_CQ : hmc_p = &cqmr->cq_pbl; -if (!cqmr->split) +if (!(iwdev->rf->sc_dev.hw_attrs.uk_attrs.feature_flags & +IRDMA_FEATURE_CQ_RESIZE )) cqmr->shadow = (dma_addr_t )arr[req->cq_pages];if (use_pbles)
drivers/infiniband/hw/irdma/verbs.h +0 -1
@@ -62,7 +62,6 @@ struct irdma_hmc_pble {struct irdma_cq_mr {struct irdma_hmc_pble cq_pbl;dma_addr_t shadow; -bool split; };struct irdma_qp_mr {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 386/1067 bpf: Check tail zero of bpf_prog_info
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 786be2b05980a5828e67fc564ad7517e2adbe9bd ]
Since there're 4 bytes padding at the end of struct bpf_prog_info, they won't be checked by bpf_check_uarg_tail_zero().
pahole -C bpf_prog_info ./vmlinux
struct bpf_prog_info {
...
__u32 attach_btf_obj_id; /* 220 4 */
__u32 attach_btf_id; /* 224 4 */
/* size: 232, cachelines: 4, members: 38 */
/* sum members: 224 */
/* sum bitfield members: 1 bits, bit holes: 1, sum bit holes: 31 bits */
/* padding: 4 */
/* forced alignments: 9 */
/* last cacheline: 40 bytes */
} __attribute__((__aligned__(8)));If a future kernel extension adds a new 4-byte field, older userspace programs allocating this structure on the stack might inadvertently pass uninitialized stack garbage into the new field, permanently breaking backward compatibility. -- sashiko [1]
Fix it by changing sizeof(info) tooffsetofend(struct bpf_prog_info, attach_btf_id).
And, add "__u32 :32" to the tail of struct bpf_prog_info.
[1] https://lore.kernel.org/bpf/[email protected]/
--- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 5 +++-- tools/include/uapi/linux/bpf.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-)
include/uapi/linux/bpf.h +1 -0
@@ -6239,6 +6239,7 @@ struct bpf_prog_info {__u32 verified_insns;__u32 attach_btf_obj_id;__u32 attach_btf_id; + __u32 :32 ; } __attribute__((aligned(8)));struct bpf_map_info {
kernel/bpf/syscall.c +3 -2
@@ -3966,10 +3966,11 @@ static int bpf_prog_get_info_by_fd(struct file *file,u32 info_len = attr->info.info_len;struct bpf_prog_kstats stats;char __user *uinsns; -u32 ulen; +u32 ulen, len;int err; - err =bpf_check_uarg_tail_zero (USER_BPFPTR (uinfo),sizeof (info), info_len); + len = offsetofend(struct bpf_prog_info, attach_btf_id); + err =bpf_check_uarg_tail_zero (USER_BPFPTR (uinfo), len, info_len);if (err)return err; info_len =min_t (u32,sizeof (info), info_len);
tools/include/uapi/linux/bpf.h +1 -0
@@ -6242,6 +6242,7 @@ struct bpf_prog_info {__u32 verified_insns;__u32 attach_btf_obj_id;__u32 attach_btf_id; + __u32 :32 ; } __attribute__((aligned(8)));struct bpf_map_info {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 387/1067 bpf: Update transport_header when encapsulating UDP tunnel in lwt
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 82d7d0adbc678064543e9d254864f6b4ea4a388c ]
Currently, bpf_lwt_push_ip_encap() does not update skb->transport_header. When a driver, e.g. ice, reuses the stale skb->transport_header to offload checksum computation to NIC hardware, VxLAN packets encapsulated by bpf_lwt_push_encap() helper may be dropped due to incorrect checksum.
Update skb->transport_header in bpf_lwt_push_ip_encap() whenever the encapsulated packet uses UDP, so checksum offload works correctly.
--- net/core/lwt_bpf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
net/core/lwt_bpf.c +12 -0
@@ -590,6 +590,7 @@ static int handle_gso_encap(struct sk_buff *skb, bool ipv4, int encap_len)int bpf_lwt_push_ip_encap (struct sk_buff *skb,void *hdr,u32 len,bool ingress) { +bool is_udp_tunnel;struct iphdr *iph;bool ipv4;int err;
@@ -603,10 +604,16 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress) ipv4 = true;if (unlikely (len < iph->ihl *4 ))return -EINVAL ; + is_udp_tunnel = iph->protocol ==IPPROTO_UDP ; +if (unlikely (is_udp_tunnel && len < iph->ihl *4 +sizeof (struct udphdr ))) +return -EINVAL ; }else if (iph->version ==6 ) { ipv4 = false;if (unlikely (len <sizeof (struct ipv6hdr )))return -EINVAL ; + is_udp_tunnel = ((struct ipv6hdr *)iph)->nexthdr ==NEXTHDR_UDP ; +if (unlikely (is_udp_tunnel && len <sizeof (struct ipv6hdr ) +sizeof (struct udphdr ))) +return -EINVAL ; }else {return -EINVAL ; }
@@ -628,6 +635,11 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress)if (ingress)skb_postpush_rcsum (skb, iph, len);skb_reset_network_header (skb); +if (is_udp_tunnel) { +size_t iph_sz = ipv4 ? iph->ihl *4 :sizeof (struct ipv6hdr ); + +skb_set_transport_header (skb,skb_network_offset (skb) + iph_sz); + }memcpy (skb_network_header (skb), hdr, len);bpf_compute_data_pointers (skb);skb_clear_hash (skb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 388/1067 wifi: wcn36xx: fix heap overflow from oversized firmware HAL response
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 88a240d86d3d64521f9194abe185ac71cc74d0bd ]
The firmware response dispatcher copies all synchronous HAL responses into the 4096-byte hal_buf without validating the response length. A response exceeding WCN36XX_HAL_BUF_SIZE causes a heap buffer overflow with firmware-controlled content.
Add a bounds check on the response length.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +4 -0
@@ -3353,6 +3353,10 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,case WCN36XX_HAL_EXIT_IMPS_RSP :case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP :case WCN36XX_HAL_ADD_BCN_FILTER_RSP : +if (len >WCN36XX_HAL_BUF_SIZE ) { +wcn36xx_warn ("HAL response too large: %d\n" , len); +break ; + }memcpy (wcn->hal_buf, buf, len); wcn->hal_rsp_len = len;complete (&wcn->hal_rsp_compl);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 389/1067 wifi: wcn36xx: fix OOB read from firmware count in PRINT_REG_INFO indication
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit df2187acfca6c6cca372c5d35f42394d9c270b09 ]
The firmware-controlled rsp->count field is used as the loop bound for indexing into the flexible rsp->regs[] array without validation against the message length. A count exceeding the actual data causes out-of- bounds reads from the heap-allocated message buffer.
Add a check that count fits within the received message.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +6 -0
@@ -2865,6 +2865,12 @@ static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,return -EIO ; } +if (rsp->count > (len -sizeof (*rsp)) /sizeof (rsp->regs[0 ])) { +wcn36xx_warn ("Truncated print reg info indication: count %u, len %zu\n" , + rsp->count, len); +return -EIO ; + } +wcn36xx_dbg (WCN36XX_DBG_HAL ,"reginfo indication, scenario: 0x%x reason: 0x%x\n" , rsp->scenario, rsp->reason);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 390/1067 wifi: wcn36xx: fix OOB read from short trigger BA firmware response
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit b5e6f21923ca89d90256e7346301056f6502691e ]
The firmware response length is only checked against sizeof(*rsp) (20 bytes), but when candidate_cnt >= 1, a 22-byte candidate struct is read at buf + 20 without verifying the response contains it. This causes an out-of-bounds read of stale heap data, corrupting the BA session state.
Add validation that the response includes the candidate data.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +3 -0
@@ -2659,6 +2659,9 @@ static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *baif (rsp->candidate_cnt <1 )return rsp->status ? rsp->status : -EINVAL ; +if (len <sizeof (*rsp) +sizeof (*candidate)) +return -EINVAL ; + candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf +sizeof (*rsp));for (i =0 ; i <STACFG_MAX_TC ; i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 391/1067 riscv: stacktrace: Remove bogus -0x4 offset in non-FP walk_stackframe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rui Qi <[email protected]>
[ Upstream commit 8ac35bac70e7e581d673b76878f7691cdadc33b8 ]
In the non-frame-pointer version of walk_stackframe, each value read from the stack is treated as a potential return address and has 0x4 subtracted before being used as the program counter. This was intended to convert the return address (the instruction after a call) back to the call site, but it is incorrect:
1. RISC-V has variable-length instructions due to the RVC (compressed instruction) extension. A call instruction can be either 4 bytes (regular) or 2 bytes (compressed, e.g. c.jal). Subtracting a fixed 0x4 assumes all call instructions are 4 bytes, which is wrong for compressed instructions.
2. Stack traces conventionally report return addresses, not call sites. Other architectures (ARM64, x86, ARM) do not subtract instruction size from return addresses in their stack unwinding code.
3. The frame-pointer version of walk_stackframe already dropped the -0x4 offset. Commit b785ec129bd9 ("riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support") replaced "pc = frame->ra - 0x4" with ftrace_graph_ret_addr(), and the commit message explicitly noted that "the original calculation, pc = frame->ra - 4, is buggy when the instruction at the return address happened to be a compressed inst." The non-FP version was simply overlooked.
Remove the bogus -0x4 offset to match the FP version and the conventions used by other architectures.
--- arch/riscv/kernel/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/kernel/stacktrace.c +1 -1
@@ -127,7 +127,7 @@ void notrace walk_stackframe(struct task_struct *task,while (!kstack_end (ksp)) {if (__kernel_text_address (pc) &&unlikely (!fn (arg, pc)))break ; - pc =READ_ONCE_NOCHECK (*ksp++) -0x4 ; + pc =READ_ONCE_NOCHECK (*ksp++); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 392/1067 ALSA: seq: Introduce SNDRV_SEQ_IOCTL_USER_PVERSION ioctl
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit afb72505e4614a2ccefe3440d37dec3a2273c330 ]
For the future extension of ALSA sequencer ABI, introduce a new ioctl SNDRV_SEQ_IOCTL_USER_PVERSION. This is similar like the ioctls used in PCM and other interfaces, for an application to specify its supporting ABI version.
The use of this ioctl will be mandatory for the upcoming UMP support.
Stable-dep-of: 705dd6dcbc0e ("ALSA: seq: Clear variable event pointer on read")
--- include/uapi/sound/asequencer.h | 1 + sound/core/seq/seq_clientmgr.c | 8 ++++++++ sound/core/seq/seq_clientmgr.h | 1 + sound/core/seq/seq_compat.c | 1 + 4 files changed, 11 insertions(+)
include/uapi/sound/asequencer.h +1 -0
@@ -561,6 +561,7 @@ struct snd_seq_query_subs {#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int)#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct snd_seq_system_info)#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct snd_seq_running_info) +#define SNDRV_SEQ_IOCTL_USER_PVERSION _IOW('S', 0x04, int)#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct snd_seq_client_info)#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct snd_seq_client_info)
sound/core/seq/seq_clientmgr.c +8 -0
@@ -1158,6 +1158,12 @@ static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg)return 0 ; } +static int snd_seq_ioctl_user_pversion (struct snd_seq_client *client,void *arg) +{ + client->user_pversion = *(unsigned int *)arg; +return 0 ; +} +static int snd_seq_ioctl_client_id (struct snd_seq_client *client,void *arg) {int *client_id = arg;
@@ -2085,6 +2091,7 @@ static const struct ioctl_handler {int (*func)(struct snd_seq_client *client,void *arg); } ioctl_handlers[] = { { SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion }, + { SNDRV_SEQ_IOCTL_USER_PVERSION, snd_seq_ioctl_user_pversion }, { SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id }, { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },
@@ -2225,6 +2232,7 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, client->accept_input =1 ; client->accept_output =1 ; client->data.kernel.card = card; + client->user_pversion =SNDRV_SEQ_VERSION ;va_start (args, name_fmt);vsnprintf (client->name,sizeof (client->name), name_fmt, args);
sound/core/seq/seq_clientmgr.h +1 -0
@@ -35,6 +35,7 @@ struct snd_seq_client {snd_seq_client_type_t type; unsigned int accept_input: 1, accept_output: 1; +unsigned int user_pversion;char name[64 ];/* client name */ int number;/* client number */ unsigned int filter;/* filter flags */
sound/core/seq/seq_compat.c +1 -0
@@ -81,6 +81,7 @@ static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned lswitch (cmd) {case SNDRV_SEQ_IOCTL_PVERSION : +case SNDRV_SEQ_IOCTL_USER_PVERSION :case SNDRV_SEQ_IOCTL_CLIENT_ID :case SNDRV_SEQ_IOCTL_SYSTEM_INFO :case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 393/1067 ALSA: seq: Add UMP support
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 46397622a3fa8372b8fda0f04b33d16923b03b1b ]
Starting from this commit, we add the basic support of UMP (Universal MIDI Packet) events on ALSA sequencer infrastructure. The biggest change here is that, for transferring UMP packets that are up to 128 bits, we extend the data payload of ALSA sequencer event record when the client is declared to support for the new UMP events.
A new event flag bit, SNDRV_SEQ_EVENT_UMP, is defined and it shall be set for the UMP packet events that have the larger payload of 128 bits, defined as struct snd_seq_ump_event.
For controlling the UMP feature enablement in kernel, a new Kconfig, CONFIG_SND_SEQ_UMP is introduced. The extended event for UMP is available only when this Kconfig item is set. Similarly, the size of the internal snd_seq_event_cell also increases (in 4 bytes) when the Kconfig item is set. (But the size increase is effective only for 32bit architectures; 64bit archs already have padding there.) Overall, when CONFIG_SND_SEQ_UMP isn't set, there is no change in the event and cell, keeping the old sizes.
For applications that want to access the UMP packets, first of all, a sequencer client has to declare the user-protocol to match with the latest one via the new SNDRV_SEQ_IOCTL_USER_PVERSION; otherwise it's treated as if a legacy client without UMP support.
Then the client can switch to the new UMP mode (MIDI 1.0 or MIDI 2.0) with a new field, midi_version, in snd_seq_client_info. When switched to UMP mode (midi_version = 1 or 2), the client can write the UMP events with SNDRV_SEQ_EVENT_UMP flag. For reads, the alignment size is changed from snd_seq_event (28 bytes) to snd_seq_ump_event (32 bytes). When a UMP sequencer event is delivered to a legacy sequencer client, it's ignored or handled as an error.
Conceptually, ALSA sequencer client and port correspond to the UMP Endpoint and Group, respectively; each client may have multiple ports and each port has the fixed number (16) of channels, total up to 256 channels.
As of this commit, ALSA sequencer core just sends and receives the UMP events as-is from/to clients. The automatic conversions between the legacy events and the new UMP events will be implemented in a later patch.
Along with this commit, bump the sequencer protocol version to 1.0.3.
Stable-dep-of: 705dd6dcbc0e ("ALSA: seq: Clear variable event pointer on read")
--- include/sound/asequencer.h | 4 + include/sound/seq_kernel.h | 8 ++ include/uapi/sound/asequencer.h | 53 +++++++---- sound/core/seq/Kconfig | 7 ++ sound/core/seq/seq_clientmgr.c | 154 +++++++++++++++++++++++--------- sound/core/seq/seq_clientmgr.h | 1 + sound/core/seq/seq_memory.c | 10 ++- sound/core/seq/seq_memory.h | 19 +++- 8 files changed, 193 insertions(+), 63 deletions(-)
include/sound/asequencer.h +4 -0
@@ -65,6 +65,10 @@#define snd_seq_ev_is_abstime (ev) (snd_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_ABS)#define snd_seq_ev_is_reltime (ev) (snd_seq_ev_timemode_type(ev) == SNDRV_SEQ_TIME_MODE_REL) +/* check whether the given event is a UMP event */ +#define snd_seq_ev_is_ump (ev) \ + (IS_ENABLED(CONFIG_SND_SEQ_UMP) && ((ev)->flags & SNDRV_SEQ_EVENT_UMP)) +/* queue sync port */ #define snd_seq_queue_sync_port (q) ((q) + 16)
include/sound/seq_kernel.h +8 -0
@@ -73,6 +73,14 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, charint snd_seq_dump_var_event (const struct snd_seq_event *event,snd_seq_dump_func_t func,void *private_data); +/* size of the event packet; it can be greater than snd_seq_event size */ +static inline size_t snd_seq_event_packet_size (struct snd_seq_event *ev) +{ +if (snd_seq_ev_is_ump (ev)) +return sizeof (struct snd_seq_ump_event ); +return sizeof (struct snd_seq_event ); +} +/* interface for OSS emulation */ int snd_seq_set_queue_tempo (int client,struct snd_seq_queue_tempo *tempo);
include/uapi/sound/asequencer.h +37 -16
90 lines not on this page · raw message
sound/core/seq/Kconfig +7 -0
@@ -60,4 +60,11 @@ config SND_SEQ_MIDI_EMUL config SND_SEQ_VIRMIDI tristate +config SND_SEQ_UMP + bool "Support for UMP events" + help + Say Y here to enable the support for handling UMP (Universal MIDI + Packet) events via ALSA sequencer infrastructure, which is an + essential feature for enabling MIDI 2.0 support. + endif # SND_SEQUENCER
sound/core/seq/seq_clientmgr.c +110 -44
314 lines not on this page · raw message
sound/core/seq/seq_clientmgr.h +1 -0
@@ -35,6 +35,7 @@ struct snd_seq_client {snd_seq_client_type_t type; unsigned int accept_input: 1, accept_output: 1; +unsigned int midi_version;unsigned int user_pversion;char name[64 ];/* client name */ int number;/* client number */
sound/core/seq/seq_memory.c +8 -2
@@ -288,6 +288,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,int ncells, err;unsigned int extlen;struct snd_seq_event_cell *cell; +int size; *cellp =NULL ;
@@ -305,7 +306,12 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,return err;/* copy the event */ - cell->event = *event; + size =snd_seq_event_packet_size (event); +memcpy (&cell->ump, event, size); +#if IS_ENABLED (CONFIG_SND_SEQ_UMP ) +if (size <sizeof (cell->event)) + cell->ump.raw.extra =0 ; +#endif /* decompose */ if (snd_seq_ev_is_variable (event)) {
@@ -323,7 +329,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, tail =NULL ;while (ncells-- >0 ) { -int size =sizeof (struct snd_seq_event ); + size =sizeof (struct snd_seq_event );if (len < size) size = len; err = snd_seq_cell_alloc(pool, &tmp, nonblock, file,
sound/core/seq/seq_memory.h +18 -1
@@ -11,9 +11,26 @@struct snd_info_buffer ; +/* aliasing for legacy and UMP event packet handling */ +union __snd_seq_event { +struct snd_seq_event legacy; +#if IS_ENABLED (CONFIG_SND_SEQ_UMP ) +struct snd_seq_ump_event ump; +#endif +struct { +struct snd_seq_event event; +#if IS_ENABLED (CONFIG_SND_SEQ_UMP ) +u32 extra; +#endif + } __packed raw; +}; +/* container for sequencer event (internal use) */ struct snd_seq_event_cell { -struct snd_seq_event event; +union { +struct snd_seq_event event; +union __snd_seq_event ump; + };struct snd_seq_pool *pool;/* used pool */ struct snd_seq_event_cell *next;/* next cell */ };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 394/1067 ALSA: seq: Clear variable event pointer on read
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit 705dd6dcbc0ea87351c660c1a6443f85f1001c76 ]
snd_seq_read() copies a queued variable-length event header to userspace before expanding the payload. Queued variable-length events use SNDRV_SEQ_EXT_CHAINED internally, and data.ext.ptr points at the first extension cell.
The read side strips SNDRV_SEQ_EXT_* bits from data.ext.len before the copy, but it leaves data.ext.ptr untouched. A userspace sequencer client can therefore write a direct variable event to itself and read back the extension-cell kernel address from the returned header.
Clear the temporary header pointer before copy_to_user(). The original queued event remains unchanged and is still passed to snd_seq_expand_var_event(), so payload expansion keeps using the internal chain.
--- sound/core/seq/seq_clientmgr.c | 1 + 1 file changed, 1 insertion(+)
sound/core/seq/seq_clientmgr.c +1 -0
@@ -464,6 +464,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,memcpy (&tmpev, &cell->event, aligned_size); tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK ; + tmpev.data.ext.ptr =NULL ;if (copy_to_user (buf, &tmpev, aligned_size)) { err = -EFAULT ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 395/1067 ACPI: IPMI: Fix message kref handling on dead device
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 63320db6a5d84ec3fed8b3d36ba5244d07ddd108 ]
acpi_ipmi_space_handler() takes an extra reference on tx_msg before checking whether the selected IPMI device is dead. The reference belongs to the tx_msg_list entry and is normally dropped by ipmi_cancel_tx_msg() or ipmi_flush_tx_msg() after the message is removed from the list.
On the dead-device path, the message has not been queued yet, but the error path still calls ipmi_msg_release() directly. That bypasses kref_put() and frees tx_msg while the queued-message reference is still recorded in the kref count.
Take the queued-message reference only after the dead-device check succeeds, immediately before adding tx_msg to the list.
--- drivers/acpi/acpi_ipmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/acpi_ipmi.c +1 -1
@@ -545,7 +545,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,return AE_TYPE ; } -acpi_ipmi_msg_get (tx_msg);mutex_lock (&driver_data.ipmi_lock);/* Do not add a tx_msg that can not be flushed. */ if (ipmi_device->dead) {
@@ -553,6 +552,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,ipmi_msg_release (tx_msg);return AE_NOT_EXIST ; } +acpi_ipmi_msg_get (tx_msg);spin_lock_irqsave (&ipmi_device->tx_msg_lock, flags);list_add_tail (&tx_msg->head, &ipmi_device->tx_msg_list);spin_unlock_irqrestore (&ipmi_device->tx_msg_lock, flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 396/1067 cpufreq: Documentation: fix conservative governor freq_step description
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengjie Zhang <[email protected]>
[ Upstream commit 03120e1425262c7d11f93362a88e579a1720390b ]
The conservative governor documentation incorrectly states that setting freq_step to 0 will use the default 5% frequency step. In reality, since at least commit 8e677ce83bf4 ("[CPUFREQ] conservative: fixup governor to function more like ondemand logic"), freq_step=0 has always caused the governor to skip frequency updates entirely.
Correct the documentation to reflect the actual behavior: freq_step=0 disables frequency changes by the governor entirely.
--- Documentation/admin-guide/pm/cpufreq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/admin-guide/pm/cpufreq.rst +2 -2
@@ -569,8 +569,8 @@ This governor exposes the following tunables: 100 (5 by default). This is how much the frequency is allowed to change in one go. Setting - it to 0 will cause the default frequency step (5 percent) to be used - and setting it to 100 effectively causes the governor to periodically + it to 0 disables frequency changes by the governor entirely and setting + it to 100 effectively causes the governor to periodically switch the frequency between the ``scaling_min_freq`` and ``scaling_max_freq`` policy limits.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 397/1067 IB/mlx5: Dont take the rereg_mr fallback without a new translation
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 55d339d200c908de83a408d023cfb7be779b0dd7 ]
Jumping to mlx5_ib_reg_user_mr() without IB_MR_REREG_TRANS set will use garbage values for start, length, and iova. Recovering the original mr parameters for ODP and DMABUF to properly recreate it is too hard in this flow, so just fail it.
--- drivers/infiniband/hw/mlx5/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/mr.c +1 -1
@@ -1463,7 +1463,7 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, }/* DM or ODP MR's don't have a normal umem so we can't re-use it */ if (!mr->umem ||is_odp_mr (mr) ||is_dmabuf_mr (mr)) - goto recreate; +return ERR_PTR (-EOPNOTSUPP );/* * Only one active MR can refer to a umem at one time, revoke
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 398/1067 IB/mlx5: Properly support implicit ODP rereg_mr
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit ee7a8335069150c3f1893a697ab30bbeca00d796 ]
Due to all the child mkeys in the implicit ODP configuration we cannot change anything in place for the parent mkey. Instead the whole thing needs to be rebuilt if any change is requested. If the user does not specify a translation then force the implicit values which will then fall through the logic into mlx5_ib_reg_user_mr() to allocate a completely new MR.
Since implicit children were also touching the mr->pd, this removes another case where the access was racy.
--- drivers/infiniband/hw/mlx5/mr.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/infiniband/hw/mlx5/mr.c +15 -0
@@ -1449,6 +1449,21 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,if (!(flags &IB_MR_REREG_PD )) new_pd = ib_mr->pd; +if (mr->is_odp_implicit && !(flags &IB_MR_REREG_TRANS )) { +if (!(new_access_flags &IB_ACCESS_ON_DEMAND )) +return ERR_PTR (-EOPNOTSUPP ); + +/* +* Due to all the child mkeys we cannot actually change an +* implicit MR in place. If the user did not specify a new +* translation then force the fixed implicit MR values. +*/ + start =0 ; + iova =0 ; + length =U64_MAX ; + flags |=IB_MR_REREG_TRANS ; + } +if (!(flags &IB_MR_REREG_TRANS )) {struct ib_umem *umem;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 399/1067 spi: ep93xx: fix double-free of zeropage on DMA setup failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 7886054b06f762f62054957a8f6de0f14e6b7541 ]
If DMA setup fails after allocating the zeropage, the error path frees the page but leaves espi->zeropage dangling. A subsequent call to ep93xx_spi_release_dma() sees the non-NULL pointer and frees the page again.
Clear the pointer after freeing in the error path of ep93xx_spi_setup_dma().
--- drivers/spi/spi-ep93xx.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-ep93xx.c +1 -0
@@ -625,6 +625,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) espi->dma_rx =NULL ; fail_free_page:free_page ((unsigned long )espi->zeropage); + espi->zeropage =NULL ;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 400/1067 firmware_loader: Fix recursive lock in device_cache_fw_images()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Vyukov <[email protected]>
[ Upstream commit d3ec78f8f8d48a04a9fac38d47275c34645e5103 ]
A recursive locking deadlock can occur in the firmware loader's power management notification handler.
During system suspend or hibernation preparation, fw_pm_notify() calls device_cache_fw_images(). This function acquires fw_lock to set the firmware cache state to FW_LOADER_START_CACHE and then iterates over all devices using dpm_for_each_dev() while still holding the lock.
For each device, dev_cache_fw_image() schedules asynchronous work to cache the firmware. If memory allocation for the async work entry fails (e.g., in out-of-memory conditions), async_schedule_node_domain() falls back to executing the work function synchronously in the current thread.
The synchronous execution path (__async_dev_cache_fw_image() -> cache_firmware() -> request_firmware() -> assign_fw()) attempts to acquire fw_lock again. Since the current thread already holds fw_lock, this results in a recursive locking deadlock.
Fix this by releasing fw_lock immediately after updating the cache state and before calling dpm_for_each_dev(). The lock is only needed to protect the state update. Concurrent firmware requests will correctly see the FW_LOADER_START_CACHE state and use the piggyback mechanism, which is independently protected by its own fwc->name_lock.
--- drivers/base/firmware_loader/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/base/firmware_loader/main.c +2 -1
@@ -1452,9 +1452,10 @@ static void device_cache_fw_images(void)mutex_lock (&fw_lock); fwc->state =FW_LOADER_START_CACHE ; -dpm_for_each_dev (NULL , dev_cache_fw_image);mutex_unlock (&fw_lock); +dpm_for_each_dev (NULL , dev_cache_fw_image); +/* wait for completion of caching firmware for all devices */ async_synchronize_full_domain (&fw_cache_domain);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 401/1067 configfs: fix lockless traversals of ->s_children
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 9b9e8bb81c41fd27e7b57a1c936fde140548535f ]
Having the parent directory locked protects entries from removal by another thread, but it does *not* protect cursors from being moved around by lseek() - or freed, for that matter.
--- fs/configfs/dir.c | 54 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 13 deletions(-)
fs/configfs/dir.c +41 -13
@@ -225,15 +225,16 @@ static int configfs_dirent_exists(struct configfs_dirent *parent_sd, {struct configfs_dirent * sd; +spin_lock (&configfs_dirent_lock);list_for_each_entry (sd, &parent_sd->s_children, s_sibling) {if (sd->s_element) { -const unsigned char *existing =configfs_get_name (sd); -if (strcmp (existing, new)) -continue ; -else +if (strcmp (configfs_get_name (sd), new) ==0 ) { +spin_unlock (&configfs_dirent_lock);return -EEXIST ; + } } } +spin_unlock (&configfs_dirent_lock);return 0 ; }
@@ -551,11 +552,28 @@ static void configfs_detach_rollback(struct dentry *dentry)configfs_detach_rollback (sd->s_dentry); } +/* +* Find the next non-cursor. configfs_dirent_lock held by caller. +*/ +static struct configfs_dirent *next_dirent (struct configfs_dirent *parent, +struct configfs_dirent *last) +{ +struct configfs_dirent *s; + + s =list_prepare_entry (last, &parent->s_children, s_sibling); + +list_for_each_entry_continue (s, &parent->s_children, s_sibling) { +if (s->s_element) +return s; + } +return NULL ; +} +static void detach_attrs (struct config_item * item) {struct dentry * dentry =dget (item->ci_dentry); -struct configfs_dirent * parent_sd; -struct configfs_dirent * sd, * tmp; +struct configfs_dirent *parent_sd; +struct configfs_dirent *sd, *next;if (!dentry)return ;
@@ -564,15 +582,19 @@ static void detach_attrs(struct config_item * item) dentry->d_name.name); parent_sd = dentry->d_fsdata; -list_for_each_entry_safe (sd, tmp, &parent_sd->s_children, s_sibling) { -if (!sd->s_element || !(sd->s_type &CONFIGFS_NOT_PINNED )) + +spin_lock (&configfs_dirent_lock); +for (sd =next_dirent (parent_sd,NULL ); sd; sd = next) { + next =next_dirent (parent_sd, sd); +if (!(sd->s_type &CONFIGFS_NOT_PINNED ))continue ; -spin_lock (&configfs_dirent_lock);list_del_init (&sd->s_sibling);spin_unlock (&configfs_dirent_lock);configfs_drop_dentry (sd, dentry);configfs_put (sd); +spin_lock (&configfs_dirent_lock); } +spin_unlock (&configfs_dirent_lock);/** * Drop reference from dget() on entrance.
@@ -621,18 +643,20 @@ static void detach_groups(struct config_group *group)struct dentry * dentry =dget (group->cg_item.ci_dentry);struct dentry *child;struct configfs_dirent *parent_sd; -struct configfs_dirent *sd, *tmp; +struct configfs_dirent *sd, *next;if (!dentry)return ; parent_sd = dentry->d_fsdata; -list_for_each_entry_safe (sd, tmp, &parent_sd->s_children, s_sibling) { -if (!sd->s_element || - !(sd->s_type &CONFIGFS_USET_DEFAULT )) +spin_lock (&configfs_dirent_lock); +for (sd =next_dirent (parent_sd,NULL ); sd; sd = next) { + next =next_dirent (parent_sd, sd); +if (!(sd->s_type &CONFIGFS_USET_DEFAULT ))continue ; child = sd->s_dentry; +spin_unlock (&configfs_dirent_lock);inode_lock (d_inode (child));
@@ -644,7 +668,9 @@ static void detach_groups(struct config_group *group)d_delete (child);dput (child); +spin_lock (&configfs_dirent_lock); } +spin_unlock (&configfs_dirent_lock);/** * Drop reference from dget() on entrance.
@@ -1096,6 +1122,7 @@ configfs_find_subsys_dentry(struct configfs_dirent *root_sd,struct configfs_dirent *p;struct configfs_dirent *ret =NULL ; +spin_lock (&configfs_dirent_lock);list_for_each_entry (p, &root_sd->s_children, s_sibling) {if (p->s_type &CONFIGFS_DIR && p->s_element == subsys_item) {
@@ -1103,6 +1130,7 @@ configfs_find_subsys_dentry(struct configfs_dirent *root_sd,break ; } } +spin_unlock (&configfs_dirent_lock);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 402/1067 watchdog: unregister PM notifier on watchdog unregister
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit a298c7302ee9584a7a1ac1e8acbede8d98ab51a4 ]
watchdog_register_device() registers wdd->pm_nb when WDOG_NO_PING_ON_SUSPEND is set, but watchdog_unregister_device() does not remove it. This leaves an embedded notifier block on the PM notifier chain after the watchdog device has been unregistered.
A later suspend/resume notification can then call watchdog_pm_notifier() with a stale watchdog_device pointer, or at minimum after wdd->wd_data has been cleared by watchdog_dev_unregister().
Unregister the PM notifier before tearing down the watchdog device.
--- drivers/watchdog/watchdog_core.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/watchdog/watchdog_core.c +3 -0
@@ -381,6 +381,9 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status))unregister_reboot_notifier (&wdd->reboot_nb); +if (test_bit (WDOG_NO_PING_ON_SUSPEND , &wdd->status)) +unregister_pm_notifier (&wdd->pm_nb); +watchdog_dev_unregister (wdd);ida_simple_remove (&watchdog_ida, wdd->id); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 403/1067 scsi: target: Fix hexadecimal CHAP_I handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Disseldorp <[email protected]>
[ Upstream commit 7e161211f1dd5288b4ea802b30e70ef919ebc3da ]
A mutual CHAP handshake requires target processing of an initiator-sent CHAP_I identifier. The RFC 3720 specification states:
11.1.4. Challenge Handshake Authentication Protocol (CHAP)
...
CHAP_A=<A> CHAP_I=<I> CHAP_C=<C>
...
Where N, (A,A1,A2), I, C, and R are (correspondingly) the Name, Algorithm, Identifier, Challenge, and Response as defined in [RFC1994], N is a text string, A,A1,A2, and I are numbers
CHAP_I parsing currently calls extract_param(), which returns the @identifier string (stripped of any 0b/0B or 0x/0X prefix) and a @type which indicates DECIMAL, HEX, or BASE64 encoding (based on any stripped prefix).
Any HEX encoded CHAP_I string is further processed via:
ret = kstrtoul(&identifier[2], 0, &id);
This is incorrect for two reasons:
* The @identifier string has already been stripped of the 0x/0X prefix, so skipping the first two bytes omits part of the number.
* The kstrtoul() call specifies a base of 0, which will see &identifier[2] parsed as a decimal, unless a '0x' or (octal) '0' is erroneously present at that offset.
Fix this by passing the (zero-offset) identifier string to kstrtoul() along with a base=16 parameter. Also add an explicit error handler for BASE64 encoding.
Hex-encoded CHAP_I handling can be testing using the libiscsi EncodedI test linked below.
--- drivers/target/iscsi/iscsi_target_auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/target/iscsi/iscsi_target_auth.c +4 -2
@@ -437,9 +437,11 @@ static int chap_server_compute_hash( }if (type ==HEX ) - ret =kstrtoul (&identifier[2 ],0 , &id); + ret =kstrtoul (identifier,16 , &id); +else if (type ==DECIMAL ) + ret =kstrtoul (identifier,10 , &id);else - ret =kstrtoul (identifier,0 , &id); + ret = -EINVAL ;if (ret <0 ) {pr_err ("kstrtoul() failed for CHAP identifier: %d\n" , ret);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 404/1067 pinctrl: mediatek: mt8516: Fix Schmitt trigger register offset of pins 34-39
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Leonardo Scorcia <[email protected]>
[ Upstream commit 1c3044cab23a056ea28da47da1cdd667a39df0b8 ]
The correct Schmitt trigger register offset for pins 34-39 is 0xA00.
--- drivers/pinctrl/mediatek/pinctrl-mt8516.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-mt8516.c +1 -1
@@ -245,7 +245,7 @@ static const struct mtk_pin_ies_smt_set mt8516_smt_set[] = {MTK_PIN_IES_SMT_SPEC (24 ,25 ,0xA00 ,12 ),MTK_PIN_IES_SMT_SPEC (26 ,30 ,0xA00 ,0 ),MTK_PIN_IES_SMT_SPEC (31 ,33 ,0xA00 ,1 ), -MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA900 ,2 ), +MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA00 ,2 ),MTK_PIN_IES_SMT_SPEC (40 ,40 ,0xA10 ,11 ),MTK_PIN_IES_SMT_SPEC (41 ,43 ,0xA00 ,10 ), MTK_PIN_IES_SMT_SPEC(44, 47, 0xA00, 11),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 405/1067 pinctrl: mediatek: mt8167: Fix Schmitt trigger register offset of pins 34-39
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Leonardo Scorcia <[email protected]>
[ Upstream commit 439bc91d20188901dac698bed4921caac76d9074 ]
The correct Schmitt trigger register offset for pins 34-39 is 0xA00. Value was verified with SoC data sheet.
--- drivers/pinctrl/mediatek/pinctrl-mt8167.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-mt8167.c +1 -1
@@ -245,7 +245,7 @@ static const struct mtk_pin_ies_smt_set mt8167_smt_set[] = {MTK_PIN_IES_SMT_SPEC (24 ,25 ,0xA00 ,12 ),MTK_PIN_IES_SMT_SPEC (26 ,30 ,0xA00 ,0 ),MTK_PIN_IES_SMT_SPEC (31 ,33 ,0xA00 ,1 ), -MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA900 ,2 ), +MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA00 ,2 ),MTK_PIN_IES_SMT_SPEC (40 ,40 ,0xA10 ,11 ),MTK_PIN_IES_SMT_SPEC (41 ,43 ,0xA00 ,10 ), MTK_PIN_IES_SMT_SPEC(44, 47, 0xA00, 11),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 406/1067 vmalloc: fix NULL pointer dereference in is_vm_area_hugepages()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Zhu <[email protected]>
[ Upstream commit c55dd3b46c1208d6d2ea737a8aefef4aa4c70cb8 ]
find_vm_area() can return NULL if the given address is not a valid vmalloc area. Check the return value before dereferencing it to avoid a kernel crash.
--- include/linux/vmalloc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
include/linux/vmalloc.h +3 -1
@@ -211,7 +211,9 @@ static inline bool is_vm_area_hugepages(const void *addr)* allocated in the vmalloc layer. */ #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC -return find_vm_area (addr)->page_order >0 ; +struct vm_struct *area =find_vm_area (addr); + +return area && area->page_order >0 ;#else return false;#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 407/1067 hwspinlock: qcom: avoid uninitialized struct members
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 8752c396ce3b2136b3d4c906fe103f6efb6782d9 ]
The reg_field is allocated on stack, so using the REG_FIELD macro will ensure that unused members do not have uninitialized values.
--- drivers/hwspinlock/qcom_hwspinlock.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/hwspinlock/qcom_hwspinlock.c +1 -4
@@ -178,7 +178,6 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev,static int qcom_hwspinlock_probe (struct platform_device *pdev) {struct hwspinlock_device *bank; -struct reg_field field;struct regmap *regmap;size_t array_size;u32 stride;
@@ -200,9 +199,7 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev)platform_set_drvdata (pdev, bank);for (i =0 ; i <QCOM_MUTEX_NUM_LOCKS ; i++) { - field.reg = base + i * stride; - field.lsb =0 ; - field.msb =31 ; +struct reg_field field =REG_FIELD (base + i * stride,0 ,31 ); bank->lock[i].priv =devm_regmap_field_alloc (&pdev->dev, regmap, field);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 408/1067 wifi: mt76: fix argument to ieee80211_is_first_frag()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjoern A. Zeeb <[email protected]>
[ Upstream commit 5832743279da8c6ae72f715bad2f7141eca6f4b8 ]
ieee80211_is_first_frag() operates on the seq_ctrl not the frame_control header field. Pass the correct one in; otherwise the results may vary.
Sponsored by: The FreeBSD Foundation
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +1 -1
@@ -1060,7 +1060,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)* All further fragments will be validated by mac80211 only. */ if (ieee80211_is_frag (hdr) && - !ieee80211_is_first_frag (hdr->frame_control)) + !ieee80211_is_first_frag (hdr->seq_ctrl))return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 409/1067 btrfs: fix invalid pointer dereference in __btrfs_run_delayed_refs()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 486f8298b6188ff11ef1f4be7f1d5d2e4d1b1fae ]
In the beginning of the loop, we try to obtain a locked delayed ref head, if 'locked_ref' is currently NULL, by calling btrfs_select_ref_head(), which can return an error pointer. If the error pointer is -EAGAIN we do a continue and go back to the beginning of the loop, which will not try again to call btrfs_select_ref_head() since 'locked_ref' is no longer NULL but it's ERR_PTR(-EAGAIN), and then we do:
spin_lock(&locked_ref->lock);
against a ERR_PTR(-EAGAIN) value, generating an invalid pointer dereference.
Fix this by ensuring that 'locked_ref' is set to NULL when btrfs_select_ref_head() returns ERR_PTR(-EAGAIN) and incrementing 'count' as well, to prevent infinite looping. We do this by doing a goto to the bottom of the loop that already sets 'locked_ref' to NULL and does a cond_resched(), with an increment to 'count' right before the goto. These measures were in place before the refactoring in commit 0110a4c43451 ("btrfs: refactor __btrfs_run_delayed_refs loop") but were unintentionally lost afterwards.
--- fs/btrfs/extent-tree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/btrfs/extent-tree.c +3 -2
@@ -2007,7 +2007,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, locked_ref =btrfs_obtain_ref_head (trans);if (IS_ERR_OR_NULL (locked_ref)) {if (PTR_ERR (locked_ref) == -EAGAIN ) { -continue ; + count++; + goto again; }else {break ; }
@@ -2056,7 +2057,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,* Either success case or btrfs_run_delayed_refs_for_head * returned -EAGAIN, meaning we need to select another head */ - +again: locked_ref =NULL ;cond_resched (); }while ((nr !=-1 && count < nr) || locked_ref);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 410/1067 fbdev: sm501fb: Fix buffer errors in OF binding code
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit d8421e09382cfe0bd2a044c8b0a822f64855dd4e ]
The code that gets the frame buffer mode from OF has 'use after free', 'buffer overrun' and memory leaks.
info->edid_data isn't free if the probe functions fail or if pd->def_mode is set.
If both the CRT and PANEL are enabled info->edid_data is used after being freed and is freed twice.
The string returned by of_get_property(np, "mode", &len) is just written over either the static "640x480-16@60" or the module parameter string without any regard for the length (which is most likely longer).
Use kstrump() for the OF mode and free everything before freeing 'info.
--- drivers/video/fbdev/sm501fb.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/video/fbdev/sm501fb.c +12 -4
@@ -95,6 +95,7 @@ struct sm501fb_info {void __iomem *fbmem;/* remapped framebuffer */ size_t fbmem_len;/* length of remapped region */ u8 *edid_data; +char *fb_mode; };/* per-framebuffer private data */
@@ -1788,12 +1789,11 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, fb->var.yres_virtual = fb->var.yres; }else {if (info->edid_data) { - ret =fb_find_mode (&fb->var, fb, fb_mode, + ret =fb_find_mode (&fb->var, fb, + info->fb_mode ?: fb_mode, fb->monspecs.modedb, fb->monspecs.modedb_len, &sm501_default_mode, default_bpp); -/* edid_data is no longer needed, free it */ -kfree (info->edid_data); }else { ret =fb_find_mode (&fb->var, fb,NULL ,NULL ,0 ,NULL ,8 );
@@ -1969,7 +1969,7 @@ static int sm501fb_probe(struct platform_device *pdev)/* Get EDID */ cp =of_get_property (np,"mode" , &len);if (cp) -strcpy (fb_mode, cp); + info->fb_mode =kstrdup (cp,GFP_KERNEL ); prop =of_get_property (np,"edid" , &len);if (prop && len ==EDID_LENGTH ) { info->edid_data = kmemdup(prop, EDID_LENGTH,
@@ -2026,6 +2026,12 @@ static int sm501fb_probe(struct platform_device *pdev) goto err_started_crt; } +/* These aren't needed any more */ +kfree (info->edid_data); +kfree (info->fb_mode); + info->edid_data =NULL ; + info->fb_mode =NULL ; +/* we registered, return ok */ return 0 ;
@@ -2043,6 +2049,8 @@ static int sm501fb_probe(struct platform_device *pdev)framebuffer_release (info->fb[HEAD_CRT ]); err_alloc: +kfree (info->edid_data); +kfree (info->fb_mode);kfree (info);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 411/1067 btrfs: zoned: dont account data relocation space-info in statfs free space
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn <[email protected]>
[ Upstream commit 52416a27aabc43eab3792fd0ca9f5dabeab58f31 ]
Don't account the free space in a data relocation space-info sub-group as usable free space in statfs.
This is misleading as no user allocations can be made in this space-info sub-group. It is only a target for relocation.
--- fs/btrfs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/btrfs/super.c +2 -1
@@ -2350,7 +2350,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)int mixed =0 ;list_for_each_entry (found, &fs_info->space_info, list) { -if (found->flags &BTRFS_BLOCK_GROUP_DATA ) { +if (found->flags &BTRFS_BLOCK_GROUP_DATA && + found->subgroup_id !=BTRFS_SUB_GROUP_DATA_RELOC ) {int i; total_free_data += found->disk_total - found->disk_used;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 412/1067 IB/mlx4: Fill in the access_flags if IB_MR_REREG_ACCESS is not specified
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit bade9a3150d44ed20b8c6484c4c8a943b7289abb ]
Sashiko noticed mlx4 was using whatever random access flags were provided when IB_MR_REREG_ACCESS is not used. Since IB_MR_REREG_TRANS needs access_flags it used the random ones which means it doesn't work sensibly if userspace provides only IB_MR_REREG_TRANS.
Keep track of the current access_flag of the MR and use it if the user does not specify one.
Also fixup a little confusion around mmr.access, it is the HW access flags so the convert_access() was missing. But nothing reads this by the time rereg_mr can happen.
--- drivers/infiniband/hw/mlx4/mlx4_ib.h | 1 + drivers/infiniband/hw/mlx4/mr.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/infiniband/hw/mlx4/mlx4_ib.h +1 -0
@@ -136,6 +136,7 @@ struct mlx4_ib_mr {dma_addr_t page_map;u32 npages;u32 max_pages; +int access_flags;struct mlx4_mr mmr;struct ib_umem *umem;size_t page_map_size;
drivers/infiniband/hw/mlx4/mr.c +7 -2
@@ -439,6 +439,7 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,if (err) goto err_mr; + mr->access_flags = access_flags; mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; mr->ibmr.page_size =1U << shift;
@@ -495,6 +496,8 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start,if (err) goto release_mpt_entry; + }else { + mr_access_flags = mmr->access_flags; }if (flags &IB_MR_REREG_TRANS ) {
@@ -536,8 +539,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start,* return a failure. But dereg_mr will free the resources. */ err =mlx4_mr_hw_write_mpt (dev->dev, &mmr->mmr, pmpt_entry); -if (!err && flags &IB_MR_REREG_ACCESS ) - mmr->mmr.access = mr_access_flags; +if (!err && flags &IB_MR_REREG_ACCESS ) { + mmr->access_flags = mr_access_flags; + mmr->mmr.access =convert_access (mr_access_flags); + } release_mpt_entry:mlx4_mr_hw_put_mpt (dev->dev, pmpt_entry);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 413/1067 vduse: hold vduse_lock across IDR lookup in open path
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang Tang <[email protected]>
[ Upstream commit e440e077748939839d9f76e24383b76b785f80ce ]
vduse_dev_open() looks up struct vduse_dev through the IDR and then acquires dev->lock only after vduse_lock has been dropped.
This leaves a window where a concurrent VDUSE_DESTROY_DEV can remove the same object from the IDR and free it before the open path locks the device, leading to a use-after-free.
Close this race by keeping vduse_lock held until dev->lock has been acquired in the open path, matching the lock ordering already used by the destroy path.
Message-ID: <[email protected]>
--- drivers/vdpa/vdpa_user/vduse_dev.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
drivers/vdpa/vdpa_user/vduse_dev.c +7 -14
@@ -1296,26 +1296,18 @@ static int vduse_dev_release(struct inode *inode, struct file *file)return 0 ; } -static struct vduse_dev *vduse_dev_get_from_minor (int minor) +static int vduse_dev_open (struct inode *inode,struct file *file) { +int ret = -EBUSY ;struct vduse_dev *dev;mutex_lock (&vduse_lock); - dev =idr_find (&vduse_idr, minor); -mutex_unlock (&vduse_lock); - -return dev; -} - -static int vduse_dev_open (struct inode *inode,struct file *file) -{ -int ret; -struct vduse_dev *dev =vduse_dev_get_from_minor (iminor (inode)); - -if (!dev) + dev =idr_find (&vduse_idr,iminor (inode)); +if (!dev) { +mutex_unlock (&vduse_lock);return -ENODEV ; + } - ret = -EBUSY ;mutex_lock (&dev->lock);if (dev->connected) goto unlock;
@@ -1325,6 +1317,7 @@ static int vduse_dev_open(struct inode *inode, struct file *file) file->private_data = dev; unlock:mutex_unlock (&dev->lock); +mutex_unlock (&vduse_lock);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 414/1067 vhost/vdpa: validate virtqueue index in mmap and fault paths
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang Tang <[email protected]>
[ Upstream commit 929e4f044621c8cc30b612fb74e1410bef09e41b ]
vhost_vdpa_mmap() and vhost_vdpa_fault() use vma->vm_pgoff as a virtqueue index for get_vq_notification(), but they do not validate that the index is smaller than v->nvqs.
The ioctl path already performs both a bounds check and array_index_nospec(), but the mmap/fault path only checks that the index fits in u16. This allows an out-of-range queue index to reach driver-specific get_vq_notification() callbacks.
Fix this by extracting a unified vhost_vdpa_get_vq_notification() helper that validates the queue index against v->nvqs and applies array_index_nospec() before calling the driver callback. Both the mmap and fault paths use this helper, and the bounds checking is consolidated into a single location.
Quoted 1 line
From source inspection, the most defensible impact is out-of-bounds
access in the callback path, potentially leading to invalid PFN remaps and crash/DoS.
Message-ID: <[email protected]>
--- drivers/vhost/vdpa.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
drivers/vhost/vdpa.c +22 -7
@@ -1295,16 +1295,32 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) }#ifdef CONFIG_MMU -static vm_fault_t vhost_vdpa_fault (struct vm_fault *vmf) +static int +vhost_vdpa_get_vq_notification (struct vhost_vdpa *v,unsigned long index, +struct vdpa_notification_area *notify) { -struct vhost_vdpa *v = vmf->vma->vm_file->private_data;struct vdpa_device *vdpa = v->vdpa;const struct vdpa_config_ops *ops = vdpa->config; + +if (index >65535 || index >= v->nvqs) +return -EINVAL ; + + index =array_index_nospec (index, v->nvqs); + + *notify = ops->get_vq_notification (vdpa, index); + +return 0 ; +} + +static vm_fault_t vhost_vdpa_fault (struct vm_fault *vmf) +{ +struct vhost_vdpa *v = vmf->vma->vm_file->private_data;struct vdpa_notification_area notify;struct vm_area_struct *vma = vmf->vma; -u16 index = vma->vm_pgoff; +unsigned long index = vma->vm_pgoff; - notify = ops->get_vq_notification (vdpa, index); +if (vhost_vdpa_get_vq_notification (v, index, ¬ify)) +return VM_FAULT_SIGBUS ;return vmf_insert_pfn (vma, vmf->address &PAGE_MASK ,PFN_DOWN (notify.addr)); }
@@ -1327,8 +1343,6 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)return -EINVAL ;if (vma->vm_flags &VM_READ )return -EINVAL ; -if (index >65535 ) -return -EINVAL ;if (!ops->get_vq_notification)return -ENOTSUPP ;
@@ -1336,7 +1350,8 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)* support the doorbell which sits on the page boundary and * does not share the page with other registers. */ - notify = ops->get_vq_notification (vdpa, index); +if (vhost_vdpa_get_vq_notification (v, index, ¬ify)) +return -EINVAL ;if (notify.addr & (PAGE_SIZE -1 ))return -EINVAL ;if (vma->vm_end - vma->vm_start != notify.size)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 415/1067 vduse: Requeue failed read to send_list head
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Tianci <[email protected]>
[ Upstream commit 373ec43ded742b2f3aecf14731ffe1a57f438f38 ]
When copy_to_iter() fails in vduse_dev_read_iter(), put the message back at the head of send_list to preserve FIFO ordering and retry the oldest pending request first.
Message-ID: <[email protected]>
--- drivers/vdpa/vdpa_user/vduse_dev.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/vdpa/vdpa_user/vduse_dev.c +7 -1
@@ -182,6 +182,12 @@ static void vduse_enqueue_msg(struct list_head *head,list_add_tail (&msg->list, head); } +static void vduse_enqueue_msg_head (struct list_head *head, +struct vduse_dev_msg *msg) +{ +list_add (&msg->list, head); +} +static void vduse_dev_broken (struct vduse_dev *dev) {struct vduse_dev_msg *msg, *tmp;
@@ -342,7 +348,7 @@ static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)spin_lock (&dev->msg_lock);if (ret != size) { ret = -EFAULT ; -vduse_enqueue_msg (&dev->send_list, msg); +vduse_enqueue_msg_head (&dev->send_list, msg); goto unlock; }vduse_enqueue_msg (&dev->recv_list, msg);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 416/1067 vhost/net: complete zerocopy ubufs only once
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Ming <[email protected]>
[ Upstream commit 8f6898fe80794f2d7c3d38c1158c806e4074a1c4 ]
vhost-net initializes one ubuf_info per outstanding zerocopy TX descriptor and hands it to the backend socket. The networking stack may then clone a zerocopy skb before all skb references are released. For example, batman-adv fragmentation reaches skb_split(), which calls skb_zerocopy_clone() and increments the same ubuf_info refcount.
vhost_zerocopy_complete() currently treats every ubuf callback as a completed vhost descriptor. It dereferences ubuf->ctx, writes the descriptor completion state, and drops the vhost_net_ubuf_ref even when the callback only releases a cloned skb reference. A backend reset can therefore wait for and free the vhost_net_ubuf_ref while another cloned skb still carries the same ubuf_info. A later completion then dereferences the freed ubufs pointer.
KASAN reports the stale completion as:
BUG: KASAN: slab-use-after-free in vhost_zerocopy_complete+0x1d7/0x1f0 BUG: KASAN: slab-use-after-free in vhost_zerocopy_complete+0x101/0x1f0 vhost_zerocopy_complete skb_copy_ubufs __dev_forward_skb2 veth_xmit
The freed object was allocated from vhost_net_ioctl() while setting the backend and freed through kfree_rcu()/kvfree_rcu_bulk after backend removal, while delayed skb completion still reached vhost_zerocopy_complete().
Honor the generic ubuf_info refcount before touching vhost state, and run the vhost descriptor completion only for the final ubuf reference. This matches the msg_zerocopy_complete() ownership rule for cloned zerocopy skbs.
Message-ID: <[email protected]>
--- drivers/vhost/net.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/vhost/net.c +11 -4
@@ -389,13 +389,20 @@ static void vhost_zerocopy_signal_used(struct vhost_net *net,static void vhost_zerocopy_callback (struct sk_buff *skb,struct ubuf_info *ubuf_base,bool success) { -struct ubuf_info_msgzc *ubuf =uarg_to_msgzc (ubuf_base); -struct vhost_net_ubuf_ref *ubufs = ubuf->ctx; -struct vhost_virtqueue *vq = ubufs->vq; +struct ubuf_info_msgzc *ubuf; +struct vhost_net_ubuf_ref *ubufs; +struct vhost_virtqueue *vq;int cnt; -rcu_read_lock_bh (); +/* Only the final cloned skb reference completes the vhost descriptor. */ +if (!refcount_dec_and_test (&ubuf_base->refcnt)) +return ; + + ubuf =uarg_to_msgzc (ubuf_base); + ubufs = ubuf->ctx; + vq = ubufs->vq; +rcu_read_lock_bh ();/* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ?VHOST_DMA_DONE_LEN :VHOST_DMA_FAILED_LEN ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 417/1067 tools/virtio: check mmap return value in vringh_test
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: longlong yan <[email protected]>
[ Upstream commit ec6177dfe98b9be1c3ede6c0dfe4394ea2a76959 ]
In parallel_test(), the return values of mmap() for both host_map and guest_map are not checked against MAP_FAILED. If mmap() fails, the subsequent code will dereference the invalid pointer, leading to a segmentation fault.
Add MAP_FAILED checks after both mmap() calls, using err() to report the error and exit, consistent with the existing error handling style in this file (e.g., the open() call on line 149).
Message-ID: <[email protected]>
--- tools/virtio/vringh_test.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/virtio/vringh_test.c +5 -0
@@ -159,7 +159,12 @@ static int parallel_test(u64 features,/* Parent and child use separate addresses, to check our mapping logic! */ host_map =mmap (NULL , mapsize,PROT_READ |PROT_WRITE ,MAP_SHARED , fd,0 ); +if (host_map ==MAP_FAILED ) +err (1 ,"mmap host_map" ); + guest_map =mmap (NULL , mapsize,PROT_READ |PROT_WRITE ,MAP_SHARED , fd,0 ); +if (guest_map ==MAP_FAILED ) +err (1 ,"mmap guest_map" );pipe (to_guest);pipe (to_host);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 418/1067 bonding: 3ad: fix mux port state on oper down
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis Scalbert <[email protected]>
[ Upstream commit 807afc7544b865d4d09068a415fd5b71bf5665cc ]
When the bonding interface has carrier down due to the absence of usable slaves and a slave transitions from down to up, the bonding interface briefly goes carrier up, then down again, and finally up once LACP negotiates collecting and distributing on the port.
When lacp_strict mode is on, the interface should not transition to carrier up until LACP negotiation is complete.
This happens because the actor and partner port states remain in Collecting_Distributing when the port goes down. When the port comes back up, it temporarily remains in this state until LACP renegotiation occurs.
Previously this was mostly cosmetic, but since the bonding carrier state may depend on the LACP negotiation state, it causes the interface to flap.
According to IEEE 802.3ad-2000 and IEEE 802.1ax-2014, Collecting and Distributing should be reset when a port goes down:
- In the Receive state machine, port_enabled == FALSE causes a transition to the PORT_DISABLED state, which is expected to clear Partner_Oper_Port_State.Synchronization.
- In the Mux state machine, Partner_Oper_Port_State.Synchronization == FALSE causes a transition to the ATTACHED state, which disables Collecting and Distributing.
However, Partner_Oper_Port_State.Synchronization is not cleared in the PORT_DISABLED state.
Clear Partner_Oper_Port_State.Synchronization in the Receive PORT_DISABLED state.
--- drivers/net/bonding/bond_3ad.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/bonding/bond_3ad.c +1 -0
@@ -1275,6 +1275,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) fallthrough;case AD_RX_PORT_DISABLED : port->sm_vars &= ~AD_PORT_MATCHED ; + port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION ;break ;case AD_RX_LACP_DISABLED : port->sm_vars &= ~AD_PORT_SELECTED ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 419/1067 selftests/bpf: Fix bpf_iter/task_vma test
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 2e8ad1ff712d2a397e407c9fde60901f68d077dc ]
For selftest bpf_iter/task_vma, I got a failure like below on my qemu run:
test_task_vma_common:FAIL:compare_output unexpected compare_output:
actual
'561593546000-561593585000r--p0000000000:241256579534/root/devshare/bpf-next/tools/testing/selftests/bpf/test_progs'
!= expected
'561593546000-561593585000r--p0000000000:245551546830/root/devshare/bpf-next/tools/testing/selftests/bpf/test_progs'Further debugging found out file->f_inode->i_ino value may exceed 32bit, e.g., i_ino = 0x14c2eae35, but the format string is '%u'. This caused inode mismatch between bpf iter and proc result.
Fix the issue by using format string '%llu' to accommodate 64bit i_ino.
--- tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c +1 -1
@@ -52,7 +52,7 @@ SEC("iter/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)bpf_d_path (&file->f_path, d_path_buf,D_PATH_BUF_SIZE );BPF_SEQ_PRINTF (seq,"%08llx " , vma->vm_pgoff <<12 ); -BPF_SEQ_PRINTF (seq,"%02x:%02x %u" ,MAJOR (dev),MINOR (dev), +BPF_SEQ_PRINTF (seq,"%02x:%02x %llu" ,MAJOR (dev),MINOR (dev), file->f_inode->i_ino);BPF_SEQ_PRINTF (seq,"\t%s\n" , d_path_buf); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 420/1067 cxl/test: Fix integer overflow in mock LSA bounds checks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit 81eafcada109b653977c4dfbd2b6a72470025a01 ]
Pre-existing issue discovered by sashiko-bot.
mock_get_lsa() and mock_set_lsa() validate the requested LSA range with "offset + length > LSA_SIZE". Both offset and length are u32 and, in mock_get_lsa(), both are taken directly from the user-supplied payload. The addition is evaluated modulo 2^32, so a large offset combined with a small length wraps around and passes the check.
Rewrite the checks to first bound offset, then compare length against the remaining LSA size.
--- tools/testing/cxl/test/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/cxl/test/mem.c +2 -2
@@ -148,7 +148,7 @@ static int mock_get_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)return -EINVAL ; offset =le32_to_cpu (get_lsa->offset); length =le32_to_cpu (get_lsa->length); -if (offset + length >LSA_SIZE ) +if (offset >LSA_SIZE || length >LSA_SIZE - offset)return -EINVAL ;if (length > cmd->size_out)return -EINVAL ;
@@ -167,7 +167,7 @@ static int mock_set_lsa(struct cxl_dev_state *cxlds, struct cxl_mbox_cmd *cmd)return -EINVAL ; offset =le32_to_cpu (set_lsa->offset); length = cmd->size_in -sizeof (*set_lsa); -if (offset + length >LSA_SIZE ) +if (offset >LSA_SIZE || length >LSA_SIZE - offset)return -EINVAL ;memcpy (lsa + offset, &set_lsa->data[0 ], length);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 421/1067 bpf: Tighten cgroup storage cookie checks for prog arrays
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 10627ddc0167aab5c1c390a10ef461e9937aba08 ]
The fix in commit abad3d0bad72 ("bpf: Fix oob access in cgroup local storage") is still incomplete. The prog-array compatibility check treats a program with no cgroup storage as compatible with any stored storage cookie. This allows a storage-less program to bridge a tail call chain between an entry program and a storage-using callee even though cgroup local storage at runtime still follows the caller's context, that is, A -> B(no storage) -> C(storage) path.
Requiring exact cookie equality would break the legitimate case of a storage-less leaf program being tail called from a storage-using one. Instead, only accept a zero storage cookie if the program cannot perform tail calls itself. This keeps A -> B(no storage) working while rejecting the A -> B(no storage) -> C(storage) bridge.
--- kernel/bpf/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/core.c +1 -1
@@ -2159,7 +2159,7 @@ bool bpf_prog_map_compatible(struct bpf_map *map, cookie = aux->cgroup_storage[i] ? aux->cgroup_storage[i]->cookie :0 ; ret = map->owner->storage_cookie[i] == cookie || - !cookie; + (!cookie && !aux->tail_call_reachable); }if (ret && map->owner->attach_func_proto != aux->attach_func_proto) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 422/1067 s390/process: Fix kernel thread function pointer type
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
[ Upstream commit d0478f5d3cba1095bfdeb43a9b063c10cdebef14 ]
In case of a kernel thread __ret_from_fork() calls the specified function indirectly. Fix the kernel thread function pointer, since kernel threads return an int instead of void.
--- arch/s390/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/process.c +1 -1
@@ -48,7 +48,7 @@ void ret_from_fork(void) asm("ret_from_fork");void __ret_from_fork (struct task_struct *prev,struct pt_regs *regs) { -void (*func)(void *arg); +int (*func)(void *arg);schedule_tail (prev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 423/1067 Bluetooth: eir: Fix stack OOB write when prepending the Flags AD
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 6f5fb689fdf80bdd143f22a502f9eb1f3c85e286 ]
eir_create_adv_data() builds the advertising data into a fixed-size buffer ("size", 31 for the legacy path). It may prepend a 3-byte "Flags" AD structure (LE_AD_NO_BREDR on an LE-only controller) and then copies the per-instance data without checking that it still fits:
memcpy(ptr, adv->adv_data, adv->adv_data_len);
tlv_data_max_len() only reserves those 3 bytes when the user-supplied flags carry a managed-flags bit, so an instance added with flags == 0 is accepted with adv_data_len up to the full buffer. At advertise time the flags are still prepended, and the memcpy() writes 3 + adv_data_len bytes into the size-byte buffer:
BUG: KASAN: stack-out-of-bounds in eir_create_adv_data (net/bluetooth/eir.c:301) Write of size 31 at addr ffff88800a547bdc by task kworker/u9:0/65 Workqueue: hci0 hci_cmd_sync_work __asan_memcpy (mm/kasan/shadow.c:106) eir_create_adv_data (net/bluetooth/eir.c:301) hci_update_adv_data_sync (net/bluetooth/hci_sync.c:1310) hci_schedule_adv_instance_sync (net/bluetooth/hci_sync.c:1817) hci_cmd_sync_work (net/bluetooth/hci_sync.c:332) This frame has 1 object: [32, 64) 'cp'
The "Flags" structure is added by the kernel, not requested by userspace, so only prepend it when it fits together with the instance advertising data; when there is no room for both, drop the flags rather than the user-provided data.
Reachable by a local user with CAP_NET_ADMIN owning an LE-only controller on the legacy advertising path.
--- net/bluetooth/eir.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/bluetooth/eir.c +5 -3
@@ -283,10 +283,12 @@ u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size)if (!flags) flags |=mgmt_get_adv_discov_flags (hdev); -/* If flags would still be empty, then there is no need to -* include the "Flags" AD field". +/* Only add the "Flags" if it fits together with the instance +* advertising data; drop it rather than overflow the buffer. */ -if (flags && (ad_len +eir_precalc_len (1 ) <= size)) { +if (flags && + (ad_len +eir_precalc_len (1 ) + + (adv ? adv->adv_data_len :0 ) <= size)) { ptr[0 ] =0x02 ; ptr[1 ] =EIR_FLAGS ; ptr[2 ] = flags;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 424/1067 Bluetooth: hci: validate codec capability element length
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Moelius <[email protected]>
[ Upstream commit c38fbcdc407925c7088f7e5f11c1fff73d2d35a2 ]
Read Local Codec Capabilities returns a sequence of capability elements. Each element starts with a one-byte length followed by that many payload bytes.
hci_read_codec_capabilities() checks that the skb contains the length byte, but then validates only caps->len against the remaining skb length. A malformed controller response with one remaining byte and caps->len set to one passes that check even though the element needs two bytes. The parser then records a two-byte capability and copies one byte beyond the advertised response payload into the codec list.
Validate the full element size, including the length byte, before adding it to the accumulated capability length. This preserves all well-formed capability elements and drops only truncated controller responses.
--- net/bluetooth/hci_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/hci_codec.c +1 -1
@@ -100,7 +100,7 @@ static void hci_read_codec_capabilities(struct hci_dev *hdev, __u8 transport, caps = (void *)skb->data;if (skb->len <sizeof (*caps)) goto error; -if (skb->len < caps->len) +if (skb->len <sizeof (caps->len) + caps->len) goto error; len +=sizeof (caps->len) + caps->len;skb_pull (skb,sizeof (caps->len) + caps->len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 425/1067 fs: efs: remove unneeded debug prints
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxwell Doose <[email protected]>
[ Upstream commit 89009392c80da5da00876c8334ff20028e6e3eb6 ]
The current code uses debug prints conditionally compiled with #ifdef DEBUG. However, that code, when compiled, causes compiler errors due to incompatible formatters and undefined variables, notably:
fs/efs/file.c: In function `efs_get_block':fs/efs/file.c:26:35: error: block' undeclared (first use in this function); did you mean iblock'?
26 | __func__, block, inode->i_blocks, inode->i_size);
| ^~~~~
and:
fs/efs/file.c: In function `efs_bmap':./include/linux/kern_levels.h:5:25: error: format %ld' expects argument of type long int', but argument 4 has type blkcnt_t' {aka long long unsigned int'} [-Werror=format=]
5 | #define KERN_SOH "\001" /* ASCII Start Of Header */
| ^~~~~~which also extends to the other formatters. As this part of the code has been dead for just about 14 years now, it has not been modernized to stay compatible with the most recent gcc compilers. Fix these issues by removing the debug prints.
--- fs/efs/file.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-)
fs/efs/file.c +3 -18
@@ -18,16 +18,9 @@ int efs_get_block(struct inode *inode, sector_t iblock,if (create)return error; -if (iblock >= inode->i_blocks) { -#ifdef DEBUG -/* -* i have no idea why this happens as often as it does -*/ -pr_warn ("%s(): block %d >= %ld (filesize %ld)\n" , - __func__, block, inode->i_blocks, inode->i_size); -#endif +if (iblock >= inode->i_blocks)return 0 ; - } + phys =efs_map_block (inode, iblock);if (phys)map_bh (bh_result, inode->i_sb, phys);
@@ -42,16 +35,8 @@ int efs_bmap(struct inode *inode, efs_block_t block) { }/* are we about to read past the end of a file ? */ -if (!(block < inode->i_blocks)) { -#ifdef DEBUG -/* -* i have no idea why this happens as often as it does -*/ -pr_warn ("%s(): block %d >= %ld (filesize %ld)\n" , - __func__, block, inode->i_blocks, inode->i_size); -#endif +if (!(block < inode->i_blocks))return 0 ; - }return efs_map_block (inode, block); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 426/1067 RDMA/mlx5: Remove raw RSS QP restrack tracking
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Patrisious Haddad <[email protected]>
[ Upstream commit 666031fed8f0fdfc29b20d125a628c1b0a04cdaf ]
Raw RSS QP restrack tracking wasn't working to begin with as it was only tracking the first raw RSS QP which was added, since at creation the raw RSS QP number is reserved so the QP number for this qp type was always zero.
The following raw RSS QP additions were always failing silently.
Since the fix isn't trivial and there were no users that required or complained about this issue we are dropping this for now instead of fixing.
--- drivers/infiniband/hw/mlx5/qp.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/mlx5/qp.c +1 -0
@@ -3005,6 +3005,7 @@ static int create_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,int err;if (params->is_rss_raw) { +rdma_restrack_no_track (&qp->ibqp.res); err =create_rss_raw_qp_tir (dev, pd, qp, params); goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 427/1067 RDMA/mlx5: Fix undefined shift of user RQ WQE size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maher Sanalla <[email protected]>
[ Upstream commit d881d60223aac8fdc12b227d89c76e131e92a9cd ]
set_rq_size() computes the RQ WQE size as "1 << rq_wqe_shift" based on the user-provided rq_wqe_shift, which is only checked to be greater than 32, so shifts of 32 are still accepted. A shift of 31 also overflows a signed integer, leading to undefined behavior.
Use check_shl_overflow() to compute the RQ WQE size and reject any invalid values.
--- drivers/infiniband/hw/mlx5/qp.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/infiniband/hw/mlx5/qp.c +4 -7
@@ -370,16 +370,13 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,if (ucmd) { qp->rq.wqe_cnt = ucmd->rq_wqe_count; -if (ucmd->rq_wqe_shift >BITS_PER_BYTE *sizeof (ucmd->rq_wqe_shift)) -return -EINVAL ; qp->rq.wqe_shift = ucmd->rq_wqe_shift; -if ((1 << qp->rq.wqe_shift) / -sizeof (struct mlx5_wqe_data_seg ) < - wq_sig) +if (check_shl_overflow (1 , qp->rq.wqe_shift, &wqe_size)) +return -EINVAL ; +if (wqe_size /sizeof (struct mlx5_wqe_data_seg ) < wq_sig)return -EINVAL ; qp->rq.max_gs = - (1 << qp->rq.wqe_shift) / -sizeof (struct mlx5_wqe_data_seg ) - + wqe_size /sizeof (struct mlx5_wqe_data_seg ) - wq_sig; qp->rq.max_post = qp->rq.wqe_cnt; }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 428/1067 RDMA/mlx5: Release the HW‑provided UAR index rather than the SW one
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 449ae7927152e46acbe5f19f97eafdae6d3a96b1 ]
Free the UAR index returned by the hardware.
--- drivers/infiniband/hw/mlx5/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/main.c +1 -1
@@ -2229,7 +2229,7 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,if (!dyn_uar)return err; -mlx5_cmd_uar_dealloc (dev->mdev, idx, context->devx_uid); +mlx5_cmd_uar_dealloc (dev->mdev, uar_index, context->devx_uid); free_bfreg:mlx5_ib_free_bfreg (dev, bfregi, bfreg_dyn_idx);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 429/1067 ASoC: codecs: hdac_hdmi: Validate written enum value
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 0b08baeccdcf52fad328ad645f5b4fbee04eea34 ]
hdac_hdmi_set_pin_port_mux() uses the written enum value to index the texts array before calling snd_soc_dapm_put_enum_double(), which validates that the value is within the enum item range.
An out-of-range value can therefore make the driver read past the texts array before the helper rejects the write. Move the lookup after the helper has accepted the value.
--- sound/soc/codecs/hdac_hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/soc/codecs/hdac_hdmi.c +3 -1
@@ -906,12 +906,14 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,struct hdac_device *hdev =dev_to_hdac_dev (dapm->dev);struct hdac_hdmi_priv *hdmi =hdev_to_hdmi_priv (hdev);struct hdac_hdmi_pcm *pcm; -const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0 ]]; +const char *cvt_name; ret =snd_soc_dapm_put_enum_double (kcontrol, ucontrol);if (ret <0 )return ret; + cvt_name = e->texts[ucontrol->value.enumerated.item[0 ]]; +if (port ==NULL )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 430/1067 ASoC: fsl: fsl_audmix: Validate written enum values
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 3cd17e4e2871114d5579fa7bc8da66faf7fc1930 ]
fsl_audmix_put_mix_clk_src() and fsl_audmix_put_out_src() convert the user-provided enum item with snd_soc_enum_item_to_val() before checking whether the item is within the enum's item count.
The generic snd_soc_put_enum_double() helper performs that validation, but these callbacks use the converted value first: the clock-source path tests it with BIT(), and the output-source path indexes the prms transition table with it.
Reject out-of-range enum items before converting them.
--- sound/soc/fsl/fsl_audmix.c | 6 ++++++ 1 file changed, 6 insertions(+)
sound/soc/fsl/fsl_audmix.c +6 -0
@@ -117,6 +117,9 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol,unsigned int *item = ucontrol->value.enumerated.item;unsigned int reg_val, val, mix_clk; +if (item[0 ] >= e->items) +return -EINVAL ; +/* Get current state */ reg_val =snd_soc_component_read (comp,FSL_AUDMIX_CTR ); mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK)
@@ -157,6 +160,9 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol,unsigned int reg_val, val, mask =0 , ctr =0 ;int ret; +if (item[0 ] >= e->items) +return -EINVAL ; +/* Get current state */ reg_val =snd_soc_component_read (comp,FSL_AUDMIX_CTR );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 431/1067 ASoC: tegra: tegra210_ahub: Validate written enum value
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 1d8aabb413b5638670dfd1162169edc0ba276a2e ]
tegra_ahub_put_value_enum() reads e->values[item[0]] before checking whether item[0] is within the enum item range. The existing check therefore happens too late to prevent an out-of-range read of the values array.
Move the check before the array access.
--- sound/soc/tegra/tegra210_ahub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/soc/tegra/tegra210_ahub.c +3 -1
@@ -60,13 +60,15 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,struct soc_enum *e = (struct soc_enum *)kctl->private_value;struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG ] = { };unsigned int *item = uctl->value.enumerated.item; -unsigned int value = e->values[item[0 ]]; +unsigned int value;unsigned int i, bit_pos, reg_idx =0 , reg_val =0 ;int change =0 ;if (item[0 ] >= e->items)return -EINVAL ; + value = e->values[item[0 ]]; +if (value) {/* Get the register index and value to set */ reg_idx = (value -1 ) / (8 * cmpnt->val_bytes);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 432/1067 net/sched: cls_flow: Dont expose folded kernel pointers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit f294fc71c4a0fa4964f6428a1b4e7929c1d83125 ]
The flow classifier falls back to addr_fold() for fields that are missing from packet headers. In map mode, userspace controls mask, xor, rshift, addend and divisor, and can observe the resulting classid through class statistics. This allows a tc classifier in a user/network namespace to recover the 32-bit folded value of skb->sk, skb_dst() or skb_nfct().
Align with standard kernel practices for pointer hashing and replace the XOR folding with a keyed siphash (which is cryptographically secure)
--- net/sched/cls_flow.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
net/sched/cls_flow.c +9 -3
@@ -21,6 +21,7 @@#include <net/inet_sock.h> #include <net/pkt_cls.h> +#include <linux/siphash.h> #include <net/ip.h> #include <net/route.h> #include <net/flow_dissector.h>
@@ -56,11 +57,15 @@ struct flow_filter {struct rcu_work rwork; }; +static siphash_aligned_key_t flow_keys_secret__read_mostly ; +static inline u32 addr_fold (void *addr) { -unsigned long a = (unsigned long )addr; - -return (a &0xFFFFFFFF ) ^ (BITS_PER_LONG >32 ? a >>32 :0 ); +#ifdef CONFIG_64BIT +return (u32 )siphash_1u64 ((u64 )addr, &flow_keys_secret); +#else +return (u32 )siphash_1u32 ((u32 )addr, &flow_keys_secret); +#endif }static u32 flow_get_src (const struct sk_buff *skb,const struct flow_keys *flow)
@@ -594,6 +599,7 @@ static int flow_init(struct tcf_proto *tp)return -ENOBUFS ;INIT_LIST_HEAD (&head->filters);rcu_assign_pointer (tp->root, head); +net_get_random_once (&flow_keys_secret,sizeof (flow_keys_secret));return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 433/1067 net: fib_rules: Dont dump dying fib_rule in fib_rules_dump().
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 2821e85c058f81c9948a2fb1a634f7b47457d51c ]
rocker_router_fib_event() calls fib_rule_get() during RCU dump.
If the fib_rule is dying, refcount_inc() will complain about it.
Let's call refcount_inc_not_zero() in fib_rules_dump().
--- include/net/fib_rules.h | 5 +++++ net/core/fib_rules.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-)
include/net/fib_rules.h +5 -0
@@ -107,6 +107,11 @@ static inline void fib_rule_get(struct fib_rule *rule)refcount_inc (&rule->refcnt); } +static inline bool fib_rule_get_safe (struct fib_rule *rule) +{ +return refcount_inc_not_zero (&rule->refcnt); +} +static inline void fib_rule_put (struct fib_rule *rule) {if (refcount_dec_and_test (&rule->refcnt))
net/core/fib_rules.c +5 -1
@@ -328,7 +328,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,if (err != -EAGAIN ) {if ((arg->flags &FIB_LOOKUP_NOREF ) || -likely (refcount_inc_not_zero (&rule->refcnt))) { +likely (fib_rule_get_safe (rule))) { arg->rule = rule; goto out; }
@@ -386,8 +386,12 @@ int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,if (!ops)return -EAFNOSUPPORT ;list_for_each_entry_rcu (rule, &ops->rules_list, list) { +if (!fib_rule_get_safe (rule)) +continue ; + err =call_fib_rule_notifier (nb,FIB_EVENT_RULE_ADD , rule, family, extack); +fib_rule_put (rule);if (err)break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 434/1067 bridge: cfm: reject invalid CCM interval at configuration time
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit f3e02edd8322b31b8e6517faa6ba053bf29d1e26 ]
ccm_tx_work_expired() re-arms itself via queue_delayed_work() using the configured exp_interval converted by interval_to_us(). When exp_interval is BR_CFM_CCM_INTERVAL_NONE or out of range, interval_to_us() returns 0, causing the worker to fire immediately in a tight loop that allocates skbs until OOM.
Fix this by validating exp_interval at configuration time:
- Constrain IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL to the valid range [BR_CFM_CCM_INTERVAL_3_3_MS, BR_CFM_CCM_INTERVAL_10_MIN] in the netlink policy so userspace cannot set an invalid value.
- Reject starting CCM TX in br_cfm_cc_ccm_tx() when exp_interval has not yet been configured (defaults to 0 from kzalloc).
--- net/bridge/br_cfm.c | 6 ++++++ net/bridge/br_cfm_netlink.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-)
net/bridge/br_cfm.c +6 -0
@@ -805,6 +805,12 @@ int br_cfm_cc_ccm_tx(struct net_bridge *br, const u32 instance, goto save; } +if (!interval_to_us (mep->cc_config.exp_interval)) { +NL_SET_ERR_MSG_MOD (extack, +"Invalid CCM interval" ); +return -EINVAL ; + } +/* Start delayed work to transmit CCM frames. It is done with zero delay * to send first frame immediately */
net/bridge/br_cfm_netlink.c +3 -1
@@ -34,7 +34,9 @@ br_cfm_cc_config_policy[IFLA_BRIDGE_CFM_CC_CONFIG_MAX + 1] = { [IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC] = { .type = NLA_REJECT }, [IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE] = { .type = NLA_U32 }, [IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE] = { .type = NLA_U32 }, - [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL] = { .type = NLA_U32 }, + [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL ] = +NLA_POLICY_RANGE (NLA_U32 ,BR_CFM_CCM_INTERVAL_3_3_MS , + BR_CFM_CCM_INTERVAL_10_MIN), [IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID ] = { .type = NLA_BINARY, .len = CFM_MAID_LENGTH }, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 435/1067 sctp: validate embedded address parameter length
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <[email protected]>
[ Upstream commit e9361d0ca55c4af12aac09e2572852fa91046229 ]
sctp_verify_asconf() and sctp_verify_param() only validate ADD_IP, DEL_IP, and SET_PRIMARY parameters against a fixed minimum size of sizeof(struct sctp_addip_param) + sizeof(struct sctp_paramhdr). This ensures the outer parameter is large enough to contain an embedded address parameter header, but does not verify that the embedded address parameter's declared length fits within the bounds of the outer parameter.
Later, sctp_process_param() and sctp_process_asconf_param() extract the embedded address parameter and pass it to af->from_addr_param(), which uses the address parameter length to parse the variable-length address payload. A malformed peer can therefore advertise an embedded address parameter length that exceeds the remaining bytes in the enclosing parameter.
Validate that addr_param->p.length does not exceed the space available after the sctp_addip_param header before processing the embedded address parameter. Reject malformed parameters when the embedded address length extends beyond the enclosing parameter bounds.
This prevents out-of-bounds reads when parsing malformed parameters carried in INIT or ASCONF processing paths.
--- net/sctp/sm_make_chunk.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/sctp/sm_make_chunk.c +8 -2
@@ -2670,6 +2670,9 @@ static int sctp_process_param(struct sctp_association *asoc, goto fall_through; addr_param = param.v +sizeof (struct sctp_addip_param ); +if (ntohs (addr_param->p.length) > +ntohs (param.p->length) -sizeof (struct sctp_addip_param )) +break ; af =sctp_get_af_specific (param_type2af (addr_param->p.type));if (!af)
@@ -3068,13 +3071,16 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,union sctp_addr addr;struct sctp_af *af; - addr_param = (void *)asconf_param +sizeof (*asconf_param); -if (asconf_param->param_hdr.type !=SCTP_PARAM_ADD_IP && asconf_param->param_hdr.type !=SCTP_PARAM_DEL_IP && asconf_param->param_hdr.type !=SCTP_PARAM_SET_PRIMARY )return SCTP_ERROR_UNKNOWN_PARAM ; + addr_param = (void *)asconf_param +sizeof (*asconf_param); +if (ntohs (addr_param->p.length) > +ntohs (asconf_param->param_hdr.length) -sizeof (*asconf_param)) +return SCTP_ERROR_PROTO_VIOLATION ; +switch (addr_param->p.type) {case SCTP_PARAM_IPV6_ADDRESS :if (!asoc->peer.ipv6_address)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 436/1067 net/sched: sch_hfsc: Dont make class passive twice
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueira <[email protected]>
[ Upstream commit 90b662ea25f5e83bb3b8ccec5b93ced810b92fb8 ]
update_vf() is called from two places for the same class during a single dequeue when the class's child qdisc (e.g. codel/fq_codel) drops its last packets while dequeuing:
1. The child calls qdisc_tree_reduce_backlog(), which, now that the child is empty, invokes hfsc_qlen_notify() -> update_vf(cl, 0, 0) and turns the class passive (cl_nactive is decremented up the hierarchy).
2. hfsc_dequeue() then calls update_vf(cl, qdisc_pkt_len(skb), cur_time) to charge the dequeued bytes.
On the second call the class is already passive, but its child qdisc is still empty, so update_vf() arms go_passive again:
if (cl->qdisc->q.qlen == 0 && cl->cl_flags & HFSC_FSC)
go_passive = 1;The leaf is then skipped by the cl_nactive == 0 check inside the loop, which does not clear go_passive, so the stale go_passive propagates to the parent and decrements its cl_nactive a second time. A parent that still has other active children is driven to cl_nactive == 0 and removed from the vttree, even though those siblings are still backlogged. They are never dequeued again and the qdisc stalls.
Fix this by only arming go_passive when the class is actually active, so an already-passive class no longer triggers a second passive transition. The byte accounting (cl->cl_total += len) still runs for every ancestor, so dequeued bytes continue to be counted exactly once.
--- net/sched/sch_hfsc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_hfsc.c +1 -1
@@ -754,7 +754,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)u64 f;/* , myf_bound, delta; */ int go_passive =0 ; -if (cl->qdisc->q.qlen ==0 && cl->cl_flags &HFSC_FSC ) +if (cl->qdisc->q.qlen ==0 && cl->cl_flags &HFSC_FSC && cl->cl_nactive) go_passive =1 ;for (; cl->cl_parent !=NULL ; cl = cl->cl_parent) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 437/1067 tipc: require net admin for TIPCv2 netlink mutators
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 86b0c540e2ea397cde021eecd24145f7c16a3d4e ]
TIPCv2 registers mutating generic-netlink operations without admin permission flags. Generic netlink only checks CAP_NET_ADMIN when an operation sets GENL_ADMIN_PERM or GENL_UNS_ADMIN_PERM, so a local unprivileged process can currently change TIPC state through commands such as TIPC_NL_NET_SET, TIPC_NL_KEY_SET, TIPC_NL_KEY_FLUSH, and bearer enable/disable.
The legacy TIPC netlink API already checks netlink_net_capable(..., CAP_NET_ADMIN) for administrative commands. Give the TIPCv2 mutators the equivalent generic-netlink gate. Use GENL_UNS_ADMIN_PERM, which maps to the same namespace-aware CAP_NET_ADMIN check that netlink_net_capable() performs, so the behaviour matches the legacy path and keeps working for CAP_NET_ADMIN holders in a non-initial user namespace (containers).
A QEMU/KASAN repro run as uid/gid 65534 with zero effective capabilities previously succeeded in changing the network id and node identity, setting and flushing key material, and enabling/disabling a UDP bearer. With this patch applied the same operations fail with -EPERM.
--- net/tipc/netlink.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
net/tipc/netlink.c +12 -0
@@ -152,11 +152,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_BEARER_DISABLE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_bearer_disable, }, { .cmd = TIPC_NL_BEARER_ENABLE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_bearer_enable, }, {
@@ -168,11 +170,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_BEARER_ADD, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_bearer_add, }, { .cmd = TIPC_NL_BEARER_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_bearer_set, }, {
@@ -197,11 +201,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_LINK_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_node_set_link, }, { .cmd = TIPC_NL_LINK_RESET_STATS, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_node_reset_link_stats, }, {
@@ -213,6 +219,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_MEDIA_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_media_set, }, {
@@ -228,6 +235,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_NET_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_net_set, }, {
@@ -238,6 +246,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_MON_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_node_set_monitor, }, {
@@ -255,6 +264,7 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_PEER_REMOVE, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_peer_rm, },#ifdef CONFIG_TIPC_MEDIA_UDP
@@ -269,11 +279,13 @@ static const struct genl_ops tipc_genl_v2_ops[] = { { .cmd = TIPC_NL_KEY_SET, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_node_set_key, }, { .cmd = TIPC_NL_KEY_FLUSH, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .flags = GENL_UNS_ADMIN_PERM, .doit = tipc_nl_node_flush_key, }, #endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 438/1067 tipc: prevent snt_unacked underflow on CONN_ACK
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit ab3e10b44ba5411779aac7afd2477917dd77750f ]
tipc_sk_conn_proto_rcv() subtracts the peer-supplied connection ack count from the unsigned 16-bit send counter snt_unacked without checking that it does not exceed the number of messages actually outstanding:
tsk->snt_unacked -= msg_conn_ack(hdr);
msg_conn_ack() is read straight from a received CONN_MANAGER/CONN_ACK message. If the ack count is larger than snt_unacked, the subtraction wraps to a near-maximum value, leaving tsk_conn_cong() permanently true and starving the connection of further transmits.
Validate the ACK count at the start of the CONN_ACK block and drop the message if it acknowledges more messages than are outstanding. A peer (or, for a local connection, the connected peer socket) can otherwise wedge a TIPC connection's send side by sending an oversized connection ack.
--- net/tipc/socket.c | 3 +++ 1 file changed, 3 insertions(+)
net/tipc/socket.c +3 -0
@@ -1366,6 +1366,9 @@ static void tipc_sk_conn_proto_rcv(struct tipc_sock *tsk, struct sk_buff *skb,__skb_queue_tail (xmitq, skb);return ; }else if (mtyp ==CONN_ACK ) { +if (tsk->snt_unacked <msg_conn_ack (hdr)) + goto exit; + was_cong =tsk_conn_cong (tsk);tipc_sk_push_backlog (tsk,msg_nagle_ack (hdr)); tsk->snt_unacked -=msg_conn_ack (hdr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 439/1067 tipc: reject inverted service ranges from peer bindings
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 2afb648f7b99216c687db1f89739c995e1144153 ]
tipc_update_nametbl() inserts a binding advertised by a peer node using the lower and upper service-range bounds taken directly from the wire, without checking that lower <= upper. The local bind path validates the ordering (tipc_uaddr_valid()), but the name-distribution path does not.
A binding with lower > upper is inserted at the far end of the service-range rbtree (keyed on lower) where no lookup or withdrawal can ever match it (service_range_foreach_match() requires sr->lower <= end). The publication, its service_range node and the augmented rbtree entry are then leaked for the lifetime of the namespace, and there is no per-peer cap equivalent to TIPC_MAX_PUBL on locally created bindings.
Reject inverted ranges in the network path as well. A peer node can otherwise leak unbounded binding-table memory by sending PUBLICATION items with lower > upper.
--- net/tipc/name_distr.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
net/tipc/name_distr.c +11 -2
@@ -280,12 +280,21 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, u32 node, u32 dtype) {struct publication *p =NULL ; +u32 lower =ntohl (i->lower); +u32 upper =ntohl (i->upper);struct tipc_socket_addr sk; -struct tipc_uaddr ua;u32 key =ntohl (i->key); +struct tipc_uaddr ua; + +/* A peer-advertised binding with lower > upper can never be matched +* or withdrawn and would leak the publication; the local bind path +* rejects such ranges, so reject ranges learned from the network too. +*/ +if (lower > upper) +return false;tipc_uaddr (&ua,TIPC_SERVICE_RANGE ,TIPC_CLUSTER_SCOPE , -ntohl (i->type),ntohl (i->lower),ntohl (i->upper)); +ntohl (i->type), lower, upper); sk.ref =ntohl (i->port); sk.node = node;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 440/1067 cxl/test: Add check after kzalloc() memory in alloc_mock_res()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit dfe28c8592538152e9611341dae6f7be1735b3f1 ]
alloc_mock_res() calls kzalloc() without checking the return value. Add scope based resource management to deal with the allocated memory cleanly.
--- tools/testing/cxl/test/cxl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
tools/testing/cxl/test/cxl.c +6 -2
@@ -264,12 +264,16 @@ static void depopulate_all_mock_resources(void)static struct cxl_mock_res *alloc_mock_res (resource_size_t size) { -struct cxl_mock_res *res =kzalloc (sizeof (*res),GFP_KERNEL );struct genpool_data_align data = { .align =SZ_256M , };unsigned long phys; + struct cxl_mock_res *res __free(kfree) = kzalloc(sizeof(*res), +GFP_KERNEL ); +if (!res) +return NULL ; +INIT_LIST_HEAD (&res->list); phys =gen_pool_alloc_algo (cxl_mock_pool, size, gen_pool_first_fit_align, &data);
@@ -284,7 +288,7 @@ static struct cxl_mock_res *alloc_mock_res(resource_size_t size)list_add (&res->list, &mock_res);mutex_unlock (&mock_res_lock); -return res; +return no_free_ptr (res); }static int populate_cedt (void )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 441/1067 crypto: marvell/octeontx - fix DMA cleanup using wrong loop index
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 7891c64c0520519782470ba29bac8a5761e295d8 ]
The sg_cleanup path used list[i] instead of list[j] when unmapping DMA buffers, leaking successfully mapped entries and repeatedly unmapping the failed one.
--- drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c +2 -2
@@ -157,8 +157,8 @@ static inline int setup_sgio_components(struct pci_dev *pdev, sg_cleanup:for (j =0 ; j < i; j++) {if (list[j].dma_addr) { -dma_unmap_single (&pdev->dev, list[i].dma_addr, - list[i].size,DMA_BIDIRECTIONAL ); +dma_unmap_single (&pdev->dev, list[j].dma_addr, + list[j].size,DMA_BIDIRECTIONAL ); } list[j].dma_addr =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 442/1067 crypto: cavium/cpt - fix DMA cleanup using wrong loop index
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 9dbf173bd32d5f81b005008b682bfb50aa093455 ]
The sg_cleanup error path used list[i] instead of list[j] when unmapping DMA buffers, leaking successfully mapped entries and repeatedly unmapping the failed one.
--- drivers/crypto/cavium/cpt/cptvf_reqmanager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/cavium/cpt/cptvf_reqmanager.c +2 -2
@@ -108,8 +108,8 @@ static int setup_sgio_components(struct cpt_vf *cptvf, struct buf_ptr *list, sg_cleanup:for (j =0 ; j < i; j++) {if (list[j].dma_addr) { -dma_unmap_single (&pdev->dev, list[i].dma_addr, - list[i].size,DMA_BIDIRECTIONAL ); +dma_unmap_single (&pdev->dev, list[j].dma_addr, + list[j].size,DMA_BIDIRECTIONAL ); } list[j].dma_addr =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 443/1067 crypto: rng - Free default RNG on module exit
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ Upstream commit 606ba888b98e0d26a2c4e5c8dc0542e3ad8f0f3a ]
When the rng module is removed the default RNG will be leaked. Call crypto_del_default_rng to free it if possible.
--- crypto/rng.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
crypto/rng.c +11 -0
@@ -232,5 +232,16 @@ void crypto_unregister_rngs(struct rng_alg *algs, int count) }EXPORT_SYMBOL_GPL (crypto_unregister_rngs); +static void __exit rng_exit(void) +{ +int err; + + err =crypto_del_default_rng (); +if (err) +pr_err ("Failed delete default RNG: %d\n" , err); +} + +module_exit (rng_exit); +MODULE_LICENSE ("GPL" );MODULE_DESCRIPTION ("Random Number Generator" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 444/1067 spi: xilinx: use FIFO occupancy register to determine buffer size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lars Pöschel <[email protected]>
[ Upstream commit 47f3b5365536e8c38f264824ab15fdb74454e066 ]
The method the driver uses to determine the size of the FIFO has a problem. What it currently does is this:
It stops the SPI hardware and writes to the TX FIFO register until TX FIFO FULL asserts in the status register. But the hardware does not only have the FIFO, it also has a shift register which can hold a byte. This can be seen, when writing a byte to the FIFO (while the SPI hardware is stopped,) the TX FIFO EMPTY is still empty. So, if we have a FIFO size of 16 for example, the current method returns a 17.
This is a problem, at least when using the driver in irq mode. The same size determined for the TX FIFO is also assumed for the RX FIFO. When a SPI transaction wants to write the amount of the FIFO size or more bytes, the following happens, for example with 16 bytes FIFO size:
The driver stops the SPI hardware and writes 17 bytes to the TX FIFO and starts the SPI hardware and goes sleep.
The hardware then shifts out 17 bytes (FIFO + shift register) and simultaneously reads bytes into the RX FIFO, but it only has 16 places, so it looses one byte. Then TX FIFO empty asserts, wakes the driver again, which has a fast path and reads 16 bytes from the RX FIFO, but before reading the last 17th byte (which is lost) it does this:
sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
xilinx_spi_rx(xspi);
rx_words--;
}It reads the status register and checks if the RX FIFO is not empty. But it is empty in our case. So this check spins in a while loop forever locking the driver.
This patch fixes the logic to determine the FIFO size.
--- drivers/spi/spi-xilinx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/spi/spi-xilinx.c +9 -2
@@ -369,11 +369,18 @@ static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi) xspi->regs + XIPIF_V123B_RESETR_OFFSET);/* Fill the Tx FIFO with as many words as possible */ -do { +while (1 ) { xspi->write_fn (0 , xspi->regs +XSPI_TXD_OFFSET ); sr = xspi->read_fn (xspi->regs +XSPI_SR_OFFSET ); +if (sr &XSPI_SR_TX_FULL_MASK ) +break ; + n_words++; - }while (!(sr &XSPI_SR_TX_FULL_MASK )); + } + +/* Handle the NO FIFO case separately */ +if (!n_words) +return 1 ;return n_words; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 445/1067 ASoC: adau1372: Clear PLL_EN on failed PLL lock without reset GPIO
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 69b4141b428bcf2cf7a863950c0d6e5c5ae89ac1 ]
The PLL lock failure path in adau1372_set_power() unwinds by putting the regmap back in cache-only mode, asserting the optional power-down GPIO and disabling mclk.
adau1372_enable_pll() enables CLK_CTRL.PLL_EN before polling the PLL lock bit. If the lock fails on a board without a power-down GPIO, the error path disables mclk and returns an error, but leaves PLL_EN set in the hardware register. The normal power-off path already handles the no-GPIO case by explicitly clearing PLL_EN.
Mirror that cleanup in the PLL lock failure path and clear PLL_EN while the regmap is still live, before switching it back to cache-only mode.
--- sound/soc/codecs/adau1372.c | 5 +++++ 1 file changed, 5 insertions(+)
sound/soc/codecs/adau1372.c +5 -0
@@ -812,6 +812,11 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)if (adau1372->use_pll) { ret =adau1372_enable_pll (adau1372);if (ret) { +if (!adau1372->pd_gpio) +regmap_update_bits (adau1372->regmap, +ADAU1372_REG_CLK_CTRL , +ADAU1372_CLK_CTRL_PLL_EN , +0 );regcache_cache_only (adau1372->regmap, true);if (adau1372->pd_gpio)gpiod_set_value (adau1372->pd_gpio,1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 446/1067 power: supply: core: fix supplied_from allocations
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tsai <[email protected]>
[ Upstream commit ba61aed9a34671222d1149acfc2f0179a9ce7e80 ]
If dts property power-supplies has multiple values, then accessing to psy->supplied_from[i-1] in __power_supply_populate_supplied_from will overrun supplied_from array.
--- drivers/power/supply/power_supply_core.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-)
drivers/power/supply/power_supply_core.c +3 -8
@@ -262,18 +262,13 @@ static int power_supply_check_supplies(struct power_supply *psy)if (cnt ==1 )return 0 ; -/* All supplies found, allocate char ** array for filling */ - psy->supplied_from =devm_kzalloc (&psy->dev,sizeof (*psy->supplied_from), +/* All supplies found, allocate char * array for filling */ + psy->supplied_from =devm_kcalloc (&psy->dev, + cnt -1 ,sizeof (*psy->supplied_from),GFP_KERNEL );if (!psy->supplied_from)return -ENOMEM ; - *psy->supplied_from =devm_kcalloc (&psy->dev, - cnt -1 ,sizeof (**psy->supplied_from), -GFP_KERNEL ); -if (!*psy->supplied_from) -return -ENOMEM ; - return power_supply_populate_supplied_from(psy); }#else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 447/1067 net/sched: sch_fq_codel: Do not call qdisc_tree_reduce_backlog during peek before restoring qlen
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueira <[email protected]>
[ Upstream commit 097f6fc7b1ae362dd7a9444b2572162fda73b284 ]
Whenever fq_codel drops packets during peek, it calls qdisc_tree_reduce_backlog. An issue arises because it calls qdisc_tree_reduce_backlog before it reincrements the qlen. If qlen drops to zero, but peek returns an skb, the parent's qlen_notify callback will be executed even though fq_codel still has 1 packet on the queue and, thus, will mistakenly deactivate the parent's class causing issues like a recent report [1] and a wild memory access in qfq:
[ 29.371146][ T360] Oops: general protection fault, probably for non-canonical address 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI [ 29.371666][ T360] KASAN: maybe wild-memory-access in range [0xdead000000000120-0xdead000000000127] [ 29.371987][ T360] CPU: 6 UID: 0 PID: 360 Comm: tc Not tainted 7.1.0-rc5-00285-gc530e5b2dbc6-dirty #82 PREEMPT(full) [ 29.372384][ T360] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 29.372620][ T360] RIP: 0010:qfq_deactivate_agg (include/linux/list.h:1029 (discriminator 2) include/linux/list.h:1043 (discriminator 2) net/sched/sch_qfq.c:1369 (discriminator 2) net/sched/sch_qfq.c:1395 (discriminator 2)) sch_qfq [ 29.373544][ T360] RSP: 0018:ffff888102417370 EFLAGS: 00010216 [ 29.373800][ T360] RAX: 0000000000000000 RBX: ffff88811224d568 RCX: dffffc0000000000 [ 29.374079][ T360] RDX: 1ffff11021fe1543 RSI: ffff88810ff0aa00 RDI: dffffc0000000000 [ 29.374368][ T360] RBP: ffff88811224c280 R08: dead000000000122 R09: 1bd5a00000000024 [ 29.374649][ T360] R10: fffffbfff7940329 R11: fffffbfff7940329 R12: 0000000000000000 [ 29.374926][ T360] R13: dead000000000100 R14: ffff88811224d580 R15: ffff88811224d578 [ 29.375207][ T360] FS: 00007f5b794e5780(0000) GS:ffff88815d1e9000(0000) knlGS:0000000000000000 [ 29.375545][ T360] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.375823][ T360] CR2: 000055ffb091f000 CR3: 000000010a305000 CR4: 0000000000750ef0 [ 29.376103][ T360] PKRU: 55555554 [ 29.376258][ T360] Call Trace: [ 29.376401][ T360] <TASK> ... [ 29.376885][ T360] qfq_reset_qdisc (net/sched/sch_qfq.c:357 net/sched/sch_qfq.c:1487) sch_qfq [ 29.377074][ T360] qdisc_reset (net/sched/sch_generic.c:1057) [ 29.377414][ T360] __qdisc_destroy (net/sched/sch_generic.c:1096) [ 29.377600][ T360] qdisc_graft (net/sched/sch_api.c:1062 net/sched/sch_api.c:1053 net/sched/sch_api.c:1159) [ 29.378593][ T360] tc_get_qdisc (net/sched/sch_api.c:1528 net/sched/sch_api.c:1556)
Fix this by only calling qdisc_tree_reduce_backlog in peek after the qlen is restored.
[1] http://lore.kernel.org/netdev/CAN2cbVe79oj0O9==m4+4x3v+O+qzRagA=2=wkrp9i9=CqYvyZA@mail.gmail.com/
--- net/sched/sch_fq_codel.c | 41 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-)
net/sched/sch_fq_codel.c +39 -2
@@ -278,7 +278,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)qdisc_qstats_drop (sch); } -static struct sk_buff *fq_codel_dequeue (struct Qdisc *sch) +static struct sk_buff *__fq_codel_dequeue (struct Qdisc *sch) {struct fq_codel_sched_data *q =qdisc_priv (sch);struct sk_buff *skb;
@@ -315,12 +315,49 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)qdisc_bstats_update (sch, skb); flow->deficit -=qdisc_pkt_len (skb); +return skb; +} + +static void fq_codel_dequeue_drop (struct Qdisc *sch) +{ +struct fq_codel_sched_data *q =qdisc_priv (sch); +if (q->cstats.drop_count) {qdisc_tree_reduce_backlog (sch, q->cstats.drop_count, q->cstats.drop_len); q->cstats.drop_count =0 ; q->cstats.drop_len =0 ; } +} + +static struct sk_buff *fq_codel_dequeue (struct Qdisc *sch) +{ +struct sk_buff *skb; + + skb =__fq_codel_dequeue (sch); + +fq_codel_dequeue_drop (sch); + +return skb; +} + +static struct sk_buff *fq_codel_peek (struct Qdisc *sch) +{ +struct sk_buff *skb =skb_peek (&sch->gso_skb); + +if (!skb) { + skb =__fq_codel_dequeue (sch); + +if (skb) { +__skb_queue_head (&sch->gso_skb, skb); +/* it's still part of the queue */ +qdisc_qstats_backlog_inc (sch, skb); + sch->q.qlen++; + } + +fq_codel_dequeue_drop (sch); + } +return skb; }
@@ -707,7 +744,7 @@ static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = { .priv_size = sizeof(struct fq_codel_sched_data), .enqueue = fq_codel_enqueue, .dequeue = fq_codel_dequeue, - .peek = qdisc_peek_dequeued, + .peek = fq_codel_peek, .init = fq_codel_init, .reset = fq_codel_reset, .destroy = fq_codel_destroy,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 448/1067 net/sched: sch_codel: Do not call qdisc_tree_reduce_backlog during peek before restoring qlen
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueira <[email protected]>
[ Upstream commit 52f1da34c9f4d5bdc1e8b44242da5c7ba8db85f3 ]
Whenever codel drops packets during peek, it calls qdisc_tree_reduce_backlog. An issue arises because it calls qdisc_tree_reduce_backlog before it reincrements the qlen. If qlen drops to zero, but peek returns an skb, the parent's qlen_notify callback will be executed even though codel still has 1 packet on the queue and, thus, will mistakenly deactivate the parent's class causing issues like a wild memory access when qfq has codel as a child:
[ 36.339843][ T370] Oops: general protection fault, probably for non-canonical address 0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI [ 36.340408][ T370] KASAN: maybe wild-memory-access in range [0xdead000000000120-0xdead000000000127] [ 36.340737][ T370] CPU: 2 UID: 0 PID: 370 Comm: tc Not tainted 7.1.0-rc5-00287-g66e13b626592 #87 PREEMPT(full) [ 36.341113][ T370] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 36.341357][ T370] RIP: 0010:qfq_deactivate_agg (include/linux/list.h:1029 (discriminator 2) include/linux/list.h:1043 (discriminator 2) net/sched/sch_qfq.c:1369 (discriminator 2) net/sched/sch_qfq.c:1395 (discriminator 2)) sch_qfq [ 36.342221][ T370] RSP: 0018:ffff8881100ef370 EFLAGS: 00010216 [ 36.342422][ T370] RAX: 0000000000000000 RBX: ffff8881058a9568 RCX: dffffc0000000000 [ 36.342664][ T370] RDX: 1ffff11021064dc3 RSI: ffff888108326e00 RDI: dffffc0000000000 [ 36.342905][ T370] RBP: ffff8881058a8280 R08: dead000000000122 R09: 1bd5a00000000024 [ 36.343140][ T370] R10: fffffbfff2940329 R11: fffffbfff2940329 R12: 0000000000000000 [ 36.343383][ T370] R13: dead000000000100 R14: ffff8881058a9580 R15: ffff8881058a9578 [ 36.343631][ T370] FS: 00007fc04b0ca780(0000) GS:ffff888184fef000(0000) knlGS:0000000000000000 [ 36.343911][ T370] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.344116][ T370] CR2: 0000557c02c02000 CR3: 000000010e0ba000 CR4: 0000000000750ef0 [ 36.344359][ T370] PKRU: 55555554 [ 36.344481][ T370] Call Trace: ... [ 36.345054][ T370] qfq_reset_qdisc (net/sched/sch_qfq.c:357 net/sched/sch_qfq.c:1487) sch_qfq [ 36.345222][ T370] qdisc_reset (net/sched/sch_generic.c:1057) [ 36.345503][ T370] __qdisc_destroy (net/sched/sch_generic.c:1096) [ 36.345677][ T370] qdisc_graft (net/sched/sch_api.c:1062 net/sched/sch_api.c:1053 net/sched/sch_api.c:1159) [ 36.346335][ T370] tc_get_qdisc (net/sched/sch_api.c:1528 net/sched/sch_api.c:1556)
Fix this by only calling qdisc_tree_reduce_backlog in peek after the qlen is restored.
--- net/sched/sch_codel.c | 48 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-)
net/sched/sch_codel.c +43 -5
@@ -86,7 +86,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)qdisc_qstats_drop (sch); } -static struct sk_buff *codel_qdisc_dequeue (struct Qdisc *sch) +static struct sk_buff *__codel_qdisc_dequeue (struct Qdisc *sch) {struct codel_sched_data *q =qdisc_priv (sch);struct sk_buff *skb;
@@ -95,13 +95,51 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch) &q->stats, qdisc_pkt_len, codel_get_enqueue_time, drop_func, dequeue_func); +if (skb) +qdisc_bstats_update (sch, skb); +return skb; +} + +static void codel_dequeue_drop (struct Qdisc *sch) +{ +struct codel_sched_data *q =qdisc_priv (sch); +if (q->stats.drop_count) { -qdisc_tree_reduce_backlog (sch, q->stats.drop_count, q->stats.drop_len); +qdisc_tree_reduce_backlog (sch, q->stats.drop_count, + q->stats.drop_len); q->stats.drop_count =0 ; q->stats.drop_len =0 ; } -if (skb) -qdisc_bstats_update (sch, skb); +} + +static struct sk_buff *codel_qdisc_dequeue (struct Qdisc *sch) +{ +struct sk_buff *skb; + + skb =__codel_qdisc_dequeue (sch); + +codel_dequeue_drop (sch); + +return skb; +} + +static struct sk_buff *codel_peek (struct Qdisc *sch) +{ +struct sk_buff *skb =skb_peek (&sch->gso_skb); + +if (!skb) { + skb =__codel_qdisc_dequeue (sch); + +if (skb) { +__skb_queue_head (&sch->gso_skb, skb); +/* it's still part of the queue */ +qdisc_qstats_backlog_inc (sch, skb); + sch->q.qlen++; + } + +codel_dequeue_drop (sch); + } +return skb; }
@@ -276,7 +314,7 @@ static struct Qdisc_ops codel_qdisc_ops __read_mostly = { .enqueue = codel_qdisc_enqueue, .dequeue = codel_qdisc_dequeue, - .peek = qdisc_peek_dequeued, + .peek = codel_peek, .init = codel_init, .reset = codel_reset, .change = codel_change,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 449/1067 net: mana: initialize gdma queue id to INVALID_QUEUE_ID
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Garg <[email protected]>
[ Upstream commit 5985474e1cb4034680fac2145497a94b0860be50 ]
mana_gd_create_mana_wq_cq() leaves queue->id as 0 (from kzalloc_obj()) until mana_create_wq_obj() assigns the firmware-returned id. If creation fails before that, cleanup calls mana_gd_destroy_cq() with id 0, NULLing gc->cq_table[0] and silently breaking whichever real CQ owns that slot.
Initialize queue->id to INVALID_QUEUE_ID right after allocation, matching mana_gd_create_eq(). The existing (id >= max_num_cqs) guard then short-circuits cleanly.
--- drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/microsoft/mana/gdma_main.c +2 -0
@@ -805,6 +805,8 @@ int mana_gd_create_mana_wq_cq(struct gdma_dev *gd,if (!queue)return -ENOMEM ; + queue->id =INVALID_QUEUE_ID ; + gmi = &queue->mem_info; err =mana_gd_alloc_memory (gc, spec->queue_size, gmi);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 450/1067 net: mana: guard TX wq object destroy with INVALID_MANA_HANDLE check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Garg <[email protected]>
[ Upstream commit f8fd56977eeea3d6939b1a9cd8bd36f1779b3ad0 ]
mana_create_txq() has several error paths (after mana_alloc_queues() or mana_create_wq_obj() failure) where tx_qp[i].tx_object stays as the INVALID_MANA_HANDLE sentinel set at allocation. mana_destroy_txq() then unconditionally calls mana_destroy_wq_obj() with (u64)-1, which firmware rejects and logs an error.
Mirror the RX-side pattern in mana_destroy_rxq() and skip the destroy when the handle is still INVALID_MANA_HANDLE.
--- drivers/net/ethernet/microsoft/mana/mana_en.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +2 -1
@@ -1413,7 +1413,8 @@ static void mana_destroy_txq(struct mana_port_context *apc)netif_napi_del (napi); apc->tx_qp[i].txq.napi_initialized = false; } -mana_destroy_wq_obj (apc,GDMA_SQ , apc->tx_qp[i].tx_object); +if (apc->tx_qp[i].tx_object !=INVALID_MANA_HANDLE ) +mana_destroy_wq_obj (apc,GDMA_SQ , apc->tx_qp[i].tx_object);mana_deinit_cq (apc, &apc->tx_qp[i].tx_cq);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 451/1067 bpf: Run generic devmap egress prog on private skb
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sun Jian <[email protected]>
[ Upstream commit 6001896f00984d317fb75160ba05c4a885fbe2a0 ]
Generic XDP devmap multi redirect uses skb_clone() for intermediate destinations and sends the last destination with the original skb. This can leave multiple destinations sharing the same packet data.
This becomes visible after generic devmap egress-program support was
added: a devmap egress program may mutate packet data, and another destination sharing the same data can observe that mutation.
Native XDP broadcast redirect does not have this issue because xdpf_clone() copies the frame data for each destination. Generic XDP should provide the same per-destination isolation before running a devmap egress program.
Fix this by making cloned skbs private before running the generic devmap egress program. Use skb_copy() instead of skb_unshare() so allocation failure does not consume the skb and the existing caller error paths keep their ownership semantics.
--- kernel/bpf/devmap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
kernel/bpf/devmap.c +12 -0
@@ -681,6 +681,18 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,if (unlikely (err))return err; +if (dst->xdp_prog &&skb_cloned (skb)) { +struct sk_buff *nskb; + + nskb =skb_copy (skb,GFP_ATOMIC ); +if (!nskb) +return -ENOMEM ; + + nskb->mac_len = skb->mac_len; +consume_skb (skb); + skb = nskb; + } +/* Redirect has already succeeded semantically at this point, so we just * return 0 even if packet is dropped. Helper below takes care of * freeing skb.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 452/1067 net/mlx5: Check max_macs devlink param value against max capability
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dragos Tatulea <[email protected]>
[ Upstream commit d7b0413b35715d7b32cb12d4d424613eff85ed2b ]
The max_macs devlink param is checked against the FW max value only at param register time (driver load) and inside the validate callback (devlink param set). The stored DRIVERINIT value persists across FW resets and devlink reloads without any further checks against the max.
If the FW link type changes from Ethernet to IB and a FW reset happens, the MAX cap for log_max_current_uc_list will become zero, but the previously stored max_macs value remains and is unconditionally programmed into the HCA caps in handle_hca_cap(). FW will then return a syndrome during SET_HCA_CAP:
mlx5_cmd_out_err:839:(pid 3831): SET_HCA_CAP(0x109) op_mod(0x0) failed, status bad parameter(0x3), syndrome (0x537801), err(-22) set_hca_cap:907:(pid 3831): handle_hca_cap failed
This results in a failure to register the RDMA device.
This patch skips programming log_max_current_uc_list when the MAX capability is 0 (in case of IB).
--- drivers/net/ethernet/mellanox/mlx5/core/main.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/main.c +7 -5
@@ -550,7 +550,6 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) {struct mlx5_profile *prof = &dev->profile;void *set_hca_cap; -int max_uc_list;int err; err =mlx5_core_get_caps (dev,MLX5_CAP_GENERAL );
@@ -627,10 +626,13 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)MLX5_SET (cmd_hca_cap, set_hca_cap, roce,mlx5_is_roce_on (dev)); - max_uc_list =max_uc_list_get_devlink_param (dev); -if (max_uc_list >0 ) -MLX5_SET (cmd_hca_cap, set_hca_cap, log_max_current_uc_list, -ilog2 (max_uc_list)); +if (MLX5_CAP_GEN_MAX (dev, log_max_current_uc_list)) { +int max_uc_list =max_uc_list_get_devlink_param (dev); + +if (max_uc_list >0 ) +MLX5_SET (cmd_hca_cap, set_hca_cap, + log_max_current_uc_list,ilog2 (max_uc_list)); + }return set_caps (dev, set_ctx,MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 453/1067 net: bcmgenet: Use weighted round-robin TX DMA arbitration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit fd615abd53110f0f815984e99e7cc51ca6b7d979 ]
Under heavy network traffic, we observed sporadic TX queue timeouts on the Raspberry Pi 4. The timeouts can be reproduced by stress testing the TX path with multiple concurrent iperf UDP streams:
iperf3 -c <ip> -u -b0 -P16 -t60
NETDEV WATCHDOG: CPU: 0: transmit queue 0 timed out 2044 ms NETDEV WATCHDOG: CPU: 3: transmit queue 0 timed out 2004 ms
Investigation showed that the timeouts are caused by the priority-based arbiter. Under heavy load the highest priority queue starves the lower priority ones, causing timeouts. The TX strict priority arbiter is not suitable for the default use case where all the traffic gets spread across all the TX queues.
Therefore, to fix this, switch the TX DMA arbiter to Weighted Round-Robin, which services all queues, so they do not stall. The weights were chosen to follow the existing priority scheme: q0 gets the smallest weight, while q1-4 get the bulk of the TX bandwidth.
--- .../net/ethernet/broadcom/genet/bcmgenet.c | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +8 -15
@@ -41,9 +41,8 @@#include "bcmgenet.h" -/* Default highest priority queue for multi queue support */ -#define GENET_Q1_PRIORITY 0 -#define GENET_Q0_PRIORITY 1 +#define GENET_Q0_WEIGHT 1 +#define GENET_Q1_WEIGHT 4#define GENET_Q0_RX_BD_CNT \ (TOTAL_DESC - priv->hw_params->rx_queues * priv->hw_params->rx_bds_per_q)
@@ -2081,13 +2080,6 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)int i; index =skb_get_queue_mapping (skb); -/* Mapping strategy: -* queue_mapping = 0, unclassified, packet xmited through ring 0 -* queue_mapping = 1, goes to ring 1. (highest priority queue) -* queue_mapping = 2, goes to ring 2. -* queue_mapping = 3, goes to ring 3. -* queue_mapping = 4, goes to ring 4. -*/ ring = &priv->tx_rings[index]; txq =netdev_get_tx_queue (dev, index);
@@ -2787,8 +2779,9 @@ static void bcmgenet_fini_tx_napi(struct bcmgenet_priv *priv)/* Initialize Tx queues * -* Queues 1-4 are priority-based, each one has 32 descriptors, -* with queue 1 being the highest priority queue. +* Queues 1-4 are the priority queues, each one has 32 descriptors. +* The weighted round-robin arbiter gives them a larger share of TX +* bandwidth than the default queue 0. * * Queue 0 is the default Tx queue with * GENET_Q0_TX_BD_CNT = 256 - 4 * 32 = 128 descriptors.
@@ -2816,8 +2809,8 @@ static void bcmgenet_init_tx_queues(struct net_device *dev) dma_ctrl =0 ; ring_cfg =0 ; -/* Enable strict priority arbiter mode */ -bcmgenet_tdma_writel (priv,DMA_ARBITER_SP ,DMA_ARB_CTRL ); +/* Enable Weighted Round-Robin arbiter mode */ +bcmgenet_tdma_writel (priv,DMA_ARBITER_WRR ,DMA_ARB_CTRL );/* Initialize Tx priority queues */ for (i =0 ; i <= priv->hw_params->tx_queues; i++) {
@@ -2827,7 +2820,7 @@ static void bcmgenet_init_tx_queues(struct net_device *dev) ring_cfg |= (1 << i); dma_ctrl |= (1 << (i +DMA_RING_BUF_EN_SHIFT )); dma_priority[DMA_PRIO_REG_INDEX (i)] |= - (i ?GENET_Q1_PRIORITY :GENET_Q0_PRIORITY ) + (i ?GENET_Q1_WEIGHT :GENET_Q0_WEIGHT ) <<DMA_PRIO_REG_SHIFT (i); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 454/1067 kcm: use WRITE_ONCE() when changing lower socket callbacks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <[email protected]>
[ Upstream commit 47186409c092cd7dd70350999186c700233e854d ]
kcm_attach() replaces a live lower TCP socket's sk_data_ready and sk_write_space callbacks with KCM handlers, and kcm_unattach() restores them later. Those callback-pointer updates are still plain stores even though the same fields can be read and invoked concurrently on other CPUs.
If another CPU observes an older callback snapshot after the live field has already been restored, callback execution can run with a mismatched target and sk_user_data state, leading to stale or misdirected wakeups.
Use WRITE_ONCE() for the callback replacement and restore operations so these shared callback fields follow the same visibility contract already established by the earlier 4022 fixes.
--- net/kcm/kcmsock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/kcm/kcmsock.c +4 -4
@@ -1403,8 +1403,8 @@ static int kcm_attach(struct socket *sock, struct socket *csock, psock->save_write_space = csk->sk_write_space; psock->save_state_change = csk->sk_state_change; csk->sk_user_data = psock; - csk->sk_data_ready = psock_data_ready; - csk->sk_write_space = psock_write_space; +WRITE_ONCE (csk->sk_data_ready, psock_data_ready); +WRITE_ONCE (csk->sk_write_space, psock_write_space); csk->sk_state_change = psock_state_change;write_unlock_bh (&csk->sk_callback_lock);
@@ -1480,8 +1480,8 @@ static void kcm_unattach(struct kcm_psock *psock)*/ write_lock_bh (&csk->sk_callback_lock); csk->sk_user_data =NULL ; - csk->sk_data_ready = psock->save_data_ready; - csk->sk_write_space = psock->save_write_space; +WRITE_ONCE (csk->sk_data_ready, psock->save_data_ready); +WRITE_ONCE (csk->sk_write_space, psock->save_write_space); csk->sk_state_change = psock->save_state_change;strp_stop (&psock->strp);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 455/1067 netfilter: nf_conncount: callers must hold rcu read lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 64d7d5abe2160bba369b4a8f06bdf5630573bab0 ]
rcu_derefence_raw() should not have been used here, it concealed this bug. Its used because struct rb_node lacks __rcu annotated pointers, so plain rcu_derefence causes sparse warnings.
The major tradeoff is that rcu_derefence_raw() doesn't warn when the caller isn't in a rcu read section.
Extend the rcu read lock scope accordingly and cause sparse warnings, those warnings are the lesser evil.
--- net/netfilter/nf_conncount.c | 6 +++--- net/openvswitch/conntrack.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
net/netfilter/nf_conncount.c +3 -3
@@ -499,7 +499,7 @@ count_tree(struct net *net, hash =jhash2 (key, data->keylen, conncount_rnd) %CONNCOUNT_SLOTS ; root = &data->root[hash]; - parent =rcu_dereference_raw (root->rb_node); + parent =rcu_dereference (root->rb_node);while (parent) {int diff;
@@ -507,9 +507,9 @@ count_tree(struct net *net, diff =key_diff (key, rbconn->key, data->keylen);if (diff <0 ) { - parent =rcu_dereference_raw (parent->rb_left); + parent =rcu_dereference (parent->rb_left); }else if (diff >0 ) { - parent =rcu_dereference_raw (parent->rb_right); + parent =rcu_dereference (parent->rb_right); }else {int ret;
net/openvswitch/conntrack.c +1 -1
@@ -2096,10 +2096,10 @@ static int ovs_ct_limit_get_zone_limit(struct net *net, }else {rcu_read_lock (); limit =ct_limit_get (info, zone); -rcu_read_unlock (); err =__ovs_ct_limit_get_zone_limit ( net, info->data, zone, limit, reply); +rcu_read_unlock ();if (err)return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 456/1067 ALSA: core: Fix unintuitive behavior of snd_power_ref_and_wait()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit b113a891252c3fa4fab11ec8c2894a22ecaf278c ]
snd_power_ref_and_wait() takes the power refcount and doesn't leave it no matter whether it returns an error or not. However, the majority of callers don't expect but just returns without unreferencing in the caller side upon errors.
For addressing the potential refcount unbalance, rather correct the behavior of snd_power_ref_wait() to unreference upon returning an error.
Note that the problem above is likely negligible; the function returns an error only when the sound card is being shutdown, hence it doesn't matter about the power refcount any longer at such a state.
--- sound/core/init.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
sound/core/init.c +8 -3
@@ -1161,7 +1161,7 @@ EXPORT_SYMBOL(snd_card_file_remove);* typically around calling control ops. * * The caller needs to pull down the refcount via snd_power_unref() later -* no matter whether the error is returned from this function or not. +* when this function returns 0. * * Return: Zero if successful, or a negative error code. */
@@ -1174,7 +1174,11 @@ int snd_power_ref_and_wait(struct snd_card *card) card->shutdown ||snd_power_get_state (card) ==SNDRV_CTL_POWER_D0 , snd_power_unref(card), snd_power_ref(card)); -return card->shutdown ? -ENODEV :0 ; +if (card->shutdown) { +snd_power_unref (card); +return -ENODEV ; + } +return 0 ; }EXPORT_SYMBOL_GPL (snd_power_ref_and_wait);
@@ -1191,7 +1195,8 @@ int snd_power_wait(struct snd_card *card)int ret; ret =snd_power_ref_and_wait (card); -snd_power_unref (card); +if (!ret) +snd_power_unref (card);return ret; }EXPORT_SYMBOL (snd_power_wait);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 457/1067 cifs: remove all cifs files before kill super
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jian Zhang <[email protected]>
[ Upstream commit 6d9a4aaaa8b2612b5ef9d581e2f286a458b71ee1 ]
Cifs files may be put into fileinfo_put_wq during umounting cifs. After umount done, cifsFileInfo_put_final is called, which cause following BUG:
BUG: kernel NULL pointer dereference, address: 0000000000000000 ... [ 134.222152] list_lru_add+0x64/0x1a0 [ 134.222399] ? cifs_put_tcon+0x171/0x340 [cifs] [ 134.222772] d_lru_add+0x44/0x60 [ 134.222997] dput+0x1fc/0x210 [ 134.223213] cifsFileInfo_put_final+0x11a/0x140 [cifs] [ 134.223576] process_one_work+0x17c/0x320 [ 134.223843] worker_thread+0x188/0x280 [ 134.224084] ? __pfx_worker_thread+0x10/0x10 [ 134.224366] kthread+0xcc/0x100 [ 134.224576] ? __pfx_kthread+0x10/0x10 [ 134.224827] ret_from_fork+0x30/0x50 [ 134.225063] ? __pfx_kthread+0x10/0x10 [ 134.225328] ret_from_fork_asm+0x1b/0x30
This can be reproduce by following:
unshare -n bash -c "
mkdir -p ${CIFS_MNT}
ip netns attach root 1
ip link add eth0 type veth peer veth0 netns root
ip link set eth0 up
ip -n root link set veth0 up
ip addr add 192.168.0.2/24 dev eth0
ip -n root addr add 192.168.0.1/24 dev veth0
ip route add default via 192.168.0.1 dev eth0
ip netns exec root sysctl net.ipv4.ip_forward=1
ip netns exec root iptables -t nat -A POSTROUTING -s 192.168.0.2 -o
${DEV} -j MASQUERADE
mount -t cifs ${CIFS_PATH} ${CIFS_MNT} -o vers=3.0,sec=ntlmssp,credentials=${CIFS_CRED},rsize=65536,wsize=65536,cache=none,echo_interval=1 touch ${CIFS_MNT}/a.txt
ip netns exec root iptables -t nat -D POSTROUTING -s 192.168.0.2 -o
${DEV} -j MASQUERADE
"
umount ${CIFS_MNT}
--- fs/smb/client/connect.c | 3 +++ 1 file changed, 3 insertions(+)
fs/smb/client/connect.c +3 -0
@@ -4187,6 +4187,9 @@ cifs_umount(struct cifs_sb_info *cifs_sb) }spin_unlock (&cifs_sb->tlink_tree_lock); +flush_workqueue (serverclose_wq); +flush_workqueue (fileinfo_put_wq); +kfree (cifs_sb->prepath);#ifdef CONFIG_CIFS_DFS_UPCALL dfs_cache_put_refsrv_sessions (&cifs_sb->dfs_mount_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 458/1067 smb/client: always return a value for FS_IOC_GETFLAGS
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huiwen He <[email protected]>
[ Upstream commit 7acbaa16b99edaf8ef432229d4b7a6f3b666767d ]
Currently, repeated lsattr calls on a regular CIFS file without the compressed attribute may show random flags:
$ touch test.bin $ lsattr test.bin s-S-ia-A-EjI---------m test.bin $ lsattr test.bin ------d-cEjI---------m test.bin
The lsattr reproducer depends on the previous contents of its userspace buffer, so it may not reproduce on every setup. A deterministic reproducer is to initialize the ioctl argument before FS_IOC_GETFLAGS on a file without the compressed attribute:
int flags = 0x7fffffff;
ioctl(fd, FS_IOC_GETFLAGS, &flags);On an affected kernel, flags remains 0x7fffffff. With the fix, it is set to 0.
This happens because when the cached inode does not have the compressed bit set, the CIFS fallback path in FS_IOC_GETFLAGS returns success without calling put_user() to write the zero flags value into the user buffer. As a result, the caller observes stale contents from its own buffer.
Fix this by always writing the visible flags value back to the user buffer before returning success, even when the value is zero.
--- fs/smb/client/ioctl.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
fs/smb/client/ioctl.c +5 -7
@@ -366,13 +366,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) }#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ #endif /* CONFIG_CIFS_POSIX */ - rc =0 ; -if (CIFS_I (inode)->cifsAttrs &ATTR_COMPRESSED ) { -/* add in the compressed bit */ - ExtAttrBits =FS_COMPR_FL ; - rc =put_user (ExtAttrBits &FS_FL_USER_VISIBLE , - (int __user *)arg); - } +if (CIFS_I (inode)->cifsAttrs &FILE_ATTRIBUTE_COMPRESSED ) + ExtAttrBits |=FS_COMPR_FL ; + + rc =put_user (ExtAttrBits &FS_FL_USER_VISIBLE , + (int __user *)arg);break ;case FS_IOC_SETFLAGS :if (pSMBFile ==NULL )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 459/1067 bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit ca0f587c029afa66227f7b932450b1c417403394 ]
When TCP over IPv4 via INET6 API, bpf_get/setsockopt with ipv4 will fail, because sk->sk_family is AF_INET6. With ipv6 will success, not take effect, because inet_csk(sk)->icsk_af_ops is ipv6_mapped and use ip_queue_xmit, inet_sk(sk)->tos.
To relax this restriction, allow getting/setting tos for those possible ipv4-mapped ipv6 sockets.
--- net/core/filter.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
net/core/filter.c +14 -1
@@ -5374,11 +5374,24 @@ static int sol_tcp_sockopt(struct sock *sk, int optname, KERNEL_SOCKPTR(optval), *optlen); } +static bool sk_allows_sol_ip_sockopt (struct sock *sk) +{ +switch (sk->sk_family) { +case AF_INET : +return true; +case AF_INET6 : +/* Allow getting/setting sockopt for possible ipv4-mapped ipv6 socket. */ +return sk->sk_type !=SOCK_RAW && !ipv6_only_sock (sk); +default : +return false; + } +} +static int sol_ip_sockopt (struct sock *sk,int optname,char *optval,int *optlen,bool getopt) { -if (sk->sk_family !=AF_INET ) +if (!sk_allows_sol_ip_sockopt (sk))return -EINVAL ;switch (optname) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 460/1067 bpf, sockmap: reject overflowing copy + len in bpf_msg_push_data()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 0c0a8ed85349dae298712d79cb276acfeb794d82 ]
When the scatterlist ring is full or nearly full, bpf_msg_push_data() enters a copy fallback path and computes copy + len for the page allocation size. Since len comes from BPF with arg3_type = ARG_ANYTHING and both are u32, a crafted len can wrap the sum to a small value, causing an undersized allocation followed by an out-of-bounds memcpy.
BUG: unable to handle page fault for address: ffffed104089a402 Oops: Oops: 0000 [#1] SMP KASAN NOPTI Call Trace: __asan_memcpy (mm/kasan/shadow.c:105) bpf_msg_push_data (net/core/filter.c:2852 net/core/filter.c:2788) bpf_prog_9ed8b5711920a7d7+0x2e/0x36 sk_psock_msg_verdict (net/core/skmsg.c:934) tcp_bpf_sendmsg (net/ipv4/tcp_bpf.c:421 net/ipv4/tcp_bpf.c:584) __sys_sendto (net/socket.c:2206) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
Add an overflow check before the allocation.
--- net/core/filter.c | 3 +++ 1 file changed, 3 insertions(+)
net/core/filter.c +3 -0
@@ -2815,6 +2815,9 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,if (!space || (space ==1 && start != offset)) copy = msg->sg.data[i].length; +if (unlikely (copy + len < copy)) +return -EINVAL ; + page =alloc_pages (__GFP_NOWARN |GFP_ATOMIC | __GFP_COMP,get_order (copy + len));if (unlikely (!page))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 461/1067 bpf, sockmap: fix integer overflow in bpf_msg_pop_data() bounds check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sechang Lim <[email protected]>
[ Upstream commit a48802fb2cd2d1e23651989f8ff4d15e9d5dad54 ]
start and len are u32, so
u64 last = start + len;
evaluates start + len in 32-bit and wraps before storing it in last. The bounds check
if (start >= offset + l || last > msg->sg.size) return -EINVAL;
can then be passed with an out-of-range start/len, after which the pop loop runs off the end of the scatterlist and sk_msg_shift_left() calls put_page() on the empty msg->sg.end slot:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] RIP: 0010:sk_msg_shift_left net/core/filter.c:2957 [inline] RIP: 0010:____bpf_msg_pop_data net/core/filter.c:3103 [inline] RIP: 0010:bpf_msg_pop_data+0x753/0x1a10 net/core/filter.c:2984 Call Trace: <TASK> bpf_prog_4cc92c278f4d5d56+0x1b1/0x1e8 bpf_prog_run_pin_on_cpu+0x107/0x320 include/linux/filter.h:746 sk_psock_msg_verdict+0x357/0x7f0 net/core/skmsg.c:934 tcp_bpf_send_verdict net/ipv4/tcp_bpf.c:420 [inline] tcp_bpf_sendmsg+0x766/0x1ae0 net/ipv4/tcp_bpf.c:583 __sock_sendmsg+0x153/0x1c0 net/socket.c:802 __sys_sendto+0x326/0x430 net/socket.c:2265 __x64_sys_sendto+0xe3/0x100 net/socket.c:2268 do_syscall_64+0x14c/0x480 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK>
Widen the addition with a (u64) cast so the bound is evaluated in 64-bit and a len near U32_MAX no longer wraps below msg->sg.size.
While here, change pop from int to u32. It counts bytes against the unsigned scatterlist lengths and can never be negative, so the signed type only invites sign-confusion in the pop loop.
--- net/core/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/filter.c +2 -2
@@ -2981,8 +2981,8 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, u32, len, u64, flags) {u32 i =0 , l =0 , space, offset =0 ; -u64 last = start + len; -int pop; +u64 last = (u64 )start + len; +u32 pop;if (unlikely (flags))return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 462/1067 MIPS: mm: Fix out-of-bounds write in maar_res_walk()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yadan Fan <[email protected]>
[ Upstream commit 1b001b16bc88f3f7817e228acfd91ee01bdcfcce ]
maar_res_walk() uses wi->num_cfg as the index into the fixed-size wi->cfg array, but checks whether the array is full only after it has filled the selected entry. If walk_system_ram_range() reports more than 16 memory ranges, the overflow call writes one struct maar_config past the end of the array before WARN_ON() prevents num_cfg from advancing.
Move the full-array check before taking the array slot and return non-zero when the scratch array is full, so walk_system_ram_range() terminates the walk instead of invoking the callback for further ranges.
--- arch/mips/mm/init.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
arch/mips/mm/init.c +8 -4
@@ -276,9 +276,15 @@ static int maar_res_walk(unsigned long start_pfn, unsigned long nr_pages, void *data) {struct maar_walk_info *wi = data; -struct maar_config *cfg = &wi->cfg[wi->num_cfg]; +struct maar_config *cfg;unsigned int maar_align; +/* Ensure we don't overflow the cfg array */ +if (WARN_ON (wi->num_cfg >=ARRAY_SIZE (wi->cfg))) +return -1 ; + + cfg = &wi->cfg[wi->num_cfg]; +/* MAAR registers hold physical addresses right shifted by 4 bits */ maar_align =BIT (MIPS_MAAR_ADDR_SHIFT +4 );
@@ -287,9 +293,7 @@ static int maar_res_walk(unsigned long start_pfn, unsigned long nr_pages, cfg->upper =ALIGN_DOWN (PFN_PHYS (start_pfn + nr_pages), maar_align) -1 ; cfg->attrs =MIPS_MAAR_S ; -/* Ensure we don't overflow the cfg array */ -if (!WARN_ON (wi->num_cfg >=ARRAY_SIZE (wi->cfg))) - wi->num_cfg++; + wi->num_cfg++;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 463/1067 powerpc/perf: fix preempt count underflow in fsl_emb_pmu_del
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aboorva Devarajan <[email protected]>
[ Upstream commit 81e3a86030462824a67d697739cf3f387f4ba350 ]
fsl_emb_pmu_del() unconditionally calls put_cpu_var(cpu_hw_events) at the 'out:' label, but only calls the matching get_cpu_var() after the 'i < 0' early-return check. When event->hw.idx is negative the function jumps to 'out:' without having taken get_cpu_var(), and the trailing put_cpu_var() then issues an unmatched preempt_enable(), underflowing preempt_count.
On a CONFIG_PREEMPT=y kernel preempt_count would underflow and eventually present as a 'scheduling while atomic' BUG.
Move put_cpu_var() to pair with get_cpu_var() so the percpu access is correctly bracketed and the 'out:' label only handles perf_pmu_enable.
--- arch/powerpc/perf/core-fsl-emb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/perf/core-fsl-emb.c +2 -1
@@ -366,9 +366,10 @@ static void fsl_emb_pmu_del(struct perf_event *event, int flags) cpuhw->n_events--; +put_cpu_var (cpu_hw_events); + out:perf_pmu_enable (event->pmu); -put_cpu_var (cpu_hw_events); }static void fsl_emb_pmu_start (struct perf_event *event,int ef_flags)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 464/1067 powerpc/powernv: fix preempt count leak in pnv_kexec_wait_secondaries_down
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aboorva Devarajan <[email protected]>
[ Upstream commit 0ecd26e93e698c8327521910fc6296f5b84a4b92 ]
pnv_kexec_wait_secondaries_down() calls get_cpu() to obtain the current CPU id but never calls the matching put_cpu(), leaking one preempt_disable() nesting level on every invocation.
In practice the imbalance does not trigger a visible splat because the kexec teardown path is a one-way trip: IRQs are already disabled, no schedule() occurs after the leak, and default_machine_kexec() overwrites preempt_count with HARDIRQ_OFFSET before jumping into kexec_sequence() which never returns. However the bookkeeping is still wrong.
The function only needs the current CPU id, and this path runs with interrupts disabled and the CPU pinned, so the preempt_disable() side-effect of get_cpu() is unnecessary. Replace it with raw_smp_processor_id().
--- arch/powerpc/platforms/powernv/setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/powerpc/platforms/powernv/setup.c +2 -1
@@ -396,7 +396,8 @@ static void pnv_kexec_wait_secondaries_down(void) {int my_cpu, i, notified =-1 ; - my_cpu =get_cpu (); +/* Called with interrupts disabled, so the CPU is pinned. */ + my_cpu =raw_smp_processor_id ();for_each_online_cpu (i) {uint8_t status;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 465/1067 powerpc/kexec: fix double get_cpu() imbalance in kexec_prepare_cpus
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aboorva Devarajan <[email protected]>
[ Upstream commit 5c86f1c1f972761a04bf22f4c0618d1aa714185b ]
kexec_prepare_cpus_wait() calls get_cpu() internally to obtain the current CPU id. kexec_prepare_cpus() calls kexec_prepare_cpus_wait() twice -- once for KEXEC_STATE_IRQS_OFF and once for KEXEC_STATE_REAL_MODE -- but only issues a single put_cpu() at the end, leaving preempt_count elevated by one extra nesting level.
In practice the imbalance does not trigger a 'scheduling while atomic' splat because the kexec path is a one-way trip: IRQs are already disabled, no schedule() occurs after the leak, and default_machine_kexec() overwrites preempt_count with HARDIRQ_OFFSET before jumping into kexec_sequence() which never returns. However the bookkeeping is still wrong.
kexec_prepare_cpus() calls local_irq_disable()/hard_irq_disable() before invoking kexec_prepare_cpus_wait(), so the CPU is already pinned and the get_cpu()/put_cpu() preempt_disable() bracketing is unnecessary. Only the current CPU id is needed, so replace get_cpu() with raw_smp_processor_id() and drop the now-unneeded put_cpu().
--- arch/powerpc/kexec/core_64.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/powerpc/kexec/core_64.c +1 -3
@@ -169,7 +169,7 @@ static void kexec_prepare_cpus_wait(int wait_state)int my_cpu, i, notified=-1 ;hw_breakpoint_disable (); - my_cpu =get_cpu (); + my_cpu =raw_smp_processor_id ();/* Make sure each CPU has at least made it to the state we need. * * FIXME: There is a (slim) chance of a problem if not all of the CPUs
@@ -267,8 +267,6 @@ static void kexec_prepare_cpus(void)/* after we tell the others to go down */ if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(0, 0); - - put_cpu(); }#else /* ! SMP */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 466/1067 KEYS: Use acquire when reading state in keyring search
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gui-Dong Han <[email protected]>
[ Upstream commit c1201b37f666f6466ab1fd3a381c2b7a4b7e9fee ]
The negative-key race fix added release/acquire ordering for key use.
Publish payload before state; read state before payload.
keyring_search_iterator() still uses READ_ONCE() before match callbacks. An asymmetric match callback calls asymmetric_key_ids(), which reads key->payload.data[asym_key_ids].
Use key_read_state() there to complete that ordering.
--- security/keys/keyring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/keyring.c +1 -1
@@ -576,7 +576,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)struct keyring_search_context *ctx = iterator_data;const struct key *key =keyring_ptr_to_key (object);unsigned long kflags =READ_ONCE (key->flags); -short state =READ_ONCE (key->state); +short state =key_read_state (key);kenter ("{%d}" , key->serial);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 467/1067 tipc: fix UAF in tipc_l2_send_msg()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit f4c3d89fc986b0da196ddfc6cfe0ea5d5d08bec6 ]
Syzbot reported a slab-use-after-free in ipvlan_hard_header() when called from tipc_l2_send_msg().
The root cause is that tipc_disable_l2_media() calls synchronize_net() while b->media_ptr is still valid. This allows concurrent RCU readers to obtain the device pointer after synchronize_net() has finished. The pointer is cleared later in bearer_disable(), but without any subsequent synchronization, allowing the device to be freed while still in use by readers.
Fix this by clearing b->media_ptr in tipc_disable_l2_media() before calling synchronize_net().
This is safe to do now because the call order in bearer_disable() was reversed in 0d051bf93c06 ("tipc: make bearer packet filtering generic") to call tipc_node_delete_links() (which needs the pointer) before disable_media().
https: //lore.kernel.org/netdev/[email protected]/T/#u
--- net/tipc/bearer.c | 1 + 1 file changed, 1 insertion(+)
net/tipc/bearer.c +1 -0
@@ -484,6 +484,7 @@ void tipc_disable_l2_media(struct tipc_bearer *b) dev = (struct net_device *)rtnl_dereference (b->media_ptr);dev_remove_pack (&b->pt);RCU_INIT_POINTER (dev->tipc_ptr,NULL ); +RCU_INIT_POINTER (b->media_ptr,NULL );synchronize_net ();dev_put (dev); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 468/1067 tcp: ipv6: clamp default adverting MSS to avoid GSO_BY_FRAGS (0xFFFF)
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 2bf43d0e2e6a27d52a7d624e2d6b9116972e8a22 ]
When MTU is large, ip6_default_advmss() can return IPV6_MAXPLEN (65535). This is interpreted by TCP as mss_clamp, allowing the MSS to reach 65535.
However, 0xFFFF is also used as a magic value GSO_BY_FRAGS in the kernel. If a TCP packet with gso_size=0xFFFF is passed to skb_segment(), it will be mistakenly treated as GSO_BY_FRAGS, leading to a NULL pointer dereference because local TCP packets do not use frag_list.
Fix this by returning min(IPV6_MAXPLEN, GSO_BY_FRAGS - 1) (65534) from ip6_default_advmss() when MTU is large.
Also update the stale comment in ip6_default_advmss() which suggested that IPV6_MAXPLEN is returned to mean "any MSS".
--- net/ipv6/route.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/ipv6/route.c +3 -3
@@ -3243,11 +3243,11 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)/* * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and * corresponding MSS is IPV6_MAXPLEN - tcp_header_size. -* IPV6_MAXPLEN is also valid and means: "any MSS, -* rely only on pmtu discovery" +* Limit the default MSS to GSO_BY_FRAGS - 1 to avoid +* collision with the GSO_BY_FRAGS magic value (0xFFFF). */ if (mtu >IPV6_MAXPLEN -sizeof (struct tcphdr )) - mtu =IPV6_MAXPLEN ; + mtu = min_t(unsigned int, IPV6_MAXPLEN, GSO_BY_FRAGS - 1);return mtu; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 469/1067 ksmbd: fix use-after-free in same_client_has_lease()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 65b655f65c3ca1ab5d598d3832bb0ff531725858 ]
same_client_has_lease() returns an opinfo pointer from ci->m_op_list after dropping ci->m_lock without taking a reference.
smb_grant_oplock() then dereferences that pointer in copy_lease() and when checking breaking_cnt. A concurrent close can remove the old lease from ci->m_op_list and drop the last reference before the caller uses the returned pointer, leading to a use-after-free.
Take a reference when same_client_has_lease() selects an existing lease, drop any previous match while scanning, and release the returned reference in smb_grant_oplock() after copying the lease state.
--- fs/smb/server/oplock.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/smb/server/oplock.c +6 -0
@@ -534,7 +534,12 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci, ret =compare_guid_key (opinfo, client_guid, lctx->lease_key);if (ret) { +if (!atomic_inc_not_zero (&opinfo->refcount)) +continue ; +if (m_opinfo) +opinfo_put (m_opinfo); m_opinfo = opinfo; +/* skip upgrading lease about breaking lease */ if (atomic_read (&opinfo->breaking_cnt)) {read_lock (&ci->m_lock);
@@ -1253,6 +1258,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,if (atomic_read (&m_opinfo->breaking_cnt)) opinfo->o_lease->flags =SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE ; +opinfo_put (m_opinfo); goto out; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 470/1067 ocfs2: fix circular locking dependency in ocfs2_dio_end_io_write
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Nogikh <[email protected]>
[ Upstream commit ff6f26c58421614b02694ac9d219ac61d924bc68 ]
A circular locking dependency involves INODE_ALLOC_SYSTEM_INODE, EXTENT_ALLOC_SYSTEM_INODE, and ORPHAN_DIR_SYSTEM_INODE.
1. ocfs2_mknod() acquires INODE_ALLOC then EXTENT_ALLOC.
2. ocfs2_dio_end_io_write() acquires EXTENT_ALLOC for unwritten extents, then ORPHAN_DIR via ocfs2_del_inode_from_orphan() while still holding EXTENT_ALLOC.
3. ocfs2_wipe_inode() acquires ORPHAN_DIR then INODE_ALLOC via ocfs2_remove_inode.
Break the cycle in ocfs2_dio_end_io_write() by freeing the allocation contexts (releasing EXTENT_ALLOC) before acquiring ORPHAN_DIR.
WARNING: possible circular locking dependency detected
------------------------------------------------------
is trying to acquire lock:ffff8881e78b33a0 (&ocfs2_sysfile_lock_key[INODE_ALLOC_SYSTEM_INODE]){+.+.}-{4:4}, at:ocfs2_evict_inode+0x1539/0x43b0 fs/ocfs2/inode.c:1299
but task is already holding lock:ffff8881e78b4fa0 (&ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]){+.+.}-{4:4}, at:ocfs2_evict_inode+0xe97/0x43b0 fs/ocfs2/inode.c:1299
the existing dependency chain (in reverse order) is:
-> #2 (&ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]){+.+.}-{4:4}:
inode_lock include/linux/fs.h:1029 [inline]
ocfs2_del_inode_from_orphan+0x12e/0x7a0 fs/ocfs2/namei.c:2728
ocfs2_dio_end_io+0xf9c/0x1370 fs/ocfs2/aops.c:2418
dio_complete+0x25b/0x790 fs/direct-io.c:281-> #1 (&ocfs2_sysfile_lock_key[EXTENT_ALLOC_SYSTEM_INODE]){+.+.}-{4:4}:
inode_lock include/linux/fs.h:1029 [inline]
ocfs2_reserve_suballoc_bits+0x16d/0x4840 fs/ocfs2/suballoc.c:882
ocfs2_reserve_new_metadata_blocks+0x415/0x9a0
fs/ocfs2/suballoc.c:1078
ocfs2_mknod+0x10f3/0x2260 fs/ocfs2/namei.c:351-> #0 (&ocfs2_sysfile_lock_key[INODE_ALLOC_SYSTEM_INODE]){+.+.}-{4:4}:
__lock_acquire+0x15a5/0x2cf0 kernel/locking/lockdep.c:5237
lock_acquire+0x106/0x350 kernel/locking/lockdep.c:5868
down_write+0x96/0x200 kernel/locking/rwsem.c:1625
inode_lock include/linux/fs.h:1029 [inline]
ocfs2_remove_inode fs/ocfs2/inode.c:733 [inline]
ocfs2_wipe_inode fs/ocfs2/inode.c:896 [inline]
ocfs2_delete_inode fs/ocfs2/inode.c:1157 [inline]
ocfs2_evict_inode+0x1539/0x43b0 fs/ocfs2/inode.c:1299
Chain exists of:
&ocfs2_sysfile_lock_key[INODE_ALLOC_SYSTEM_INODE] -->
&ocfs2_sysfile_lock_key[EXTENT_ALLOC_SYSTEM_INODE] -->
&ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]
Possible unsafe locking scenario: CPU0 CPU1
---- ----
lock(&ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]);
lock(&ocfs2_sysfile_lock_key[EXTENT_ALLOC_SYSTEM_INODE]);
lock(&ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE]); lock(&ocfs2_sysfile_lock_key[INODE_ALLOC_SYSTEM_INODE]);
*** DEADLOCK ***
--- fs/ocfs2/aops.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/ocfs2/aops.c +9 -4
@@ -2400,6 +2400,15 @@ static int ocfs2_dio_end_io_write(struct inode *inode, unlock:up_write (&oi->ip_alloc_sem); +if (data_ac) { +ocfs2_free_alloc_context (data_ac); + data_ac =NULL ; + } +if (meta_ac) { +ocfs2_free_alloc_context (meta_ac); + meta_ac =NULL ; + } +/* everything looks good, let's start the cleanup */ if (!ret && dwc->dw_orphaned) {BUG_ON (dwc->dw_writer_pid !=task_pid_nr (current));
@@ -2411,10 +2420,6 @@ static int ocfs2_dio_end_io_write(struct inode *inode,ocfs2_inode_unlock (inode,1 );brelse (di_bh); out: -if (data_ac) -ocfs2_free_alloc_context (data_ac); -if (meta_ac) -ocfs2_free_alloc_context (meta_ac);ocfs2_run_deallocs (osb, &dealloc);ocfs2_dio_free_write_ctx (inode, dwc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 471/1067 net/9p: fix race condition on rdma->state in trans_rdma.c
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
[ Upstream commit 7d54894a1ee265a72d70f7cae1da6cc774cccc71 ]
The rdma->state field is modified without holding req_lock in both recv_done() and p9_cm_event_handler(), while rdma_request() accesses the same field under the req_lock spinlock. This inconsistent locking creates a race condition:
- recv_done() running in softirq completion context sets rdma->state = P9_RDMA_FLUSHING without acquiring req_lock
- p9_cm_event_handler() modifies rdma->state at multiple points (ADDR_RESOLVED, ROUTE_RESOLVED, ESTABLISHED, CLOSED) without req_lock
- rdma_request() uses spin_lock_irqsave(&rdma->req_lock, flags) to protect the read-modify-write of rdma->state
The race can cause lost state transitions: recv_done() or the CM event handler could set state to FLUSHING/CLOSED while rdma_request() is concurrently checking or modifying state under the lock, leading to the FLUSHING transition being silently overwritten by CLOSING. This corrupts the connection state machine and can cause use-after-free on RDMA request objects during teardown.
Fix by adding req_lock protection to all rdma->state modifications in recv_done() and p9_cm_event_handler(), matching the pattern already used in rdma_request(). Use spin_lock_irqsave/spin_unlock_irqrestore in the CM event handler since it can race with recv_done() which runs in softirq context.
Tested with a kernel module that races two threads (simulating rdma_request and recv_done/CM handler) on rdma->state with proper
locking: 5.5M+ FLUSHING writes over 27M iterations with 0 lost transitions.
Message-ID: <[email protected]>
--- net/9p/trans_rdma.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
net/9p/trans_rdma.c +17 -2
@@ -241,25 +241,36 @@ p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) {struct p9_client *c = id->context;struct p9_trans_rdma *rdma = c->trans; +unsigned long flags; +switch (event->event) {case RDMA_CM_EVENT_ADDR_RESOLVED : +spin_lock_irqsave (&rdma->req_lock, flags);BUG_ON (rdma->state !=P9_RDMA_INIT ); rdma->state =P9_RDMA_ADDR_RESOLVED ; +spin_unlock_irqrestore (&rdma->req_lock, flags);break ;case RDMA_CM_EVENT_ROUTE_RESOLVED : +spin_lock_irqsave (&rdma->req_lock, flags);BUG_ON (rdma->state !=P9_RDMA_ADDR_RESOLVED ); rdma->state =P9_RDMA_ROUTE_RESOLVED ; +spin_unlock_irqrestore (&rdma->req_lock, flags);break ;case RDMA_CM_EVENT_ESTABLISHED : +spin_lock_irqsave (&rdma->req_lock, flags);BUG_ON (rdma->state !=P9_RDMA_ROUTE_RESOLVED ); rdma->state =P9_RDMA_CONNECTED ; +spin_unlock_irqrestore (&rdma->req_lock, flags);break ;case RDMA_CM_EVENT_DISCONNECTED : -if (rdma) +if (rdma) { +spin_lock_irqsave (&rdma->req_lock, flags); rdma->state =P9_RDMA_CLOSED ; +spin_unlock_irqrestore (&rdma->req_lock, flags); + } c->status = Disconnected;break ;
@@ -297,6 +308,7 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc)struct p9_req_t *req;int err =0 ;int16_t tag; +unsigned long flags; req =NULL ; ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize,
@@ -333,7 +345,10 @@ recv_done(struct ib_cq *cq, struct ib_wc *wc) err_out:p9_debug (P9_DEBUG_ERROR ,"req %p err %d status %d\n" , req, err, wc->status); - rdma->state =P9_RDMA_FLUSHING ; +spin_lock_irqsave (&rdma->req_lock, flags); +if (rdma->state <P9_RDMA_FLUSHING ) + rdma->state =P9_RDMA_FLUSHING ; +spin_unlock_irqrestore (&rdma->req_lock, flags); client->status = Disconnected; goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 472/1067 staging: nvec: fix use-after-free in nvec_rx_completed()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandru Hossu <[email protected]>
[ Upstream commit 26813881181deb3a32fbb59eadb2599cbe8423f6 ]
In nvec_rx_completed(), when an incomplete RX transfer is detected, nvec_msg_free() is called to return the message back to the pool by clearing its 'used' atomic flag. Immediately after this, the code accesses nvec->rx->data[0] to check the message type.
Since nvec_msg_free() marks the pool slot as available via atomic_set(), any concurrent or subsequent call to nvec_msg_alloc() could claim that same slot and overwrite its data[] array. Reading nvec->rx->data[0] after freeing the message is therefore a use-after-free.
Fix this by saving the message type byte before calling nvec_msg_free(), then using the saved value for the battery quirk check.
--- drivers/staging/nvec/nvec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/staging/nvec/nvec.c +3 -1
@@ -489,6 +489,8 @@ static void nvec_tx_completed(struct nvec_chip *nvec)static void nvec_rx_completed (struct nvec_chip *nvec) {if (nvec->rx->pos !=nvec_msg_size (nvec->rx)) { +unsigned char msg_type = nvec->rx->data[0 ]; +dev_err (nvec->dev,"RX incomplete: Expected %u bytes, got %u\n" , (uint )nvec_msg_size (nvec->rx), (uint )nvec->rx->pos);
@@ -497,7 +499,7 @@ static void nvec_rx_completed(struct nvec_chip *nvec) nvec->state =0 ;/* Battery quirk - Often incomplete, and likes to crash */ -if (nvec->rx->data[0 ] ==NVEC_BAT ) +if (msg_type ==NVEC_BAT )complete (&nvec->ec_transfer);return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 473/1067 coresight: cti: Fix DT filter signals silently ignored
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yingchao Deng <[email protected]>
[ Upstream commit 551bb2fd5e4ed63d33aa11f07102cce5179b7595 ]
In cti_plat_process_filter_sigs(), after allocating a temporary cti_trig_grp struct via kzalloc_obj(), the code never assigns tg->nr_sigs = nr_filter_sigs. Since kzalloc zero-initialises the struct, tg->nr_sigs remains 0. cti_plat_read_trig_group() guards with:
if (!tgrp->nr_sigs)
return 0;so it returns immediately without reading any signal indices from DT.
Fix by assigning tg->nr_sigs before calling cti_plat_read_trig_group().
--- drivers/hwtracing/coresight/coresight-cti-platform.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwtracing/coresight/coresight-cti-platform.c +1 -0
@@ -329,6 +329,7 @@ static int cti_plat_process_filter_sigs(struct cti_drvdata *drvdata,if (!tg)return -ENOMEM ; + tg->nr_sigs = nr_filter_sigs; err =cti_plat_read_trig_group (tg, fwnode,CTI_DT_FILTER_OUT_SIGS );if (!err) drvdata->config.trig_out_filter |= tg->used_mask;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 474/1067 coresight: etm4x: Correct TRCVMIDCCTLR1 save and restore
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Yan <[email protected]>
[ Upstream commit 0ec0a8785d21f63db520bd9d2a67c55e855d36a8 ]
It is a typo to use trcvmidcctlr0 to save and restore TRCVMIDCCTLR1. Use trcvmidcctlr1 instead.
--- drivers/hwtracing/coresight/coresight-etm4x-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwtracing/coresight/coresight-etm4x-core.c +2 -2
@@ -1758,7 +1758,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata) state->trcvmidcctlr0 =etm4x_read32 (csa,TRCVMIDCCTLR0 );if (drvdata->numvmidc >4 ) - state->trcvmidcctlr0 =etm4x_read32 (csa,TRCVMIDCCTLR1 ); + state->trcvmidcctlr1 =etm4x_read32 (csa,TRCVMIDCCTLR1 ); state->trcclaimset =etm4x_read32 (csa,TRCCLAIMCLR );
@@ -1884,7 +1884,7 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)etm4x_relaxed_write32 (csa, state->trcvmidcctlr0,TRCVMIDCCTLR0 );if (drvdata->numvmidc >4 ) -etm4x_relaxed_write32 (csa, state->trcvmidcctlr0,TRCVMIDCCTLR1 ); +etm4x_relaxed_write32 (csa, state->trcvmidcctlr1,TRCVMIDCCTLR1 );etm4x_relaxed_write32 (csa, state->trcclaimset,TRCCLAIMSET );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 475/1067 PCI/ASPM: Dont reconfigure ASPM entering low-power state
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Bilbao <[email protected]>
[ Upstream commit c855c9921da72e535c24737c748f603a52d03f7e ]
Reconfiguring ASPM when a device transitions to low-power state can enable L1.1/L1.2 substates on the PCIe link at a time when the device is sleeping and may be unable to exit them. ASPM should be reconfigured on D0 entry (resume), not on the way down.
pci_set_low_power_state() calls pcie_aspm_pm_state_change() after writing D3hot to PCI_PM_CTRL. pcie_aspm_pm_state_change() resets link->aspm_capable to link->aspm_support and then calls pcie_config_aspm_path(), which can enable ASPM L1.1/L1.2 substates on the PCIe link. If the device cannot recover the link from L1.2 while in D3hot, subsequent config space reads return 0xFFFF ("device inaccessible") and pci_power_up() fails with messages like:
vfio-pci 0000:5d:00.0: Unable to change power state from D3hot to D0, device inaccessible
This was observed on NVIDIA H100 SXM5 GPUs bound to vfio-pci when Linux runtime PM suspends them to D3hot: the GPU becomes permanently inaccessible and disappears from the PCIe bus.
The call to pcie_aspm_pm_state_change() in pci_set_low_power_state() was restored by f93e71aea6c6 ("Revert "PCI/ASPM: Remove pcie_aspm_pm_state_change()""), which reverted 08d0cc5f3426 ("PCI/ASPM:
Remove pcie_aspm_pm_state_change()"). The revert was necessary because the removal broke suspend/resume on certain platforms that required ASPM to be reconfigured on D0 entry. However, the revert restored the call in both pci_set_full_power_state() (D0 entry) and pci_set_low_power_state() (low-power entry).
Only the D0-entry call is needed to fix the suspend/resume regression. The low-power-entry call is harmful: reconfiguring ASPM immediately after putting a device into D3hot can enable link substates that the device or platform cannot exit while the device is sleeping.
Remove the pcie_aspm_pm_state_change() call from pci_set_low_power_state(). ASPM will still be reconfigured correctly when the device returns to D0 via pci_set_full_power_state().
--- drivers/pci/pci.c | 3 --- 1 file changed, 3 deletions(-)
drivers/pci/pci.c +0 -3
@@ -1488,9 +1488,6 @@ static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state, boolpci_power_name (dev->current_state), pci_power_name(state)); -if (dev->bus->self) -pcie_aspm_pm_state_change (dev->bus->self, locked); -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 476/1067 PCI: Introduce named defines for PCI ROM
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guixin Liu <[email protected]>
[ Upstream commit 113e86bc58a918f85d250723436a4d541a873358 ]
Convert the magic numbers associated with PCI ROM into named definitions. Some of these definitions will be used in the second fix patch.
Stable-dep-of: 538796b807fc ("PCI: Check ROM header and data structure addr before accessing")
--- drivers/pci/rom.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-)
drivers/pci/rom.c +28 -12
@@ -5,13 +5,28 @@* (C) Copyright 2004 Jon Smirl <[email protected]> * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <[email protected]> */ + +#include <linux/bits.h> #include <linux/kernel.h> #include <linux/export.h> #include <linux/pci.h> +#include <linux/sizes.h> #include <linux/slab.h> #include "pci.h" +#define PCI_ROM_HEADER_SIZE 0x1A +#define PCI_ROM_POINTER_TO_DATA_STRUCT 0x18 +#define PCI_ROM_LAST_IMAGE_INDICATOR 0x15 +#define PCI_ROM_LAST_IMAGE_INDICATOR_BIT BIT(7) +#define PCI_ROM_IMAGE_LEN 0x10 +#define PCI_ROM_IMAGE_SECTOR_SIZE SZ_512 +#define PCI_ROM_IMAGE_SIGNATURE 0xAA55 + +/* Data structure signature is "PCIR" in ASCII representation */ +#define PCI_ROM_DATA_STRUCT_SIGNATURE 0x52494350 +#define PCI_ROM_DATA_STRUCT_LEN 0x0A +/** * pci_enable_rom - enable ROM decoding for a PCI device * @pdev: PCI device to enable
@@ -91,26 +106,27 @@ static size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, do { void __iomem *pds; /* Standard PCI ROMs start out with these bytes 55 AA */ - if (readw(image) != 0xAA55) { - pci_info(pdev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n", - readw(image)); + if (readw(image) != PCI_ROM_IMAGE_SIGNATURE) { + pci_info(pdev, "Invalid PCI ROM header signature: expecting %#06x, got %#06x\n", + PCI_ROM_IMAGE_SIGNATURE, readw(image)); break; } - /* get the PCI data structure and check its "PCIR" signature */ - pds = image + readw(image + 24); - if (readl(pds) != 0x52494350) { - pci_info(pdev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n", - readl(pds)); + /* Get the PCI data structure and check its "PCIR" signature */ + pds = image + readw(image + PCI_ROM_POINTER_TO_DATA_STRUCT); + if (readl(pds) != PCI_ROM_DATA_STRUCT_SIGNATURE) { + pci_info(pdev, "Invalid PCI ROM data signature: expecting %#010x, got %#010x\n", + PCI_ROM_DATA_STRUCT_SIGNATURE, readl(pds)); break; } - last_image = readb(pds + 21) & 0x80; - length = readw(pds + 16); - image += length * 512; + last_image = readb(pds + PCI_ROM_LAST_IMAGE_INDICATOR) & + PCI_ROM_LAST_IMAGE_INDICATOR_BIT; + length = readw(pds + PCI_ROM_IMAGE_LEN); + image += length * PCI_ROM_IMAGE_SECTOR_SIZE; /* Avoid iterating through memory outside the resource window */ if (image >= rom + size) break; if (!last_image) { - if (readw(image) != 0xAA55) { + if (readw(image) != PCI_ROM_IMAGE_SIGNATURE) { pci_info(pdev, "No more image in the PCI ROM\n"); break; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 477/1067 PCI: Check ROM header and data structure addr before accessing
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guixin Liu <[email protected]>
[ Upstream commit 538796b807fcfb81b2ce40cc97a614fd8588feb5 ]
We meet a crash when running stress-ng on x86_64 machine:
BUG: unable to handle page fault for address: ffa0000007f40000
RIP: 0010:pci_get_rom_size+0x52/0x220
Call Trace:
<TASK>
pci_map_rom+0x80/0x130
pci_read_rom+0x4b/0xe0
kernfs_file_read_iter+0x96/0x180
vfs_read+0x1b1/0x300Our analysis reveals that the ROM space's start address is 0xffa0000007f30000, and size is 0x10000. Because of broken ROM space, before calling readl(pds), the pds's value is 0xffa0000007f3ffff, which is already pointed to the ROM space end, invoking readl() would read 4 bytes therefore cause an out-of-bounds access and trigger a crash. Fix this by adding image header and data structure checking.
We also found another crash on arm64 machine:
Unable to handle kernel paging request at virtual address ffff8000dd1393ff Mem abort info: ESR = 0x0000000096000021 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x21: alignment fault
The call trace is the same with x86_64, but the crash reason is that the data structure addr is not aligned with 4, and arm64 machine report "alignment fault". Fix this by adding alignment checking.
--- drivers/pci/rom.c | 123 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 18 deletions(-)
drivers/pci/rom.c +105 -18
@@ -6,9 +6,12 @@* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <[email protected]> */ +#include <linux/align.h> #include <linux/bits.h> #include <linux/kernel.h> #include <linux/export.h> +#include <linux/io.h> +#include <linux/overflow.h> #include <linux/pci.h> #include <linux/sizes.h> #include <linux/slab.h>
@@ -27,6 +30,15 @@#define PCI_ROM_DATA_STRUCT_SIGNATURE 0x52494350#define PCI_ROM_DATA_STRUCT_LEN 0x0A +/* +* Per PCI Firmware r3.3, sec 5.1.3, a conformant PCI Data Structure is at +* least 24 bytes (0x18), large enough to cover every fixed field this +* driver reads (up to the Indicator byte at offset 0x15). Reject smaller +* device-claimed lengths so the follow-up readers in pci_get_rom_size() +* cannot escape the mapped ROM window. +*/ +#define PCI_ROM_DATA_STRUCT_MIN_LEN 0x18 +/** * pci_enable_rom - enable ROM decoding for a PCI device * @pdev: PCI device to enable
@@ -84,6 +96,91 @@ void pci_disable_rom(struct pci_dev *pdev) }EXPORT_SYMBOL_GPL (pci_disable_rom); +static bool pci_rom_header_valid (struct pci_dev *pdev,void __iomem *image, +void __iomem *rom,size_t size, +bool expect_valid) +{ +unsigned long rom_end = (unsigned long )rom + size -1 ; +unsigned long header_end; +u16 signature; + +/* +* Per PCI Firmware r3.3, sec 5.1, each image must start on a +* 512-byte boundary and must contain the PCI Expansion ROM header. +* Because @rom is page-aligned (returned by ioremap()), checking +* 512-byte alignment of @image is equivalent to enforcing the +* spec's sector-aligned layout within the ROM. This also +* satisfies the natural-alignment requirement of readw() on archs +* such as arm64 that disallow unaligned IOMEM access. +*/ +if (!IS_ALIGNED ((unsigned long )image,PCI_ROM_IMAGE_SECTOR_SIZE )) +return false; + +if (check_add_overflow ((unsigned long )image,PCI_ROM_HEADER_SIZE -1 , + &header_end)) +return false; + +if (image < rom || header_end > rom_end) +return false; + +/* Standard PCI ROMs start out with these bytes 55 AA */ + signature =readw (image); +if (signature !=PCI_ROM_IMAGE_SIGNATURE ) { +if (expect_valid) { +pci_info (pdev,"Invalid PCI ROM header signature: expecting %#06x, got %#06x\n" , +PCI_ROM_IMAGE_SIGNATURE , signature); + }else { +pci_info (pdev,"No more images in PCI ROM\n" ); + } +return false; + } + +return true; +} + +static bool pci_rom_data_struct_valid (struct pci_dev *pdev,void __iomem *pds, +void __iomem *rom,size_t size) +{ +unsigned long rom_end = (unsigned long )rom + size -1 ; +unsigned long end; +u32 signature; +u16 data_len; + +/* +* Some CPU architectures require IOMEM access addresses to be +* aligned, for example arm64, so since we're about to call +* readl(), check here for 4-byte alignment. +*/ +if (!IS_ALIGNED ((unsigned long )pds,4 )) +return false; + +if (check_add_overflow ((unsigned long )pds,PCI_ROM_DATA_STRUCT_LEN +1 , + &end)) +return false; + +if (pds < rom || end > rom_end) +return false; + + signature =readl (pds); +if (signature !=PCI_ROM_DATA_STRUCT_SIGNATURE ) { +pci_info (pdev,"Invalid PCI ROM data signature: expecting %#010x, got %#010x\n" , +PCI_ROM_DATA_STRUCT_SIGNATURE , signature); +return false; + } + + data_len =readw (pds +PCI_ROM_DATA_STRUCT_LEN ); +if (data_len <PCI_ROM_DATA_STRUCT_MIN_LEN || data_len ==U16_MAX ) +return false; + +if (check_add_overflow ((unsigned long )pds, data_len -1 , &end)) +return false; + +if (end > rom_end) +return false; + +return true; +} +/** * pci_get_rom_size - obtain the actual size of the ROM image * @pdev: target PCI device
@@ -99,38 +196,28 @@ static size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) {void __iomem *image; -int last_image;unsigned int length; +bool last_image; image = rom;do {void __iomem *pds; -/* Standard PCI ROMs start out with these bytes 55 AA */ -if (readw (image) !=PCI_ROM_IMAGE_SIGNATURE ) { -pci_info (pdev,"Invalid PCI ROM header signature: expecting %#06x, got %#06x\n" , -PCI_ROM_IMAGE_SIGNATURE ,readw (image)); +if (!pci_rom_header_valid (pdev, image, rom, size, true))break ; - } +/* Get the PCI data structure and check its "PCIR" signature */ pds = image +readw (image +PCI_ROM_POINTER_TO_DATA_STRUCT ); -if (readl (pds) !=PCI_ROM_DATA_STRUCT_SIGNATURE ) { -pci_info (pdev,"Invalid PCI ROM data signature: expecting %#010x, got %#010x\n" , -PCI_ROM_DATA_STRUCT_SIGNATURE ,readl (pds)); +if (!pci_rom_data_struct_valid (pdev, pds, rom, size))break ; - } + last_image =readb (pds +PCI_ROM_LAST_IMAGE_INDICATOR ) &PCI_ROM_LAST_IMAGE_INDICATOR_BIT ; length =readw (pds +PCI_ROM_IMAGE_LEN ); image += length *PCI_ROM_IMAGE_SECTOR_SIZE ; -/* Avoid iterating through memory outside the resource window */ -if (image >= rom + size) + +if (!last_image && + !pci_rom_header_valid (pdev, image, rom, size, false))break ; -if (!last_image) { -if (readw (image) !=PCI_ROM_IMAGE_SIGNATURE ) { -pci_info (pdev,"No more image in the PCI ROM\n" ); -break ; - } - } }while (length && !last_image);/* never return a size larger than the PCI resource window */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 478/1067 x86/platform/olpc: xo15: Drop wakeup source on driver removal
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit cc966553e6ff0849978b5754531b768b0ff54985 ]
Prevent leaking a wakeup source object after removing the driver by adding appropriate cleanup code to its remove callback function.
--- arch/x86/platform/olpc/olpc-xo15-sci.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/platform/olpc/olpc-xo15-sci.c +1 -0
@@ -185,6 +185,7 @@ static int xo15_sci_add(struct acpi_device *device)static int xo15_sci_remove (struct acpi_device *device) { +device_init_wakeup (&device->dev, false);acpi_disable_gpe (NULL , xo15_sci_gpe);acpi_remove_gpe_handler (NULL , xo15_sci_gpe, xo15_sci_gpe_handler);cancel_work_sync (&sci_work);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 479/1067 platform/x86: xo15-ebook: Fix wakeup source and GPE handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit b2fc2c6ebbd2d49935c8960755d8170faead2159 ]
The device_set_wakeup_enable() call in ebook_switch_add() doesn't actually do anything because power.can_wakeup is not set for ACPI device objects. Moreover, had it done anything, it would have registered a wakeup source object that wouldn't have been used going forward and that wakeup source would have been leaked after driver removal because ebook_switch_remove() doesn't clean it up. Accordingly, remove that call from ebook_switch_add().
Also prevent leaking an enabled ACPI GPE after removing the driver by adding appropriate cleanup code to ebook_switch_remove().
--- drivers/platform/x86/xo15-ebook.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/platform/x86/xo15-ebook.c +6 -1
@@ -38,6 +38,7 @@ MODULE_DEVICE_TABLE(acpi, ebook_device_ids);struct ebook_switch {struct input_dev *input;char phys[32 ];/* for input device */ +bool gpe_enabled; };static int ebook_send_state (struct acpi_device *device)
@@ -131,7 +132,7 @@ static int ebook_switch_add(struct acpi_device *device)/* Button's GPE is run-wake GPE */ acpi_enable_gpe (device->wakeup.gpe_device, device->wakeup.gpe_number); -device_set_wakeup_enable (&device->dev, true); + button->gpe_enabled = true; }return 0 ;
@@ -147,6 +148,10 @@ static int ebook_switch_remove(struct acpi_device *device) {struct ebook_switch *button =acpi_driver_data (device); +if (button->gpe_enabled) +acpi_disable_gpe (device->wakeup.gpe_device, + device->wakeup.gpe_number); +input_unregister_device (button->input);kfree (button);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 480/1067 perf sched: Add missing mmap2 handler in timehist
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Rogers <[email protected]>
[ Upstream commit 91182741369b261c441e63e6678893032a6d7e4c ]
perf_sched__timehist() registers event handlers for options using the sched->tool struct. It registers handlers for MMAP, COMM, EXIT, FORK, etc. but completely omits registering a handler for MMAP2 events.
Failing to register both MMAP and MMAP2 handlers causes modern systems (which primarily output MMAP2 records) to silently drop VMA map mappings. This results in uninitialized machine/thread mapping structures, making it impossible to resolve shared library instruction pointers (IPs) to dynamic symbols/DSOs during timehist callchain analysis.
Fix this by correctly registering perf_event__process_mmap2 in sched->tool inside perf_sched__timehist().
--- tools/perf/builtin-sched.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-sched.c +1 -0
@@ -3055,6 +3055,7 @@ static int perf_sched__timehist(struct perf_sched *sched)*/ sched->tool.sample = perf_timehist__process_sample; sched->tool.mmap = perf_event__process_mmap; + sched->tool.mmap2 = perf_event__process_mmap2; sched->tool.comm = perf_event__process_comm; sched->tool.exit = perf_event__process_exit; sched->tool.fork = perf_event__process_fork;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 481/1067 PCI: loongson: Do not ignore downstream devices on external bridges
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rong Zhang <[email protected]>
[ Upstream commit 1389ab9bf9f627d4daed86f492091b00f110aa86 ]
Loongson PCI host controllers have a hardware quirk that requires software to ignore downstream devices with device number > 0 on the internal bridges. The current implementation applies the workaround to all non-root buses, which breaks external bridges (e.g., PCIe switches) with multiple downstream devices.
Fix it by only applying the workaround to internal bridges.
Tested on Loongson-LS3A4000-7A1000-NUC-SE, using AMD Promontory 21 chipset add-in card [1].
$ lspci -tnnnvvv
-[0000:00]-+-00.0 Loongson Technology LLC 7A1000 Chipset Hyper Transport Bridge Controller [0014:7a00]
+-00.1 Loongson Technology LLC 7A2000 Chipset Hyper Transport Bridge Controller [0014:7a10]
+-03.0 Loongson Technology LLC 2K1000/2000 / 7A1000 Chipset Gigabit Ethernet Controller [0014:7a03]
+-04.0 Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB OHCI Controller [0014:7a24]
+-04.1 Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB EHCI Controller [0014:7a14]
+-05.0 Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB OHCI Controller [0014:7a24]
+-05.1 Loongson Technology LLC 2K1000 / 7A1000/2000 Chipset USB EHCI Controller [0014:7a14]
+-06.0 Loongson Technology LLC 7A1000 Chipset Vivante GC1000 GPU [0014:7a15]
+-06.1 Loongson Technology LLC 2K1000 / 7A1000 Chipset Display Controller [0014:7a06]
+-07.0 Loongson Technology LLC 2K1000/2000/3000 / 3B6000M / 7A1000/2000 Chipset HD Audio Controller [0014:7a07]
+-08.0 Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
+-08.1 Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
+-08.2 Loongson Technology LLC 2K1000 / 7A1000 Chipset 3Gb/s SATA AHCI Controller [0014:7a08]
+-09.0-[01]----00.0 Qualcomm Technologies, Inc QCNFA765 Wireless Network Adapter [17cb:1103]
+-0a.0-[02]----00.0 Etron Technology, Inc. EJ188/EJ198 USB 3.0 Host Controller [1b6f:7052]
+-0f.0-[03-08]----00.0-[04-08]--+-00.0-[05]----00.0 Shenzhen Longsys Electronics Co., Ltd. FORESEE XP1000 / Lexar Professional CFexpress Type B Gold series, NM620 PCIe NVME SSD (DRAM-less) [1d97:5216]
| +-08.0-[06]----00.0 MAXIO Technology (Hangzhou) Ltd. NVMe SSD Controller MAP1202 (DRAM-less) [1e4b:1202]
| +-0c.0-[07]----00.0 Advanced Micro Devices, Inc. [AMD] 600 Series Chipset USB 3.2 Controller [1022:43f7]
| \-0d.0-[08]----00.0 Advanced Micro Devices, Inc. [AMD] 600 Series Chipset SATA Controller [1022:43f6]
\-16.0 Loongson Technology LLC 7A1000 Chipset SPI Controller [0014:7a0b]--- drivers/pci/controller/pci-loongson.c | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-)
drivers/pci/controller/pci-loongson.c +16 -15
@@ -80,6 +80,18 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,DECLARE_PCI_FIXUP_EARLY (PCI_VENDOR_ID_LOONGSON ,DEV_LS7A_LPC , system_bus_quirk); +static const struct pci_device_id loongson_internal_bridge_devids[] = { + {PCI_VDEVICE (LOONGSON ,DEV_LS2K_PCIE_PORT0 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT0 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT1 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT2 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT3 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT4 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT5 ) }, + {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT6 ) }, + {0 , }, +}; +/* * Some Loongson PCIe ports have hardware limitations on their Maximum Read * Request Size. They can't handle anything larger than this. Sane
@@ -92,24 +104,13 @@ static void loongson_set_min_mrrs_quirk(struct pci_dev *pdev) {struct pci_bus *bus = pdev->bus;struct pci_dev *bridge; -static const struct pci_device_id bridge_devids[] = { - {PCI_VDEVICE (LOONGSON ,DEV_LS2K_PCIE_PORT0 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT0 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT1 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT2 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT3 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT4 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT5 ) }, - {PCI_VDEVICE (LOONGSON ,DEV_LS7A_PCIE_PORT6 ) }, - {0 , }, - };/* look for the matching bridge */ while (!pci_is_root_bus (bus)) { bridge = bus->self; bus = bus->parent; -if (pci_match_id (bridge_devids, bridge)) { +if (pci_match_id (loongson_internal_bridge_devids, bridge)) {if (pcie_get_readrq (pdev) >256 ) {pci_info (pdev,"limiting MRRS to 256\n" );pcie_set_readrq (pdev,256 );
@@ -230,11 +231,11 @@ static void __iomem *pci_loongson_map_bus(struct pci_bus *bus,struct loongson_pci *priv =pci_bus_to_loongson_pci (bus);/* -* Do not read more than one device on the bus other than -* the host bus. +* Do not read more than one device on the internal bridges. */ if ((priv->data->flags &FLAG_DEV_FIX ) && bus->self) { -if (!pci_is_root_bus (bus) && (device >0 )) +if (!pci_is_root_bus (bus) && (device >0 ) && +pci_match_id (loongson_internal_bridge_devids, bus->self))return NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 482/1067 bus: mhi: ep: Fix potential deadlock in mhi_ep_reset_worker()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sumit Kumar <[email protected]>
[ Upstream commit 9dece4435d396e9877e27483552b910ba8654169 ]
There is a potential deadlock scenario in mhi_ep_reset_worker() where the state_lock mutex is acquired twice in the same call chain:
mhi_ep_reset_worker()
mutex_lock(&mhi_cntrl->state_lock)
mhi_ep_power_up()
mhi_ep_set_ready_state()
mutex_lock(&mhi_cntrl->state_lock) <- DeadlockFix this by releasing the state_lock before calling mhi_ep_power_up(). The lock is only needed to protect current MHI state read operation. The lock can be safely released before proceeding with the power up sequence.
--- drivers/bus/mhi/ep/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/bus/mhi/ep/main.c +3 -4
@@ -1026,11 +1026,12 @@ static void mhi_ep_reset_worker(struct work_struct *work)mhi_ep_power_down (mhi_cntrl); -mutex_lock (&mhi_cntrl->state_lock); -/* Reset MMIO to signal host that the MHI_RESET is completed in endpoint */ mhi_ep_mmio_reset (mhi_cntrl); + +mutex_lock (&mhi_cntrl->state_lock); cur_state = mhi_cntrl->mhi_state; +mutex_unlock (&mhi_cntrl->state_lock);/* * Only proceed further if the reset is due to SYS_ERR. The host will
@@ -1039,8 +1040,6 @@ static void mhi_ep_reset_worker(struct work_struct *work)*/ if (cur_state ==MHI_STATE_SYS_ERR )mhi_ep_power_up (mhi_cntrl); - -mutex_unlock (&mhi_cntrl->state_lock); }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 483/1067 phy: phy-can-transceiver: Check driver match and driver data against NULL
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit ebee9004cc0200b2b708ebf7ac625d35c71c049f ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override() so platform drivers that rely on the existence of a device's driver data need to verify its presence.
Accordingly, add requisite match and driver data checks against NULL to the driver where they are missing.
--- drivers/phy/phy-can-transceiver.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/phy/phy-can-transceiver.c +3 -0
@@ -106,6 +106,9 @@ static int can_transceiver_phy_probe(struct platform_device *pdev)return -ENOMEM ; match =of_match_node (can_transceiver_phy_ids, pdev->dev.of_node); +if (!match || !match->data) +return -ENODEV ; + drvdata = match->data;if (of_property_read_bool (dev->of_node,"mux-states" )) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 484/1067 mailbox: mtk-adsp: fix UAF during device teardown
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Senozhatsky <[email protected]>
[ Upstream commit b57d1a40bc43258372fa1f4d39305e093947a262 ]
When the SOF audio driver fails to initialize (e.g. firmware boot timeout), its devres unwind frees the snd_sof_dev object that the mailbox client (mtk-adsp-ipc) reaches via chan->cl->rx_callback. The mtk-adsp-mailbox shutdown clears the mailbox command registers but leaves the IRQ line unmasked, so a late interrupt can still queue a threaded handler after mbox_free_channel() had cleared chan->cl, and mbox_chan_received_data() would then trigger UAF:
BUG: KASAN: slab-use-after-free in sof_ipc3_validate_fw_version sof_ipc3_validate_fw_version sof_ipc3_do_rx_work sof_ipc3_rx_msg mt8196_dsp_handle_request mtk_adsp_ipc_recv mbox_chan_received_data mtk_adsp_mbox_isr irq_thread_fn Freed by task ...: kfree devres_release_all really_probe ... (sof-audio-of-mt8196 probe failure)
The crash was observed roughly three seconds after the failed probe.
disable_irq() in shutdown and enable_irq() in startup. disable_irq() also waits for any in-flight interrupts, so by the time mbox_free_channel() proceeds to clear chan->cl no rx_callback can run.
In addition, request the IRQ with IRQF_NO_AUTOEN so it stays masked between probe and the first client bind — otherwise an early interrupt can crash on chan->cl == NULL in mbox_chan_received_data().
--- drivers/mailbox/mtk-adsp-mailbox.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/mailbox/mtk-adsp-mailbox.c +8 -1
@@ -18,6 +18,7 @@ struct mtk_adsp_mbox_priv {struct mbox_controller mbox;void __iomem *va_mboxreg;const struct mtk_adsp_mbox_cfg *cfg; +int irq; };struct mtk_adsp_mbox_cfg {
@@ -66,6 +67,8 @@ static int mtk_adsp_mbox_startup(struct mbox_chan *chan)writel (0xFFFFFFFF , priv->va_mboxreg + priv->cfg->clr_in);writel (0xFFFFFFFF , priv->va_mboxreg + priv->cfg->clr_out); +enable_irq (priv->irq); +return 0 ; }
@@ -73,6 +76,8 @@ static void mtk_adsp_mbox_shutdown(struct mbox_chan *chan) {struct mtk_adsp_mbox_priv *priv =get_mtk_adsp_mbox_priv (chan->mbox); +disable_irq (priv->irq); +/* Clear ADSP mbox command */ writel (0xFFFFFFFF , priv->va_mboxreg + priv->cfg->clr_in);writel (0xFFFFFFFF , priv->va_mboxreg + priv->cfg->clr_out);
@@ -138,8 +143,10 @@ static int mtk_adsp_mbox_probe(struct platform_device *pdev)if (irq <0 )return irq; + priv->irq = irq; ret =devm_request_threaded_irq (dev, irq, mtk_adsp_mbox_irq, - mtk_adsp_mbox_isr,IRQF_TRIGGER_NONE , + mtk_adsp_mbox_isr, +IRQF_TRIGGER_NONE |IRQF_NO_AUTOEN ,dev_name (dev), mbox->chans);if (ret <0 )return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 485/1067 staging: most: video: avoid double free on video register failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 7cb1c5b32a2bfde961fff8d5204526b609bcb30a ]
comp_register_videodev() allocates a video_device with video_device_alloc() and releases it if video_register_device() fails.
This can double free the video_device when __video_register_device() reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev) comp_register_videodev()
-> video_device_release(mdev->vdev)
Use video_device_release_empty() while registering the device so that registration failure paths do not free mdev->vdev through vdev->release(). comp_register_videodev() then releases mdev->vdev exactly once on failure. Restore video_device_release() after successful registration so the registered device keeps its normal lifetime handling.
This issue was found by a static analysis tool I am developing.
--- drivers/staging/most/video/video.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/staging/most/video/video.c +6 -1
@@ -416,6 +416,7 @@ static int comp_register_videodev(struct most_video_dev *mdev)/* Fill the video capture device struct */ *mdev->vdev = comp_videodev_template; + mdev->vdev->release = video_device_release_empty; mdev->vdev->v4l2_dev = &mdev->v4l2_dev; mdev->vdev->lock = &mdev->lock; snprintf(mdev->vdev->name, sizeof(mdev->vdev->name), "MOST: %s",
@@ -428,9 +429,13 @@ static int comp_register_videodev(struct most_video_dev *mdev)v4l2_err (&mdev->v4l2_dev,"video_register_device failed (%d)\n" , ret);video_device_release (mdev->vdev); +return ret; } -return ret; + mdev->vdev->release = video_device_release; + +return 0 ; + }static void comp_unregister_videodev (struct most_video_dev *mdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 486/1067 usb: host: max3421: Fix shift-out-of-bounds in max3421_hub_control()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seungjin Bae <[email protected]>
[ Upstream commit cff06b03b530ae1fe8a13e93a7848f2130e00fb4 ]
The max3421_hub_control() function handles USB hub class requests to the virtual root hub. In the default branches of both the ClearPortFeature and SetPortFeature switch statements, it modifies max3421_hcd->port_status by left shifting 1 by the request's value parameter. However, it does not validate whether this shift will exceed the width of port_status.
So if a malicious userspace task with access to the root hub via /dev/bus/usb/.../001 issues a USBDEVFS_CONTROL ioctl with wValue greater than or equal to 32, the left shift operation invokes shift-out-of-bounds undefined behavior. This results in arbitrary bit corruption of port_status, including the normally-immutable change bits, which can bypass internal state checks and confuse the hub status.
Fix this by rejecting requests whose value exceeds the shift width before performing the shift.
This issue was found using a KLEE-based symbolic execution tool for kernel drivers that I'm currently developing.
--- drivers/usb/host/max3421-hcd.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/host/max3421-hcd.c +4 -0
@@ -1703,6 +1703,8 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index, !pdata->vbus_active_level); fallthrough;default : +if (value >=32 ) + goto error; max3421_hcd->port_status &= ~(1 << value); }break ;
@@ -1756,6 +1758,8 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index,max3421_reset_port (hcd); fallthrough;default : +if (value >=32 ) + goto error;if ((max3421_hcd->port_status &USB_PORT_STAT_POWER ) !=0 ) max3421_hcd->port_status |= (1 << value);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 487/1067 usb: host: max3421: Reject hub port requests for non-existent ports
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seungjin Bae <[email protected]>
[ Upstream commit 11b5c101e2fd206104b05bc92554d356989423a8 ]
The max3421_hub_control() function handles USB hub class requests to the virtual root hub. The GetPortStatus case correctly rejects requests with index != 1, since the virtual root hub has only a single port. However, the ClearPortFeature and SetPortFeature cases lack the same check.
Fix this by extending the index != 1 rejection to both cases, matching the existing behavior of GetPortStatus.
--- drivers/usb/host/max3421-hcd.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/host/max3421-hcd.c +4 -0
@@ -1694,6 +1694,8 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index,case ClearHubFeature:break ;case ClearPortFeature: +if (index !=1 ) + goto error;switch (value) {case USB_PORT_FEAT_SUSPEND :break ;
@@ -1737,6 +1739,8 @@ max3421_hub_control(struct usb_hcd *hcd, u16 type_req, u16 value, u16 index,break ;case SetPortFeature: +if (index !=1 ) + goto error;switch (value) {case USB_PORT_FEAT_LINK_STATE :case USB_PORT_FEAT_U1_TIMEOUT :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 488/1067 char: tlclk: fix use-after-free in tlclk_cleanup()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Kim <[email protected]>
[ Upstream commit bbf003b7794d6ad6f939fdd29f1f1bde8ac554c1 ]
This patch improves the module cleanup process in the tlclk driver to prevent potential use-after-free and race conditions.
Currently, the file_operations structure does not specify the .owner field, which could allow the module to be unloaded while user-space processes are still interacting with the device. Additionally, the tlclk_cleanup() function frees the alarm_events memory before ensuring that blocked processes in the waitqueue are fully awakened and that the switchover_timer has completed.
To address these cases, this patch:
- Sets '.owner = THIS_MODULE' in tlclk_fops to safely defer module unloading while the device is in use.
- Updates tlclk_cleanup() to explicitly wake up all blocked readers (wake_up_all), properly release hardware I/O regions, and safely delete the timer (timer_delete_sync) prior to freeing memory.
--- drivers/char/tlclk.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/char/tlclk.c +4 -0
@@ -263,6 +263,7 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, }static const struct file_operations tlclk_fops = { + .owner =THIS_MODULE , .read = tlclk_read, .open = tlclk_open, .release = tlclk_release,
@@ -852,6 +853,9 @@ static void __exit tlclk_cleanup(void)misc_deregister (&tlclk_miscdev);unregister_chrdev (tlclk_major,"telco_clock" ); + got_event =1 ; +wake_up_all (&wq); +release_region (TLCLK_BASE ,8 );del_timer_sync (&switchover_timer);kfree (alarm_events);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 489/1067 perf header: Sanity check HEADER_EVENT_DESC attr.size before swap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 944f65c8b8231d26d4db6be67bcb641142603cb4 ]
read_event_desc() reads nre (event count), sz (attr size), and nr (IDs per event) from the file and uses them to control allocations and loops without validating them against the section size.
A crafted perf.data could trigger large allocations or many loop iterations before __do_read() eventually rejects the reads.
Add bounds checks in read_event_desc():
- Reject sz smaller than PERF_ATTR_SIZE_VER0.
- Require at least one event (nre > 0).
- Check that nre events fit in the remaining section, using the minimum per-event footprint of sz + sizeof(u32).
- Pre-swap attr->size to native byte order, then reject values below PERF_ATTR_SIZE_VER0 or above sz before calling perf_event__attr_swap() to prevent heap out-of-bounds access.
- Handle ABI0 (attr.size == 0): substitute PERF_ATTR_SIZE_VER0, and on native-endian files write the value back so free_event_desc() does not treat the zero as its end-of-array sentinel (it iterates while attr.size != 0). The swap path skips the write-back — perf_event__attr_swap() has its own ABI0 fallback that sets VER0 after swapping.
- Check that nr IDs fit in the remaining section before allocating.
--- tools/perf/util/header.c | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
tools/perf/util/header.c +54 -0
@@ -1900,9 +1900,28 @@ static struct evsel *read_event_desc(struct feat_fd *ff)if (do_read_u32 (ff, &nre)) goto error; +/* Size of each of the nre attributes. */ if (do_read_u32 (ff, &sz)) goto error; +/* +* Require at least one event with an attr no smaller than the +* first published struct, and reject sz values where +* sz + sizeof(u32) would overflow size_t (possible on 32-bit) +* or nre == UINT32_MAX where nre + 1 wraps to 0 in the calloc. +* +* The minimum section footprint per event is sz bytes for the +* attr plus a u32 for the id count, check that nre events fit. +*/ +if (!nre || sz <PERF_ATTR_SIZE_VER0 || + sz > ff->size || (size_t )sz >SIZE_MAX -sizeof (u32) || + nre ==UINT32_MAX || + nre > (ff->size - ff->offset) / (sz +sizeof (u32))) { +pr_err ("Invalid HEADER_EVENT_DESC: nre=%u sz=%u (min %d)\n" , + nre, sz,PERF_ATTR_SIZE_VER0 ); + goto error; + } +/* buffer to hold on file attr struct */ buf =malloc (sz);if (!buf)
@@ -1918,6 +1937,9 @@ static struct evsel *read_event_desc(struct feat_fd *ff) msz = sz;for (i =0 , evsel = events; i < nre; evsel++, i++) { +struct perf_event_attr *attr = buf; +u32 attr_size; + evsel->core.idx = i;/*
@@ -1927,6 +1949,32 @@ static struct evsel *read_event_desc(struct feat_fd *ff)if (__do_read (ff, buf, sz)) goto error; +/* Reject before attr_swap to prevent OOB via bswap_safe() */ + attr_size = ff->ph->needs_swap ?bswap_32 (attr->size) : attr->size; +/* ABI0: size == 0 means the producer didn't set it */ +if (!attr_size) { + attr_size =PERF_ATTR_SIZE_VER0 ; +/* +* Write back so free_event_desc() doesn't +* treat this event as the end-of-array sentinel +* (it iterates while attr.size != 0). +* +* Only for native — the swap path must NOT +* write native-endian VER0 here because +* perf_event__attr_swap() would re-swap it +* to 0x40000000, defeating bswap_safe() bounds. +* perf_event__attr_swap() has its own ABI0 +* fallback that sets VER0 after swapping. +*/ +if (!ff->ph->needs_swap) + attr->size = attr_size; + } +if (attr_size <PERF_ATTR_SIZE_VER0 || attr_size > sz) { +pr_err ("Event %d attr.size (%u) invalid (min: %d, max: %u)\n" , + i, attr_size,PERF_ATTR_SIZE_VER0 , sz); + goto error; + } +if (ff->ph->needs_swap)perf_event__attr_swap (buf);
@@ -1948,6 +1996,12 @@ static struct evsel *read_event_desc(struct feat_fd *ff)if (!nr)continue ; +/* Prevent oversized allocation from crafted nr */ +if (nr > (ff->size - ff->offset) /sizeof (*id)) { +pr_err ("Event %d: id count %u exceeds remaining section\n" , i, nr); + goto error; + } + id =calloc (nr,sizeof (*id));if (!id) goto error;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 490/1067 iio: light: si1133: reset counter to prevent race condition
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
[ Upstream commit 0a5f45ed2342aabae1e32c72558d15be28940a95 ]
Sashiko reported a potential race condition happening when the driver returns an errno after a timeout in the si1133_command() function. The premature exit causes the hardware and software counters to become out of sync by not updating data->rsp_seq, therefore the internal hardware counter keeps incrementing.
Fix this by adding a call to si1133_cmd_reset_counter() before returning from timeout.
--- drivers/iio/light/si1133.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/iio/light/si1133.c +5 -0
@@ -427,6 +427,11 @@ static int si1133_command(struct si1133_data *data, u8 cmd)dev_warn (dev,"Failed to read command 0x%02x, ret=%d\n" , cmd, err); +/* +* Reset counter on err to prevent software and hardware +* counters being out of sync. +*/ +si1133_cmd_reset_counter (data); goto out; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 491/1067 iio: light: si1133: prevent race condition on timeout
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
[ Upstream commit 8c50a95ceb230d17801758a9e41ffbbbe46f8b4d ]
Sashiko reported a bug where the si1133_command exits on timeout without halting the sensor or masking the interrupt. If the sensor completes the command later, any subsequent command to the sensor will cause the IRQ handler to complete immediately, returning stale data to the driver all while the command hasn't finished yet, shifting all potential reads in the future.
Fix this by masking the IRQ if wait_for_completion_timeout() fails. When initiating a new command, do a dummy read of the IRQ_STATUS register and turn the IRQ back on.
--- drivers/iio/light/si1133.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/iio/light/si1133.c +8 -1
@@ -395,8 +395,14 @@ static int si1133_command(struct si1133_data *data, u8 cmd) expected_seq = (data->rsp_seq +1 ) &SI1133_MAX_CMD_CTR ; -if (cmd ==SI1133_CMD_FORCE ) +if (cmd ==SI1133_CMD_FORCE ) { +/* Flush pending IRQs from a previous timeout. */ +regmap_read (data->regmap,SI1133_REG_IRQ_STATUS , &resp); +regmap_write (data->regmap,SI1133_REG_IRQ_ENABLE , +SI1133_IRQ_CHANNEL_ENABLE ); +reinit_completion (&data->completion); + } err =regmap_write (data->regmap,SI1133_REG_COMMAND , cmd);if (err) {
@@ -409,6 +415,7 @@ static int si1133_command(struct si1133_data *data, u8 cmd)/* wait for irq */ if (!wait_for_completion_timeout (&data->completion,msecs_to_jiffies (SI1133_COMPLETION_TIMEOUT_MS ))) { +regmap_write (data->regmap,SI1133_REG_IRQ_ENABLE ,0 ); err = -ETIMEDOUT ; goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 492/1067 iio: magnetometer: ak8975: fix potential kernel stack memory leak
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
[ Upstream commit a9a00d727b7bbc5e913a919530a9dd468935bf95 ]
Currently in the AK8975 driver there are four instances where potential uninitialized kernel stack memory leaks can occur. If i2c_smbus_read_i2c_block_data_or_emulated() returns a value less than the size of the buffer, uninitialized bytes are retained in the buffer and later the buffer is passed on to IIO buffers, potentially leaking memory to userspace.
Fix this by adding checks whether the return value of the function is equal to the size of the buffer and subsequently if the value is lesser than zero to distinguish from a returned error code.
--- drivers/iio/magnetometer/ak8975.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
drivers/iio/magnetometer/ak8975.c +14 -0
@@ -464,6 +464,10 @@ static int ak8975_who_i_am(struct i2c_client *client,dev_err (&client->dev,"Error reading WIA\n" );return ret; } +if (ret !=sizeof (wia_val)) { +dev_err (&client->dev,"Error reading WIA\n" ); +return -EIO ; + }if (wia_val[0 ] !=AK8975_DEVICE_ID )return -ENODEV ;
@@ -580,6 +584,10 @@ static int ak8975_setup(struct i2c_client *client)dev_err (&client->dev,"Not able to read asa data\n" );return ret; } +if (ret !=sizeof (data->asa)) { +dev_err (&client->dev,"Error reading asa data\n" ); +return -EIO ; + }/* After reading fuse ROM data set power-down mode */ ret =ak8975_set_mode (data,POWER_DOWN );
@@ -719,6 +727,10 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val) sizeof(rval), (u8*)&rval);if (ret <0 ) goto exit; +if (ret !=sizeof (rval)) { + ret = -EIO ; + goto exit; + }/* Read out ST2 for release lock on measurment data. */ ret =i2c_smbus_read_byte_data (client, data->def->ctrl_regs[ST2 ]);
@@ -848,6 +860,8 @@ static void ak8975_fill_buffer(struct iio_dev *indio_dev) (u8 *)fval);if (ret <0 ) goto unlock; +if (ret !=sizeof (fval)) + goto unlock;mutex_unlock (&data->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 493/1067 iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guilherme Ivo Bozi <[email protected]>
[ Upstream commit 947eb6f0a274f8b15a0248051a65b069effd5057 ]
ams_event_to_channel() may return a pointer past the end of dev->channels when no matching scan_index is found. This can lead to invalid memory access in ams_handle_event().
Add a bounds check in ams_event_to_channel() and return NULL when no channel is found. Also guard the caller to safely handle this case.
--- drivers/iio/adc/xilinx-ams.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/iio/adc/xilinx-ams.c +5 -0
@@ -861,6 +861,9 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,if (dev->channels[i].scan_index == scan_index)break ; +if (i == dev->num_channels) +return NULL ; +return &dev->channels[i]; }
@@ -1002,6 +1005,8 @@ static void ams_handle_event(struct iio_dev *indio_dev, u32 event)const struct iio_chan_spec *chan; chan =ams_event_to_channel (indio_dev, event); +if (!chan) +return ;if (chan->type ==IIO_TEMP ) {/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 494/1067 iio: accel: mma8452: handle I2C read error(s) in mma8452_read()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanjay Chitroda <[email protected]>
[ Upstream commit 5bdff291d20c31b365d9ddfe9c426fbfb41da5bb ]
Currently, If i2c_smbus_read_i2c_block_data() fails but mma8452_set_runtime_pm_state() succeeds, mma8452_read() returns 0.
As a result, the caller mma8452_read_raw() assumes the read was successful and proceeds to use a buffer containing uninitialized stack memory.
Add proper checking of the I2C read return value and propagate errors to the caller.
--- drivers/iio/accel/mma8452.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/iio/accel/mma8452.c +2 -0
@@ -254,6 +254,8 @@ static int mma8452_read(struct mma8452_data *data, __be16 buf[3]) ret =i2c_smbus_read_i2c_block_data (data->client,MMA8452_OUT_X ,3 *sizeof (__be16), (u8 *)buf); +if (ret <0 ) +return ret; ret =mma8452_set_runtime_pm_state (data->client, false);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 495/1067 clk: at91: keep securam node alive while mapping it
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 22fa1c39ba6fe726b547c877c924379b7fee260a ]
pmc_register_ops() gets an owned reference to the "atmel,sama5d2-securam" node with of_find_compatible_node(). The success path dropped that reference before passing the node to of_iomap(), leaving of_iomap() to consume a node pointer after the caller had released its reference.
Move of_node_put() after of_iomap() so the node remains referenced for the mapping operation. The unavailable-node error path already releases the reference.
--- drivers/clk/at91/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/at91/pmc.c +1 -1
@@ -176,9 +176,9 @@ static int __init pmc_register_ops(void)of_node_put (np);return -ENODEV ; } -of_node_put (np); at91_pmc_backup_suspend =of_iomap (np,0 ); +of_node_put (np);if (!at91_pmc_backup_suspend) {pr_warn ("%s(): unable to map securam\n" , __func__);return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 496/1067 HID: logitech-hidpp: remove excess kernel-doc member in hidpp_scroll_counter
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit f22a5db8a7d38152556f230d6d68e59dbc27971b ]
The @dev member described in the kernel-doc does not exist in the struct. Remove the stale entry.
--- drivers/hid/hid-logitech-hidpp.c | 1 - 1 file changed, 1 deletion(-)
drivers/hid/hid-logitech-hidpp.c +0 -1
@@ -159,7 +159,6 @@ struct hidpp_battery {/** * struct hidpp_scroll_counter - Utility class for processing high-resolution * scroll events. -* @dev: the input device for which events should be reported. * @wheel_multiplier: the scalar multiplier to be applied to each wheel event * @remainder: counts the number of high-resolution units moved since the last * low-resolution event (REL_WHEEL or REL_HWHEEL) was sent. Should
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 497/1067 fs/ntfs3: add bounds check to run_get_highest_vcn()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit bb11485a87fbb2254b62cfed630b699d50e57da8 ]
run_get_highest_vcn() parses a packed NTFS mapping-pairs buffer without any length bound, relying solely on a 0x00 terminator to stop. A crafted $LogFile UpdateMappingPairs record whose embedded attribute contains mapping-pairs runs without a terminator causes the function to read past the slab allocation, triggering a KASAN slab-out-of-bounds read on mount.
The sibling function run_unpack() received an analogous bounds-check in commit b62567bca474 ("ntfs3: add buffer boundary checks to run_unpack()"), but run_get_highest_vcn() was missed.
Take a run_buf_size parameter and reject any run header whose payload would extend past the buffer end, mirroring the pattern used by run_unpack(). The caller in fslog.c passes the remaining attribute bytes after the mapping-pairs offset.
KASAN report (on mainline v7.1 merge window HEAD):
BUG: KASAN: slab-out-of-bounds in run_get_highest_vcn+0x3c0/0x410 Read of size 1 at addr ffff88800e2d5400 by task mount/72 Call Trace: run_get_highest_vcn+0x3c0/0x410 do_action.isra.0+0x3ba8/0x7b50 log_replay+0x9ddd/0x10200 ntfs_loadlog_and_replay+0x4ad/0x610 ntfs_fill_super+0x214a/0x4540
--- fs/ntfs3/fslog.c | 5 ++++- fs/ntfs3/ntfs_fs.h | 3 ++- fs/ntfs3/run.c | 9 +++++++-- 3 files changed, 13 insertions(+), 4 deletions(-)
fs/ntfs3/fslog.c +4 -1
@@ -3367,7 +3367,10 @@ static int do_action(struct ntfs_log *log, struct OPEN_ATTR_ENRTY *oe,memmove (Add2Ptr (attr, aoff), data, dlen);if (run_get_highest_vcn (le64_to_cpu (attr->nres.svcn), -attr_run (attr), &t64)) { +attr_run (attr), +le32_to_cpu (attr->size) - +le16_to_cpu (attr->nres.run_off), + &t64)) { goto dirty_vol; }
fs/ntfs3/ntfs_fs.h +2 -1
@@ -809,7 +809,8 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,#else #define run_unpack_ex run_unpack#endif -int run_get_highest_vcn (CLST vcn,const u8 *run_buf,u64 *highest_vcn); +int run_get_highest_vcn (CLST vcn,const u8 *run_buf,size_t run_buf_size, +u64 *highest_vcn);int run_clone (const struct runs_tree *run,struct runs_tree *new_run);/* Globals from super.c */
fs/ntfs3/run.c +7 -2
@@ -1152,18 +1152,23 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,* Return the highest vcn from a mapping pairs array * it used while replaying log file. */ -int run_get_highest_vcn (CLST vcn,const u8 *run_buf,u64 *highest_vcn) +int run_get_highest_vcn (CLST vcn,const u8 *run_buf,size_t run_buf_size, +u64 *highest_vcn) { +const u8 *run_last = run_buf + run_buf_size;u64 vcn64 = vcn;u8 size_size; -while ((size_size = *run_buf &0xF )) { +while (run_buf < run_last && (size_size = *run_buf &0xF )) {u8 offset_size = *run_buf++ >>4 ;u64 len;if (size_size >8 || offset_size >8 )return -EINVAL ; +if (run_buf + size_size + offset_size > run_last) +return -EINVAL ; + len =run_unpack_s64 (run_buf, size_size,0 );if (!len)return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 498/1067 drm/amd/display: Add missing kdoc for ALLM parameters
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit d4c6ec729fb7a8bf8a27b19bd70a1b945ad93dac ]
Add descriptions for the missing parameters for ALLMEnabled and ALLMValue to keep the function documentation synchronized with the function prototype mod_build_hf_vsif_infopacket().
Fixes the below with gcc W=1:../display/modules/info_packet/info_packet.c:507 function parameter 'ALLMEnabled' not described in 'mod_build_hf_vsif_infopacket' ../display/modules/info_packet/info_packet.c:507 function parameter 'ALLMValue' not described in 'mod_build_hf_vsif_infopacket'
--- drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +2 -0
@@ -445,6 +445,8 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,* * @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.) * @info_packet: output structure where to store VSIF +* @ALLMEnabled: indicates whether ALLM HF-VSIF should be generated +* @ALLMValue: ALLM bit value to advertise in HF-VSIF */ void mod_build_hf_vsif_infopacket (const struct dc_stream_state *stream,struct dc_info_packet *info_packet)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 499/1067 dmaengine: imx-sdma: Refine spba bus searching in probe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <[email protected]>
[ Upstream commit d52d42e2e5d9f13166e81ac837ebb023d1306e61 ]
There are multi spba-busses for i.MX8M* platforms, if only search for the first spba-bus in DT, the found spba-bus may not the real bus of audio devices, which cause issue for sdma p2p case, as the sdma p2p script presently does not deal with the transactions involving two devices connected to the AIPS bus.
Search the SDMA parent node first, which should be the AIPS bus, then search the child node whose compatible string is spba-bus under that AIPS bus for the above multi spba-busses case.
--- drivers/dma/imx-sdma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/imx-sdma.c +3 -1
@@ -2301,7 +2301,9 @@ static int sdma_probe(struct platform_device *pdev) goto err_register; } - spba_bus =of_find_compatible_node (NULL ,NULL ,"fsl,spba-bus" ); + struct device_node *sdma_parent_np __free(device_node) = of_get_parent(np); + + spba_bus =of_get_compatible_child (sdma_parent_np,"fsl,spba-bus" ); ret =of_address_to_resource (spba_bus,0 , &spba_res);if (!ret) { sdma->spba_start_addr = spba_res.start;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 500/1067 perf: Fix off-by-one stack buffer overflow in kallsyms__parse()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rui Qi <[email protected]>
[ Upstream commit 68018df3f55eba96a20dd703f5f276a6518f4963 ]
In kallsyms__parse(), the loop reading symbol names iterates with i < sizeof(symbol_name), which allows i to reach sizeof(symbol_name) upon loop exit. The subsequent symbol_name[i] = '\0' then writes one byte past the end of the stack-allocated symbol_name[] array.
Fix this by changing the loop bound to KSYM_NAME_LEN, so the null terminator always lands within the array. The overflow is triggerable by a kallsyms entry with a symbol name of KSYM_NAME_LEN+1 or more characters (e.g., long Rust mangled names or a malicious /proc/kallsyms).
--- tools/lib/symbol/kallsyms.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/lib/symbol/kallsyms.c +4 -1
@@ -60,7 +60,7 @@ int kallsyms__parse(const char *filename, void *arg,read_to_eol (&io);continue ; } -for (i =0 ; i <sizeof (symbol_name); i++) { +for (i =0 ; i <KSYM_NAME_LEN ; i++) { ch =io__get_char (&io);if (ch <0 || ch =='\n' )break ;
@@ -68,6 +68,9 @@ int kallsyms__parse(const char *filename, void *arg, } symbol_name[i] ='\0' ; +if (i ==KSYM_NAME_LEN ) +read_to_eol (&io); + err =process_symbol (arg, symbol_name, symbol_type, start);if (err)break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 501/1067 perf sched: Replace BUG_ON on invalid CPU with graceful skip
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 1e2c83f732deb329ebce23e26cbc482f4c4bf194 ]
latency_switch_event(), latency_runtime_event(), and map_switch_event() use BUG_ON(cpu >= MAX_CPUS || cpu < 0) to validate the sample CPU. When PERF_SAMPLE_CPU is absent from the sample type, evsel__parse_sample() initializes sample->cpu to (u32)-1. Casting this to int yields -1, which triggers the BUG_ON and aborts perf sched.
The central CPU validation in perf_session__deliver_event() intentionally preserves the (u32)-1 sentinel for downstream tools like perf script and perf inject, so leaf callbacks must handle it themselves.
Replace the three BUG_ON calls with graceful skips using pr_warning(), matching the existing pattern in process_sched_switch_event() and process_sched_runtime_event() earlier in the same file. Include the file offset for cross-referencing with perf report -D.
Stable-dep-of: 8cbca8a480e1 ("perf sched: Fix NULL dereference in latency_runtime_event")
--- tools/perf/builtin-sched.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
tools/perf/builtin-sched.c +19 -3
@@ -1154,7 +1154,12 @@ static int latency_switch_event(struct perf_sched *sched,int cpu = sample->cpu, err =-1 ;s64 delta; -BUG_ON (cpu >=MAX_CPUS || cpu <0 ); +/* perf.data is untrusted input — CPU may be absent or corrupted */ +if (cpu >=MAX_CPUS || cpu <0 ) { +pr_warning ("WARNING: at offset %#" PRIx64": out-of-bound sample CPU %d, skipping sample\n" , + sample->file_offset, cpu); +return 0 ; + } timestamp0 = sched->cpu_last_switched[cpu]; sched->cpu_last_switched[cpu] = timestamp;
@@ -1225,7 +1230,13 @@ static int latency_runtime_event(struct perf_sched *sched,if (thread ==NULL )return -1 ; -BUG_ON (cpu >=MAX_CPUS || cpu <0 ); +/* perf.data is untrusted input — CPU may be absent or corrupted */ +if (cpu >=MAX_CPUS || cpu <0 ) { +pr_warning ("WARNING: at offset %#" PRIx64": out-of-bound sample CPU %d, skipping sample\n" , + sample->file_offset, cpu); + err =0 ; + goto out_put; + }if (!atoms) {if (thread_atoms_insert (sched, thread)) goto out_put;
@@ -1581,7 +1592,12 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,const char *color =PERF_COLOR_NORMAL ;char stimestamp[32 ]; -BUG_ON (this_cpu.cpu >=MAX_CPUS || this_cpu.cpu <0 ); +/* perf.data is untrusted input — CPU may be absent or corrupted */ +if (this_cpu.cpu >=MAX_CPUS || this_cpu.cpu <0 ) { +pr_warning ("WARNING: at offset %#" PRIx64": out-of-bound sample CPU %d, skipping sample\n" , + sample->file_offset, this_cpu.cpu); +return 0 ; + }if (this_cpu.cpu > sched->max_cpu.cpu) sched->max_cpu = this_cpu;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 502/1067 perf sched: Fix NULL dereference in latency_runtime_event
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 8cbca8a480e15f6326ce94287570993f27a4b2d5 ]
latency_runtime_event() passes the return value of machine__findnew_thread() directly to thread_atoms_search() at line 1216, before checking for NULL at line 1220. thread_atoms_search() calls pid_cmp() which dereferences the thread pointer via thread__tid(), causing a NULL pointer dereference if the allocation fails.
All other callers of thread_atoms_search() in this file (latency_switch_event, latency_wakeup_event, latency_migrate_task_event) correctly check for NULL first.
Move the atoms assignment after the NULL check to match the pattern used by the other callers.
--- tools/perf/builtin-sched.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/builtin-sched.c +3 -1
@@ -1223,13 +1223,15 @@ static int latency_runtime_event(struct perf_sched *sched,const u32 pid =evsel__intval (evsel, sample,"pid" );const u64 runtime =evsel__intval (evsel, sample,"runtime" );struct thread *thread =machine__findnew_thread (machine,-1 , pid); -struct work_atoms *atoms =thread_atoms_search (&sched->atom_root, thread, &sched->cmp_pid); +struct work_atoms *atoms;u64 timestamp = sample->time;int cpu = sample->cpu, err =-1 ;if (thread ==NULL )return -1 ; + atoms =thread_atoms_search (&sched->atom_root, thread, &sched->cmp_pid); +/* perf.data is untrusted input — CPU may be absent or corrupted */ if (cpu >=MAX_CPUS || cpu <0 ) { pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 503/1067 perf tools: Add bounds check to cpu__get_node()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 1e7921d7227de5da0dfc167943092c823ec7e49b ]
cpu__get_node() accesses cpunode_map[cpu.cpu] without checking against max_cpu_num, the allocation size of cpunode_map. Callers such as builtin-kmem.c:evsel__process_alloc_event() pass sample->cpu from perf.data events, which may exceed the host's CPU count when analyzing cross-machine recordings.
Add a bounds check against max_cpu_num before indexing, returning -1 for out-of-range values. This is a central fix that protects all callers.
--- tools/perf/util/cpumap.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/cpumap.c +4 -0
@@ -486,6 +486,10 @@ int cpu__get_node(struct perf_cpu cpu)return -1 ; } +/* cpunode_map allocated for max_cpu_num entries; input may be untrusted */ +if (cpu.cpu <0 || cpu.cpu >= max_cpu_num.cpu) +return -1 ; +return cpunode_map[cpu.cpu]; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 504/1067 perf mmap: Guard cpu__get_node() return in aio_bind()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit f32dc302a090f48893477ef297a888db109ec0bd ]
perf_mmap__aio_bind() passes the cpu__get_node() return value directly to an unsigned long variable (node_index). When cpu__get_node() returns -1 for an unknown CPU, the implicit int-to-unsigned-long conversion sign-extends it to ULONG_MAX.
This causes bitmap_zalloc(ULONG_MAX + 1) which wraps to bitmap_zalloc(0), returning a zero-sized allocation. The subsequent __set_bit(ULONG_MAX, node_mask) then writes massively out of bounds.
Check the return value in a signed temporary before assigning to node_index, and skip the NUMA binding when the node is unknown.
--- tools/perf/util/mmap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
tools/perf/util/mmap.c +7 -1
@@ -103,9 +103,15 @@ static int perf_mmap__aio_bind(struct mmap *map, int idx, struct perf_cpu cpu, iint err =0 ;if (affinity !=PERF_AFFINITY_SYS &&cpu__max_node () >1 ) { +int node; + data = map->aio.data[idx]; mmap_len =mmap__mmap_len (map); - node_index =cpu__get_node (cpu); + node =cpu__get_node (cpu); +/* -1 sign-extends to ULONG_MAX, wrapping bitmap_zalloc(0) and OOB __set_bit */ +if (node <0 ) +return 0 ; + node_index = node; node_mask =bitmap_zalloc (node_index +1 );if (!node_mask) {pr_err ("Failed to allocate node mask for mbind: error %m\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 505/1067 perf sched: Clean up idle_threads entry on init failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit cda5a94ad9181cd60cbf04be11d524201bf489a2 ]
get_idle_thread() allocates a thread via thread__new() and stores it in idle_threads[cpu], then calls init_idle_thread() to set up the private data. If init_idle_thread() fails (e.g. OOM for the idle_thread_runtime struct), the function returns NULL but leaves the partially initialized thread in idle_threads[cpu].
On subsequent calls for the same CPU, get_idle_thread() finds a non-NULL idle_threads[cpu], skips allocation, and returns thread__get() on a thread that has no priv data. Callers then get a thread whose thread__priv() returns NULL, leading to unexpected behavior.
Release the thread and reset the slot to NULL on init failure so the entry doesn't persist in a corrupted state.
--- tools/perf/builtin-sched.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/perf/builtin-sched.c +4 -1
@@ -2349,8 +2349,11 @@ static struct thread *get_idle_thread(int cpu) idle_threads[cpu] =thread__new (0 ,0 );if (idle_threads[cpu]) { -if (init_idle_thread (idle_threads[cpu]) <0 ) +if (init_idle_thread (idle_threads[cpu]) <0 ) { +/* clean up so next call doesn't find a half-initialized thread */ +thread__zput (idle_threads[cpu]);return NULL ; + } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 506/1067 perf sched: Replace BUG_ON and add NULL checks in replay event helpers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 75eafe4a3a93a0143a20c0cc286bfb9008ac1478 ]
get_new_event() has three issues:
1. The zalloc() result is dereferenced without a NULL check, crashing on allocation failure.
2. BUG_ON(!task->atoms) kills the process when realloc() fails. Since perf.data is untrusted input, this should be a graceful error.
3. The realloc pattern assigns directly to task->atoms, losing the old pointer on failure. task->nr_events is also incremented before the realloc, leaving corrupted state on failure.
Fix get_new_event() to:
- Check the zalloc() result before dereferencing
- Use a temporary for realloc() to avoid losing the old pointer
- Increment nr_events only after successful realloc
- Return NULL instead of calling BUG_ON on failure
Also fix add_sched_event_wakeup() where zalloc() for wait_sem is passed to sem_init() without a NULL check.
Update all callers (add_sched_event_run, add_sched_event_wakeup, add_sched_event_sleep) to handle NULL returns by returning early. The replay may produce incomplete output on OOM but will not crash.
--- tools/perf/builtin-sched.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
tools/perf/builtin-sched.c +25 -3
@@ -363,14 +363,25 @@ get_new_event(struct task_desc *task, u64 timestamp)struct sched_atom *event =zalloc (sizeof (*event));unsigned long idx = task->nr_events;size_t size; +struct sched_atom **atoms_p; + +if (event ==NULL ) { +pr_err ("ERROR: sched: failed to allocate event\n" ); +return NULL ; + } event->timestamp = timestamp; event->nr = idx; + size =sizeof (struct sched_atom *) * (task->nr_events +1 ); + atoms_p =realloc (task->atoms, size); +if (!atoms_p) { +pr_err ("ERROR: sched: failed to grow atoms array\n" ); +free (event); +return NULL ; + } + task->atoms = atoms_p; task->nr_events++; - size =sizeof (struct sched_atom *) * task->nr_events; - task->atoms =realloc (task->atoms, size); -BUG_ON (!task->atoms); task->atoms[idx] = event;
@@ -401,6 +412,8 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task } event =get_new_event (task, timestamp); +if (event ==NULL ) +return ; event->type =SCHED_EVENT_RUN ; event->duration = duration;
@@ -414,6 +427,8 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *tstruct sched_atom *event, *wakee_event; event =get_new_event (task, timestamp); +if (event ==NULL ) +return ; event->type =SCHED_EVENT_WAKEUP ; event->wakee = wakee;
@@ -428,6 +443,10 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t } wakee_event->wait_sem =zalloc (sizeof (*wakee_event->wait_sem)); +if (!wakee_event->wait_sem) { +pr_err ("ERROR: sched: failed to allocate semaphore\n" ); +return ; + }sem_init (wakee_event->wait_sem,0 ,0 ); wakee_event->specific_wait =1 ; event->wait_sem = wakee_event->wait_sem;
@@ -440,6 +459,9 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta {struct sched_atom *event =get_new_event (task, timestamp); +if (event ==NULL ) +return ; + event->type =SCHED_EVENT_SLEEP ; sched->nr_sleep_events++;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 507/1067 perf mmap: Fix NULL deref in aio cleanup on alloc failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 25627346b10e6a564610ea2c49dc6dd54812226d ]
perf_mmap__aio_mmap() sets map->aio.nr_cblocks before allocating the data array. If calloc() for aiocb or cblocks fails before the data array is allocated, the return -1 path leads to perf_mmap__aio_munmap() which loops nr_cblocks times calling perf_mmap__aio_free(). Both versions of perf_mmap__aio_free() (NUMA and non-NUMA) dereference map->aio.data[idx] without checking if data is NULL, causing a NULL pointer dereference.
Add NULL checks for map->aio.data at the top of both perf_mmap__aio_free() variants so the cleanup path is safe when allocation fails partway through perf_mmap__aio_mmap().
--- tools/perf/util/mmap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/mmap.c +6 -4
@@ -88,10 +88,10 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx)static void perf_mmap__aio_free (struct mmap *map,int idx) { -if (map->aio.data[idx]) { -munmap (map->aio.data[idx],mmap__mmap_len (map)); - map->aio.data[idx] =NULL ; - } +if (!map->aio.data || !map->aio.data[idx]) +return ; +munmap (map->aio.data[idx],mmap__mmap_len (map)); + map->aio.data[idx] =NULL ; }static int perf_mmap__aio_bind (struct mmap *map,int idx,struct perf_cpu cpu,int affinity)
@@ -140,6 +140,8 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx)static void perf_mmap__aio_free (struct mmap *map,int idx) { +if (!map->aio.data) +return ;zfree (&(map->aio.data[idx])); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 508/1067 perf c2c: Fix use-after-free in he__get_c2c_hists() error path
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 5e5e6196d737c5be03d20647428316b36621608d ]
he__get_c2c_hists() assigns c2c_he->hists before calling c2c_hists__init(). If init fails, the error path calls free(hists) but leaves c2c_he->hists pointing to freed memory. On teardown, c2c_he_free() finds the non-NULL pointer and calls hists__delete_entries() on it, causing a use-after-free.
Set c2c_he->hists to NULL before freeing so teardown skips the already-freed allocation.
--- tools/perf/builtin-c2c.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/builtin-c2c.c +1 -0
@@ -216,6 +216,7 @@ he__get_c2c_hists(struct hist_entry *he, ret =c2c_hists__init (hists, sort, nr_header_lines);if (ret) { + c2c_he->hists =NULL ;free (hists);return NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 509/1067 dmaengine: qcom: gpi: set DMA_PRIVATE capability
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Icenowy Zheng <[email protected]>
[ Upstream commit 4e351f408743354d54ee1af5193fc78234f2044e ]
The GPI DMA controller is only responsible for QUP peripherals, and cannot work as a general-purpose DMA accelerator.
Set DMA_PRIVATE capability for it.
This fixes error messages about GPI being shown when an async-tx consumer is loaded.
--- drivers/dma/qcom/gpi.c | 1 + 1 file changed, 1 insertion(+)
drivers/dma/qcom/gpi.c +1 -0
@@ -2253,6 +2253,7 @@ static int gpi_probe(struct platform_device *pdev)/* clear and Set capabilities */ dma_cap_zero (gpi_dev->dma_device.cap_mask);dma_cap_set (DMA_SLAVE , gpi_dev->dma_device.cap_mask); +dma_cap_set (DMA_PRIVATE , gpi_dev->dma_device.cap_mask);/* configure dmaengine apis */ gpi_dev->dma_device.directions =BIT (DMA_DEV_TO_MEM ) |BIT (DMA_MEM_TO_DEV );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 510/1067 dmaengine: Fix possible use after free
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nuno Sá <[email protected]>
[ Upstream commit 92f853f0645aebf1d05d333e97ab7c342ace1892 ]
In dma_release_channel(), check chan->device->privatecnt after call dma_chan_put(). However, dma_chan_put() call dma_device_put() which could release the last reference of the device if the DMA provider is already gone and hence free it.
Fixes it by moving dma_chan_put() after the check.
--- drivers/dma/dmaengine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/dma/dmaengine.c +2 -1
@@ -905,11 +905,12 @@ void dma_release_channel(struct dma_chan *chan)mutex_lock (&dma_list_mutex);WARN_ONCE (chan->client_count !=1 ,"chan reference count %d != 1\n" , chan->client_count); -dma_chan_put (chan);/* drop PRIVATE cap enabled by __dma_request_channel() */ if (--chan->device->privatecnt ==0 )dma_cap_clear (DMA_PRIVATE , chan->device->cap_mask); +dma_chan_put (chan); +if (chan->slave) {sysfs_remove_link (&chan->dev->device.kobj,DMA_SLAVE_NAME );sysfs_remove_link (&chan->slave->kobj, chan->name);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 511/1067 clk: qcom: a53: Corrected frequency multiplier for 1152MHz
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Varney <[email protected]>
[ Upstream commit bb56147ea9fce98ebde1d367335ba006cba61fbd ]
The 1152MHz frequency entry for the a53 currently selects a multiplier of 62, giving 1190MHz. This changes the mulitiplier to 60 giving the intended 1152MHz.
--- drivers/clk/qcom/a53-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/qcom/a53-pll.c +1 -1
@@ -20,7 +20,7 @@static const struct pll_freq_tbl a53pll_freq[] = { {998400000 ,52 ,0x0 ,0x1 ,0 }, {1094400000 ,57 ,0x0 ,0x1 ,0 }, - {1152000000 ,62 ,0x0 ,0x1 ,0 }, + {1152000000 ,60 ,0x0 ,0x1 ,0 }, {1209600000 ,63 ,0x0 ,0x1 ,0 }, {1248000000 ,65 ,0x0 ,0x1 ,0 }, {1363200000 ,71 ,0x0 ,0x1 ,0 },
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 512/1067 pNFS/filelayout: fix cheking if a layout is striped
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sagi Grimberg <[email protected]>
[ Upstream commit 91668417d4e925c98cae4a55b1b9860380ddbf16 ]
A layout can still be striped with num_fh = 1 as it is perfectly possible that both MDS and DSs can handle the same filehandle. Hence check according to stripe_count > 1, which is the correct check to begin with.
We should not be called with flseg->dsaddr = NULL, but if for some reason we do, return our best guess with is flseg->num_fh > 1.
--- fs/nfs/filelayout/filelayout.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfs/filelayout/filelayout.c +2 -0
@@ -786,6 +786,8 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,static bool filelayout_lseg_is_striped (const struct nfs4_filelayout_segment *flseg) { +if (flseg->dsaddr) +return flseg->dsaddr->stripe_count >1 ;return flseg->num_fh >1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 513/1067 xprtrdma: Remove temp allocation of rpcrdma_rep objects
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0e13dd9ea8be46f980a46c3ffd8cb786f3e2fb5b ]
The original code was designed so that most calls to rpcrdma_rep_create() would occur on the NUMA node that the device preferred. There are a few cases where that's not possible, so those reps are marked as temporary.
However, we have the device (and its preferred node) already in rpcrdma_rep_create(), so let's use that to guarantee the memory is allocated from the correct node.
Stable-dep-of: e786233d2e0b ("xprtrdma: Decouple req recycling from RPC completion")
--- net/sunrpc/xprtrdma/rpc_rdma.c | 3 +- net/sunrpc/xprtrdma/verbs.c | 57 ++++++++++++++------------------- net/sunrpc/xprtrdma/xprt_rdma.h | 3 +- 3 files changed, 26 insertions(+), 37 deletions(-)
net/sunrpc/xprtrdma/rpc_rdma.c +1 -2
@@ -1471,8 +1471,7 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) credits =1 ;/* don't deadlock */ else if (credits > r_xprt->rx_ep->re_max_requests) credits = r_xprt->rx_ep->re_max_requests; -rpcrdma_post_recvs (r_xprt, credits + (buf->rb_bc_srv_max_requests <<1 ), - false); +rpcrdma_post_recvs (r_xprt, credits + (buf->rb_bc_srv_max_requests <<1 ));if (buf->rb_credits != credits)rpcrdma_update_cwnd (r_xprt, credits);
net/sunrpc/xprtrdma/verbs.c +24 -33
146 lines not on this page · raw message
net/sunrpc/xprtrdma/xprt_rdma.h +1 -2
@@ -198,7 +198,6 @@ struct rpcrdma_rep {__be32 rr_proc;int rr_wc_flags;u32 rr_inv_rkey; -bool rr_temp;struct rpcrdma_regbuf *rr_rdmabuf;struct rpcrdma_xprt *rr_rxprt;struct rpc_rqst *rr_rqst;
@@ -466,7 +465,7 @@ void rpcrdma_flush_disconnect(struct rpcrdma_xprt *r_xprt, struct ib_wc *wc);int rpcrdma_xprt_connect (struct rpcrdma_xprt *r_xprt);void rpcrdma_xprt_disconnect (struct rpcrdma_xprt *r_xprt); -void rpcrdma_post_recvs (struct rpcrdma_xprt *r_xprt,int needed,bool temp); +void rpcrdma_post_recvs (struct rpcrdma_xprt *r_xprt,int needed);/* * Buffer calls - xprtrdma/verbs.c
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 514/1067 xprtrdma: Avoid 250 ms delay on backlog wakeup
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 100142093e22b3f7741ac88e94878bb3694e306f ]
Commit a721035477fb ("SUNRPC/xprt: async tasks mustn't block waiting for memory") changed xprt_rdma_alloc_slot() to set tk_status to -ENOMEM so that call_reserveresult() would sleep HZ/4 before retrying. That rationale applies to xprt_dynamic_alloc_slot(), where an immediate retry under memory pressure wastes CPU, but not to the RDMA backlog path: a task woken from the backlog has a slot waiting for it, so the 250 ms rpc_delay adds latency without benefit.
This also aligns the code with the existing kernel-doc for xprt_rdma_alloc_slot(), which already documented %-EAGAIN.
Stable-dep-of: e786233d2e0b ("xprtrdma: Decouple req recycling from RPC completion")
--- net/sunrpc/xprtrdma/transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sunrpc/xprtrdma/transport.c +1 -1
@@ -520,7 +520,7 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)return ; out_sleep: - task->tk_status = -ENOMEM ; + task->tk_status = -EAGAIN ;xprt_add_backlog (xprt, task); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 515/1067 xprtrdma: Close lost-wakeup race in xprt_rdma_alloc_slot
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 765bde47fe7f197dabeb12da76831f40d0b20377 ]
xprt_rdma_alloc_slot() and xprt_rdma_free_slot() lack serialization between the buffer pool and the backlog queue. A buffer freed after rpcrdma_buffer_get() finds the pool empty but before rpc_sleep_on() places the task on the backlog is returned to the pool with no waiter to wake, leaving the task stuck on the backlog indefinitely.
After joining the backlog, re-check the pool and route any recovered buffer through xprt_wake_up_backlog(), whose queue lock serializes with concurrent wakeups and avoids double-assignment of slots.
Because xprt_rdma_free_slot() does not hold reserve_lock, the XPRT_CONGESTED double-check in xprt_throttle_congested() is
ineffective: a task can join the backlog through that path after free_slot has already found it empty and cleared the bit. Avoid this by using xprt_add_backlog_noncongested(), which queues the task without setting XPRT_CONGESTED, so every allocation reaches xprt_rdma_alloc_slot() and its post-sleep re-check.
Stable-dep-of: e786233d2e0b ("xprtrdma: Decouple req recycling from RPC completion")
--- include/linux/sunrpc/xprt.h | 2 ++ net/sunrpc/xprt.c | 16 ++++++++++++++++ net/sunrpc/xprtrdma/transport.c | 15 ++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-)
include/linux/sunrpc/xprt.h +2 -0
@@ -378,6 +378,8 @@ struct rpc_xprt * xprt_alloc(struct net *net, size_t size, unsigned int max_req);void xprt_free (struct rpc_xprt *);void xprt_add_backlog (struct rpc_xprt *xprt,struct rpc_task *task); +void xprt_add_backlog_noncongested (struct rpc_xprt *xprt, +struct rpc_task *task);bool xprt_wake_up_backlog (struct rpc_xprt *xprt,struct rpc_rqst *req);void xprt_cleanup_ids (void );
net/sunrpc/xprt.c +16 -0
@@ -1651,6 +1651,22 @@ void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task) }EXPORT_SYMBOL_GPL (xprt_add_backlog); +/** +* xprt_add_backlog_noncongested - queue task on backlog +* @xprt: transport whose backlog queue receives the task +* @task: task to queue +* +* Like xprt_add_backlog, but does not set XPRT_CONGESTED. +* For transports whose free_slot path does not synchronize +* with xprt_throttle_congested via reserve_lock. +*/ +void xprt_add_backlog_noncongested (struct rpc_xprt *xprt, +struct rpc_task *task) +{ +rpc_sleep_on (&xprt->backlog, task, xprt_complete_request_init); +} +EXPORT_SYMBOL_GPL (xprt_add_backlog_noncongested); +static bool __xprt_set_rq (struct rpc_task *task,void *data) {struct rpc_rqst *req = data;
net/sunrpc/xprtrdma/transport.c +14 -1
@@ -521,7 +521,20 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) out_sleep: task->tk_status = -EAGAIN ; -xprt_add_backlog (xprt, task); +xprt_add_backlog_noncongested (xprt, task); +/* A buffer freed between buffer_get and rpc_sleep_on +* goes back to the pool with no waiter to wake. +* Re-check after joining the backlog to close that gap. +*/ + req =rpcrdma_buffer_get (&r_xprt->rx_buf); +if (req) { +struct rpc_rqst *rqst = &req->rl_slot; + +if (!xprt_wake_up_backlog (xprt, rqst)) { +memset (rqst,0 ,sizeof (*rqst)); +rpcrdma_buffer_put (&r_xprt->rx_buf, req); + } + } }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 516/1067 xprtrdma: Post receive buffers after RPC completion
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 704f3f640f72db4d44ec5ce3db8d4e150c974bc7 ]
rpcrdma_post_recvs() runs in CQ poll context and its cost falls on the latency-critical path between polling a Receive completion and waking the RPC consumer. Every cycle spent refilling the Receive Queue delays delivery of the reply to the NFS layer.
Move the rpcrdma_post_recvs() call in rpcrdma_reply_handler() to after the RPC has been decoded and completed. The larger batch size from the preceding patch provides sufficient Receive Queue headroom to absorb the brief delay before buffers are replenished.
Stable-dep-of: e786233d2e0b ("xprtrdma: Decouple req recycling from RPC completion")
--- net/sunrpc/xprtrdma/rpc_rdma.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
net/sunrpc/xprtrdma/rpc_rdma.c +9 -5
@@ -1471,7 +1471,6 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep) credits =1 ;/* don't deadlock */ else if (credits > r_xprt->rx_ep->re_max_requests) credits = r_xprt->rx_ep->re_max_requests; -rpcrdma_post_recvs (r_xprt, credits + (buf->rb_bc_srv_max_requests <<1 ));if (buf->rb_credits != credits)rpcrdma_update_cwnd (r_xprt, credits);
@@ -1490,15 +1489,20 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)/* LocalInv completion will complete the RPC */ else kref_put(&req->rl_kref, rpcrdma_reply_done); -return ; -out_badversion: -trace_xprtrdma_reply_vers_err (rep); - goto out; +out_post: +rpcrdma_post_recvs (r_xprt, + credits + (buf->rb_bc_srv_max_requests <<1 )); +return ; out_norqst:spin_unlock (&xprt->queue_lock);trace_xprtrdma_reply_rqst_err (rep); +rpcrdma_rep_put (buf, rep); + goto out_post; + +out_badversion: +trace_xprtrdma_reply_vers_err (rep); goto out; out_shortreply:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 517/1067 xprtrdma: Use sendctx DMA state for Send signaling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2797ae7c929610fb2d2303a996a08173fa096730 ]
Send signaling matters only when the prepared Send has page mappings to unmap. Today that test is expressed indirectly with rl_kref, because the Send-side reference is taken only for Sends with mapped SGEs.
Split the SGE DMA unmap loop into its own helper and use sc_unmap_count directly for the signaling decision. This keeps the current behavior but removes one dependency on the old rl_kref semantics before the request lifetime rules are changed.
Stable-dep-of: e786233d2e0b ("xprtrdma: Decouple req recycling from RPC completion")
--- net/sunrpc/xprtrdma/frwr_ops.c | 2 +- net/sunrpc/xprtrdma/rpc_rdma.c | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-)
net/sunrpc/xprtrdma/frwr_ops.c +1 -1
@@ -404,7 +404,7 @@ int frwr_send(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) ++num_wrs; } -if ((kref_read (&req->rl_kref) >1 ) || num_wrs > ep->re_send_count) { +if (req->rl_sendctx->sc_unmap_count || num_wrs > ep->re_send_count) { send_wr->send_flags |=IB_SEND_SIGNALED ; ep->re_send_count = min_t(unsigned int, ep->re_send_batch, num_wrs - ep->re_send_count);
net/sunrpc/xprtrdma/rpc_rdma.c +13 -9
@@ -526,19 +526,11 @@ static void rpcrdma_sendctx_done(struct kref *kref) rep->rr_rxprt->rx_stats.reply_waits_for_send++; } -/** -* rpcrdma_sendctx_unmap - DMA-unmap Send buffer -* @sc: sendctx containing SGEs to unmap -* -*/ -void rpcrdma_sendctx_unmap (struct rpcrdma_sendctx *sc) +static void rpcrdma_sendctx_dma_unmap (struct rpcrdma_sendctx *sc) {struct rpcrdma_regbuf *rb = sc->sc_req->rl_sendbuf;struct ib_sge *sge; -if (!sc->sc_unmap_count) -return ; -/* The first two SGEs contain the transport header and * the inline buffer. These are always left mapped so * they can be cheaply re-used.
@@ -547,7 +539,19 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc) ++sge, --sc->sc_unmap_count)ib_dma_unmap_page (rdmab_device (rb), sge->addr, sge->length,DMA_TO_DEVICE ); +} + +/** +* rpcrdma_sendctx_unmap - DMA-unmap Send buffer +* @sc: sendctx containing SGEs to unmap +* +*/ +void rpcrdma_sendctx_unmap (struct rpcrdma_sendctx *sc) +{ +if (!sc->sc_unmap_count) +return ; +rpcrdma_sendctx_dma_unmap (sc);kref_put (&sc->sc_req->rl_kref, rpcrdma_sendctx_done); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 518/1067 xprtrdma: Decouple req recycling from RPC completion
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit e786233d2e0bbff9a82e43f02ae3a46ab4b08ec3 ]
rl_kref formerly served two distinct lifetimes through a single
refcount: it gated when a Reply could wake its RPC task, and it gated when an rpcrdma_req could return to its free pool. The marshal path took the Send-side reference only when SGEs needed DMA-unmap (sc_unmap_count > 0), which made a Send carrying only pre-registered buffers an exception: the Reply handler dropped rl_kref from 1 to 0 and freed the req while the HCA might still be DMA-reading from its send buffer.
Give rl_kref a narrower job. The RPC layer takes one reference when slot allocation hands a req out. rpcrdma_prepare_send_sges() takes a Send-side reference unconditionally after WR preparation succeeds. xprt_rdma_free_slot() and xprt_rdma_bc_free_rqst() drop the RPC-layer reference; rpcrdma_sendctx_unmap() drops the Send-side reference. The req returns to its free pool only after both owners have signed off.
The existing kref_init(&req->rl_kref) call in rpcrdma_prepare_send_sges() is removed. Initialization moves to the slot-allocation paths (xprt_rdma_alloc_slot and rpcrdma_bc_rqst_get), and the release callback re-arms rl_kref before the req returns to a free pool. A re-init in the marshal path would discard the RPC-layer reference that already exists on entry.
Three invariants follow:
- Any rpcrdma_req held by an rpc_rqst has rl_kref >= 1. xprt_rdma_alloc_slot(), rpcrdma_bc_rqst_get(), and the backlog-wake branch in xprt_rdma_alloc_slot() each kref_init rl_kref before publishing the req. Without this invariant, an RPC task that aborts between slot allocation and marshal (gss_refresh failure or signal during call_connect, for example) would drive xprt_release() -> xprt_rdma_free_slot() -> kref_put against a refcount of zero, saturating refcount_t and stranding the slot.
- The Send-side reference is taken only after WR prep succeeds. A mapping failure in rpcrdma_prepare_send_sges() runs rpcrdma_sendctx_cancel(), which DMA-unmaps the sendctx and clears sc_req without touching rl_kref. The sendctx ring walks in rpcrdma_sendctx_put_locked() and rpcrdma_sendctxs_destroy() skip entries with sc_req == NULL, so a burst of -EIO marshal failures cannot hold reqs off rb_send_bufs.
- The release callback re-arms rl_kref so the next consumer enters with the invariant satisfied.
Replies now complete the RPC directly. rpcrdma_reply_handler() calls rpcrdma_complete_rqst() in place of kref_put on the non-LocalInv branch. The LocalInv branch already completes the RPC from frwr_unmap_async() and is unaffected.
Because Send-side references can now outlive RPC completion, connection teardown drains sendctx entries whose unsignaled Sends never had a later signaled completion to walk the ring. rpcrdma_sendctxs_destroy() walks the active range and runs rpcrdma_sendctx_unmap() on each entry with a non-NULL sc_req before the request buffers are reset, and is moved ahead of rpcrdma_reqs_reset() in rpcrdma_xprt_disconnect() so the reqs are still in their pre-reset state when the Send-side refs are released.
The drain creates a teardown-ordering hazard on the backchannel path. With the new lifetime, releasing a bc_prealloc req from rpcrdma_req_release() re-adds it to bc_pa_list. The disconnect in xprt_rdma_destroy() runs after xprt_destroy_backchannel() has already emptied bc_pa_list, so the drained reqs would otherwise leak. xprt_rdma_destroy() now runs xprt_rdma_bc_destroy(xprt, 0) a second time after the disconnect to reclaim them.
--- net/sunrpc/xprtrdma/backchannel.c | 5 ++- net/sunrpc/xprtrdma/rpc_rdma.c | 47 +++++++++++--------------- net/sunrpc/xprtrdma/transport.c | 55 ++++++++++++++++++++++++++++--- net/sunrpc/xprtrdma/verbs.c | 29 +++++++++++++--- net/sunrpc/xprtrdma/xprt_rdma.h | 2 +- 5 files changed, 97 insertions(+), 41 deletions(-)
net/sunrpc/xprtrdma/backchannel.c +2 -3
@@ -158,9 +158,7 @@ void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)rpcrdma_rep_put (&r_xprt->rx_buf, rep); req->rl_reply =NULL ; -spin_lock (&xprt->bc_pa_lock); -list_add_tail (&rqst->rq_bc_pa_list, &xprt->bc_pa_list); -spin_unlock (&xprt->bc_pa_lock); +rpcrdma_req_put (req);xprt_put (xprt); }
@@ -202,6 +200,7 @@ static struct rpc_rqst *rpcrdma_bc_rqst_get(struct rpcrdma_xprt *r_xprt) rqst->rq_xprt = xprt;__set_bit (RPC_BC_PA_IN_USE , &rqst->rq_bc_pa_state);xdr_buf_init (&rqst->rq_snd_buf,rdmab_data (req->rl_sendbuf), size); +kref_init (&req->rl_kref);return rqst; }
net/sunrpc/xprtrdma/rpc_rdma.c +19 -28
105 lines not on this page · raw message
net/sunrpc/xprtrdma/transport.c +50 -5
91 lines not on this page · raw message
net/sunrpc/xprtrdma/verbs.c +25 -4
@@ -65,6 +65,8 @@static int rpcrdma_sendctxs_create (struct rpcrdma_xprt *r_xprt);static void rpcrdma_sendctxs_destroy (struct rpcrdma_xprt *r_xprt); +static unsigned long rpcrdma_sendctx_next (struct rpcrdma_buffer *buf, +unsigned long item);static void rpcrdma_sendctx_put_locked (struct rpcrdma_xprt *r_xprt,struct rpcrdma_sendctx *sc);static int rpcrdma_reqs_setup (struct rpcrdma_xprt *r_xprt);
@@ -566,9 +568,9 @@ void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt)rpcrdma_xprt_drain (r_xprt);rpcrdma_reps_unmap (r_xprt); +rpcrdma_sendctxs_destroy (r_xprt);rpcrdma_reqs_reset (r_xprt);rpcrdma_mrs_destroy (r_xprt); -rpcrdma_sendctxs_destroy (r_xprt);if (rpcrdma_ep_put (ep))rdma_destroy_id (id);
@@ -600,6 +602,20 @@ static void rpcrdma_sendctxs_destroy(struct rpcrdma_xprt *r_xprt)if (!buf->rb_sc_ctxs)return ; + +/* The QP is drained, but the final unsignaled Sends might not +* have been walked by a signaled Send completion. Release those +* Send owners before request buffers are reset. +*/ +for (i =rpcrdma_sendctx_next (buf, buf->rb_sc_tail); + i !=rpcrdma_sendctx_next (buf, buf->rb_sc_head); + i =rpcrdma_sendctx_next (buf, i)) { +struct rpcrdma_sendctx *sc = buf->rb_sc_ctxs[i]; + +if (sc && sc->sc_req) +rpcrdma_sendctx_unmap (sc); + } +for (i =0 ; i <= buf->rb_sc_last; i++)kfree (buf->rb_sc_ctxs[i]);kfree (buf->rb_sc_ctxs);
@@ -722,15 +738,20 @@ static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,struct rpcrdma_buffer *buf = &r_xprt->rx_buf;unsigned long next_tail; -/* Unmap SGEs of previously completed but unsignaled -* Sends by walking up the queue until @sc is found. +/* Release previously completed but unsignaled Sends by walking +* up the queue until @sc is found. Entries left behind by a +* failed rpcrdma_prepare_send_sges() have sc_req cleared. */ next_tail = buf->rb_sc_tail;do { +struct rpcrdma_sendctx *cur; + next_tail =rpcrdma_sendctx_next (buf, next_tail);/* ORDER: item must be accessed _before_ tail is updated */ -rpcrdma_sendctx_unmap (buf->rb_sc_ctxs[next_tail]); + cur = buf->rb_sc_ctxs[next_tail]; +if (cur->sc_req) +rpcrdma_sendctx_unmap (cur); }while (buf->rb_sc_ctxs[next_tail] != sc);
net/sunrpc/xprtrdma/xprt_rdma.h +1 -1
@@ -408,7 +408,6 @@ struct rpcrdma_stats {/* accessed when receiving a reply */ unsigned long long total_rdma_reply;unsigned long long fixup_copy_count; -unsigned long reply_waits_for_send;unsigned long local_inv_needed;unsigned long nomsg_call_count;unsigned long bcall_count;
@@ -486,6 +485,7 @@ void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req);void rpcrdma_rep_put (struct rpcrdma_buffer *buf,struct rpcrdma_rep *rep);void rpcrdma_reply_put (struct rpcrdma_buffer *buffers,struct rpcrdma_req *req); +void rpcrdma_req_put (struct rpcrdma_req *req);bool rpcrdma_regbuf_realloc (struct rpcrdma_regbuf *rb,size_t size,gfp_t flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 519/1067 NFSv4/pnfs: defer return_range callbacks until after inode unlock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 77b160b2d863d37f36b6c38e80a7d259ce939e69 ]
Sometimes unmounting an NFS filesystem mounted with pNFS SCSI layouts triggers the following warning:
BUG: scheduling while atomic: umount.nfs4/...
__schedule_bug+0xbd/0x100
schedule_debug.constprop.0+0x19f/0x220
__schedule+0x10d/0x10a0
schedule+0x74/0x190
schedule_timeout+0xf5/0x220
io_schedule_timeout+0xd5/0x160
__wait_for_common+0x186/0x4b0
blk_execute_rq+0x2ef/0x3a0
scsi_execute_cmd+0x1ff/0x700
sd_pr_out_command.isra.0+0x242/0x380 [sd_mod]
bl_unregister_scsi.constprop.0+0x109/0x3c0 [blocklayoutdriver]
bl_unregister_dev+0x175/0x1c0 [blocklayoutdriver]
bl_free_device+0x1f/0x1b0 [blocklayoutdriver]
bl_free_deviceid_node+0x12/0x30 [blocklayoutdriver]
nfs4_put_deviceid_node+0x171/0x360 [nfsv4]
ext_tree_remove+0x11c/0x1d0 [blocklayoutdriver]
_pnfs_return_layout+0x416/0x900 [nfsv4]
nfs4_evict_inode+0x108/0x130 [nfsv4]
evict+0x316/0x750
dispose_list+0xf1/0x1a0
evict_inodes+0x33f/0x440
generic_shutdown_super+0xc9/0x4e0
kill_anon_super+0x3a/0x90
nfs_kill_super+0x44/0x60 [nfs]
deactivate_locked_super+0xb8/0x1b0
cleanup_mnt+0x25a/0x380
task_work_run+0x13e/0x210
exit_to_user_mode_loop+0x169/0x400
do_syscall_64+0x467/0x1550
entry_SYSCALL_64_after_hwframe+0x76/0x7eThe warning occurs because the block layout driver unregisters the SCSI device while the inode lock is still held. Device unregistration issues a SCSI PR command, which may sleep, resulting in a "scheduling while atomic" warning.
During layout return, ext_tree_remove() invokes the layout driver's return_range callback while holding the inode lock. For block layouts, this callback eventually calls bl_unregister_scsi(), which may block in scsi_execute_cmd() while issuing PR commands to the device.
Fix this by deferring the return_range callbacks until after the inode lock has been released. The layout header reference count is incremented before invoking return_range(), ensuring that the layout header remains valid while the layout driver removes extents from the extent tree.
--- fs/nfs/callback_proc.c | 9 +++++---- fs/nfs/pnfs.c | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-)
fs/nfs/callback_proc.c +5 -4
@@ -248,6 +248,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,struct pnfs_layout_hdr *lo;u32 rv =NFS4ERR_NOMATCHING_LAYOUT ;LIST_HEAD (free_me_list); +bool return_range = false; ino =nfs_layout_find_inode (clp, &args->cbl_fh, &args->cbl_stateid);if (IS_ERR (ino)) {
@@ -292,13 +293,13 @@ static u32 initiate_file_draining(struct nfs_client *clp,/* Embrace your forgetfulness! */ rv =NFS4ERR_NOMATCHING_LAYOUT ; -if (NFS_SERVER (ino)->pnfs_curr_ld->return_range) { -NFS_SERVER (ino)->pnfs_curr_ld->return_range (lo, - &args->cbl_range); - } + return_range = true; } unlock:spin_unlock (&ino->i_lock); +if (return_range &&NFS_SERVER (ino)->pnfs_curr_ld->return_range) +NFS_SERVER (ino)->pnfs_curr_ld->return_range (lo, + &args->cbl_range);pnfs_free_lseg_list (&free_me_list);/* Free all lsegs that are attached to commit buckets */ nfs_commit_inode (ino,0 );
fs/nfs/pnfs.c +2 -2
@@ -1375,8 +1375,6 @@ _pnfs_return_layout(struct inode *ino)pnfs_clear_layoutcommit (ino, &tmp_list);pnfs_mark_matching_lsegs_return (lo, &tmp_list, &range,0 ); -if (NFS_SERVER (ino)->pnfs_curr_ld->return_range) -NFS_SERVER (ino)->pnfs_curr_ld->return_range (lo, &range);/* Don't send a LAYOUTRETURN if list was initially empty */ if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) ||
@@ -1388,6 +1386,8 @@ _pnfs_return_layout(struct inode *ino) send =pnfs_prepare_layoutreturn (lo, &stateid, &cred,NULL );spin_unlock (&ino->i_lock); +if (NFS_SERVER (ino)->pnfs_curr_ld->return_range) +NFS_SERVER (ino)->pnfs_curr_ld->return_range (lo, &range);if (send) status =pnfs_send_layoutreturn (lo, &stateid, &cred,IOMODE_ANY , true); out_wait_layoutreturn:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 520/1067 NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS on fatal DS connect errors
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer <[email protected]>
[ Upstream commit 7a375cafc14ed151508f908ea5681caf0a9cc1d6 ]
Commit f06bedfa62d5 ("pNFS/flexfiles: don't attempt pnfs on fatal DS errors") teaches ff_layout_{read,write}_pagelist() to return PNFS_NOT_ATTEMPTED when nfs4_ff_layout_prepare_ds() fails with a nfs_error_is_fatal() errno (e.g. -ETIMEDOUT from a SOFTCONN connect deadline, -ENOMEM, -ERESTARTSYS), so that the client gives up instead of spinning. pnfs_do_{read,write}() then dispatches the I/O through pnfs_{read,write}_through_mds() → nfs_pageio_reset_{read,write}_mds().
That fallback is unconditional and silently violates FF_FLAGS_NO_IO_THRU_MDS:
when the layout segment carries the flag (typically single-mirror appliance layouts where MDS I/O is explicitly forbidden), theout_failed: path's \&& !ds_fatal_error\ clause overrides the flag's short-circuit through ff_layout_avoid_mds_available_ds() and routes the I/O to the MDS file handle anyway.
This is reachable in practice during a data-server restart: SOFTCONN exhaustion produces -ETIMEDOUT, which is fatal per nfs_error_is_fatal(), which triggers PNFS_NOT_ATTEMPTED, which silently goes to MDS.
Preserve the upstream "don't spin on fatal errors" intent for layouts that permit MDS fallback. For layouts with FF_FLAGS_NO_IO_THRU_MDS set, mark the layout for return and request PNFS_TRY_AGAIN instead; if the server cannot supply a usable layout the failure now surfaces cleanly via pnfs_update_layout(), rather than via silent MDS I/O that contradicts the flag.
--- fs/nfs/flexfilelayout/flexfilelayout.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
fs/nfs/flexfilelayout/flexfilelayout.c +16 -0
@@ -1902,6 +1902,14 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) out_failed:if (ff_layout_avoid_mds_available_ds (lseg) && !ds_fatal_error)return PNFS_TRY_AGAIN ; +if (ff_layout_no_fallback_to_mds (lseg)) { +/* +* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET, +* never fall through to MDS I/O. +*/ +pnfs_error_mark_layout_for_return (hdr->inode, lseg); +return PNFS_TRY_AGAIN ; + }trace_pnfs_mds_fallback_read_pagelist (hdr->inode, hdr->args.offset, hdr->args.count,IOMODE_READ ,NFS_I (hdr->inode)->layout, lseg);
@@ -1973,6 +1981,14 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) out_failed:if (ff_layout_avoid_mds_available_ds (lseg) && !ds_fatal_error)return PNFS_TRY_AGAIN ; +if (ff_layout_no_fallback_to_mds (lseg)) { +/* +* FF_FLAGS_NO_IO_THRU_MDS: force fresh LAYOUTGET, +* never fall through to MDS I/O. +*/ +pnfs_error_mark_layout_for_return (hdr->inode, lseg); +return PNFS_TRY_AGAIN ; + }trace_pnfs_mds_fallback_write_pagelist (hdr->inode, hdr->args.offset, hdr->args.count,IOMODE_RW ,NFS_I (hdr->inode)->layout, lseg);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 521/1067 NFSv4/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS in pg_get_mirror_count_write
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer <[email protected]>
[ Upstream commit 1d62e659c0bf11649cf48e002c2a55d148f2610a ]
The FF_FLAGS_NO_IO_THRU_MDS flag lives on each lseg, so any fallback decision made when there is no current lseg (e.g. between LAYOUTRETURN and the next LAYOUTGET) cannot run the per-lseg check.
Introduce a sticky hdr-level ditto for FF_FLAGS_NO_IO_THRU_MDS in struct nfs4_flexfile_layout::flags (NFS4_FF_HDR_NO_IO_THRU_MDS bit), set whenever ff_layout_alloc_lseg() parses an lseg with the flag. The bit is never cleared for the lifetime of the layout hdr; the server is assumed to be consistent in its no-fallback policy per file. kzalloc() in ff_layout_alloc_layout_hdr() zero-initializes the field.
Use the new ff_layout_hdr_no_fallback_to_mds() helper to gate ff_layout_pg_get_mirror_count_write(): when pnfs_update_layout() returns NULL (e.g. NFS_LAYOUT_BULK_RECALL, pnfs_layout_io_test_failed, pnfs_layoutgets_blocked) the existing code unconditionally calls nfs_pageio_reset_write_mds(). This is a source of unwanted WRITE to MDS. Fix it by checking NFS4_FF_HDR_NO_IO_THRU_MDS bit, and if set surface -EAGAIN instead; the writepage-side caller (nfs_do_writepage() for buffered, nfs_direct_write_reschedule() for O_DIRECT) then redirties the request so writeback retries via pNFS.
--- fs/nfs/flexfilelayout/flexfilelayout.c | 13 +++++++++++++ fs/nfs/flexfilelayout/flexfilelayout.h | 16 ++++++++++++++++ 2 files changed, 29 insertions(+)
fs/nfs/flexfilelayout/flexfilelayout.c +13 -0
@@ -539,6 +539,9 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,if (!p) goto out_sort_mirrors; fls->flags =be32_to_cpup (p); +if (fls->flags &FF_FLAGS_NO_IO_THRU_MDS ) +set_bit (NFS4_FF_HDR_NO_IO_THRU_MDS , + &FF_LAYOUT_FROM_HDR (lh)->flags); p =xdr_inline_decode (&stream,4 );if (!p)
@@ -992,6 +995,16 @@ ff_layout_pg_get_mirror_count_write(struct nfs_pageio_descriptor *pgio,0 ,NFS4_MAX_UINT64 ,IOMODE_RW ,NFS_I (pgio->pg_inode)->layout, pgio->pg_lseg); +if (NFS_I (pgio->pg_inode)->layout && +ff_layout_hdr_no_fallback_to_mds (NFS_I (pgio->pg_inode)->layout)) { +/* +* FF_FLAGS_NO_IO_THRU_MDS: no current lseg but the server's +* policy forbids MDS fallback. Surface -EAGAIN so writeback +* retries rather than silently issuing the WRITE via MDS. +*/ + pgio->pg_error = -EAGAIN ; + goto out; + }/* no lseg means that pnfs is not in use, so no mirroring here */ nfs_pageio_reset_write_mds (pgio); out:
fs/nfs/flexfilelayout/flexfilelayout.h +16 -0
@@ -102,12 +102,16 @@ struct nfs4_ff_layout_segment {struct nfs4_ff_layout_mirror *mirror_array[]; }; +/* nfs4_flexfile_layout::flags bit indices */ +#define NFS4_FF_HDR_NO_IO_THRU_MDS 0/* any lseg has had FF_FLAGS_NO_IO_THRU_MDS */ +struct nfs4_flexfile_layout {struct pnfs_layout_hdr generic_hdr;struct pnfs_ds_commit_info commit_info;struct list_head mirrors;struct list_head error_list;/* nfs4_ff_layout_ds_err */ ktime_t last_report_time;/* Layoutstat report times */ +unsigned long flags; };struct nfs4_flexfile_layoutreturn_args {
@@ -174,6 +178,18 @@ ff_layout_no_fallback_to_mds(struct pnfs_layout_segment *lseg)return FF_LAYOUT_LSEG (lseg)->flags &FF_FLAGS_NO_IO_THRU_MDS ; } +/* +* Sticky hdr-level mirror of FF_FLAGS_NO_IO_THRU_MDS so callers that have +* no current lseg (e.g. between LAYOUTRETURN and the next LAYOUTGET) can +* still honor the no-MDS-fallback policy. +*/ +static inline bool +ff_layout_hdr_no_fallback_to_mds (struct pnfs_layout_hdr *lo) +{ +return test_bit (NFS4_FF_HDR_NO_IO_THRU_MDS , + &FF_LAYOUT_FROM_HDR (lo)->flags); +} +static inline bool ff_layout_no_read_on_rw (struct pnfs_layout_segment *lseg) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 522/1067 PCI: mediatek: Fix operator precedence in PCIE_FTS_NUM_L0 macro
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 282305d7e9c0e27fd8b4df34b7cd5506a1eccdd6 ]
The original PCIE_FTS_NUM_L0(x) macro was buggy due to improper operator precedence, where ((x) & 0xff << 8) was evaluated as ((x) & 0xff00).
Instead of just fixing the parentheses, use the standard FIELD_PREP() macro. This makes the code more robust by automatically handling masks and shifts, while also adding compile-time type and range checking to ensure the value fits within PCIE_FTS_NUM_MASK.
--- drivers/pci/controller/pcie-mediatek.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pci/controller/pcie-mediatek.c +2 -1
@@ -7,6 +7,7 @@* Honghui Zhang <[email protected]> */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/iopoll.h>
@@ -60,7 +61,7 @@/* MediaTek specific configuration registers */ #define PCIE_FTS_NUM 0x70c#define PCIE_FTS_NUM_MASK GENMASK(15, 8) -#define PCIE_FTS_NUM_L0 (x) ((x) & 0xff << 8) +#define PCIE_FTS_NUM_L0 (x) FIELD_PREP(PCIE_FTS_NUM_MASK, x)#define PCIE_FC_CREDIT 0x73c#define PCIE_FC_CREDIT_MASK (GENMASK(31, 31) | GENMASK(28, 16))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 523/1067 perf tools: Fix get_max_num() size_t underflow on empty sysfs file
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 0a012113bb3a44482c163f16f4db03ccaa37a339 ]
get_max_num() reads a sysfs file (cpu/possible, cpu/present, or node/possible) and scans backward from the end to find the last number. If the file is empty, filename__read_str() returns num == 0. The loop while (--num) decrements the size_t from 0 to SIZE_MAX, reading backward across the heap until a comma or hyphen is found or unmapped memory is hit.
Add an early return for empty files before the backward scan.
--- tools/perf/util/cpumap.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/perf/util/cpumap.c +6 -0
@@ -366,6 +366,12 @@ static int get_max_num(char *path, int *max) buf[num] ='\0' ; +/* empty file — nothing to parse */ +if (num ==0 ) { + err =-1 ; + goto out; + } +/* start on the right, to find highest node num */ while (--num) {if ((buf[num] ==',' ) || (buf[num] =='-' )) {
Signature · 1 line
2.53.0