From fad75018ba11208e30e47cbf66a8d8faf6877be7 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Wed, 3 Dec 2025 15:04:08 +0100 Subject: [PATCH 01/11] ALSA: usb-audio: Validate UAC3 cluster segment descriptors jira VULN-152932 cve CVE-2025-39757 commit-author Takashi Iwai commit ecfd41166b72b67d3bdeb88d224ff445f6163869 UAC3 class segment descriptors need to be verified whether their sizes match with the declared lengths and whether they fit with the allocated buffer sizes, too. Otherwise malicious firmware may lead to the unexpected OOB accesses. Fixes: 11785ef53228 ("ALSA: usb-audio: Initial Power Domain support") Reported-and-tested-by: Youngjun Lee Cc: Link: https://patch.msgid.link/20250814081245.8902-2-tiwai@suse.de Signed-off-by: Takashi Iwai (cherry picked from commit ecfd41166b72b67d3bdeb88d224ff445f6163869) Signed-off-by: Roxana Nicolescu --- sound/usb/stream.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 50c12430bf0ea..479681b8fea62 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -336,20 +336,28 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor len = le16_to_cpu(cluster->wLength); c = 0; - p += sizeof(struct uac3_cluster_header_descriptor); + p += sizeof(*cluster); + len -= sizeof(*cluster); - while (((p - (void *)cluster) < len) && (c < channels)) { + while (len > 0 && (c < channels)) { struct uac3_cluster_segment_descriptor *cs_desc = p; u16 cs_len; u8 cs_type; + if (len < sizeof(*p)) + break; cs_len = le16_to_cpu(cs_desc->wLength); + if (len < cs_len) + break; cs_type = cs_desc->bSegmentType; if (cs_type == UAC3_CHANNEL_INFORMATION) { struct uac3_cluster_information_segment_descriptor *is = p; unsigned char map; + if (cs_len < sizeof(*is)) + break; + /* * TODO: this conversion is not complete, update it * after adding UAC3 values to asound.h @@ -451,6 +459,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor chmap->map[c++] = map; } p += cs_len; + len -= cs_len; } if (channels < c) @@ -870,7 +879,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, u64 badd_formats = 0; unsigned int num_channels; struct audioformat *fp; - u16 cluster_id, wLength; + u16 cluster_id, wLength, cluster_wLength; int clock = 0; int err; @@ -997,6 +1006,16 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, return ERR_PTR(-EIO); } + cluster_wLength = le16_to_cpu(cluster->wLength); + if (cluster_wLength < sizeof(*cluster) || + cluster_wLength > wLength) { + dev_err(&dev->dev, + "%u:%d : invalid Cluster Descriptor size\n", + iface_no, altno); + kfree(cluster); + return ERR_PTR(-EIO); + } + num_channels = cluster->bNrChannels; chmap = convert_chmap_v3(cluster); kfree(cluster); From cf2c1d8f101082040d6e4af0c2c3242dfd8472ef Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Wed, 3 Dec 2025 15:05:09 +0100 Subject: [PATCH 02/11] ALSA: usb-audio: Fix size validation in convert_chmap_v3() jira VULN-152932 cve-bf CVE-2025-39757 commit-author Dan Carpenter commit 89f0addeee3cb2dc49837599330ed9c4612f05b0 The "p" pointer is void so sizeof(*p) is 1. The intent was to check sizeof(*cs_desc), which is 3, instead. Fixes: ecfd41166b72 ("ALSA: usb-audio: Validate UAC3 cluster segment descriptors") Signed-off-by: Dan Carpenter Link: https://patch.msgid.link/aKL5kftC1qGt6lpv@stanley.mountain Signed-off-by: Takashi Iwai (cherry picked from commit 89f0addeee3cb2dc49837599330ed9c4612f05b0) Signed-off-by: Roxana Nicolescu --- sound/usb/stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 479681b8fea62..2b69c0a746ac3 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -344,7 +344,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor u16 cs_len; u8 cs_type; - if (len < sizeof(*p)) + if (len < sizeof(*cs_desc)) break; cs_len = le16_to_cpu(cs_desc->wLength); if (len < cs_len) From 507c1dccc249bd4f80601c3ac65a002c7a7bc714 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Wed, 3 Dec 2025 16:21:37 +0100 Subject: [PATCH 03/11] net: sched: delete duplicate cleanup of backlog and qlen jira VULN-155239 cve-pre CVE-2022-50356 commit-author Zhengchao Shao commit c19d893fbf3f2f8fa864ae39652c7fee939edde2 qdisc_reset() is clearing qdisc->q.qlen and qdisc->qstats.backlog _after_ calling qdisc->ops->reset. There is no need to clear them again in the specific reset function. Signed-off-by: Zhengchao Shao Link: https://lore.kernel.org/r/20220824005231.345727-1-shaozhengchao@huawei.com Signed-off-by: Paolo Abeni (cherry picked from commit c19d893fbf3f2f8fa864ae39652c7fee939edde2) Signed-off-by: Roxana Nicolescu --- include/net/sch_generic.h | 1 - net/sched/sch_atm.c | 1 - net/sched/sch_cbq.c | 1 - net/sched/sch_choke.c | 2 -- net/sched/sch_drr.c | 2 -- net/sched/sch_dsmark.c | 2 -- net/sched/sch_etf.c | 3 --- net/sched/sch_ets.c | 2 -- net/sched/sch_fq_codel.c | 2 -- net/sched/sch_fq_pie.c | 3 --- net/sched/sch_hfsc.c | 2 -- net/sched/sch_htb.c | 2 -- net/sched/sch_multiq.c | 1 - net/sched/sch_prio.c | 2 -- net/sched/sch_qfq.c | 2 -- net/sched/sch_red.c | 2 -- net/sched/sch_sfb.c | 2 -- net/sched/sch_skbprio.c | 3 --- net/sched/sch_taprio.c | 2 -- net/sched/sch_tbf.c | 2 -- net/sched/sch_teql.c | 1 - 21 files changed, 40 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 4fc36751be5ca..d1543c4f98ecb 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -1175,7 +1175,6 @@ static inline void __qdisc_reset_queue(struct qdisc_skb_head *qh) static inline void qdisc_reset_queue(struct Qdisc *sch) { __qdisc_reset_queue(&sch->q); - sch->qstats.backlog = 0; } static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new, diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 678f1fa527e52..b6f291685b3df 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -575,7 +575,6 @@ static void atm_tc_reset(struct Qdisc *sch) pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p); list_for_each_entry(flow, &p->flows, list) qdisc_reset(flow->q); - sch->q.qlen = 0; } static void atm_tc_destroy(struct Qdisc *sch) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index ba586e9659040..027d69135ddef 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -1058,7 +1058,6 @@ cbq_reset(struct Qdisc *sch) cl->cpriority = cl->priority; } } - sch->q.qlen = 0; } diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index a400f7f756e19..efdb5426982b0 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -319,8 +319,6 @@ static void choke_reset(struct Qdisc *sch) rtnl_qdisc_drop(skb, sch); } - sch->q.qlen = 0; - sch->qstats.backlog = 0; if (q->tab) memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *)); q->head = q->tail = 0; diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 01609025118e5..abf48a316fb94 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -447,8 +447,6 @@ static void drr_reset_qdisc(struct Qdisc *sch) qdisc_reset(cl->qdisc); } } - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void drr_destroy_qdisc(struct Qdisc *sch) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 5b52f5bb93ab8..baabc706ddf77 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -408,8 +408,6 @@ static void dsmark_reset(struct Qdisc *sch) pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p); if (p->q) qdisc_reset(p->q); - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void dsmark_destroy(struct Qdisc *sch) diff --git a/net/sched/sch_etf.c b/net/sched/sch_etf.c index c48f91075b5c6..d96103b0e2bf5 100644 --- a/net/sched/sch_etf.c +++ b/net/sched/sch_etf.c @@ -445,9 +445,6 @@ static void etf_reset(struct Qdisc *sch) timesortedlist_clear(sch); __qdisc_reset_queue(&sch->q); - sch->qstats.backlog = 0; - sch->q.qlen = 0; - q->last = 0; } diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c index 70568054d0ef0..269572bbd9019 100644 --- a/net/sched/sch_ets.c +++ b/net/sched/sch_ets.c @@ -731,8 +731,6 @@ static void ets_qdisc_reset(struct Qdisc *sch) } for (band = 0; band < q->nbands; band++) qdisc_reset(q->classes[band].qdisc); - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void ets_qdisc_destroy(struct Qdisc *sch) diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 14a57cadb0fba..ab48b96210836 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -351,8 +351,6 @@ static void fq_codel_reset(struct Qdisc *sch) codel_vars_init(&flow->cvars); } memset(q->backlogs, 0, q->flows_cnt * sizeof(u32)); - sch->q.qlen = 0; - sch->qstats.backlog = 0; q->memory_usage = 0; } diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c index 1e8b2690264df..1ed43494d9daa 100644 --- a/net/sched/sch_fq_pie.c +++ b/net/sched/sch_fq_pie.c @@ -514,9 +514,6 @@ static void fq_pie_reset(struct Qdisc *sch) INIT_LIST_HEAD(&flow->flowchain); pie_vars_init(&flow->vars); } - - sch->q.qlen = 0; - sch->qstats.backlog = 0; } static void fq_pie_destroy(struct Qdisc *sch) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 0deb453be9e83..730a2fd2ad11b 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1511,8 +1511,6 @@ hfsc_reset_qdisc(struct Qdisc *sch) } q->eligible = RB_ROOT; qdisc_watchdog_cancel(&q->watchdog); - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 217fe2208c7c4..b5b4008509a45 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -977,8 +977,6 @@ static void htb_reset(struct Qdisc *sch) } qdisc_watchdog_cancel(&q->watchdog); __qdisc_reset_queue(&q->direct_queue); - sch->q.qlen = 0; - sch->qstats.backlog = 0; memset(q->hlevel, 0, sizeof(q->hlevel)); memset(q->row_mask, 0, sizeof(q->row_mask)); } diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 56490f6fdcd1b..8133a678929fe 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c @@ -163,7 +163,6 @@ multiq_reset(struct Qdisc *sch) for (band = 0; band < q->bands; band++) qdisc_reset(q->queues[band]); - sch->q.qlen = 0; q->curband = 0; } diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index fe5b7387f220d..4ee5c4ade9bd0 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -139,8 +139,6 @@ prio_reset(struct Qdisc *sch) for (prio = 0; prio < q->bands; prio++) qdisc_reset(q->queues[prio]); - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static int prio_offload(struct Qdisc *sch, struct tc_prio_qopt *qopt) diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index fae81a097e7c1..d3e727fe8bd9d 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -1487,8 +1487,6 @@ static void qfq_reset_qdisc(struct Qdisc *sch) qdisc_reset(cl->qdisc); } } - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void qfq_destroy_qdisc(struct Qdisc *sch) diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 2f89d5f43a6f4..5159db1da3ddb 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -182,8 +182,6 @@ static void red_reset(struct Qdisc *sch) struct red_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); - sch->qstats.backlog = 0; - sch->q.qlen = 0; red_restart(&q->vars); } diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index 493b60871fa35..ddef74cb6ab63 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -457,8 +457,6 @@ static void sfb_reset(struct Qdisc *sch) struct sfb_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); - sch->qstats.backlog = 0; - sch->q.qlen = 0; q->slot = 0; q->double_buffering = false; sfb_zero_all_buckets(q); diff --git a/net/sched/sch_skbprio.c b/net/sched/sch_skbprio.c index 3d9de52849bc5..1d5ece3a7831a 100644 --- a/net/sched/sch_skbprio.c +++ b/net/sched/sch_skbprio.c @@ -217,9 +217,6 @@ static void skbprio_reset(struct Qdisc *sch) struct skbprio_sched_data *q = qdisc_priv(sch); int prio; - sch->qstats.backlog = 0; - sch->q.qlen = 0; - for (prio = 0; prio < SKBPRIO_MAX_PRIORITY; prio++) __skb_queue_purge(&q->qdiscs[prio]); diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index ab5e2eefa3ad1..99be93da5b46b 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1658,8 +1658,6 @@ static void taprio_reset(struct Qdisc *sch) if (q->qdiscs[i]) qdisc_reset(q->qdiscs[i]); } - sch->qstats.backlog = 0; - sch->q.qlen = 0; } static void taprio_destroy(struct Qdisc *sch) diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 678862a91a8f2..4054d5a87df84 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -321,8 +321,6 @@ static void tbf_reset(struct Qdisc *sch) struct tbf_sched_data *q = qdisc_priv(sch); qdisc_reset(q->qdisc); - sch->qstats.backlog = 0; - sch->q.qlen = 0; q->t_c = ktime_get_ns(); q->tokens = q->buffer; q->ptokens = q->mtu; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 163364124691c..7c3447019de98 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -128,7 +128,6 @@ teql_reset(struct Qdisc *sch) struct teql_sched_data *dat = qdisc_priv(sch); skb_queue_purge(&dat->q); - sch->q.qlen = 0; } static void From d37302abd579054678cb820ac72d0a1ac054ea91 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Wed, 3 Dec 2025 16:25:14 +0100 Subject: [PATCH 04/11] net: sched: sfb: fix null pointer access issue when sfb_init() fails jira VULN-155239 cve CVE-2022-50356 commit-author Zhengchao Shao commit 2a3fc78210b9f0e85372a2435368962009f480fc When the default qdisc is sfb, if the qdisc of dev_queue fails to be inited during mqprio_init(), sfb_reset() is invoked to clear resources. In this case, the q->qdisc is NULL, and it will cause gpf issue. The process is as follows: qdisc_create_dflt() sfb_init() tcf_block_get() --->failed, q->qdisc is NULL ... qdisc_put() ... sfb_reset() qdisc_reset(q->qdisc) --->q->qdisc is NULL ops = qdisc->ops The following is the Call Trace information: general protection fault, probably for non-canonical address 0xdffffc0000000003: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f] RIP: 0010:qdisc_reset+0x2b/0x6f0 Call Trace: sfb_reset+0x37/0xd0 qdisc_reset+0xed/0x6f0 qdisc_destroy+0x82/0x4c0 qdisc_put+0x9e/0xb0 qdisc_create_dflt+0x2c3/0x4a0 mqprio_init+0xa71/0x1760 qdisc_create+0x3eb/0x1000 tc_modify_qdisc+0x408/0x1720 rtnetlink_rcv_msg+0x38e/0xac0 netlink_rcv_skb+0x12d/0x3a0 netlink_unicast+0x4a2/0x740 netlink_sendmsg+0x826/0xcc0 sock_sendmsg+0xc5/0x100 ____sys_sendmsg+0x583/0x690 ___sys_sendmsg+0xe8/0x160 __sys_sendmsg+0xbf/0x160 do_syscall_64+0x35/0x80 entry_SYSCALL_64_after_hwframe+0x46/0xb0 RIP: 0033:0x7f2164122d04 Fixes: e13e02a3c68d ("net_sched: SFB flow scheduler") Signed-off-by: Zhengchao Shao Signed-off-by: David S. Miller (cherry picked from commit 2a3fc78210b9f0e85372a2435368962009f480fc) Signed-off-by: Roxana Nicolescu --- net/sched/sch_sfb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index ddef74cb6ab63..b79283c8ec5b0 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -456,7 +456,8 @@ static void sfb_reset(struct Qdisc *sch) { struct sfb_sched_data *q = qdisc_priv(sch); - qdisc_reset(q->qdisc); + if (likely(q->qdisc)) + qdisc_reset(q->qdisc); q->slot = 0; q->double_buffering = false; sfb_zero_all_buckets(q); From 4aba33f61e055d70834ff9ca9c2c8b0bb0e5170c Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 14:49:56 +0100 Subject: [PATCH 05/11] scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write() jira VULN-70476 cve-pre CVE-2022-50030 commit-author Dan Carpenter commit 9020be114a47bf7ff33e179b3bb0016b91a098e6 The "mybuf" string comes from the user, so we need to ensure that it is NUL terminated. Link: https://lore.kernel.org/r/20211214070527.GA27934@kili Fixes: bd2cdd5e400f ("scsi: lpfc: NVME Initiator: Add debugfs support") Reviewed-by: James Smart Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen (cherry picked from commit 9020be114a47bf7ff33e179b3bb0016b91a098e6) Signed-off-by: Roxana Nicolescu --- drivers/scsi/lpfc/lpfc_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index b71cd0e0fd634..0afb1d1441b3c 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -2954,8 +2954,8 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, char mybuf[64]; char *pbuf; - if (nbytes > 64) - nbytes = 64; + if (nbytes > 63) + nbytes = 63; memset(mybuf, 0, sizeof(mybuf)); From 9ae17c44f2fc658cc5c1289241845e3c3667f741 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 14:50:56 +0100 Subject: [PATCH 06/11] scsi: lpfc: Prevent buffer overflow crashes in debugfs with malformed user input jira VULN-70476 cve CVE-2022-50030 commit-author James Smart commit f8191d40aa612981ce897e66cda6a88db8df17bb Malformed user input to debugfs results in buffer overflow crashes. Adapt input string lengths to fit within internal buffers, leaving space for NULL terminators. Link: https://lore.kernel.org/r/20220701211425.2708-3-jsmart2021@gmail.com Co-developed-by: Justin Tee Signed-off-by: Justin Tee Signed-off-by: James Smart Signed-off-by: Martin K. Petersen (cherry picked from commit f8191d40aa612981ce897e66cda6a88db8df17bb) Signed-off-by: Roxana Nicolescu --- drivers/scsi/lpfc/lpfc_debugfs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 0afb1d1441b3c..98bf524630747 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -2607,8 +2607,8 @@ lpfc_debugfs_multixripools_write(struct file *file, const char __user *buf, struct lpfc_sli4_hdw_queue *qp; struct lpfc_multixri_pool *multixri_pool; - if (nbytes > 64) - nbytes = 64; + if (nbytes > sizeof(mybuf) - 1) + nbytes = sizeof(mybuf) - 1; memset(mybuf, 0, sizeof(mybuf)); @@ -2688,8 +2688,8 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf, if (!phba->targetport) return -ENXIO; - if (nbytes > 64) - nbytes = 64; + if (nbytes > sizeof(mybuf) - 1) + nbytes = sizeof(mybuf) - 1; memset(mybuf, 0, sizeof(mybuf)); @@ -2826,8 +2826,8 @@ lpfc_debugfs_ioktime_write(struct file *file, const char __user *buf, char mybuf[64]; char *pbuf; - if (nbytes > 64) - nbytes = 64; + if (nbytes > sizeof(mybuf) - 1) + nbytes = sizeof(mybuf) - 1; memset(mybuf, 0, sizeof(mybuf)); @@ -2954,8 +2954,8 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, char mybuf[64]; char *pbuf; - if (nbytes > 63) - nbytes = 63; + if (nbytes > sizeof(mybuf) - 1) + nbytes = sizeof(mybuf) - 1; memset(mybuf, 0, sizeof(mybuf)); @@ -3060,8 +3060,8 @@ lpfc_debugfs_hdwqstat_write(struct file *file, const char __user *buf, char *pbuf; int i; - if (nbytes > 64) - nbytes = 64; + if (nbytes > sizeof(mybuf) - 1) + nbytes = sizeof(mybuf) - 1; memset(mybuf, 0, sizeof(mybuf)); From 3169b96f662564248115b6da60125ff4d97a4746 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 15:05:58 +0100 Subject: [PATCH 07/11] ASoC: SOF: Intel: hda: Define rom_status_reg in sof_intel_dsp_desc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jira VULN-70503 cve-pre CVE-2022-50050 commit-author Ranjani Sridharan commit 71778f7940f0b496aa1ca1134f3b70b425a59bab Add the rom_status_reg field to struct sof_intel_dsp_desc and define it for HDA platforms. This will be used to check the ROM status during FW boot. Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20220414184817.362215-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown (cherry picked from commit 71778f7940f0b496aa1ca1134f3b70b425a59bab) Signed-off-by: Roxana Nicolescu --- sound/soc/sof/intel/apl.c | 1 + sound/soc/sof/intel/cnl.c | 2 ++ sound/soc/sof/intel/hda-loader.c | 14 ++++++++------ sound/soc/sof/intel/hda.c | 8 ++++++-- sound/soc/sof/intel/icl.c | 1 + sound/soc/sof/intel/shim.h | 1 + sound/soc/sof/intel/tgl.c | 4 ++++ 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 9917c08a8a0b8..856a417c204fb 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -144,6 +144,7 @@ const struct sof_intel_dsp_desc apl_chip_info = { .ipc_ack = HDA_DSP_REG_HIPCIE, .ipc_ack_mask = HDA_DSP_REG_HIPCIE_DONE, .ipc_ctl = HDA_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 150, .ssp_count = APL_SSP_COUNT, .ssp_base_offset = APL_SSP_BASE_OFFSET, diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index e65504d70ac9a..7bce5b413d96c 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -349,6 +349,7 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = CNL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -368,6 +369,7 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index abad6d0ceb837..355335161be86 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -162,7 +162,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) /* step 7: wait for ROM init */ ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, - HDA_DSP_SRAM_REG_ROM_STATUS, status, + chip->rom_status_reg, status, ((status & HDA_DSP_ROM_STS_MASK) == HDA_DSP_ROM_INIT), HDA_DSP_REG_POLL_INTERVAL_US, @@ -173,8 +173,8 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag) if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) dev_err(sdev->dev, - "error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n", - __func__); + "%s: timeout with rom_status_reg (%#x) read\n", + __func__, chip->rom_status_reg); err: flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL; @@ -250,6 +250,8 @@ static int cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) { + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; unsigned int reg; int ret, status; @@ -260,7 +262,7 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) } status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, - HDA_DSP_SRAM_REG_ROM_STATUS, reg, + chip->rom_status_reg, reg, ((reg & HDA_DSP_ROM_STS_MASK) == HDA_DSP_ROM_FW_ENTERED), HDA_DSP_REG_POLL_INTERVAL_US, @@ -273,8 +275,8 @@ static int cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream) if (status < 0) { dev_err(sdev->dev, - "error: %s: timeout HDA_DSP_SRAM_REG_ROM_STATUS read\n", - __func__); + "%s: timeout with rom_status_reg (%#x) read\n", + __func__, chip->rom_status_reg); } ret = cl_trigger(sdev, stream, SNDRV_PCM_TRIGGER_STOP); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 9dacb85150825..eae359f8d1576 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -480,11 +480,13 @@ static const struct hda_dsp_msg_code hda_dsp_rom_msg[] = { static void hda_dsp_get_status(struct snd_sof_dev *sdev) { + const struct sof_intel_dsp_desc *chip; u32 status; int i; + chip = get_chip_info(sdev->pdata); status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, - HDA_DSP_SRAM_REG_ROM_STATUS); + chip->rom_status_reg); for (i = 0; i < ARRAY_SIZE(hda_dsp_rom_msg); i++) { if (status == hda_dsp_rom_msg[i].code) { @@ -529,13 +531,15 @@ static void hda_dsp_get_registers(struct snd_sof_dev *sdev, /* dump the first 8 dwords representing the extended ROM status */ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags) { + const struct sof_intel_dsp_desc *chip; char msg[128]; int len = 0; u32 value; int i; + chip = get_chip_info(sdev->pdata); for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) { - value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_ROM_STATUS + i * 0x4); + value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + i * 0x4); len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value); } diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 965ed04a963e4..ab17f494ec931 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -144,6 +144,7 @@ const struct sof_intel_dsp_desc icl_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index e9f7d4d7fcce8..96707758ebc51 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -161,6 +161,7 @@ struct sof_intel_dsp_desc { int ipc_ack; int ipc_ack_mask; int ipc_ctl; + int rom_status_reg; int rom_init_timeout; int ssp_count; /* ssp count of the platform */ int ssp_base_offset; /* base address of the SSPs */ diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 1497520cfadb9..de04dcd1993d1 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -139,6 +139,7 @@ const struct sof_intel_dsp_desc tgl_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -158,6 +159,7 @@ const struct sof_intel_dsp_desc tglh_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -177,6 +179,7 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -196,6 +199,7 @@ const struct sof_intel_dsp_desc adls_chip_info = { .ipc_ack = CNL_DSP_REG_HIPCIDA, .ipc_ack_mask = CNL_DSP_REG_HIPCIDA_DONE, .ipc_ctl = CNL_DSP_REG_HIPCCTL, + .rom_status_reg = HDA_DSP_SRAM_REG_ROM_STATUS, .rom_init_timeout = 300, .ssp_count = ICL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, From 4ea57db54a1d98c22ed7f052e90d3d097d5af3da Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 15:06:50 +0100 Subject: [PATCH 08/11] ASoC: SOF: Intel: hda: Fix potential buffer overflow by snprintf() jira VULN-70503 cve CVE-2022-50050 commit-author Takashi Iwai commit 94c1ceb043c1a002de9649bb630c8e8347645982 snprintf() returns the would-be-filled size when the string overflows the given buffer size, hence using this value may result in the buffer overflow (although it's unrealistic). This patch replaces with a safer version, scnprintf() for papering over such a potential issue. Fixes: 29c8e4398f02 ("ASoC: SOF: Intel: hda: add extended rom status dump to error log") Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220801165420.25978-4-tiwai@suse.de Signed-off-by: Mark Brown (cherry picked from commit 94c1ceb043c1a002de9649bb630c8e8347645982) Signed-off-by: Roxana Nicolescu --- sound/soc/sof/intel/hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index eae359f8d1576..4a700a7711aab 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -540,7 +540,7 @@ static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, u32 flags) chip = get_chip_info(sdev->pdata); for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) { value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + i * 0x4); - len += snprintf(msg + len, sizeof(msg) - len, " 0x%x", value); + len += scnprintf(msg + len, sizeof(msg) - len, " 0x%x", value); } dev_err(sdev->dev, "extended rom status: %s", msg); From 30254c31895c8238a6e5d6f557529981de575c92 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 15:33:20 +0100 Subject: [PATCH 09/11] firmware: arm_scpi: convert platform driver to use dev_groups jira VULN-70082 cve-pre CVE-2022-50087 commit-author Greg Kroah-Hartman commit 43b9ac937be6f2afb2f0cf060d40cea365c09d07 Platform drivers now have the option to have the platform core create and remove any needed sysfs attribute files. So take advantage of that and do not register "by hand" a sysfs group of attributes. Acked-by: Sudeep Holla Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20190731124349.4474-6-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 43b9ac937be6f2afb2f0cf060d40cea365c09d07) Signed-off-by: Roxana Nicolescu --- drivers/firmware/arm_scpi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index c7d06a36b23a5..ad9a0dfe69b75 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -1022,10 +1022,6 @@ static int scpi_probe(struct platform_device *pdev) scpi_info->firmware_version)); scpi_info->scpi_ops = &scpi_ops; - ret = devm_device_add_groups(dev, versions_groups); - if (ret) - dev_err(dev, "unable to create sysfs version group\n"); - return devm_of_platform_populate(dev); } @@ -1041,6 +1037,7 @@ static struct platform_driver scpi_driver = { .driver = { .name = "scpi_protocol", .of_match_table = scpi_of_match, + .dev_groups = versions_groups, }, .probe = scpi_probe, .remove = scpi_remove, From d2104a7e948d8d8ce293a33f3b1989ccfc369e3e Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Thu, 4 Dec 2025 15:34:01 +0100 Subject: [PATCH 10/11] firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails jira VULN-70082 cve CVE-2022-50087 commit-author Sudeep Holla commit 689640efc0a2c4e07e6f88affe6d42cd40cc3f85 When scpi probe fails, at any point, we need to ensure that the scpi_info is not set and will remain NULL until the probe succeeds. If it is not taken care, then it could result use-after-free as the value is exported via get_scpi_ops() and could refer to a memory allocated via devm_kzalloc() but freed when the probe fails. Link: https://lore.kernel.org/r/20220701160310.148344-1-sudeep.holla@arm.com Cc: stable@vger.kernel.org # 4.19+ Reported-by: huhai Reviewed-by: Jackie Liu Signed-off-by: Sudeep Holla (cherry picked from commit 689640efc0a2c4e07e6f88affe6d42cd40cc3f85) Signed-off-by: Roxana Nicolescu --- drivers/firmware/arm_scpi.c | 61 +++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index ad9a0dfe69b75..8da145340daae 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -824,7 +824,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info) info->firmware_version = le32_to_cpu(caps.platform_version); } /* Ignore error if not implemented */ - if (scpi_info->is_legacy && ret == -EOPNOTSUPP) + if (info->is_legacy && ret == -EOPNOTSUPP) return 0; return ret; @@ -914,13 +914,14 @@ static int scpi_probe(struct platform_device *pdev) struct resource res; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + struct scpi_drvinfo *scpi_drvinfo; - scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); - if (!scpi_info) + scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL); + if (!scpi_drvinfo) return -ENOMEM; if (of_match_device(legacy_scpi_of_match, &pdev->dev)) - scpi_info->is_legacy = true; + scpi_drvinfo->is_legacy = true; count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); if (count < 0) { @@ -928,19 +929,19 @@ static int scpi_probe(struct platform_device *pdev) return -ENODEV; } - scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan), - GFP_KERNEL); - if (!scpi_info->channels) + scpi_drvinfo->channels = + devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL); + if (!scpi_drvinfo->channels) return -ENOMEM; - ret = devm_add_action(dev, scpi_free_channels, scpi_info); + ret = devm_add_action(dev, scpi_free_channels, scpi_drvinfo); if (ret) return ret; - for (; scpi_info->num_chans < count; scpi_info->num_chans++) { + for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) { resource_size_t size; - int idx = scpi_info->num_chans; - struct scpi_chan *pchan = scpi_info->channels + idx; + int idx = scpi_drvinfo->num_chans; + struct scpi_chan *pchan = scpi_drvinfo->channels + idx; struct mbox_client *cl = &pchan->cl; struct device_node *shmem = of_parse_phandle(np, "shmem", idx); @@ -984,45 +985,53 @@ static int scpi_probe(struct platform_device *pdev) return ret; } - scpi_info->commands = scpi_std_commands; + scpi_drvinfo->commands = scpi_std_commands; - platform_set_drvdata(pdev, scpi_info); + platform_set_drvdata(pdev, scpi_drvinfo); - if (scpi_info->is_legacy) { + if (scpi_drvinfo->is_legacy) { /* Replace with legacy variants */ scpi_ops.clk_set_val = legacy_scpi_clk_set_val; - scpi_info->commands = scpi_legacy_commands; + scpi_drvinfo->commands = scpi_legacy_commands; /* Fill priority bitmap */ for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++) set_bit(legacy_hpriority_cmds[idx], - scpi_info->cmd_priority); + scpi_drvinfo->cmd_priority); } - ret = scpi_init_versions(scpi_info); + scpi_info = scpi_drvinfo; + + ret = scpi_init_versions(scpi_drvinfo); if (ret) { dev_err(dev, "incorrect or no SCP firmware found\n"); + scpi_info = NULL; return ret; } - if (scpi_info->is_legacy && !scpi_info->protocol_version && - !scpi_info->firmware_version) + if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version && + !scpi_drvinfo->firmware_version) dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n"); else dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n", FIELD_GET(PROTO_REV_MAJOR_MASK, - scpi_info->protocol_version), + scpi_drvinfo->protocol_version), FIELD_GET(PROTO_REV_MINOR_MASK, - scpi_info->protocol_version), + scpi_drvinfo->protocol_version), FIELD_GET(FW_REV_MAJOR_MASK, - scpi_info->firmware_version), + scpi_drvinfo->firmware_version), FIELD_GET(FW_REV_MINOR_MASK, - scpi_info->firmware_version), + scpi_drvinfo->firmware_version), FIELD_GET(FW_REV_PATCH_MASK, - scpi_info->firmware_version)); - scpi_info->scpi_ops = &scpi_ops; + scpi_drvinfo->firmware_version)); + + scpi_drvinfo->scpi_ops = &scpi_ops; - return devm_of_platform_populate(dev); + ret = devm_of_platform_populate(dev); + if (ret) + scpi_info = NULL; + + return ret; } static const struct of_device_id scpi_of_match[] = { From a3868bcfb11b2f30dd157650fc70ca774b26461b Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Fri, 5 Dec 2025 16:41:20 +0100 Subject: [PATCH 11/11] fs: fix UAF/GPF bug in nilfs_mdt_destroy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jira VULN-155283 cve CVE-2022-50367 commit-author Dongliang Mu commit 2e488f13755ffbb60f307e991b27024716a33b29 upstream-diff | Adjusted context in inode_init_always to due rh specific variable rh_reserved2 being initialized to 0 added in commit: dbb05b7432a1f9 ("Rebuild centos8 with kernel-4.18.0-80.el8") In alloc_inode, inode_init_always() could return -ENOMEM if security_inode_alloc() fails, which causes inode->i_private uninitialized. Then nilfs_is_metadata_file_inode() returns true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), which frees the uninitialized inode->i_private and leads to crashes(e.g., UAF/GPF). Fix this by moving security_inode_alloc just prior to this_cpu_inc(nr_inodes) Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com Reported-by: butt3rflyh4ck Reported-by: Hao Sun Reported-by: Jiacheng Xu Reviewed-by: Christian Brauner (Microsoft) Signed-off-by: Dongliang Mu Cc: Al Viro Cc: stable@vger.kernel.org Signed-off-by: Al Viro (cherry picked from commit 2e488f13755ffbb60f307e991b27024716a33b29) Signed-off-by: Roxana Nicolescu --- fs/inode.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 6cd6e8e5f6af7..46dbbf250641a 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -168,8 +168,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->rh_reserved2 = 0; - if (security_inode_alloc(inode)) - goto out; spin_lock_init(&inode->i_lock); lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); @@ -200,11 +198,12 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_fsnotify_mask = 0; #endif inode->i_flctx = NULL; + + if (unlikely(security_inode_alloc(inode))) + return -ENOMEM; this_cpu_inc(nr_inodes); return 0; -out: - return -ENOMEM; } EXPORT_SYMBOL(inode_init_always);