Skip to contentSkip to conversation

Support needed to continue Smatch work

PATCH Applied Dan Carpenter 29 participants 84 messages Dec 8, 2025 – Mar 5

Subsystems (26)
lore
Share & tools
lore
#0 lore raw

I have been doing Smatch static analysis work at Linaro under a larger umbrella project to do with Linux kernel quality but unfortunately that project has ended so I will be wrapping up at the end of the year unless we can raise new support.

Smatch is an important tool for kernel development so hopefully there are enough companies willing to support it financially and I will be able to continue. In fact, there potentially is an opportunity to expand if companies with other large C projects and want static analysis. This isn't something we have explored very deeply but reach out if you want to have that discussion. Please contact Bill Fletcher <[email protected]> for any inquiries, either about supporting Smatch in the Linux kernel or about other static analysis projects.

Background: I am the author of the Smatch static checker.
https://github.com/error27/smatch

In the kernel we use a number of different static analysis tools with different features and goals. What makes Smatch unique is the flow analysis. Flow analysis is basically the logic of saying that if X is true that must mean Y is true. Smatch is the only Open Source static checker with this level of flow analysis and the only one that does analysis across function boundaries. Being Open Source is important because it lets you write project specific checks. There are a number of commercial static analysis tools that exist as well, however, for parsing kernel code nothing else is at the same level.

This is borne out in the numbers. I have been working on Smatch since 2010, first at Oracle and now at Linaro. Over that period I have been the number 12 bug fixer with 5568 patches and the number 2 bug reporter with 2587 bug reports and almost all those fixes are driven by Smatch. Smatch is included in several subsystem CI tools, such as Media and Wireless and many maintainers use Smatch as well.

I like to say that static analysis is not just a product, it is an on-going process. I regularly review CVEs to consider how these bugs could have been caught earlier with static analysis. Also the kernel is constantly changing and adding new APIs. Without continuous updates then a static checker will eventually bit rot.

An important part of what I do is review static checker warnings and filter out the false positives. People complain about false positives but in some ways, with static analysis the false positive ratio is a knob you can adjust where you can either have very few false positives and miss bugs or you can have more false positives and catch more bugs. Since the kernel is very important I prefer to have more false positives and then manually review them. This lets us catch as many bugs as possible without annoying the developers.

Especially for cross function bugs, you need a human to figure out who the correct developer is to handle an issue. I've also found that adding a bit of explanation to each bug report helps developers know how to handle them faster.

To be honest, the work with Smatch will need to continue either way because it's really important but it would be great if I could be a part of that. I still have a lot of plans for changes and improvements that should be made. I'm hoping there are several companies who could support this project by paying a proportion of my salary. This is something that Linaro has done before with other shared cost projects.

I'll post again closer to the end of the year to let people know what's happening next.

#1 lore raw

I need to post an update on the current situation with Smatch.

First of all, I want to start by thanking Brad Spengler from grsecurity who reached out to me on this, offered some funding, and has been trying to push the Smatch work forward. It really means a lot to me.

Unfortunately, we haven't been able to raise enough support to continue my Smatch work. I have still been filtering zero day bot warnings and I am a bit worried that people have the impression that I'm reviewing static checker warnings when I am not.

The situation isn't great. The zero day bot can't do cross function analsysis and it only looks at checks with a low false positive rate. We're missing out on a bunch of bugs. I'm going to add some of the those missed warnings to this thread so people have a better picture of what we're missing. There are some buffer overflows in there. A bunch of off by one bugs. A missing error code in fork(). And random other minor things as well.

https://lore.kernel.org/all/[email protected]/

I am still trying to figure out a way to restart Smatch checking. The funding model would be that several companies would support this project by paying a proportion of my salary. Part of that goes to reporting bugs like the ones above and part of that goes to developing Smatch and writing new checks. Please, contact
Bill Fletcher <[email protected]> if you would like to support this work.

regards,
dan carpenter

#2 lore raw

[bug report] net: ethtool: Introduce per-PHY DUMP operations

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Maxime Chevallier,

Commit 172265b44cd3 ("net: ethtool: Introduce per-PHY DUMP operations") from May 2, 2025 (linux-next), leads to the following Smatch static checker warning:

	net/ethtool/netlink.c:714 ethnl_perphy_start()
	error: buffer overflow 'ethnl_default_requests' 52 <= 255 user_rl='0-255' uncapped

net/ethtool/netlink.c

    700 static int ethnl_perphy_start(struct netlink_callback *cb)
    701 {
    702         struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb);
    703         const struct genl_dumpit_info *info = genl_dumpit_info(cb);
    704         struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx;
    705         struct ethnl_reply_data *reply_data;
    706         const struct ethnl_request_ops *ops;
    707         struct ethnl_req_info *req_info;
    708         struct genlmsghdr *ghdr;
    709         int ret;
    710 
    711         BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
    712 
    713         ghdr = nlmsg_data(cb->nlh);

--> 714 ops = ethnl_default_requests[ghdr->cmd];

Smatch thinks nlmsg_data() is untrusted data, so it could be out of bounds. It's a u8, but there are only 52 elements in the ethnl_default_requests[] array.

    715         if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd))
    716                 return -EOPNOTSUPP;
    717         req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
    718         if (!req_info)
    719                 return -ENOMEM;
    720         reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL);
    721         if (!reply_data) {
    722                 ret = -ENOMEM;
    723                 goto free_req_info;
    724         }
    725 
    726         /* Unlike per-dev dump, don't ignore dev. The dump handler
    727          * will notice it and dump PHYs from given dev. We only keep track of
    728          * the dev's ifindex, .dumpit() will grab and release the netdev itself.
    729          */
    730         ret = ethnl_default_parse(req_info, &info->info, ops, false);
    731         if (ret < 0)
    732                 goto free_reply_data;
    733         if (req_info->dev) {
    734                 phy_ctx->ifindex = req_info->dev->ifindex;
    735                 netdev_put(req_info->dev, &req_info->dev_tracker);
    736                 req_info->dev = NULL;
    737         }
    738 
    739         ctx->ops = ops;
    740         ctx->req_info = req_info;
    741         ctx->reply_data = reply_data;
    742         ctx->pos_ifindex = 0;
    743 
    744         return 0;
    745 
    746 free_reply_data:
    747         kfree(reply_data);
    748 free_req_info:
    749         kfree(req_info);
    750 
    751         return ret;
    752 }

regards,
dan carpenter

#3 lore raw

Re: [bug report] net: ethtool: Introduce per-PHY DUMP operations

Hi Dan,

Quoted 27 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Maxime Chevallier,

Commit 172265b44cd3 ("net: ethtool: Introduce per-PHY DUMP operations") from May 2, 2025 (linux-next), leads to the following Smatch static checker warning:

	net/ethtool/netlink.c:714 ethnl_perphy_start()
	error: buffer overflow 'ethnl_default_requests' 52 <= 255 user_rl='0-255' uncapped

net/ethtool/netlink.c

    700 static int ethnl_perphy_start(struct netlink_callback *cb)
    701 {
    702         struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb);
    703         const struct genl_dumpit_info *info = genl_dumpit_info(cb);
    704         struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx;
    705         struct ethnl_reply_data *reply_data;
    706         const struct ethnl_request_ops *ops;
    707         struct ethnl_req_info *req_info;
    708         struct genlmsghdr *ghdr;
    709         int ret;
    710 
    711         BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
    712 
    713         ghdr = nlmsg_data(cb->nlh);
Quoted 5 lines

--> 714 ops = ethnl_default_requests[ghdr->cmd];

Smatch thinks nlmsg_data() is untrusted data, so it could be out of bounds. It's a u8, but there are only 52 elements in the ethnl_default_requests[] array.

I see, then we also have the same problem in ethnl_default_start().

I'd expect the genl part to validate cmd (I haven't checked yet), but we do have a WARN_ONCE just below for the case 'cmd' is wrong, so we could definitely add some more sanity checks before accessing ethnl_default_requests[].

I'll look further into that and send the relevant fixes :)

Thanks for the report,

Maxime

#4 lore raw

Re: [bug report] net: ethtool: Introduce per-PHY DUMP operations

Quoted 21 lines · Maxime Chevallier
Quoted 15 lines

net/ethtool/netlink.c

    700 static int ethnl_perphy_start(struct netlink_callback *cb)
    701 {
    702         struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb);
    703         const struct genl_dumpit_info *info = genl_dumpit_info(cb);
    704         struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx;
    705         struct ethnl_reply_data *reply_data;
    706         const struct ethnl_request_ops *ops;
    707         struct ethnl_req_info *req_info;
    708         struct genlmsghdr *ghdr;
    709         int ret;
    710 
    711         BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
    712 
    713         ghdr = nlmsg_data(cb->nlh);
Quoted 5 lines

--> 714 ops = ethnl_default_requests[ghdr->cmd];

Smatch thinks nlmsg_data() is untrusted data, so it could be out of bounds. It's a u8, but there are only 52 elements in the ethnl_default_requests[] array.

Quoted 6 lines

I see, then we also have the same problem in ethnl_default_start().

I'd expect the genl part to validate cmd (I haven't checked yet), but we do have a WARN_ONCE just below for the case 'cmd' is wrong, so we could definitely add some more sanity checks before accessing ethnl_default_requests[].

The WARN_ONCE() doesn't doesn't work as bounds checking since there is no guarantee that the array will be followed by NULL pointers. I didn't see a bounds check for this, but I'm not an expert.

netlink_rcv_skb() <- receives untrusted data nlh = nlmsg_hdr(skb); -> nfnetlink_rcv_msg() <- calls nc->call()
-> ip_set_dump()

      -> netlink_dump_start()
         -> __netlink_dump_start() <- calls control->start(cb);
            -> genl_start() <- this is where the validation would be
                               when we call
                               genl_family_rcv_msg_attrs_parse()
               -> ethnl_perphy_start()

Also the WARN_ONCE() warns if we try to do a cmd which doesn't have a matching operation in ethnl_default_requests[]. Every time we check for missing commands it triggers a WARN_ONCE(). There are quite a few which don't have a handler so I'm surprised that syzbot doesn't trigger the warning and complain. Here is a list of commands without a handler:

ETHTOOL_MSG_USER_NONE,
ETHTOOL_MSG_FEATURES_SET,
ETHTOOL_MSG_CABLE_TEST_ACT,
ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
ETHTOOL_MSG_TUNNEL_INFO_GET,
ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
ETHTOOL_MSG_RSS_CREATE_ACT,
ETHTOOL_MSG_RSS_DELETE_ACT,

regards,
dan carpenter

#5 lore raw

Re: [bug report] net: ethtool: Introduce per-PHY DUMP operations

Hi Dan,

Quoted 50 lines · Dan Carpenter
Quoted 21 lines · Maxime Chevallier
Quoted 15 lines

net/ethtool/netlink.c

    700 static int ethnl_perphy_start(struct netlink_callback *cb)
    701 {
    702         struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb);
    703         const struct genl_dumpit_info *info = genl_dumpit_info(cb);
    704         struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx;
    705         struct ethnl_reply_data *reply_data;
    706         const struct ethnl_request_ops *ops;
    707         struct ethnl_req_info *req_info;
    708         struct genlmsghdr *ghdr;
    709         int ret;
    710 
    711         BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
    712 
    713         ghdr = nlmsg_data(cb->nlh);
Quoted 5 lines

--> 714 ops = ethnl_default_requests[ghdr->cmd];

Smatch thinks nlmsg_data() is untrusted data, so it could be out of bounds. It's a u8, but there are only 52 elements in the ethnl_default_requests[] array.

Quoted 6 lines

I see, then we also have the same problem in ethnl_default_start().

I'd expect the genl part to validate cmd (I haven't checked yet), but we do have a WARN_ONCE just below for the case 'cmd' is wrong, so we could definitely add some more sanity checks before accessing ethnl_default_requests[].

The WARN_ONCE() doesn't doesn't work as bounds checking since there is no guarantee that the array will be followed by NULL pointers. I didn't see a bounds check for this, but I'm not an expert.

netlink_rcv_skb() <- receives untrusted data nlh = nlmsg_hdr(skb); -> nfnetlink_rcv_msg() <- calls nc->call()
-> ip_set_dump()

      -> netlink_dump_start()
         -> __netlink_dump_start() <- calls control->start(cb);
            -> genl_start() <- this is where the validation would be
                               when we call
                               genl_family_rcv_msg_attrs_parse()
               -> ethnl_perphy_start()

Also the WARN_ONCE() warns if we try to do a cmd which doesn't have a matching operation in ethnl_default_requests[]. Every time we check for missing commands it triggers a WARN_ONCE(). There are quite a few which don't have a handler so I'm surprised that syzbot doesn't trigger the warning and complain. Here is a list of commands without a handler:

Quoted 8 lines

ETHTOOL_MSG_USER_NONE,
ETHTOOL_MSG_FEATURES_SET,
ETHTOOL_MSG_CABLE_TEST_ACT,
ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
ETHTOOL_MSG_TUNNEL_INFO_GET,
ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
ETHTOOL_MSG_RSS_CREATE_ACT,
ETHTOOL_MSG_RSS_DELETE_ACT,

While these commands don't have ethnl_request_ops handlers, they still have a genetlink handler, see the ethtool_genl_ops array [1]

The ethnl_request_ops are there to provide a framework for ethtool netlink commands, as most of them have roughly the same behaviour of needing to grab some info from the netdev/phy_device under rtnl, then populate a netlink message based on that outside rtnl.

It's expected that not all ethnl commands use that ethnl framework as some behave in a manner that don't fit the ethnl scaffholding. In the end, the "cmd" validation is done by the generic netlink infrastructure, that's why we don't see reports from fuzzing bots.

The WARN_ONCE we see in ethnl_default_start() and ethnl_perphy_start() is there in case a programmer tries to use the ethnl framework without having the ethnl ops populated.

[1] :
https://elixir.bootlin.com/linux/v6.18.6/source/net/ethtool/netlink.c#L1132

In reality, we should never end-up with an out of bounds cmd as the validation will occur higher-up, in the genetlink part.

However, I'm OK with adding a check, or a least a comment :)

Maxime

#6 lore raw

Re: [bug report] net: ethtool: Introduce per-PHY DUMP operations

Quoted 11 lines
Quoted 8 lines

ETHTOOL_MSG_USER_NONE,
ETHTOOL_MSG_FEATURES_SET,
ETHTOOL_MSG_CABLE_TEST_ACT,
ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
ETHTOOL_MSG_TUNNEL_INFO_GET,
ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
ETHTOOL_MSG_RSS_CREATE_ACT,
ETHTOOL_MSG_RSS_DELETE_ACT,

While these commands don't have ethnl_request_ops handlers, they still have a genetlink handler, see the ethtool_genl_ops array [1]

At least for the *_ACT commands, they are not expected in the userspace->kernel space direction. They should only be sent by the kernel to user space, to indicate some action has been performed, or happened. I don't know the netlink code too well, but i assume there is something which will throw out such commands if sent to the kernel, without even looking at the parameters?

Andrew

#7 lore raw

Re: [bug report] net: ethtool: Introduce per-PHY DUMP operations

Quoted 12 lines · Andrew Lunn
Quoted 11 lines
Quoted 8 lines

ETHTOOL_MSG_USER_NONE,
ETHTOOL_MSG_FEATURES_SET,
ETHTOOL_MSG_CABLE_TEST_ACT,
ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
ETHTOOL_MSG_TUNNEL_INFO_GET,
ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
ETHTOOL_MSG_RSS_CREATE_ACT,
ETHTOOL_MSG_RSS_DELETE_ACT,

While these commands don't have ethnl_request_ops handlers, they still have a genetlink handler, see the ethtool_genl_ops array [1]

Quoted 6 lines

At least for the *_ACT commands, they are not expected in the userspace->kernel space direction. They should only be sent by the kernel to user space, to indicate some action has been performed, or happened. I don't know the netlink code too well, but i assume there is something which will throw out such commands if sent to the kernel, without even looking at the parameters?

Ah. Got it. Thanks!

regards,
dan carpenter

#8 lore raw

[bug report] net: wwan: Add Qualcomm BAM-DMUX WWAN network driver

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Stephan Gerhold,

Commit 21a0ffd9b38c ("net: wwan: Add Qualcomm BAM-DMUX WWAN network driver") from Nov 27, 2021 (linux-next), leads to the following Smatch static checker warning:

	drivers/net/wwan/qcom_bam_dmux.c:505 bam_dmux_cmd_data()
	error: buffer overflow 'dmux->netdevs' 8 <= 255 user_rl='0-255' uncapped

drivers/net/wwan/qcom_bam_dmux.c

    500 static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma)
    501 {
    502         struct bam_dmux *dmux = skb_dma->dmux;
    503         struct sk_buff *skb = skb_dma->skb;
    504         struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data;
--> 505         struct net_device *netdev = dmux->netdevs[hdr->ch];
                                                          ^^^^^^^

Smatch thinks skb->data is untrusted. This is the rx path.

    506 
    507         if (!netdev || !netif_running(netdev)) {
    508                 dev_warn(dmux->dev, "Data for inactive channel %u\n", hdr->ch);
    509                 return;
    510         }
    511 

regards,
dan carpenter

#9 lore raw

Re: [bug report] net: wwan: Add Qualcomm BAM-DMUX WWAN network driver

Hi Dan,

Quoted 13 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Stephan Gerhold,

Commit 21a0ffd9b38c ("net: wwan: Add Qualcomm BAM-DMUX WWAN network driver") from Nov 27, 2021 (linux-next), leads to the following Smatch static checker warning:

	drivers/net/wwan/qcom_bam_dmux.c:505 bam_dmux_cmd_data()
	error: buffer overflow 'dmux->netdevs' 8 <= 255 user_rl='0-255' uncapped

drivers/net/wwan/qcom_bam_dmux.c

Quoted 9 lines
    500 static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma)
    501 {
    502         struct bam_dmux *dmux = skb_dma->dmux;
    503         struct sk_buff *skb = skb_dma->skb;
    504         struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data;
--> 505         struct net_device *netdev = dmux->netdevs[hdr->ch];
                                                          ^^^^^^^

Smatch thinks skb->data is untrusted. This is the rx path.

Thanks a lot for the report!

I believe this is not a problem in practice, since there is an existing check for this in bam_dmux_rx_callback() (which is the only function that calls bam_dmux_cmd_data()):

	if (hdr->ch >= BAM_DMUX_NUM_CH) {
		dev_dbg(dmux->dev, "Unsupported channel: %u\n", hdr->ch);
		goto out;
	}

	switch (hdr->cmd) {
	case BAM_DMUX_CMD_DATA:
		bam_dmux_cmd_data(skb_dma);
		break;

Is that something Smatch should be able to detect?

Thanks,
Stephan

#10 lore raw

Re: [bug report] net: wwan: Add Qualcomm BAM-DMUX WWAN network driver

Quoted 42 lines · Stephan Gerhold

Hi Dan,

Quoted 13 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Stephan Gerhold,

Commit 21a0ffd9b38c ("net: wwan: Add Qualcomm BAM-DMUX WWAN network driver") from Nov 27, 2021 (linux-next), leads to the following Smatch static checker warning:

	drivers/net/wwan/qcom_bam_dmux.c:505 bam_dmux_cmd_data()
	error: buffer overflow 'dmux->netdevs' 8 <= 255 user_rl='0-255' uncapped

drivers/net/wwan/qcom_bam_dmux.c

Quoted 9 lines
    500 static void bam_dmux_cmd_data(struct bam_dmux_skb_dma *skb_dma)
    501 {
    502         struct bam_dmux *dmux = skb_dma->dmux;
    503         struct sk_buff *skb = skb_dma->skb;
    504         struct bam_dmux_hdr *hdr = (struct bam_dmux_hdr *)skb->data;
--> 505         struct net_device *netdev = dmux->netdevs[hdr->ch];
                                                          ^^^^^^^

Smatch thinks skb->data is untrusted. This is the rx path.

Thanks a lot for the report!

I believe this is not a problem in practice, since there is an existing check for this in bam_dmux_rx_callback() (which is the only function that calls bam_dmux_cmd_data()):

	if (hdr->ch >= BAM_DMUX_NUM_CH) {
		dev_dbg(dmux->dev, "Unsupported channel: %u\n", hdr->ch);
		goto out;
	}

	switch (hdr->cmd) {
	case BAM_DMUX_CMD_DATA:
		bam_dmux_cmd_data(skb_dma);
		break;
Quoted 2 lines

Is that something Smatch should be able to detect?

Ah, you are right. Thanks.

The problem is that skb->data is a buffer of u8 data. Smatch does cross function analysis, but it treats a buffer like that as opaque data.

Btw, I see that this code is actually from five years ago so I don't know why it's showing up as a warning now. :/ Sorry about that.

regards,
dan carpenter

#11 lore raw

[bug report] iommu/amd: Introduce gDomID-to-hDomID Mapping and handle parent domain invalidation

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Suravee Suthikulpanit,

Commit 757d2b1fdf5b ("iommu/amd: Introduce gDomID-to-hDomID Mapping and handle parent domain invalidation") from Jan 15, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/iommu/amd/nested.c:161 amd_iommu_alloc_domain_nested()
	warn: 'gdom_info->hdom_id' unsigned <= 0

drivers/iommu/amd/nested.c

    148         /* Check if gDomID exist */
    149         if (refcount_inc_not_zero(&gdom_info->users)) {
    150                 ndom->gdom_info = gdom_info;
    151                 xa_unlock(&aviommu->gdomid_array);
    152 
    153                 pr_debug("%s: Found gdom_id=%#x, hdom_id=%#x\n",
    154                           __func__, ndom->gdom_id, gdom_info->hdom_id);
    155 
    156                 return &ndom->domain;
    157         }
    158 
    159         /* The gDomID does not exist. We allocate new hdom_id */
    160         gdom_info->hdom_id = amd_iommu_pdom_id_alloc();

--> 161 if (gdom_info->hdom_id <= 0) {

gdom_info->hdom_id is unsigned. amd_iommu_pdom_id_alloc() can't return zero. It either returns negatives or 1-65535.

    162                 __xa_cmpxchg(&aviommu->gdomid_array,
    163                              ndom->gdom_id, gdom_info, NULL, GFP_ATOMIC);
    164                 xa_unlock(&aviommu->gdomid_array);
    165                 ret = -ENOSPC;
    166                 goto out_err_gdom_info;
    167         }
    168 
    169         ndom->gdom_info = gdom_info;

regards,
dan carpenter

#12 lore raw

[bug report] drm/amdkfd: add debug set and clear address watch points operation

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jonathan Kim,

Commit e0f85f4690d0 ("drm/amdkfd: add debug set and clear address watch points operation") from May 6, 2022 (linux-next), leads to the following Smatch static checker warning:

	drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_debug.c:448 kfd_dbg_trap_clear_dev_address_watch()
	error: buffer overflow 'pdd->watch_points' 4 <= u32max user_rl='0-3,2147483648-u32max' uncapped

drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_debug.c

    433 int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd,
    434                                         uint32_t watch_id)
    435 {
    436         int r;
    437 
    438         if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id))

kfd_dbg_owns_dev_watch_id() doesn't check for negative values so if watch_id is larger than INT_MAX it leads to a buffer overflow. (Negative shifts are undefined).

    439                 return -EINVAL;
    440 
    441         if (!pdd->dev->kfd->shared_resources.enable_mes) {
    442                 r = debug_lock_and_unmap(pdd->dev->dqm);
    443                 if (r)
    444                         return r;
    445         }
    446 
    447         amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
--> 448         pdd->watch_points[watch_id] = pdd->dev->kfd2kgd->clear_address_watch(
    449                                                         pdd->dev->adev,
    450                                                         watch_id);
    451         amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
    452 
    453         if (!pdd->dev->kfd->shared_resources.enable_mes)
    454                 r = debug_map_and_unlock(pdd->dev->dqm);
    455         else
    456                 r = kfd_dbg_set_mes_debug_mode(pdd, true);
    457 
    458         kfd_dbg_clear_dev_watch_id(pdd, watch_id);
    459 
    460         return r;
    461 }

regards,
dan carpenter

#13 lore raw

PATCH 1/1 mtd: spi-nor: hisi-sfc: fix refcounting bug in hisi_spi_nor_register_all()

In reply to Dan Carpenter

This was converted to a _scoped() loop but this of_node_put() was accidentally left behind which is a double free.

Fixes aa8cb72c2018 ("mtd: spi-nor: hisi-sfc: Simplify with scoped for each OF child loop")
---
 drivers/mtd/spi-nor/controllers/hisi-sfc.c | 1 -
 1 file changed, 1 deletion(-)
drivers/mtd/spi-nor/controllers/hisi-sfc.c +0 -1
index 54c49a8423a2..6897ced2d57b 100644
@@ -403,7 +403,6 @@ static int hisi_spi_nor_register_all(struct hifmc_host *host)
 
 		if (host->num_chip == HIFMC_MAX_CHIP_NUM) {
 			dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n");
-			of_node_put(np);
 			break;
 		}
 	}
Signature · 1 line
2.51.0
maintainer Reviewed-by on v1 1/1
#14 lore raw

Re: [PATCH next] mtd: spi-nor: hisi-sfc: fix refcounting bug in hisi_spi_nor_register_all()

Quoted 5 lines · Dan Carpenter

This was converted to a _scoped() loop but this of_node_put() was accidentally left behind which is a double free.

Fixes aa8cb72c2018 ("mtd: spi-nor: hisi-sfc: Simplify with scoped for each OF child loop")

Miquel, since you took the original patch through the NAND tree, can you please take this one too?

[...]

Signature · 2 lines
Regards,
Pratyush Yadav
maintainer
#15 lore raw

Re: [PATCH next] mtd: spi-nor: hisi-sfc: fix refcounting bug in hisi_spi_nor_register_all()

Hello,

Quoted 5 lines · Pratyush Yadav
Quoted 3 lines · Dan Carpenter

This was converted to a _scoped() loop but this of_node_put() was accidentally left behind which is a double free.

Quoted 7 lines
Quoted 2 lines
Fixes aa8cb72c2018 ("mtd: spi-nor: hisi-sfc: Simplify with scoped for each OF child loop")

Miquel, since you took the original patch through the NAND tree, can you please take this one too?

Yes I will, thanks!

Miquèl

maintainer Applied
#16 lore raw

Re: [PATCH next] mtd: spi-nor: hisi-sfc: fix refcounting bug in hisi_spi_nor_register_all()

In reply to Dan Carpenter
Quoted 4 lines · Dan Carpenter

This was converted to a _scoped() loop but this of_node_put() was accidentally left behind which is a double free.

Applied to nand/next, thanks!

[1/1] mtd: spi-nor: hisi-sfc: fix refcounting bug in hisi_spi_nor_register_all()

      commit: 6c7860aa28b81b7e909b8d2072ed76fa22db6eda

Patche(s) should be available on mtd/linux.git and will be part of the next PR (provided that no robot complains by then).

Kind regards,
Miquèl

#17 lore raw

[bug report] media: synopsys: add driver for the designware mipi csi-2 receiver

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Michael Riesch,

Commit 355a11004066 ("media: synopsys: add driver for the designware mipi csi-2 receiver") from Jan 20, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/media/platform/synopsys/dw-mipi-csi2rx.c:307 dw_mipi_csi2rx_enum_mbus_code()
	warn: array off by one? 'csi2->formats[code->index]'

drivers/media/platform/synopsys/dw-mipi-csi2rx.c

    286 static int
    287 dw_mipi_csi2rx_enum_mbus_code(struct v4l2_subdev *sd,
    288                               struct v4l2_subdev_state *sd_state,
    289                               struct v4l2_subdev_mbus_code_enum *code)
    290 {
    291         struct dw_mipi_csi2rx_device *csi2 = to_csi2(sd);
    292 
    293         switch (code->pad) {
    294         case DW_MIPI_CSI2RX_PAD_SRC:
    295                 if (code->index)
    296                         return -EINVAL;
    297 
    298                 code->code =
    299                         v4l2_subdev_state_get_format(sd_state,
    300                                                      DW_MIPI_CSI2RX_PAD_SINK)->code;
    301 
    302                 return 0;
    303         case DW_MIPI_CSI2RX_PAD_SINK:
    304                 if (code->index > csi2->formats_num)

This should be >=.

    305                         return -EINVAL;
    306 
--> 307                 code->code = csi2->formats[code->index].code;
    308                 return 0;
    309         default:
    310                 return -EINVAL;
    311         }
    312 }

regards,
dan carpenter

#18 lore raw

[bug report] crush: remove forcefeed functionality

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ceph Maintainers,

Commit 41ebcc0907c5 ("crush: remove forcefeed functionality") from May 7, 2012 (linux-next), leads to the following Smatch static checker warning:

	net/ceph/crush/mapper.c:1015 crush_do_rule()
	warn: iterator 'j' not incremented

net/ceph/crush/mapper.c

    897 int crush_do_rule(const struct crush_map *map,
    898                   int ruleno, int x, int *result, int result_max,
    899                   const __u32 *weight, int weight_max,
    900                   void *cwin, const struct crush_choose_arg *choose_args)
    901 {
    902         int result_len;
    903         struct crush_work *cw = cwin;
    904         int *a = cwin + map->working_size;
    905         int *b = a + result_max;
    906         int *c = b + result_max;
    907         int *w = a;
    908         int *o = b;
    909         int recurse_to_leaf;
    910         int wsize = 0;
    911         int osize;
    912         const struct crush_rule *rule;
    913         __u32 step;
    914         int i, j;
    915         int numrep;
    916         int out_size;
    917         /*
    918          * the original choose_total_tries value was off by one (it
    919          * counted "retries" and not "tries").  add one.
    920          */
    921         int choose_tries = map->choose_total_tries + 1;
    922         int choose_leaf_tries = 0;
    923         /*
    924          * the local tries values were counted as "retries", though,
    925          * and need no adjustment
    926          */
    927         int choose_local_retries = map->choose_local_tries;
    928         int choose_local_fallback_retries = map->choose_local_fallback_tries;
    929 
    930         int vary_r = map->chooseleaf_vary_r;
    931         int stable = map->chooseleaf_stable;
    932 
    933         if ((__u32)ruleno >= map->max_rules) {
    934                 dprintk(" bad ruleno %d\n", ruleno);
    935                 return 0;
    936         }
    937 
    938         rule = map->rules[ruleno];
    939         result_len = 0;
    940 
    941         for (step = 0; step < rule->len; step++) {
    942                 int firstn = 0;
    943                 const struct crush_rule_step *curstep = &rule->steps[step];
    944 
    945                 switch (curstep->op) {
    946                 case CRUSH_RULE_TAKE:
    947                         if ((curstep->arg1 >= 0 &&
    948                              curstep->arg1 < map->max_devices) ||
    949                             (-1-curstep->arg1 >= 0 &&
    950                              -1-curstep->arg1 < map->max_buckets &&
    951                              map->buckets[-1-curstep->arg1])) {
    952                                 w[0] = curstep->arg1;
    953                                 wsize = 1;
    954                         } else {
    955                                 dprintk(" bad take value %d\n", curstep->arg1);
    956                         }
    957                         break;
    958 
    959                 case CRUSH_RULE_SET_CHOOSE_TRIES:
    960                         if (curstep->arg1 > 0)
    961                                 choose_tries = curstep->arg1;
    962                         break;
    963 
    964                 case CRUSH_RULE_SET_CHOOSELEAF_TRIES:
    965                         if (curstep->arg1 > 0)
    966                                 choose_leaf_tries = curstep->arg1;
    967                         break;
    968 
    969                 case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES:
    970                         if (curstep->arg1 >= 0)
    971                                 choose_local_retries = curstep->arg1;
    972                         break;
    973 
    974                 case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES:
    975                         if (curstep->arg1 >= 0)
    976                                 choose_local_fallback_retries = curstep->arg1;
    977                         break;
    978 
    979                 case CRUSH_RULE_SET_CHOOSELEAF_VARY_R:
    980                         if (curstep->arg1 >= 0)
    981                                 vary_r = curstep->arg1;
    982                         break;
    983 
    984                 case CRUSH_RULE_SET_CHOOSELEAF_STABLE:
    985                         if (curstep->arg1 >= 0)
    986                                 stable = curstep->arg1;
    987                         break;
    988 
    989                 case CRUSH_RULE_CHOOSELEAF_FIRSTN:
    990                 case CRUSH_RULE_CHOOSE_FIRSTN:
    991                         firstn = 1;
    992                         fallthrough;
    993                 case CRUSH_RULE_CHOOSELEAF_INDEP:
    994                 case CRUSH_RULE_CHOOSE_INDEP:
    995                         if (wsize == 0)
    996                                 break;
    997 
    998                         recurse_to_leaf =
    999                                 curstep->op ==
    1000                                  CRUSH_RULE_CHOOSELEAF_FIRSTN ||
    1001                                 curstep->op ==
    1002                                 CRUSH_RULE_CHOOSELEAF_INDEP;
    1003 
    1004                         /* reset output */
    1005                         osize = 0;
    1006 
    1007                         for (i = 0; i < wsize; i++) {
    1008                                 int bno;
    1009                                 numrep = curstep->arg1;
    1010                                 if (numrep <= 0) {
    1011                                         numrep += result_max;
    1012                                         if (numrep <= 0)
    1013                                                 continue;
    1014                                 }
--> 1015                                 j = 0;
                                         ^^^^^

    1016                                 /* make sure bucket id is valid */
    1017                                 bno = -1 - w[i];
    1018                                 if (bno < 0 || bno >= map->max_buckets) {
    1019                                         /* w[i] is probably CRUSH_ITEM_NONE */
    1020                                         dprintk("  bad w[i] %d\n", w[i]);
    1021                                         continue;
    1022                                 }
    1023                                 if (firstn) {
    1024                                         int recurse_tries;
    1025                                         if (choose_leaf_tries)
    1026                                                 recurse_tries =
    1027                                                         choose_leaf_tries;
    1028                                         else if (map->chooseleaf_descend_once)
    1029                                                 recurse_tries = 1;
    1030                                         else
    1031                                                 recurse_tries = choose_tries;
    1032                                         osize += crush_choose_firstn(
    1033                                                 map,
    1034                                                 cw,
    1035                                                 map->buckets[bno],
    1036                                                 weight, weight_max,
    1037                                                 x, numrep,
    1038                                                 curstep->arg2,
    1039                                                 o+osize, j,
    1040                                                 result_max-osize,
    1041                                                 choose_tries,
    1042                                                 recurse_tries,
    1043                                                 choose_local_retries,
    1044                                                 choose_local_fallback_retries,
    1045                                                 recurse_to_leaf,
    1046                                                 vary_r,
    1047                                                 stable,
    1048                                                 c+osize,
    1049                                                 0,
    1050                                                 choose_args);
    1051                                 } else {
    1052                                         out_size = ((numrep < (result_max-osize)) ?
    1053                                                     numrep : (result_max-osize));
    1054                                         crush_choose_indep(
    1055                                                 map,
    1056                                                 cw,
    1057                                                 map->buckets[bno],
    1058                                                 weight, weight_max,
    1059                                                 x, out_size, numrep,
    1060                                                 curstep->arg2,
    1061                                                 o+osize, j,
    1062                                                 choose_tries,
    1063                                                 choose_leaf_tries ?
    1064                                                    choose_leaf_tries : 1,
    1065                                                 recurse_to_leaf,
    1066                                                 c+osize,
    1067                                                 0,
    1068                                                 choose_args);
    1069                                         osize += out_size;
    1070                                 }

There used to be a j++ around here but it was deleted.

    1071                         }
    1072 
    1073                         if (recurse_to_leaf)
    1074                                 /* copy final _leaf_ values to output set */
    1075                                 memcpy(o, c, osize*sizeof(*o));
    1076 
    1077                         /* swap o and w arrays */
    1078                         swap(o, w);
    1079                         wsize = osize;
    1080                         break;
    1081 
    1082 
    1083                 case CRUSH_RULE_EMIT:
    1084                         for (i = 0; i < wsize && result_len < result_max; i++) {
    1085                                 result[result_len] = w[i];
    1086                                 result_len++;
    1087                         }
    1088                         wsize = 0;
    1089                         break;
    1090 
    1091                 default:
    1092                         dprintk(" unknown op %d at step %d\n",
    1093                                 curstep->op, step);
    1094                         break;
    1095                 }
    1096         }
    1097 
    1098         return result_len;
    1099 }

regards,
dan carpenter

#19 lore raw

Re: [bug report] crush: remove forcefeed functionality

Quoted 11 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_all_aTaiGSbWZ9DJaGo7-40stanley.mountain_&d=DwIBAg&c=BSDicqBQBDjDI9RkVyTcHQ&r=q5bIm4AXMzc8NJu1_RGmnQ2fMWKq4Y4RAkElvUgSs00&m=EbbQA8mLawUrIpoBP1JgkEbj9ykB2zMAgU-BpxccK9crlqQp8eHphKm2eDfswppo&s=4dnJgIrt1z5jJRZwXTmcMBeS0RZ5lg-CZ04H1P9fcrE&e= -dan ]

Hello Ceph Maintainers,

Commit 41ebcc0907c5 ("crush: remove forcefeed functionality") from May 7, 2012 (linux-next), leads to the following Smatch static checker warning:

	net/ceph/crush/mapper.c:1015 crush_do_rule()
	warn: iterator 'j' not incremented

Yeah, it looks like an issue.

Quoted 114 lines

net/ceph/crush/mapper.c

    897 int crush_do_rule(const struct crush_map *map,
    898                   int ruleno, int x, int *result, int result_max,
    899                   const __u32 *weight, int weight_max,
    900                   void *cwin, const struct crush_choose_arg *choose_args)
    901 {
    902         int result_len;
    903         struct crush_work *cw = cwin;
    904         int *a = cwin + map->working_size;
    905         int *b = a + result_max;
    906         int *c = b + result_max;
    907         int *w = a;
    908         int *o = b;
    909         int recurse_to_leaf;
    910         int wsize = 0;
    911         int osize;
    912         const struct crush_rule *rule;
    913         __u32 step;
    914         int i, j;
    915         int numrep;
    916         int out_size;
    917         /*
    918          * the original choose_total_tries value was off by one (it
    919          * counted "retries" and not "tries").  add one.
    920          */
    921         int choose_tries = map->choose_total_tries + 1;
    922         int choose_leaf_tries = 0;
    923         /*
    924          * the local tries values were counted as "retries", though,
    925          * and need no adjustment
    926          */
    927         int choose_local_retries = map->choose_local_tries;
    928         int choose_local_fallback_retries = map->choose_local_fallback_tries;
    929 
    930         int vary_r = map->chooseleaf_vary_r;
    931         int stable = map->chooseleaf_stable;
    932 
    933         if ((__u32)ruleno >= map->max_rules) {
    934                 dprintk(" bad ruleno %d\n", ruleno);
    935                 return 0;
    936         }
    937 
    938         rule = map->rules[ruleno];
    939         result_len = 0;
    940 
    941         for (step = 0; step < rule->len; step++) {
    942                 int firstn = 0;
    943                 const struct crush_rule_step *curstep = &rule->steps[step];
    944 
    945                 switch (curstep->op) {
    946                 case CRUSH_RULE_TAKE:
    947                         if ((curstep->arg1 >= 0 &&
    948                              curstep->arg1 < map->max_devices) ||
    949                             (-1-curstep->arg1 >= 0 &&
    950                              -1-curstep->arg1 < map->max_buckets &&
    951                              map->buckets[-1-curstep->arg1])) {
    952                                 w[0] = curstep->arg1;
    953                                 wsize = 1;
    954                         } else {
    955                                 dprintk(" bad take value %d\n", curstep->arg1);
    956                         }
    957                         break;
    958 
    959                 case CRUSH_RULE_SET_CHOOSE_TRIES:
    960                         if (curstep->arg1 > 0)
    961                                 choose_tries = curstep->arg1;
    962                         break;
    963 
    964                 case CRUSH_RULE_SET_CHOOSELEAF_TRIES:
    965                         if (curstep->arg1 > 0)
    966                                 choose_leaf_tries = curstep->arg1;
    967                         break;
    968 
    969                 case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES:
    970                         if (curstep->arg1 >= 0)
    971                                 choose_local_retries = curstep->arg1;
    972                         break;
    973 
    974                 case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES:
    975                         if (curstep->arg1 >= 0)
    976                                 choose_local_fallback_retries = curstep->arg1;
    977                         break;
    978 
    979                 case CRUSH_RULE_SET_CHOOSELEAF_VARY_R:
    980                         if (curstep->arg1 >= 0)
    981                                 vary_r = curstep->arg1;
    982                         break;
    983 
    984                 case CRUSH_RULE_SET_CHOOSELEAF_STABLE:
    985                         if (curstep->arg1 >= 0)
    986                                 stable = curstep->arg1;
    987                         break;
    988 
    989                 case CRUSH_RULE_CHOOSELEAF_FIRSTN:
    990                 case CRUSH_RULE_CHOOSE_FIRSTN:
    991                         firstn = 1;
    992                         fallthrough;
    993                 case CRUSH_RULE_CHOOSELEAF_INDEP:
    994                 case CRUSH_RULE_CHOOSE_INDEP:
    995                         if (wsize == 0)
    996                                 break;
    997 
    998                         recurse_to_leaf =
    999                                 curstep->op ==
    1000                                  CRUSH_RULE_CHOOSELEAF_FIRSTN ||
    1001                                 curstep->op ==
    1002                                 CRUSH_RULE_CHOOSELEAF_INDEP;
    1003 
    1004                         /* reset output */
    1005                         osize = 0;
    1006 
    1007                         for (i = 0; i < wsize; i++) {
    1008                                 int bno;
Quoted 8 lines
    1009                                 numrep = curstep->arg1;
    1010                                 if (numrep <= 0) {
    1011                                         numrep += result_max;
    1012                                         if (numrep <= 0)
    1013                                                 continue;
    1014                                 }
--> 1015                                 j = 0;
                                         ^^^^^

It looks like intentional initialization of variable. But let me spend some time to better understand the crush_choose_firstn() and crush_choose_indep() logic and the history of this function modifications in commits.

Thanks,
Slava.

Quoted 91 lines
    1016                                 /* make sure bucket id is valid */
    1017                                 bno = -1 - w[i];
    1018                                 if (bno < 0 || bno >= map->max_buckets) {
    1019                                         /* w[i] is probably CRUSH_ITEM_NONE */
    1020                                         dprintk("  bad w[i] %d\n", w[i]);
    1021                                         continue;
    1022                                 }
    1023                                 if (firstn) {
    1024                                         int recurse_tries;
    1025                                         if (choose_leaf_tries)
    1026                                                 recurse_tries =
    1027                                                         choose_leaf_tries;
    1028                                         else if (map->chooseleaf_descend_once)
    1029                                                 recurse_tries = 1;
    1030                                         else
    1031                                                 recurse_tries = choose_tries;
    1032                                         osize += crush_choose_firstn(
    1033                                                 map,
    1034                                                 cw,
    1035                                                 map->buckets[bno],
    1036                                                 weight, weight_max,
    1037                                                 x, numrep,
    1038                                                 curstep->arg2,
    1039                                                 o+osize, j,
    1040                                                 result_max-osize,
    1041                                                 choose_tries,
    1042                                                 recurse_tries,
    1043                                                 choose_local_retries,
    1044                                                 choose_local_fallback_retries,
    1045                                                 recurse_to_leaf,
    1046                                                 vary_r,
    1047                                                 stable,
    1048                                                 c+osize,
    1049                                                 0,
    1050                                                 choose_args);
    1051                                 } else {
    1052                                         out_size = ((numrep < (result_max-osize)) ?
    1053                                                     numrep : (result_max-osize));
    1054                                         crush_choose_indep(
    1055                                                 map,
    1056                                                 cw,
    1057                                                 map->buckets[bno],
    1058                                                 weight, weight_max,
    1059                                                 x, out_size, numrep,
    1060                                                 curstep->arg2,
    1061                                                 o+osize, j,
    1062                                                 choose_tries,
    1063                                                 choose_leaf_tries ?
    1064                                                    choose_leaf_tries : 1,
    1065                                                 recurse_to_leaf,
    1066                                                 c+osize,
    1067                                                 0,
    1068                                                 choose_args);
    1069                                         osize += out_size;
    1070                                 }

There used to be a j++ around here but it was deleted.

    1071                         }
    1072 
    1073                         if (recurse_to_leaf)
    1074                                 /* copy final _leaf_ values to output set */
    1075                                 memcpy(o, c, osize*sizeof(*o));
    1076 
    1077                         /* swap o and w arrays */
    1078                         swap(o, w);
    1079                         wsize = osize;
    1080                         break;
    1081 
    1082 
    1083                 case CRUSH_RULE_EMIT:
    1084                         for (i = 0; i < wsize && result_len < result_max; i++) {
    1085                                 result[result_len] = w[i];
    1086                                 result_len++;
    1087                         }
    1088                         wsize = 0;
    1089                         break;
    1090 
    1091                 default:
    1092                         dprintk(" unknown op %d at step %d\n",
    1093                                 curstep->op, step);
    1094                         break;
    1095                 }
    1096         }
    1097 
    1098         return result_len;
    1099 }

regards,
dan carpenter

#20 lore raw

[bug report] net: ethernet: ti: am65-cpsw: enable bc/mc storm prevention support

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Grygorii Strashko,

Commit 5ec836be11b3 ("net: ethernet: ti: am65-cpsw: enable bc/mc storm prevention support") from Apr 12, 2022 (linux-next), leads to the following Smatch static checker warning:

	drivers/net/ethernet/ti/am65-cpsw-qos.c:1126 am65_cpsw_qos_configure_clsflower()
	warn: iterator 'i' not incremented

drivers/net/ethernet/ti/am65-cpsw-qos.c

    1118 static int am65_cpsw_qos_configure_clsflower(struct am65_cpsw_port *port,
    1119                                              struct flow_cls_offload *cls)
    1120 {
    1121         struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
    1122         struct netlink_ext_ack *extack = cls->common.extack;
    1123         const struct flow_action_entry *act;
    1124         int i, ret;
    1125 

--> 1126 flow_action_for_each(i, act, &rule->action) {

This loop only iterates one time. Is that intentional? We could use "act = flow_action_first_entry_geti(&rule->action);" if we just want the first entry.

    1127                 switch (act->id) {
    1128                 case FLOW_ACTION_POLICE:
    1129                         ret = am65_cpsw_qos_clsflower_policer_validate(&rule->action, act, extack);
    1130                         if (ret)
    1131                                 return ret;
    1132 
    1133                         return am65_cpsw_qos_clsflower_add_policer(port, extack, cls,
    1134                                                                    act->police.rate_pkt_ps);
    1135                 default:
    1136                         NL_SET_ERR_MSG_MOD(extack,
    1137                                            "Action not supported");
    1138                         return -EOPNOTSUPP;
    1139                 }
    1140         }
    1141         return -EOPNOTSUPP;
    1142 }

regards,
dan carpenter

#21 lore raw

[bug report] phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Xiangxu Yin,

Commit 81791c45c8e0 ("phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support") from Dec 15, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/qualcomm/phy-qcom-qmp-usbc.c:803 qmp_v2_configure_dp_swing()
	index hardmax out of bounds '(*cfg->swing_tbl)[v_level]' size=4 max='4' rl='0-4'

drivers/phy/qualcomm/phy-qcom-qmp-usbc.c

    777 static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp)
    778 {
    779         const struct qmp_phy_cfg *cfg = qmp->cfg;
    780         const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
    781         void __iomem *tx = qmp->dp_tx;
    782         void __iomem *tx2 = qmp->dp_tx2;
    783         unsigned int v_level = 0, p_level = 0;
    784         u8 voltage_swing_cfg, pre_emphasis_cfg;
    785         int i;
    786 
    787         if (dp_opts->lanes > 4) {
    788                 dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes);
    789                 return -EINVAL;
    790         }
    791 
    792         for (i = 0; i < dp_opts->lanes; i++) {
    793                 v_level = max(v_level, dp_opts->voltage[i]);
    794                 p_level = max(p_level, dp_opts->pre[i]);
    795         }
    796 
    797         if (v_level > 4 || p_level > 4) {

These should be >= 4 instead of >.

    798                 dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n",
    799                         v_level, p_level);
    800                 return -EINVAL;
    801         }
    802 
--> 803         voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level];
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is a 4x4 array.

    804         pre_emphasis_cfg = (*cfg->pre_emphasis_tbl)[v_level][p_level];
    805 
    806         voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN;
    807         pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN;
    808 
    809         if (voltage_swing_cfg == 0xff && pre_emphasis_cfg == 0xff)
    810                 return -EINVAL;
    811 
    812         writel(voltage_swing_cfg, tx + QSERDES_V2_TX_TX_DRV_LVL);
    813         writel(pre_emphasis_cfg, tx + QSERDES_V2_TX_TX_EMP_POST1_LVL);
    814         writel(voltage_swing_cfg, tx2 + QSERDES_V2_TX_TX_DRV_LVL);
    815         writel(pre_emphasis_cfg, tx2 + QSERDES_V2_TX_TX_EMP_POST1_LVL);
    816 
    817         return 0;
    818 }

regards,
dan carpenter

#22 lore raw

Re: [bug report] phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support

Quoted 37 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Xiangxu Yin,

Commit 81791c45c8e0 ("phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support") from Dec 15, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/qualcomm/phy-qcom-qmp-usbc.c:803 qmp_v2_configure_dp_swing()
	index hardmax out of bounds '(*cfg->swing_tbl)[v_level]' size=4 max='4' rl='0-4'

drivers/phy/qualcomm/phy-qcom-qmp-usbc.c

    777 static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp)
    778 {
    779         const struct qmp_phy_cfg *cfg = qmp->cfg;
    780         const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
    781         void __iomem *tx = qmp->dp_tx;
    782         void __iomem *tx2 = qmp->dp_tx2;
    783         unsigned int v_level = 0, p_level = 0;
    784         u8 voltage_swing_cfg, pre_emphasis_cfg;
    785         int i;
    786 
    787         if (dp_opts->lanes > 4) {
    788                 dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes);
    789                 return -EINVAL;
    790         }
    791 
    792         for (i = 0; i < dp_opts->lanes; i++) {
    793                 v_level = max(v_level, dp_opts->voltage[i]);
    794                 p_level = max(p_level, dp_opts->pre[i]);
    795         }
    796 
    797         if (v_level > 4 || p_level > 4) {

These should be >= 4 instead of >.

Quoted 8 lines
    798                 dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n",
    799                         v_level, p_level);
    800                 return -EINVAL;
    801         }
    802 
--> 803         voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level];
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is a 4x4 array.

Thanks Dan for the report

Xiangxu, are you planning to send a patch to address that?

Konrad

#23 lore raw

Re: [bug report] phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support

Quoted 46 lines · Konrad Dybcio
Quoted 37 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Xiangxu Yin,

Commit 81791c45c8e0 ("phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support") from Dec 15, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/qualcomm/phy-qcom-qmp-usbc.c:803 qmp_v2_configure_dp_swing()
	index hardmax out of bounds '(*cfg->swing_tbl)[v_level]' size=4 max='4' rl='0-4'

drivers/phy/qualcomm/phy-qcom-qmp-usbc.c

    777 static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp)
    778 {
    779         const struct qmp_phy_cfg *cfg = qmp->cfg;
    780         const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
    781         void __iomem *tx = qmp->dp_tx;
    782         void __iomem *tx2 = qmp->dp_tx2;
    783         unsigned int v_level = 0, p_level = 0;
    784         u8 voltage_swing_cfg, pre_emphasis_cfg;
    785         int i;
    786 
    787         if (dp_opts->lanes > 4) {
    788                 dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes);
    789                 return -EINVAL;
    790         }
    791 
    792         for (i = 0; i < dp_opts->lanes; i++) {
    793                 v_level = max(v_level, dp_opts->voltage[i]);
    794                 p_level = max(p_level, dp_opts->pre[i]);
    795         }
    796 
    797         if (v_level > 4 || p_level > 4) {

These should be >= 4 instead of >.

Quoted 8 lines
    798                 dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n",
    799                         v_level, p_level);
    800                 return -EINVAL;
    801         }
    802 
--> 803         voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level];
                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is a 4x4 array.

Quoted 5 lines

Thanks Dan for the report

Xiangxu, are you planning to send a patch to address that?

Konrad

Thanks for the notice, Dan & Konrad.

I just got back from a long leave and will submit the relevant patches as soon as possible.

#24 lore raw

[bug report] drm/amd/display: add DC changes for DCN351

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Hamza Mahfooz,

Commit 2728e9c7c842 ("drm/amd/display: add DC changes for DCN351") from Feb 23, 2024 (linux-next), leads to the following Smatch static checker warning:

drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn351/dcn351_resource.c:1284 dcn35_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn36/dcn36_resource.c:1285 dcn35_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn321/dcn321_resource.c:1222 dcn321_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn315/dcn315_resource.c:1252 dcn315_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn35/dcn35_resource.c:1304 dcn35_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn32/dcn32_resource.c:1241 dcn32_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5' drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn316/dcn316_resource.c:1245 dcn316_stream_encoder_create() index hardmax out of bounds 'stream_enc_regs[eng_id]' size=5 max='5' rl='s32min-5'

drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn351/dcn351_resource.c

    1246 static struct stream_encoder *dcn35_stream_encoder_create(
    1247         enum engine_id eng_id,
    1248         struct dc_context *ctx)
    1249 {
    1250         struct dcn10_stream_encoder *enc1;
    1251         struct vpg *vpg;
    1252         struct afmt *afmt;
    1253         int vpg_inst;
    1254         int afmt_inst;
    1255 
    1256         /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
    1257         if (eng_id <= ENGINE_ID_DIGF) {

ENGINE_ID_DIGF is 5. should <= be <?

Unrelated but, ugh, why is Smatch saying that "eng_id" can be negative? end_id is type signed long, but there are checks in the caller which prevent it from being negative.

    1258                 vpg_inst = eng_id;
    1259                 afmt_inst = eng_id;
    1260         } else
    1261                 return NULL;
    1262 
    1263         enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
    1264         vpg = dcn31_vpg_create(ctx, vpg_inst);
    1265         afmt = dcn31_afmt_create(ctx, afmt_inst);
    1266 
    1267         if (!enc1 || !vpg || !afmt) {
    1268                 kfree(enc1);
    1269                 kfree(vpg);
    1270                 kfree(afmt);
    1271                 return NULL;
    1272         }
    1273 
    1274 #undef REG_STRUCT
    1275 #define REG_STRUCT stream_enc_regs
    1276         stream_enc_regs_init(0),
    1277         stream_enc_regs_init(1),
    1278         stream_enc_regs_init(2),
    1279         stream_enc_regs_init(3),
    1280         stream_enc_regs_init(4);
    1281 
    1282         dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
    1283                                         eng_id, vpg, afmt,
--> 1284                                         &stream_enc_regs[eng_id],
                                                  ^^^^^^^^^^^^^^^^^^^^^^^

This stream_enc_regs[] array has 5 elements so we are one element beyond the end of the array.

    1285                                         &se_shift, &se_mask);
    1286 
    1287         return &enc1->base;
    1288 }

regards,
dan carpenter

#25 lore raw

[bug report] media: rockchip: rkcif: add support for rk3568 vicap mipi capture

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Michael Riesch,

Commit 1f2353f5a1af ("media: rockchip: rkcif: add support for rk3568 vicap mipi capture") from Nov 14, 2025 (linux-next), leads to the following Smatch static checker warning:

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c:519 rkcif_mipi_id_get_reg() index hardmax out of bounds 'rkcif->match_data->mipi->regs_id[id]' size=4 max='4' rl='0-u32max'

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c:519 rkcif_mipi_id_get_reg() index hardmax out of bounds 'rkcif->match_data->mipi->regs_id[id][index]' size=11 max='11' rl='0-11'

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c

    504 static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream,
    505                                                  unsigned int index)
    506 {
    507         struct rkcif_device *rkcif = stream->rkcif;
    508         unsigned int block, id, offset, reg;
    509 
    510         block = stream->interface->index - RKCIF_MIPI_BASE;
    511         id = stream->id;
    512 
    513         if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
    514             WARN_ON_ONCE(id > RKCIF_ID_MAX) ||
    515             WARN_ON_ONCE(index > RKCIF_MIPI_ID_REGISTER_MAX))

The id and index checks should be >=. Not sure about block but I assume it's off by one as well.

    516                 return RKCIF_REGISTER_NOTSUPPORTED;
    517 
    518         offset = rkcif->match_data->mipi->blocks[block].offset;
--> 519         reg = rkcif->match_data->mipi->regs_id[id][index];
    520         if (reg == RKCIF_REGISTER_NOTSUPPORTED)
    521                 return reg;
    522 
    523         return offset + reg;
    524 }

regards,
dan carpenter

#26 lore raw

Re: [bug report] media: rockchip: rkcif: add support for rk3568 vicap mipi capture

Hi Dan,

Quoted 30 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Michael Riesch,

Commit 1f2353f5a1af ("media: rockchip: rkcif: add support for rk3568 vicap mipi capture") from Nov 14, 2025 (linux-next), leads to the following Smatch static checker warning:

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c:519 rkcif_mipi_id_get_reg() index hardmax out of bounds 'rkcif->match_data->mipi->regs_id[id]' size=4 max='4' rl='0-u32max'

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c:519 rkcif_mipi_id_get_reg() index hardmax out of bounds 'rkcif->match_data->mipi->regs_id[id][index]' size=11 max='11' rl='0-11'

drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c

    504 static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream,
    505                                                  unsigned int index)
    506 {
    507         struct rkcif_device *rkcif = stream->rkcif;
    508         unsigned int block, id, offset, reg;
    509 
    510         block = stream->interface->index - RKCIF_MIPI_BASE;
    511         id = stream->id;
    512 
    513         if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
    514             WARN_ON_ONCE(id > RKCIF_ID_MAX) ||
    515             WARN_ON_ONCE(index > RKCIF_MIPI_ID_REGISTER_MAX))
Quoted 2 lines

The id and index checks should be >=. Not sure about block but I assume it's off by one as well.

Thanks for the heads up. I started fixing this and then recalled some previous work on that issue.

I found that you submitted a patch that fixes exactly this, but this patch hasn't been applied for whatever reason.

Since I have some other fixes for the rkcif driver, I'll give your patch another spin in the scope of that series -- hope this is OK for you!

Best regards,
Michael

Quoted 13 lines
    516                 return RKCIF_REGISTER_NOTSUPPORTED;
    517 
    518         offset = rkcif->match_data->mipi->blocks[block].offset;
--> 519         reg = rkcif->match_data->mipi->regs_id[id][index];
    520         if (reg == RKCIF_REGISTER_NOTSUPPORTED)
    521                 return reg;
    522 
    523         return offset + reg;
    524 }

regards,
dan carpenter

#27 lore raw

[bug report] drm/imagination: Add gpuid module parameter

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Alexandru Dadu,

Commit 3bf74137340a ("drm/imagination: Add gpuid module parameter") from Jan 13, 2026 (linux-next), leads to the following Smatch static checker warning:

drivers/gpu/drm/imagination/pvr_device.c:485 pvr_gpuid_decode_string()
warn: error code type promoted to positive: 'ret'

drivers/gpu/drm/imagination/pvr_device.c

    475         int ret, idx = 0;
    476         u16 user_bvnc_u16[4];
    477         u8 dot_cnt = 0;
    478 
    479         ret = strscpy(str_cpy, param_bvnc);
    480 
    481         /*
    482          * strscpy() should return at least a size 7 for the input to be valid.
    483          * Returns -E2BIG for the case when the string is empty or too long.
    484          */

--> 485 if (ret < PVR_GPUID_STRING_MIN_LENGTH) {

PVR_GPUID_STRING_MIN_LENGTH is unsigned so -E2BIG is type promoted to positive and treated as success.

    486                 drm_info(drm_dev,
    487                          "Invalid size of the input GPU ID (BVNC): %s",
    488                          str_cpy);
    489                 return -EINVAL;
    490         }
    491 
    492         while (*param_bvnc) {
    493                 if (*param_bvnc == '.')
    494                         dot_cnt++;
    495                 param_bvnc++;
    496         }

regards,
dan carpenter

#28 lore raw

[bug report] ASoC: SOF: ipc4-control: Add support for generic bytes control

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Peter Ujfalusi,

Commit 2a28b5240f2b ("ASoC: SOF: ipc4-control: Add support for generic bytes control") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning:

	sound/soc/sof/ipc4-control.c:365 sof_ipc4_refresh_bytes_control()
	warn: missing error code here? '_dev_err()' failed. 'ret' = '0'

sound/soc/sof/ipc4-control.c

    324 static int
    325 sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock)
    326 {
    327         struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
    328         struct snd_soc_component *scomp = scontrol->scomp;
    329         struct sof_ipc4_control_msg_payload *msg_data;
    330         struct sof_abi_hdr *data = cdata->data;
    331         struct sof_ipc4_msg *msg = &cdata->msg;
    332         size_t data_size;
    333         int ret = 0;
    334 
    335         if (!scontrol->comp_data_dirty)
    336                 return 0;
    337 
    338         if (!pm_runtime_active(scomp->dev))
    339                 return 0;
    340 
    341         data_size = scontrol->max_size - sizeof(*data);
    342         if (data_size < sizeof(*msg_data))
    343                 data_size = sizeof(*msg_data);
    344 
    345         msg_data = kzalloc(data_size, GFP_KERNEL);
    346         if (!msg_data)
    347                 return -ENOMEM;
    348 
    349         msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
    350 
    351         msg_data->id = cdata->index;
    352         msg_data->num_elems = 0; /* ignored for bytes */
    353 
    354         msg->data_ptr = msg_data;
    355         msg->data_size = data_size;
    356 
    357         scontrol->comp_data_dirty = false;
    358         ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock);
    359         if (!ret) {
    360                 if (msg->data_size > scontrol->max_size - sizeof(*data)) {
    361                         dev_err(scomp->dev,
    362                                 "%s: no space for data in %s (%zu, %zu)\n",
    363                                 __func__, scontrol->name, msg->data_size,
    364                                 scontrol->max_size - sizeof(*data));

--> 365 goto out;

ret = -EINVAL;

    366                 }
    367 
    368                 data->size = msg->data_size;
    369                 scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size;
    370                 memcpy(data->data, msg->data_ptr, data->size);
    371         } else {
    372                 dev_err(scomp->dev, "Failed to read control data for %s\n",
    373                         scontrol->name);
    374                 scontrol->comp_data_dirty = true;
    375         }
    376 
    377 out:
    378         msg->data_ptr = NULL;
    379         msg->data_size = 0;
    380 
    381         kfree(msg_data);
    382 
    383         return ret;
    384 }

regards,
dan carpenter

#29 lore raw

[bug report] media: iris: gen1: Destroy internal buffers after FW releases

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Dikshita Agarwal,

Commit 1dabf00ee206 ("media: iris: gen1: Destroy internal buffers after FW releases") from Dec 29, 2025 (linux-next), leads to the following Smatch static checker warning:

drivers/media/platform/qcom/iris/iris_buffer.c:588 iris_release_internal_buffers()
error: dereferencing freed memory 'buffer' (line 585)

drivers/media/platform/qcom/iris/iris_buffer.c

    572 static int iris_release_internal_buffers(struct iris_inst *inst,
    573                                          enum iris_buffer_type buffer_type)
    574 {
    575         const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops;
    576         struct iris_buffers *buffers = &inst->buffers[buffer_type];
    577         struct iris_buffer *buffer, *next;
    578         int ret;
    579 
    580         list_for_each_entry_safe(buffer, next, &buffers->list, list) {
    581                 if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
    582                         continue;
    583                 if (!(buffer->attr & BUF_ATTR_QUEUED))
    584                         continue;
    585                 ret = hfi_ops->session_release_buf(inst, buffer);

The commit adds a free of buffer to ->session_release_buf().

586 if (ret)
587 return ret;

--> 588                 buffer->attr |= BUF_ATTR_PENDING_RELEASE;
                        ^^^^^^^^^^^^

Use after free.

    589         }
    590 
    591         return 0;
    592 }

regards,
dan carpenter

#30 lore raw

[bug report] cifs: Fix locking usage for tcon fields

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Shyam Prasad N,

Commit 91c866a6abb0 ("cifs: Fix locking usage for tcon fields") from Feb 1, 2026 (linux-next), leads to the following Smatch static checker warning:

	fs/smb/client/smb2ops.c:3179 smb2_get_dfs_refer()
	error: dereferencing freed memory 'tcon' (line 3178)

fs/smb/client/smb2ops.c

    3079 static int
    3080 smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
    3081                    const char *search_name,
    3082                    struct dfs_info3_param **target_nodes,
    3083                    unsigned int *num_of_nodes,
    3084                    const struct nls_table *nls_codepage, int remap)
    3085 {
    3086         int rc;
    3087         __le16 *utf16_path = NULL;
    3088         int utf16_path_len = 0;
    3089         struct cifs_tcon *tcon;
    3090         struct fsctl_get_dfs_referral_req *dfs_req = NULL;
    3091         struct get_dfs_referral_rsp *dfs_rsp = NULL;
    3092         u32 dfs_req_size = 0, dfs_rsp_size = 0;
    3093         int retry_once = 0;
    3094 
    3095         cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name);
    3096 
    3097         /*
    3098          * Try to use the IPC tcon, otherwise just use any
    3099          */
    3100         tcon = ses->tcon_ipc;
    3101         if (tcon == NULL) {
    3102                 spin_lock(&cifs_tcp_ses_lock);
    3103                 tcon = list_first_entry_or_null(&ses->tcon_list,
    3104                                                 struct cifs_tcon,
    3105                                                 tcon_list);
    3106                 if (tcon) {
    3107                         spin_lock(&tcon->tc_lock);
    3108                         tcon->tc_count++;
    3109                         spin_unlock(&tcon->tc_lock);
    3110                         trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
    3111                                             netfs_trace_tcon_ref_get_dfs_refer);
    3112                 }
    3113                 spin_unlock(&cifs_tcp_ses_lock);
    3114         }
    3115 
    3116         if (tcon == NULL) {
    3117                 cifs_dbg(VFS, "session %p has no tcon available for a dfs referral request\n",
    3118                          ses);
    3119                 rc = -ENOTCONN;
    3120                 goto out;
    3121         }
    3122 
    3123         utf16_path = cifs_strndup_to_utf16(search_name, PATH_MAX,
    3124                                            &utf16_path_len,
    3125                                            nls_codepage, remap);
    3126         if (!utf16_path) {
    3127                 rc = -ENOMEM;
    3128                 goto out;
    3129         }
    3130 
    3131         dfs_req_size = sizeof(*dfs_req) + utf16_path_len;
    3132         dfs_req = kzalloc(dfs_req_size, GFP_KERNEL);
    3133         if (!dfs_req) {
    3134                 rc = -ENOMEM;
    3135                 goto out;
    3136         }
    3137 
    3138         /* Highest DFS referral version understood */
    3139         dfs_req->MaxReferralLevel = DFS_VERSION;
    3140 
    3141         /* Path to resolve in an UTF-16 null-terminated string */
    3142         memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
    3143 
    3144         for (;;) {
    3145                 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
    3146                                 FSCTL_DFS_GET_REFERRALS,
    3147                                 (char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
    3148                                 (char **)&dfs_rsp, &dfs_rsp_size);
    3149                 if (fatal_signal_pending(current)) {
    3150                         rc = -EINTR;
    3151                         break;
    3152                 }
    3153                 if (!is_retryable_error(rc) || retry_once++)
    3154                         break;
    3155                 usleep_range(512, 2048);
    3156         }
    3157 
    3158         if (!rc && !dfs_rsp)
    3159                 rc = smb_EIO(smb_eio_trace_dfsref_no_rsp);
    3160         if (rc) {
    3161                 if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
    3162                         cifs_tcon_dbg(FYI, "%s: ioctl error: rc=%d\n", __func__, rc);
    3163                 goto out;
    3164         }
    3165 
    3166         rc = parse_dfs_referrals(dfs_rsp, dfs_rsp_size,
    3167                                  num_of_nodes, target_nodes,
    3168                                  nls_codepage, remap, search_name,
    3169                                  true /* is_unicode */);
    3170         if (rc && rc != -ENOENT) {
    3171                 cifs_tcon_dbg(VFS, "%s: failed to parse DFS referral %s: %d\n",
    3172                               __func__, search_name, rc);
    3173         }
    3174 
    3175  out:
    3176         if (tcon && !tcon->ipc) {
    3177                 /* ipc tcons are not refcounted */
    3178                 cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer);
                                       ^^^^

This free

--> 3179 trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,

                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

needs to happen after these dereferences.

    3180                                     netfs_trace_tcon_ref_dec_dfs_refer);
    3181         }
    3182         kfree(utf16_path);
    3183         kfree(dfs_req);
    3184         kfree(dfs_rsp);
    3185         return rc;
    3186 }

regards,
dan carpenter

#31 lore raw

[bug report] drm/xe: Avoid toggling schedule state to check LRC timestamp in TDR

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Matthew Brost,

Commit bb63e7257e63 ("drm/xe: Avoid toggling schedule state to check LRC timestamp in TDR") from Jan 9, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/gpu/drm/xe/xe_lrc.c:2450 xe_lrc_timestamp()
	error: uninitialized symbol 'new_ts'.

drivers/gpu/drm/xe/xe_lrc.c

    2421 u64 xe_lrc_timestamp(struct xe_lrc *lrc)
    2422 {
    2423         u64 lrc_ts, reg_ts, new_ts;
    2424         u32 engine_id;
    2425 
    2426         lrc_ts = xe_lrc_ctx_timestamp(lrc);
    2427         /* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */
    2428         if (IS_SRIOV_VF(lrc_to_xe(lrc))) {
    2429                 new_ts = lrc_ts;
    2430                 goto done;
    2431         }
    2432 
    2433         if (lrc_ts == CONTEXT_ACTIVE) {
    2434                 engine_id = xe_lrc_engine_id(lrc);
    2435                 if (!get_ctx_timestamp(lrc, engine_id, &reg_ts))
    2436                         new_ts = reg_ts;

Imagine lrc_ts is active but get_ctx_timestamp() returns -1.

    2437 
    2438                 /* read lrc again to ensure context is still active */
    2439                 lrc_ts = xe_lrc_ctx_timestamp(lrc);
    2440         }
    2441 
    2442         /*
    2443          * If context switched out, just use the lrc_ts. Note that this needs to
    2444          * be a separate if condition.
    2445          */
    2446         if (lrc_ts != CONTEXT_ACTIVE)
    2447                 new_ts = lrc_ts;
    2448 
    2449 done:

--> 2450 return new_ts;

Then new_ts could be uninitialized.

    2451 }

regards,
dan carpenter

#32 lore raw

[bug report] iio: dac: adding support for Microchip MCP47FEB02

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ariana Lazar,

Commit bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02") from Dec 16, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/dac/mcp47feb02.c:732 mcp47feb02_init_scales_avail()
	warn: passing zero to 'dev_err_probe'

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717 
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719 
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724 
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727 
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730 
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^

vref1_mV is not a valid error code. Return -EINVAL.

    733 
    734                 if (data->use_vref1)
    735                         tmp_vref = vref1_mV;
    736                 else
    737                         tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    738 
    739                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1,
    740                                       tmp_vref, data->scale_1);
    741                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2,
    742                                       tmp_vref * 2, data->scale_1);
    743         }
    744 
    745         return 0;
    746 }

regards,
dan carpenter

#33 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 11 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ariana Lazar,

Commit bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02") from Dec 16, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/dac/mcp47feb02.c:732 mcp47feb02_init_scales_avail()
	warn: passing zero to 'dev_err_probe'

Btw, why the bot mangles the patch, please?
Adding leading information (line number and some other markings) should not mangle the code (tab-based indentation).

Quoted 23 lines

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717 
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719 
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724 
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727 
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730 
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^
Quoted 1 line

vref1_mV is not a valid error code.

Why not? When it's negative I believe the above statement is not true.

Quoted 1 line

Return -EINVAL.

Probably true for the == 0 case.

With the above, this probably should be

Quoted 4 lines
    734                 if (data->use_vref1)
    735                         tmp_vref = vref1_mV;
    736                 else
    737                         tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
                 if (data->use_vref1) {
                         if (vref1_mV < 0)
                                  return dev_err_probe(dev, vref1_mV, "Can't get voltage for Vref1\n");
			 if (vref1_mV == 0)
                                  return dev_err_probe(dev, -ERANGE, "Invalid voltage for Vref1\n");
			 // or -EINVAL?
                         tmp_vref = vref1_mV;
		 } else {
                         tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
		 }
Quoted 8 lines
    739                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1,
    740                                       tmp_vref, data->scale_1);
    741                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2,
    742                                       tmp_vref * 2, data->scale_1);
    743         }
    744 
    745         return 0;
    746 }
Signature · 2 lines
With Best Regards,
Andy Shevchenko
#34 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 25 lines · Andy Shevchenko
Quoted 23 lines

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717 
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719 
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724 
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727 
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730 
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^
Quoted 1 line

vref1_mV is not a valid error code.

Quoted 2 lines

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input. vref1_mV is never actually negative. I don't know if devm_regulator_get_enable_read_voltage() can return less than one millivolt.

regards,
dan carpenter

#35 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 26 lines · Dan Carpenter
Quoted 25 lines · Andy Shevchenko
Quoted 24 lines

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717 
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719 
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724 
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727 
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730 
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^

vref1_mV is not a valid error code.

Quoted 5 lines
Quoted 1 line

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input. vref1_mV is never actually negative. I don't know if devm_regulator_get_enable_read_voltage() can return less than one millivolt.

* In cases where the supply is not strictly required, callers can check for
* -ENODEV error and handle it accordingly.
*
* Returns: voltage in microvolts on success, or an negative error number on failure.

What did I miss?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#36 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 33 lines · Andy Shevchenko
Quoted 26 lines · Dan Carpenter
Quoted 25 lines · Andy Shevchenko
Quoted 24 lines

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717 
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719 
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724 
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727 
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730 
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^

vref1_mV is not a valid error code.

Quoted 5 lines
Quoted 1 line

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input. vref1_mV is never actually negative. I don't know if devm_regulator_get_enable_read_voltage() can return less than one millivolt.

Quoted 7 lines

* In cases where the supply is not strictly required, callers can check for
* -ENODEV error and handle it accordingly.
*
* Returns: voltage in microvolts on success, or an negative error number on failure.

What did I miss?

drivers/iio/dac/mcp47feb02.c
1157 if (chip_features->have_ext_vref1) {
1158 ret = devm_regulator_get_enable_read_voltage(dev, "vref1");
1159 if (ret > 0) {
1160 vref1_mV = ret / MILLI;

Potentially, if ret is in the 1-999 range then vref1_mV could be zero, but it can't be negative.

  1161                          data->use_vref1 = true;
  1162                  } else {
  1163                          dev_dbg(dev, "using internal band gap as voltage reference 1.\n");
  1164                          dev_dbg(dev, "Vref1 is unavailable.\n");
  1165                  }
  1166          }
  1167  
  1168          ret = mcp47feb02_init_ctrl_regs(data);
  1169          if (ret)
  1170                  return dev_err_probe(dev, ret, "Error initialising vref register\n");
  1171  
  1172          ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV);
                                                                       ^^^^^^^^

1173 if (ret)
1174 return ret;

regards,
dan carpenter

#37 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 42 lines · Dan Carpenter
Quoted 33 lines · Andy Shevchenko
Quoted 26 lines · Dan Carpenter
Quoted 25 lines · Andy Shevchenko
Quoted 24 lines

drivers/iio/dac/mcp47feb02.c

    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale);
    726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale);
    727
    728         if (data->phys_channels >= 4) {
    729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730
    731                 if (data->use_vref1 && vref1_mV <= 0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");
                                                          ^^^^^^^^

vref1_mV is not a valid error code.

Quoted 5 lines
Quoted 1 line

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input. vref1_mV is never actually negative. I don't know if devm_regulator_get_enable_read_voltage() can return less than one millivolt.

Quoted 7 lines

* In cases where the supply is not strictly required, callers can check for
* -ENODEV error and handle it accordingly.
*
* Returns: voltage in microvolts on success, or an negative error number on failure.

What did I miss?

Quoted 8 lines

drivers/iio/dac/mcp47feb02.c
1157 if (chip_features->have_ext_vref1) {
1158 ret = devm_regulator_get_enable_read_voltage(dev, "vref1");
1159 if (ret > 0) {
1160 vref1_mV = ret / MILLI;

Potentially, if ret is in the 1-999 range then vref1_mV could be zero, but it can't be negative.

I see, thanks!

So, it means that the validation should be moved here on ret < 0 and ret < 1000 (if positive).

Quoted 4 lines
  1161                          data->use_vref1 = true;
  1162                  } else {
  1163                          dev_dbg(dev, "using internal band gap as voltage reference 1.\n");
  1164                          dev_dbg(dev, "Vref1 is unavailable.\n");

But... ret < 0 is checked here.
Hence the only one left is the range [0..999].

Quoted 12 lines
  1165                  }
  1166          }
  1167
  1168          ret = mcp47feb02_init_ctrl_regs(data);
  1169          if (ret)
  1170                  return dev_err_probe(dev, ret, "Error initialising vref register\n");
  1171
  1172          ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV);
                                                                       ^^^^^^^^

1173 if (ret)
1174 return ret;

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#38 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 103 lines · Andy Shevchenko

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

Quoted 66 lines · Dan Carpenter
Quoted 48 lines · Andy Shevchenko
Quoted 38 lines · Dan Carpenter
Quoted 36 lines · Andy Shevchenko
Quoted 35 lines

drivers/iio/dac/mcp47feb02.c
    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale); 726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale); 727
    728         if (data->phys_channels >= 4) { 729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730
    731                 if (data->use_vref1 && vref1_mV <=
0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");

^^^^^^^^
vref1_mV is not a valid error code.

Quoted 8 lines
Quoted 2 lines

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input.  vref1_mV is never
actually negative.  I don't know if devm_regulator_get_enable_read_voltage()
can return less than one millivolt.

Quoted 9 lines

 * In cases where the supply is not strictly required, callers can check for
 * -ENODEV error and handle it accordingly.
 *
 * Returns: voltage in microvolts on success, or an negative error number on failure.

What did I miss?

drivers/iio/dac/mcp47feb02.c
  1157          if (chip_features->have_ext_vref1) { 1158                  ret = devm_regulator_get_enable_read_voltage(dev, "vref1"); 1159                  if (ret > 0) {
  1160                          vref1_mV = ret / MILLI;

Quoted 3 lines

Potentially, if ret is in the 1-999 range then vref1_mV could be zero,
but it can't be negative.

I see, thanks!

So, it means that the validation should be moved here on ret < 0 and ret < 1000 (if positive).

Quoted 6 lines

  1161                          data->use_vref1 = true; 1162                  } else {
  1163                          dev_dbg(dev, "using internal band gap as voltage reference 1.\n");
  1164                          dev_dbg(dev, "Vref1 is unavailable.\n");

But... ret < 0  is checked here.
Hence the only one left is the range [0..999].

Quoted 13 lines

  1165                  }
  1166          }
  1167
  1168          ret = mcp47feb02_init_ctrl_regs(data); 1169          if (ret)
  1170                  return dev_err_probe(dev, ret, "Error initialising vref register\n");
  1171
  1172          ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV);

    ^^^^^^^^

Quoted 7 lines
Quoted 2 lines

  1173          if (ret)
  1174                  return ret;

--
With Best Regards,
Andy Shevchenko

Hello Dan and Andy,

Thank you for bringing to my attention this bug. I fixed it by storing voltages
in microvolts instead of millivolts in order to avoid the [1, 999] case.
I removed dividing by MILLI from the probe function and kept the computation of
the scale values only in init_scale function.

I will send a follow on patch.

Best regards,
Ariana

maintainer
#39 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 123 lines · On Tue, 10 Feb 2026 10:26:05 +0000 <[email protected]> wrote:
Quoted 103 lines · Andy Shevchenko

EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe

Quoted 66 lines · Dan Carpenter
Quoted 48 lines · Andy Shevchenko
Quoted 38 lines · Dan Carpenter
Quoted 36 lines · Andy Shevchenko
Quoted 35 lines

drivers/iio/dac/mcp47feb02.c
    712 static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV,
    713                                         int vref_mV, int vref1_mV)
    714 {
    715         struct device *dev = regmap_get_device(data->regmap);
    716         int tmp_vref;
    717
    718         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale);
    719
    720         if (data->use_vref)
    721                 tmp_vref = vref_mV;
    722         else
    723                 tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV;
    724
    725         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale); 726         mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale); 727
    728         if (data->phys_channels >= 4) { 729                 mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1);
    730
    731                 if (data->use_vref1 && vref1_mV <=
0)
--> 732                         return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n");

^^^^^^^^
vref1_mV is not a valid error code.

Quoted 8 lines
Quoted 2 lines

Why not? When it's negative I believe the above statement is not true.

I saw this as just sanity checking the input.  vref1_mV is never
actually negative.  I don't know if devm_regulator_get_enable_read_voltage()
can return less than one millivolt.

Quoted 9 lines

 * In cases where the supply is not strictly required, callers can check for
 * -ENODEV error and handle it accordingly.
 *
 * Returns: voltage in microvolts on success, or an negative error number on failure.

What did I miss?

drivers/iio/dac/mcp47feb02.c
  1157          if (chip_features->have_ext_vref1) { 1158                  ret = devm_regulator_get_enable_read_voltage(dev, "vref1"); 1159                  if (ret > 0) {
  1160                          vref1_mV = ret / MILLI;

Quoted 3 lines

Potentially, if ret is in the 1-999 range then vref1_mV could be zero,
but it can't be negative.

I see, thanks!

So, it means that the validation should be moved here on ret < 0 and ret < 1000 (if positive).

Quoted 6 lines

  1161                          data->use_vref1 = true; 1162                  } else {
  1163                          dev_dbg(dev, "using internal band gap as voltage reference 1.\n");
  1164                          dev_dbg(dev, "Vref1 is unavailable.\n");

But... ret < 0  is checked here.
Hence the only one left is the range [0..999].

Quoted 13 lines

  1165                  }
  1166          }
  1167
  1168          ret = mcp47feb02_init_ctrl_regs(data); 1169          if (ret)
  1170                  return dev_err_probe(dev, ret, "Error initialising vref register\n");
  1171
  1172          ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV);

    ^^^^^^^^

Quoted 7 lines
Quoted 2 lines

  1173          if (ret)
  1174                  return ret;

--
With Best Regards,
Andy Shevchenko

Hello Dan and Andy,

Thank you for bringing to my attention this bug. I fixed it by storing voltages
in microvolts instead of millivolts in order to avoid the [1, 999] case.
I removed dividing by MILLI from the probe function and kept the computation of
the scale values only in init_scale function.

Quoted 1 line

I will send a follow on patch.

Hi Ariana,

Just a reminder that this one still seems to be outstanding. Maybe I missed a patch?

Thanks,

Jonathan

Quoted 4 lines

Best regards,
Ariana

#40 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 13 lines

Just a reminder that this one still seems to be outstanding. Maybe I missed a patch?

Thanks,

Jonathan

Quoted 4 lines

Best regards,
Ariana

Hi Jonathan,

Given the latest reviews, I was wondering how do you prefer the next patch to be sent. At the moment I am working on the version with three modules in order to include both protocol families. If you prefer, I will firstly send a patch to fix these bugs for MCP47FEB02 and then I will send another one with the combined implementation.

Best regards,
Ariana

maintainer
#41 lore raw

Re: [bug report] iio: dac: adding support for Microchip MCP47FEB02

Quoted 13 lines · On Mon, 2 Mar 2026 10:28:04 +0000 <[email protected]> wrote:
Quoted 12 lines

Just a reminder that this one still seems to be outstanding. Maybe I missed a patch?

Thanks,

Jonathan

Quoted 4 lines

Best regards,
Ariana

Quoted 7 lines

Hi Jonathan,

Given the latest reviews, I was wondering how do you prefer the next patch to be sent. At the moment I am working on the version with three modules in order to include both protocol families. If you prefer, I will firstly send a patch to fix these bugs for MCP47FEB02 and then I will send another one with the combined implementation.

That last option sounds like the right approach. The fix will need to go upstream first, then once that's available in upstream I can merge into the togreg branch and apply new stuff on top of it.

Thanks,

Jonathan

Quoted 3 lines

Best regards,
Ariana

#42 lore raw

[bug report] power: sequencing: qcom-wcn: add support for WCN39xx

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Dmitry Baryshkov,

Commit 0eb85f468ef5 ("power: sequencing: qcom-wcn: add support for WCN39xx") from Jan 6, 2026 (linux-next), leads to the following Smatch static checker warning:

drivers/power/sequencing/pwrseq-qcom-wcn.c:492 pwrseq_qcom_wcn_probe()
warn: passing zero to 'dev_err_probe'

drivers/power/sequencing/pwrseq-qcom-wcn.c

    458 static int pwrseq_qcom_wcn_probe(struct platform_device *pdev)
    459 {
    460         struct device *dev = &pdev->dev;
    461         struct pwrseq_qcom_wcn_ctx *ctx;
    462         struct pwrseq_config config;
    463         int i, ret;
    464 
    465         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
    466         if (!ctx)
    467                 return -ENOMEM;
    468 
    469         ctx->of_node = dev->of_node;
    470 
    471         ctx->pdata = device_get_match_data(dev);
    472         if (!ctx->pdata)
    473                 return dev_err_probe(dev, -ENODEV,
    474                                      "Failed to obtain platform data\n");
    475 
    476         ctx->regs = devm_kcalloc(dev, ctx->pdata->num_vregs,
    477                                  sizeof(*ctx->regs), GFP_KERNEL);
    478         if (!ctx->regs)
    479                 return -ENOMEM;
    480 
    481         for (i = 0; i < ctx->pdata->num_vregs; i++)
    482                 ctx->regs[i].supply = ctx->pdata->vregs[i];
    483 
    484         ret = devm_regulator_bulk_get(dev, ctx->pdata->num_vregs, ctx->regs);
    485         if (ret < 0)
    486                 return dev_err_probe(dev, ret,
    487                                      "Failed to get all regulators\n");
    488 
    489         if (ctx->pdata->has_vddio) {
    490                 ctx->vddio = devm_regulator_get(dev, "vddio");
    491                 if (IS_ERR(ctx->vddio))

--> 492 return dev_err_probe(dev, ret, "Failed to get VDDIO\n");

s/ret/PTR_ERR(ctx->vddio)/

    493         }
    494 
    495         ctx->bt_gpio = devm_gpiod_get_optional(dev, "bt-enable", GPIOD_OUT_LOW);
    496         if (IS_ERR(ctx->bt_gpio))
    497                 return dev_err_probe(dev, PTR_ERR(ctx->bt_gpio),
    498                                      "Failed to get the Bluetooth enable GPIO\n");
    499 
    500         /*

regards,
dan carpenter

#43 lore raw

[bug report] io_uring: add task fork hook

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jens Axboe,

Commit 4f08520591a2 ("io_uring: add task fork hook") from Jan 16, 2026 (linux-next), leads to the following Smatch static checker warning:

	kernel/fork.c:2544 copy_process()
	warn: passing zero to 'ERR_PTR'

kernel/fork.c
2128 #ifdef CONFIG_IO_URING
2129 p->io_uring = NULL;
2130 retval = io_uring_fork(p);

The patch added this assignment.

  2131          if (unlikely(retval))
  2132                  goto bad_fork_cleanup_delayacct;
  2133  #endif
  2134  
  2135          p->default_timer_slack_ns = current->timer_slack_ns;
  2136  
  2137  #ifdef CONFIG_PSI
  2138          p->psi_flags = 0;
  2139  #endif
  2140  
  2141          task_io_accounting_init(&p->ioac);
  2142          acct_clear_integrals(p);
  2143  
  2144          posix_cputimers_init(&p->posix_cputimers);
  2145          tick_dep_init_task(p);
  2146  
  2147          p->io_context = NULL;
  2148          audit_set_context(p, NULL);
  2149          cgroup_fork(p);
  2150          if (args->kthread) {
  2151                  if (!set_kthread_struct(p))
  2152                          goto bad_fork_cleanup_delayacct;

So now retval is success where previously it had been -EAGAIN

2153 }

regards,
dan carpenter

maintainer
#44 lore raw

Re: [bug report] io_uring: add task fork hook

Quoted 42 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jens Axboe,

Commit 4f08520591a2 ("io_uring: add task fork hook") from Jan 16, 2026 (linux-next), leads to the following Smatch static checker warning:

	kernel/fork.c:2544 copy_process()
	warn: passing zero to 'ERR_PTR'

kernel/fork.c
2128 #ifdef CONFIG_IO_URING
2129 p->io_uring = NULL;
2130 retval = io_uring_fork(p);

The patch added this assignment.

  2131          if (unlikely(retval))
  2132                  goto bad_fork_cleanup_delayacct;
  2133  #endif
  2134  
  2135          p->default_timer_slack_ns = current->timer_slack_ns;
  2136  
  2137  #ifdef CONFIG_PSI
  2138          p->psi_flags = 0;
  2139  #endif
  2140  
  2141          task_io_accounting_init(&p->ioac);
  2142          acct_clear_integrals(p);
  2143  
  2144          posix_cputimers_init(&p->posix_cputimers);
  2145          tick_dep_init_task(p);
  2146  
  2147          p->io_context = NULL;
  2148          audit_set_context(p, NULL);
  2149          cgroup_fork(p);
  2150          if (args->kthread) {
  2151                  if (!set_kthread_struct(p))
  2152                          goto bad_fork_cleanup_delayacct;
Quoted 3 lines

So now retval is success where previously it had been -EAGAIN

2153 }

Thanks, fixed up.

Signature · 1 line
Jens Axboe
#45 lore raw

[bug report] ACPI: battery: Adjust event notification routine

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Rafael J. Wysocki,

This is a semi-automatic email about new static checker warnings.

Commit 08b54fd57782 ("ACPI: battery: Adjust event notification routine") from Dec 15, 2025, leads to the following Smatch complaint:

drivers/acpi/battery.c:1062 acpi_battery_notify()
warn: variable dereferenced before check 'battery' (see line 1059)

drivers/acpi/battery.c
1058 struct acpi_battery *battery = data;

  1059		struct acpi_device *device = battery->device;
                                             ^^^^^^^^^^^^^^^

The patch adds a dereference.

1060 struct power_supply *old;
1061
1062 if (!battery)

                    ^^^^^^^^

Checked too late.

1063 return;
1064

regards,
dan carpenter

#46 lore raw

PATCH 1/1 ACPI: battery: Drop redundant check from acpi_battery_notify()

Quoted 20 lines · CET Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Rafael J. Wysocki,

This is a semi-automatic email about new static checker warnings.

Commit 08b54fd57782 ("ACPI: battery: Adjust event notification routine") from Dec 15, 2025, leads to the following Smatch complaint:

drivers/acpi/battery.c:1062 acpi_battery_notify()
warn: variable dereferenced before check 'battery' (see line 1059)

drivers/acpi/battery.c
1058 struct acpi_battery *battery = data;

  1059		struct acpi_device *device = battery->device;
                                             ^^^^^^^^^^^^^^^

The patch adds a dereference.

Quoted 8 lines

1060 struct power_supply *old;
1061
1062 if (!battery)

                    ^^^^^^^^

Checked too late.

1063 return;
1064

Thanks for the report, but the check above is redundant.

For the reason explained in the changelog of the patch below, the battery pointer above cannot be NULL.

---
From: Rafael J. Wysocki <[email protected]>
Subject: [PATCH v1] ACPI: battery: Drop redundant check from acpi_battery_notify()

The battery pointer check against NULL in acpi_battery_notify() is redundant because the value of that pointer is the one passed to acpi_dev_install_notify_handler() in acpi_battery_probe() as the last argument which is not NULL.

Drop the redundant check.

No intentional functional impact.

---
 drivers/acpi/battery.c |    3 ---
 1 file changed, 3 deletions(-)
drivers/acpi/battery.c +0 -3
@@ -1066,9 +1066,6 @@ static void acpi_battery_notify(acpi_han
 	struct acpi_device *device = battery->device;
 	struct power_supply *old;
 
-	if (!battery)
-		return;
-
 	guard(mutex)(&battery->update_lock);
 
 	old = battery->bat;
#47 lore raw

[bug report] iio: adc: Add support for ad4062

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jorge Marques,

Commit d5284402d28f ("iio: adc: Add support for ad4062") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/adc/ad4062.c:1557 ad4062_probe()
	warn: passing positive error code 's32min-(-1),1-3' to 'dev_err_probe'

drivers/iio/adc/ad4062.c

    1547         pm_runtime_set_active(dev);
    1548         ret = devm_pm_runtime_enable(dev);
    1549         if (ret)
    1550                 return dev_err_probe(dev, ret, "Failed to enable pm_runtime\n");
    1551 
    1552         pm_runtime_set_autosuspend_delay(dev, 1000);
    1553         pm_runtime_use_autosuspend(dev);
    1554 
    1555         ret = ad4062_request_ibi(i3cdev);
    1556         if (ret)

--> 1557 return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");

The comments for ad4062_request_ibi() say it returns negative error codes but the comments for i3c_master_enec_locked() say it returns "a positive I3C error code if the error is one of the official Mx error codes, and a negative error code otherwise."

    1558 
    1559         ret = ad4062_gpio_init(st);
    1560         if (ret)
    1561                 return ret;
    1562 
    1563         ret = devm_work_autocancel(dev, &st->trig_conv, ad4062_trigger_work);
    1564         if (ret)
    1565                 return ret;
    1566 
    1567         return devm_iio_device_register(dev, indio_dev);
    1568 }

regards,
dan carpenter

#48 lore raw

Re: [bug report] iio: adc: Add support for ad4062

Quoted 2 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Oh, this is indeed sad. Wondering if LF can donate...

Quoted 9 lines

Commit d5284402d28f ("iio: adc: Add support for ad4062") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/adc/ad4062.c:1557 ad4062_probe()
	warn: passing positive error code 's32min-(-1),1-3' to 'dev_err_probe'

    1555         ret = ad4062_request_ibi(i3cdev);
    1556         if (ret)
	if (ret < 0)

resolves immediate isssue, but...

Quoted 6 lines

--> 1557 return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");

The comments for ad4062_request_ibi() say it returns negative error codes but the comments for i3c_master_enec_locked() say it returns "a positive I3C error code if the error is one of the official Mx error codes, and a negative error code otherwise."

...would be nice to have a conversion helper to get Linux error codes from the Mx ones.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#49 lore raw

Re: [bug report] iio: adc: Add support for ad4062

Quoted 22 lines · On Fri, 6 Feb 2026 16:07:36 +0200 Andy Shevchenko…
Quoted 2 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Oh, this is indeed sad. Wondering if LF can donate...

Quoted 9 lines

Commit d5284402d28f ("iio: adc: Add support for ad4062") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/adc/ad4062.c:1557 ad4062_probe()
	warn: passing positive error code 's32min-(-1),1-3' to 'dev_err_probe'  

    1555         ret = ad4062_request_ibi(i3cdev);
    1556         if (ret)  
	if (ret < 0)

resolves immediate isssue, but...

Quoted 2 lines

--> 1557 return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");

Quoted 8 lines
Quoted 4 lines

The comments for ad4062_request_ibi() say it returns negative error codes but the comments for i3c_master_enec_locked() say it returns "a positive I3C error code if the error is one of the official Mx error codes, and a negative error code otherwise."

...would be nice to have a conversion helper to get Linux error codes from the Mx ones.

@Jorge, can you take a look at this please and ideally send a fix.

Thanks,

Jonathan

#50 lore raw

Re: [bug report] iio: adc: Add support for ad4062

Quoted 30 lines · Jonathan Cameron
Quoted 27 lines · On Fri, 6 Feb 2026 16:07:36 +0200 Andy Shevchenko…
Quoted 2 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Oh, this is indeed sad. Wondering if LF can donate...

Quoted 9 lines

Commit d5284402d28f ("iio: adc: Add support for ad4062") from Dec 17, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/iio/adc/ad4062.c:1557 ad4062_probe()
	warn: passing positive error code 's32min-(-1),1-3' to 'dev_err_probe'  

    1555         ret = ad4062_request_ibi(i3cdev);
    1556         if (ret)  
	if (ret < 0)

resolves immediate isssue, but...

Quoted 6 lines

--> 1557 return dev_err_probe(dev, ret, "Failed to request i3c ibi\n");

The comments for ad4062_request_ibi() say it returns negative error codes but the comments for i3c_master_enec_locked() say it returns "a positive I3C error code if the error is one of the official Mx error codes, and a negative error code otherwise."

Quoted 5 lines
Quoted 3 lines

...would be nice to have a conversion helper to get Linux error codes from the Mx ones.

@Jorge, can you take a look at this please and ideally send a fix.

Hi Andy, Jonathan,

I found nine paths that returned positive Mx error codes when 0 or negative was expected.

i3c/device.h suggests returning -EIO. The error codes range from M0 to M2; only M2 is suppressed during [RST|ENT]DAA (means "no active device on the bus"), which is already done internally but duplicated.

I will submit the changes to the i3c subsystem after CI/CD and hardware tests are run to make sure, since many paths are involved.

Note that the immediate fix is not valid, if a Mx code was returned as is, we would like to return an error still, since that would mean the target device did not acknowledge the enable target events (instead we would convert to -EIO).

Thanks,
Jorge

Quoted 4 lines

Thanks,

Jonathan

#51 lore raw

[bug report] ext4: refactor zeroout path and handle all cases

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ojaswin Mujoo,

Commit a985e07c2645 ("ext4: refactor zeroout path and handle all cases") from Jan 23, 2026 (linux-next), leads to the following Smatch static checker warning:

	fs/ext4/extents.c:3369 ext4_split_extent_zeroout()
	warn: duplicate zero check 'err' (previous on line 3363)

fs/ext4/extents.c

    3361 
    3362         err = ext4_ext_get_access(handle, inode, path + depth);
    3363         if (err)
    3364                 return err;
    3365 
    3366         ext4_ext_mark_initialized(ex);
    3367 
    3368         ext4_ext_dirty(handle, inode, path + depth);

Presumably "err = ext4_ext_dirty()".

--> 3369 if (err)

    3370                 return err;
    3371 
    3372         return 0;
    3373 }

regards,
dan carpenter

#52 lore raw

Re: [bug report] ext4: refactor zeroout path and handle all cases

Quoted 24 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ojaswin Mujoo,

Commit a985e07c2645 ("ext4: refactor zeroout path and handle all cases") from Jan 23, 2026 (linux-next), leads to the following Smatch static checker warning:

	fs/ext4/extents.c:3369 ext4_split_extent_zeroout()
	warn: duplicate zero check 'err' (previous on line 3363)

fs/ext4/extents.c

    3361 
    3362         err = ext4_ext_get_access(handle, inode, path + depth);
    3363         if (err)
    3364                 return err;
    3365 
    3366         ext4_ext_mark_initialized(ex);
    3367 
    3368         ext4_ext_dirty(handle, inode, path + depth);

Presumably "err = ext4_ext_dirty()".

Quoted 8 lines

--> 3369 if (err)

    3370                 return err;
    3371 
    3372         return 0;
    3373 }

regards,
dan carpenter

Hi dan,

Thanks for the report, I'll send a patch for this.

Many thanks for all the work you do and hope you are able to work out a way to carry the smatch project forward!

Regards,
ojaswin

#53 lore raw

[bug report] media: chips-media: wave5: Fix Null reference while testing fluster

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jackson Lee,

Commit e66ff2b08e4e ("media: chips-media: wave5: Fix Null reference while testing fluster") from Nov 19, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/media/platform/chips-media/wave5/wave5-vpu.c:415 wave5_vpu_probe()
	error: 'dev->irq_thread' dereferencing possible ERR_PTR()

drivers/media/platform/chips-media/wave5/wave5-vpu.c

    261 static int wave5_vpu_probe(struct platform_device *pdev)
    262 {
    263         int ret;
    264         struct vpu_device *dev;
    265         const struct wave5_match_data *match_data;
    266         u32 fw_revision;
    267 
    268         match_data = device_get_match_data(&pdev->dev);
    269         if (!match_data) {
    270                 dev_err(&pdev->dev, "missing device match data\n");
    271                 return -EINVAL;
    272         }
    273 
    274         /* physical addresses limited to 32 bits */
    275         ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
    276         if (ret) {
    277                 dev_err(&pdev->dev, "Failed to set DMA mask: %d\n", ret);
    278                 return ret;
    279         }
    280 
    281         dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
    282         if (!dev)
    283                 return -ENOMEM;
    284 
    285         dev->vdb_register = devm_platform_ioremap_resource(pdev, 0);
    286         if (IS_ERR(dev->vdb_register))
    287                 return PTR_ERR(dev->vdb_register);
    288         ida_init(&dev->inst_ida);
    289 
    290         mutex_init(&dev->dev_lock);
    291         mutex_init(&dev->hw_lock);
    292         mutex_init(&dev->irq_lock);
    293         spin_lock_init(&dev->irq_spinlock);
    294         dev_set_drvdata(&pdev->dev, dev);
    295         dev->dev = &pdev->dev;
    296 
    297         dev->resets = devm_reset_control_array_get_optional_exclusive(&pdev->dev);
    298         if (IS_ERR(dev->resets)) {
    299                 return dev_err_probe(&pdev->dev, PTR_ERR(dev->resets),
    300                                      "Failed to get reset control\n");
    301         }
    302 
    303         ret = reset_control_deassert(dev->resets);
    304         if (ret)
    305                 return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n");
    306 
    307         ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
    308 
    309         /* continue without clock, assume externally managed */
    310         if (ret < 0) {
    311                 dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret);
    312                 ret = 0;
    313         }
    314         dev->num_clks = ret;
    315 
    316         ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
    317         if (ret) {
    318                 dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
    319                 goto err_reset_assert;
    320         }
    321 
    322         dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
    323         if (!dev->sram_pool)
    324                 dev_warn(&pdev->dev, "sram node not found\n");
    325 
    326         dev->sram_size = match_data->sram_size;
    327 
    328         dev->product_code = wave5_vdi_read_register(dev, VPU_PRODUCT_CODE_REGISTER);
    329         ret = wave5_vdi_init(&pdev->dev);
    330         if (ret < 0) {
    331                 dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret);
    332                 goto err_clk_dis;
    333         }
    334         dev->product = wave5_vpu_get_product_id(dev);
    335 
    336         INIT_LIST_HEAD(&dev->instances);
    337 
    338         dev->irq = platform_get_irq(pdev, 0);
    339         if (dev->irq < 0) {
    340                 dev_err(&pdev->dev, "failed to get irq resource, falling back to polling\n");
    341                 sema_init(&dev->irq_sem, 1);
    342                 dev->irq_thread = kthread_run(irq_thread, dev, "irq thread");

Add error checking for if kthread_run() fails?

    343                 hrtimer_setup(&dev->hrtimer, &wave5_vpu_timer_callback, CLOCK_MONOTONIC,
    344                               HRTIMER_MODE_REL_PINNED);
    345                 dev->worker = kthread_run_worker(0, "vpu_irq_thread");
    346                 if (IS_ERR(dev->worker)) {
    347                         dev_err(&pdev->dev, "failed to create vpu irq worker\n");
    348                         ret = PTR_ERR(dev->worker);
    349                         goto err_vdi_release;
    350                 }
    351                 dev->vpu_poll_interval = vpu_poll_interval;
    352                 kthread_init_work(&dev->work, wave5_vpu_irq_work_fn);
    353         } else {
    354                 ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave5_vpu_irq,
    355                                                 wave5_vpu_irq_thread, IRQF_ONESHOT, "vpu_irq", dev);
    356                 if (ret) {
    357                         dev_err(&pdev->dev, "Register interrupt handler, fail: %d\n", ret);
    358                         goto err_enc_unreg;
    359                 }
    360         }
    361 
    362         ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
    363         if (ret) {
    364                 dev_err(&pdev->dev, "v4l2_device_register, fail: %d\n", ret);
    365                 goto err_irq_release;
    366         }
    367 
    368         if (match_data->flags & WAVE5_IS_DEC) {
    369                 ret = wave5_vpu_dec_register_device(dev);
    370                 if (ret) {
    371                         dev_err(&pdev->dev, "wave5_vpu_dec_register_device, fail: %d\n", ret);
    372                         goto err_v4l2_unregister;
    373                 }
    374         }
    375         if (match_data->flags & WAVE5_IS_ENC) {
    376                 ret = wave5_vpu_enc_register_device(dev);
    377                 if (ret) {
    378                         dev_err(&pdev->dev, "wave5_vpu_enc_register_device, fail: %d\n", ret);
    379                         goto err_dec_unreg;
    380                 }
    381         }
    382 
    383         ret = wave5_vpu_load_firmware(&pdev->dev, match_data->fw_name, &fw_revision);
    384         if (ret) {
    385                 dev_err(&pdev->dev, "wave5_vpu_load_firmware, fail: %d\n", ret);
    386                 goto err_enc_unreg;
    387         }
    388 
    389         dev_info(&pdev->dev, "Added wave5 driver with caps: %s %s\n",
    390                  (match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "",
    391                  (match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "");
    392         dev_info(&pdev->dev, "Product Code:      0x%x\n", dev->product_code);
    393         dev_info(&pdev->dev, "Firmware Revision: %u\n", fw_revision);
    394 
    395         pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
    396         pm_runtime_use_autosuspend(&pdev->dev);
    397         pm_runtime_enable(&pdev->dev);
    398         wave5_vpu_sleep_wake(&pdev->dev, true, NULL, 0);
    399 
    400         return 0;
    401 
    402 err_enc_unreg:
    403         if (match_data->flags & WAVE5_IS_ENC)
    404                 wave5_vpu_enc_unregister_device(dev);
    405 err_dec_unreg:
    406         if (match_data->flags & WAVE5_IS_DEC)
    407                 wave5_vpu_dec_unregister_device(dev);
    408 err_v4l2_unregister:
    409         v4l2_device_unregister(&dev->v4l2_dev);
    410 err_irq_release:
    411         if (dev->irq < 0)
    412                 kthread_destroy_worker(dev->worker);
    413 err_vdi_release:
    414         if (dev->irq_thread) {
--> 415                 kthread_stop(dev->irq_thread);
    416                 up(&dev->irq_sem);
    417                 dev->irq_thread = NULL;
    418         }
    419         wave5_vdi_release(&pdev->dev);
    420 err_clk_dis:
    421         clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
    422 err_reset_assert:
    423         reset_control_assert(dev->resets);
    424 
    425         return ret;
    426 }

regards,
dan carpenter

#54 lore raw

RE: [bug report] media: chips-media: wave5: Fix Null reference while testing fluster

Hi, Dan.

Quoted 41 lines

-----Original Message-----
From: Dan Carpenter <[email protected]>
Sent: Friday, February 6, 2026 10:41 PM
To: jackson.lee <[email protected]>
Cc: [email protected]; linux-kernel <linux- [email protected]>
Subject: [bug report] media: chips-media: wave5: Fix Null reference while testing fluster

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jackson Lee,

Commit e66ff2b08e4e ("media: chips-media: wave5: Fix Null reference while testing fluster") from Nov 19, 2025 (linux-next), leads to the following Smatch static checker warning:

drivers/media/platform/chips-media/wave5/wave5-vpu.c:415
wave5_vpu_probe()

	error: 'dev->irq_thread' dereferencing possible ERR_PTR()

drivers/media/platform/chips-media/wave5/wave5-vpu.c
327
328 dev->product_code = wave5_vdi_read_register(dev,

VPU_PRODUCT_CODE_REGISTER);
   329         ret = wave5_vdi_init(&pdev->dev);
   330         if (ret < 0) {
   331                 dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret);
   332                 goto err_clk_dis;
   333         }
   334         dev->product = wave5_vpu_get_product_id(dev);
   335
   336         INIT_LIST_HEAD(&dev->instances);
   337
   338         dev->irq = platform_get_irq(pdev, 0);
   339         if (dev->irq < 0) {
   340                 dev_err(&pdev->dev, "failed to get irq resource, falling
back to polling\n");
   341                 sema_init(&dev->irq_sem, 1);
   342                 dev->irq_thread = kthread_run(irq_thread, dev, "irq
Quoted 3 lines

thread");

Add error checking for if kthread_run() fails?

Thanks for the report.

A fix has been proposed by Alper Ak in a separate thread:
https://lore.kernel.org/all/[email protected]/
I'm going to check it and run tests on my side.

Thanks.
Nas.

Quoted 7 lines
   343                 hrtimer_setup(&dev->hrtimer, &wave5_vpu_timer_callback,

CLOCK_MONOTONIC,
344 HRTIMER_MODE_REL_PINNED);

regards,
dan carpenter

#55 lore raw

[bug report] phy: apple: Add Apple Type-C PHY

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Sven Peter,

Commit 8e98ca1e74db ("phy: apple: Add Apple Type-C PHY") from Dec 14, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/apple/atc.c:2209 atcphy_map_resources()
	warn: 'resources[i]->addr' isn't an ERR_PTR

drivers/phy/apple/atc.c

    2191 static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcphy *atcphy)
    2192 {
    2193         struct {
    2194                 const char *name;
    2195                 void __iomem **addr;
    2196                 struct resource **res;
    2197         } resources[] = {
    2198                 { "core", &atcphy->regs.core, &atcphy->res.core },
    2199                 { "lpdptx", &atcphy->regs.lpdptx, NULL },
    2200                 { "axi2af", &atcphy->regs.axi2af, &atcphy->res.axi2af },
    2201                 { "usb2phy", &atcphy->regs.usb2phy, NULL },
    2202                 { "pipehandler", &atcphy->regs.pipehandler, NULL },
    2203         };
    2204         struct resource *res;
    2205 
    2206         for (int i = 0; i < ARRAY_SIZE(resources); i++) {
    2207                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name);
    2208                 *resources[i].addr = devm_ioremap_resource(&pdev->dev, res);

--> 2209 if (IS_ERR(resources[i].addr))

This is checking the wrong variable. The * is missing. if (IS_ERR(*resources[i].addr)) {

    2210                         return dev_err_probe(atcphy->dev, PTR_ERR(resources[i].addr),
    2211                                              "Unable to map %s regs", resources[i].name);
    2212 
    2213                 if (resources[i].res)
    2214                         *resources[i].res = res;
    2215         }
    2216 
    2217         return 0;
    2218 }

regards,
dan carpenter

#56 lore raw

Re: [bug report] phy: apple: Add Apple Type-C PHY

Quoted 2 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

This is unfortunate, there have been useful bug reports.

Quoted 26 lines

Commit 8e98ca1e74db ("phy: apple: Add Apple Type-C PHY") from Dec 14, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/apple/atc.c:2209 atcphy_map_resources()
	warn: 'resources[i]->addr' isn't an ERR_PTR

drivers/phy/apple/atc.c

    2191 static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcphy *atcphy)
    2192 {
    2193         struct {
    2194                 const char *name;
    2195                 void __iomem **addr;
    2196                 struct resource **res;
    2197         } resources[] = {
    2198                 { "core", &atcphy->regs.core, &atcphy->res.core },
    2199                 { "lpdptx", &atcphy->regs.lpdptx, NULL },
    2200                 { "axi2af", &atcphy->regs.axi2af, &atcphy->res.axi2af },
    2201                 { "usb2phy", &atcphy->regs.usb2phy, NULL },
    2202                 { "pipehandler", &atcphy->regs.pipehandler, NULL },
    2203         };
    2204         struct resource *res;
    2205 
    2206         for (int i = 0; i < ARRAY_SIZE(resources); i++) {
    2207                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name);
    2208                 *resources[i].addr = devm_ioremap_resource(&pdev->dev, res);
Quoted 4 lines

--> 2209 if (IS_ERR(resources[i].addr))

This is checking the wrong variable. The * is missing. if (IS_ERR(*resources[i].addr)) {

This issue was identified by testing and is fixed in next by commit 7d55b44e2be1 ("phy: apple: atc: Actually check return value of devm_apple_tunable_parse").

https://lore.kernel.org/all/[email protected]/

Thanks for the report

Janne

#57 lore raw

Re: [bug report] phy: apple: Add Apple Type-C PHY

Quoted 34 lines · Janne Grunau
Quoted 2 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

This is unfortunate, there have been useful bug reports.

Quoted 28 lines

Commit 8e98ca1e74db ("phy: apple: Add Apple Type-C PHY") from Dec 14, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/phy/apple/atc.c:2209 atcphy_map_resources()
	warn: 'resources[i]->addr' isn't an ERR_PTR

drivers/phy/apple/atc.c

     2191 static int atcphy_map_resources(struct platform_device *pdev, struct apple_atcphy *atcphy)
     2192 {
     2193         struct {
     2194                 const char *name;
     2195                 void __iomem **addr;
     2196                 struct resource **res;
     2197         } resources[] = {
     2198                 { "core", &atcphy->regs.core, &atcphy->res.core },
     2199                 { "lpdptx", &atcphy->regs.lpdptx, NULL },
     2200                 { "axi2af", &atcphy->regs.axi2af, &atcphy->res.axi2af },
     2201                 { "usb2phy", &atcphy->regs.usb2phy, NULL },
     2202                 { "pipehandler", &atcphy->regs.pipehandler, NULL },
     2203         };
     2204         struct resource *res;
     2205
     2206         for (int i = 0; i < ARRAY_SIZE(resources); i++) {
     2207                 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resources[i].name);
     2208                 *resources[i].addr = devm_ioremap_resource(&pdev->dev, res);

--> 2209 if (IS_ERR(resources[i].addr))

Quoted 8 lines
Quoted 2 lines

This is checking the wrong variable. The * is missing. if (IS_ERR(*resources[i].addr)) {

This issue was identified by testing and is fixed in next by commit 7d55b44e2be1 ("phy: apple: atc: Actually check return value of devm_apple_tunable_parse").

https://lore.kernel.org/all/[email protected]/

I think I actually messed this up *twice*! Once for the tunables and once again for the resources here :(

Sven

#58 lore raw

[bug report] spi: stm32: properly fail on dma_request_chan error

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Alain Volmat,

Commit c266d19b7d4e ("spi: stm32: properly fail on dma_request_chan error") from Dec 18, 2025 (linux-next), leads to the following Smatch static checker warning:

	drivers/spi/spi-stm32.c:2578 stm32_spi_probe()
	error: 'spi->dma_rx' dereferencing possible ERR_PTR()

drivers/spi/spi-stm32.c

    2480         if (STM32_SPI_DEVICE_MODE(spi))
    2481                 ctrl->target_abort = stm32h7_spi_device_abort;
    2482 
    2483         spi->dma_tx = dma_request_chan(spi->dev, "tx");
    2484         if (IS_ERR(spi->dma_tx)) {
    2485                 ret = PTR_ERR(spi->dma_tx);
    2486                 if (ret == -ENODEV) {
    2487                         dev_info(&pdev->dev, "tx dma disabled\n");
    2488                         spi->dma_tx = NULL;
    2489                 } else {
    2490                         dev_err_probe(&pdev->dev, ret, "failed to request tx dma channel\n");
    2491                         goto err_clk_disable;
    2492                 }
    2493         } else {
    2494                 ctrl->dma_tx = spi->dma_tx;
    2495         }
    2496 
    2497         spi->dma_rx = dma_request_chan(spi->dev, "rx");
    2498         if (IS_ERR(spi->dma_rx)) {
    2499                 ret = PTR_ERR(spi->dma_rx);
    2500                 if (ret == -ENODEV) {
    2501                         dev_info(&pdev->dev, "rx dma disabled\n");
    2502                         spi->dma_rx = NULL;
    2503                 } else {
    2504                         dev_err_probe(&pdev->dev, ret, "failed to request rx dma channel\n");
    2505                         goto err_dma_release;

spi->dma_rx is an erorr pointer at this goto so it will crash.

    2506                 }
    2507         } else {
    2508                 ctrl->dma_rx = spi->dma_rx;
    2509         }
    2510 
    2511         if (spi->dma_tx || spi->dma_rx)
    2512                 ctrl->can_dma = stm32_spi_can_dma;
    2513 
    2514         spi->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
    2515         if (spi->sram_pool) {
    2516                 spi->sram_rx_buf_size = gen_pool_size(spi->sram_pool);
    2517                 dev_info(&pdev->dev, "SRAM pool: %zu KiB for RX DMA/MDMA chaining\n",
    2518                          spi->sram_rx_buf_size / 1024);
    2519                 spi->sram_rx_buf = gen_pool_dma_zalloc(spi->sram_pool, spi->sram_rx_buf_size,
    2520                                                        &spi->sram_dma_rx_buf);
    2521                 if (!spi->sram_rx_buf) {
    2522                         dev_err(&pdev->dev, "failed to allocate SRAM buffer\n");
    2523                 } else {
    2524                         spi->mdma_rx = dma_request_chan(spi->dev, "rxm2m");
    2525                         if (IS_ERR(spi->mdma_rx)) {
    2526                                 ret = PTR_ERR(spi->mdma_rx);
    2527                                 spi->mdma_rx = NULL;
    2528                                 if (ret == -EPROBE_DEFER) {
    2529                                         goto err_pool_free;
    2530                                 } else {
    2531                                         gen_pool_free(spi->sram_pool,
    2532                                                       (unsigned long)spi->sram_rx_buf,
    2533                                                       spi->sram_rx_buf_size);
    2534                                         dev_warn(&pdev->dev,
    2535                                                  "failed to request rx mdma channel, DMA only\n");
    2536                                 }
    2537                         }
    2538                 }
    2539         }
    2540 
    2541         pm_runtime_set_autosuspend_delay(&pdev->dev,
    2542                                          STM32_SPI_AUTOSUSPEND_DELAY);
    2543         pm_runtime_use_autosuspend(&pdev->dev);
    2544         pm_runtime_set_active(&pdev->dev);
    2545         pm_runtime_get_noresume(&pdev->dev);
    2546         pm_runtime_enable(&pdev->dev);
    2547 
    2548         ret = spi_register_controller(ctrl);
    2549         if (ret) {
    2550                 dev_err(&pdev->dev, "spi controller registration failed: %d\n",
    2551                         ret);
    2552                 goto err_pm_disable;
    2553         }
    2554 
    2555         pm_runtime_put_autosuspend(&pdev->dev);
    2556 
    2557         dev_info(&pdev->dev, "driver initialized (%s mode)\n",
    2558                  STM32_SPI_HOST_MODE(spi) ? "host" : "device");
    2559 
    2560         return 0;
    2561 
    2562 err_pm_disable:
    2563         pm_runtime_disable(&pdev->dev);
    2564         pm_runtime_put_noidle(&pdev->dev);
    2565         pm_runtime_set_suspended(&pdev->dev);
    2566         pm_runtime_dont_use_autosuspend(&pdev->dev);
    2567 
    2568         if (spi->mdma_rx)
    2569                 dma_release_channel(spi->mdma_rx);
    2570 err_pool_free:
    2571         if (spi->sram_pool)
    2572                 gen_pool_free(spi->sram_pool, (unsigned long)spi->sram_rx_buf,
    2573                               spi->sram_rx_buf_size);
    2574 err_dma_release:
    2575         if (spi->dma_tx)
    2576                 dma_release_channel(spi->dma_tx);
    2577         if (spi->dma_rx)
--> 2578                 dma_release_channel(spi->dma_rx);
                                             ^^^^^^^^^^^

Here.

    2579 err_clk_disable:
    2580         clk_disable_unprepare(spi->clk);
    2581 
    2582         return ret;
    2583 }

regards,
dan carpenter

#59 lore raw

[bug report] tracing: Properly process error handling in event_hist_trigger_parse()

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Miaoqian Lin,

Commit 0550069cc25f ("tracing: Properly process error handling in event_hist_trigger_parse()") from Dec 11, 2025 (linux-next), leads to the following Smatch static checker warning:

kernel/trace/trace_events_hist.c:6925 event_hist_trigger_parse()
error: we previously assumed 'trigger_data' could be null (see line 6856)

kernel/trace/trace_events_hist.c

    6855         trigger_data = trigger_data_alloc(cmd_ops, cmd, param, hist_data);
    6856         if (!trigger_data) {
    6857                 ret = -ENOMEM;
    6858                 goto out_free;

trigger_data is NULL here.

    6859         }
    6860 
    6861         ret = event_trigger_set_filter(cmd_ops, file, filter, trigger_data);
    6862         if (ret < 0)
    6863                 goto out_free;
    6864 
    6865         if (remove) {
    6866                 if (!have_hist_trigger_match(trigger_data, file))
    6867                         goto out_free;
    6868 
    6869                 if (hist_trigger_check_refs(trigger_data, file)) {
    6870                         ret = -EBUSY;
    6871                         goto out_free;
    6872                 }
    6873 
    6874                 event_trigger_unregister(cmd_ops, file, glob+1, trigger_data);
    6875                 se_name = trace_event_name(file->event_call);
    6876                 se = find_synth_event(se_name);
    6877                 if (se)
    6878                         se->ref--;
    6879                 ret = 0;
    6880                 goto out_free;
    6881         }
    6882 
    6883         if (existing_hist_update_only(glob, trigger_data, file))
    6884                 goto out_free;
    6885 
    6886         if (!get_named_trigger_data(trigger_data)) {
    6887 
    6888                 ret = create_actions(hist_data);
    6889                 if (ret)
    6890                         goto out_free;
    6891 
    6892                 if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
    6893                         ret = save_hist_vars(hist_data);
    6894                         if (ret)
    6895                                 goto out_free;
    6896                 }
    6897 
    6898                 ret = tracing_map_init(hist_data->map);
    6899                 if (ret)
    6900                         goto out_free;
    6901         }
    6902 
    6903         ret = event_trigger_register(cmd_ops, file, glob, trigger_data);
    6904         if (ret < 0)
    6905                 goto out_free;
    6906 
    6907         ret = hist_trigger_enable(trigger_data, file);
    6908         if (ret)
    6909                 goto out_unreg;
    6910 
    6911         se_name = trace_event_name(file->event_call);
    6912         se = find_synth_event(se_name);
    6913         if (se)
    6914                 se->ref++;
    6915  out:
    6916         if (ret == 0 && glob[0])
    6917                 hist_err_clear();
    6918 
    6919         return ret;
    6920  out_unreg:
    6921         event_trigger_unregister(cmd_ops, file, glob+1, trigger_data);
    6922  out_free:
    6923         remove_hist_vars(hist_data);
    6924 

--> 6925 trigger_data_free(trigger_data);

Originally this was kfree(trigger_data) so passing a NULL pointer was fine, but now it will crash.

    6926 
    6927         destroy_hist_data(hist_data);
    6928         goto out;
    6929 }
    6930 
    6931 static struct event_command trigger_hist_cmd = {
    6932         .name                        = "hist",
    6933         .trigger_type                = ETT_EVENT_HIST,
    6934         .flags                        = EVENT_CMD_FL_NEEDS_REC,
    6935         .parse                        = event_hist_trigger_parse,

regards,
dan carpenter

#60 lore raw

[bug report] drm/amd/display: Only poll analog connectors

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Timur Kristóf,

Commit f6cc7f1c11a7 ("drm/amd/display: Only poll analog connectors") from Jan 18, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_irq.c:940 amdgpu_dm_hpd_init()
	error: we previously assumed 'dc_link' could be null (see line 931)

drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_irq.c

    923                 /*
    924                  * Analog connectors may be hot-plugged unlike other connector
    925                  * types that don't support HPD. Only poll analog connectors.
    926                  */
    927                 use_polling |=
    928                         amdgpu_dm_connector->dc_link &&
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The patch adds this NULL check but hopefully it can be removed

    929                         dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
    930 
    931                 dc_link = amdgpu_dm_connector->dc_link;

dc_link assigned here.

932
933 /*
934 * Get a base driver irq reference for hpd ints for the lifetime
935 * of dm. Note that only hpd interrupt types are registered with
936 * base driver; hpd_rx types aren't. IOW, amdgpu_irq_get/put on
937 * hpd_rx isn't available. DM currently controls hpd_rx
938 * explicitly with dc_interrupt_set()
939 */

--> 940                 if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
                            ^^^^^^^^^^^^^^^^^^^^^^^

If it's NULL then we are trouble because we dereference it here.

941 irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1;
942 /*
943 * TODO: There's a mismatch between mode_info.num_hpd
944 * and what bios reports as the # of connectors with hpd

regards,
dan carpenter

#61 lore raw

[bug report] fs/ntfs3: Add initialization of super block

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Konstantin Komarov,

Commit 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") from Aug 13, 2021 (linux-next), leads to the following Smatch static checker warning:

fs/ntfs3/fsntfs.c:1260 ntfs_read_run_nb_ra() error: we previously assumed 'run' could be null (see line 1178) fs/ntfs3/fsntfs.c:1259 ntfs_read_run_nb_ra() error: uninitialized symbol 'clen'. fs/ntfs3/fsntfs.c:1260 ntfs_read_run_nb_ra() error: uninitialized symbol 'idx'.

fs/ntfs3/fsntfs.c

    1161 int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
    1162                         u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb,
    1163                         struct file_ra_state *ra)
    1164 {
    1165         int err;
    1166         struct super_block *sb = sbi->sb;
    1167         struct address_space *mapping = sb->s_bdev->bd_mapping;
    1168         u32 blocksize = sb->s_blocksize;
    1169         u8 cluster_bits = sbi->cluster_bits;
    1170         u32 off = vbo & sbi->cluster_mask;
    1171         u32 nbh = 0;
    1172         CLST vcn_next, vcn = vbo >> cluster_bits;
    1173         CLST lcn, clen;
    1174         u64 lbo, len;
    1175         size_t idx;
    1176         struct buffer_head *bh;
    1177 
    1178         if (!run) {
    1179                 /* First reading of $Volume + $MFTMirr + $LogFile goes here. */
    1180                 if (vbo > MFT_REC_VOL * sbi->record_size) {
    1181                         err = -ENOENT;
    1182                         goto out;
    1183                 }
    1184 
    1185                 /* Use absolute boot's 'MFTCluster' to read record. */
    1186                 lbo = vbo + sbi->mft.lbo;
    1187                 len = sbi->record_size;

If run is NULL then "clen" is uninitialized.

    1188         } else if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
    1189                 err = -ENOENT;
    1190                 goto out;
    1191         } else {
    1192                 if (lcn == SPARSE_LCN) {
    1193                         err = -EINVAL;
    1194                         goto out;
    1195                 }
    1196 
    1197                 lbo = ((u64)lcn << cluster_bits) + off;
    1198                 len = ((u64)clen << cluster_bits) - off;
    1199         }
    1200 
    1201         off = lbo & (blocksize - 1);
    1202         if (nb) {
    1203                 nb->off = off;
    1204                 nb->bytes = bytes;
    1205         }
    1206 
    1207         if (ra && !ra->ra_pages)
    1208                 file_ra_state_init(ra, mapping);
    1209 
    1210         for (;;) {
    1211                 u32 len32 = len >= bytes ? bytes : len;
    1212                 sector_t block = lbo >> sb->s_blocksize_bits;
    1213 
    1214                 if (ra) {
    1215                         pgoff_t index = lbo >> PAGE_SHIFT;
    1216                         if (!ra_has_index(ra, index)) {
    1217                                 page_cache_sync_readahead(mapping, ra, NULL,
    1218                                                           index, 1);
    1219                                 ra->prev_pos = (loff_t)index << PAGE_SHIFT;
    1220                         }
    1221                 }
    1222 
    1223                 do {
    1224                         u32 op = blocksize - off;
    1225 
    1226                         if (op > len32)
    1227                                 op = len32;
    1228 
    1229                         bh = ntfs_bread(sb, block);
    1230                         if (!bh) {
    1231                                 err = -EIO;
    1232                                 goto out;
    1233                         }
    1234 
    1235                         if (buf) {
    1236                                 memcpy(buf, bh->b_data + off, op);
    1237                                 buf = Add2Ptr(buf, op);
    1238                         }
    1239 
    1240                         if (!nb) {
    1241                                 put_bh(bh);
    1242                         } else if (nbh >= ARRAY_SIZE(nb->bh)) {
    1243                                 err = -EINVAL;
    1244                                 goto out;
    1245                         } else {
    1246                                 nb->bh[nbh++] = bh;
    1247                                 nb->nbufs = nbh;
    1248                         }
    1249 
    1250                         bytes -= op;
    1251                         if (!bytes)
    1252                                 return 0;
    1253                         len32 -= op;
    1254                         block += 1;
    1255                         off = 0;
    1256 
    1257                 } while (len32);
    1258 
--> 1259                 vcn_next = vcn + clen;
                                          ^^^^

Used uninitalized here.

    1260                 if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||

But also if we pass a NULL run to run_get_entry() it will crash. I'm a bit confused by this code.

    1261                     vcn != vcn_next) {
    1262                         err = -ENOENT;
    1263                         goto out;
    1264                 }
    1265 
    1266                 if (lcn == SPARSE_LCN) {
    1267                         err = -EINVAL;
    1268                         goto out;
    1269                 }
    1270 
    1271                 lbo = ((u64)lcn << cluster_bits);
    1272                 len = ((u64)clen << cluster_bits);
    1273         }
    1274 
    1275 out:
    1276         if (!nbh)
    1277                 return err;
    1278 
    1279         while (nbh) {
    1280                 put_bh(nb->bh[--nbh]);
    1281                 nb->bh[nbh] = NULL;
    1282         }
    1283 
    1284         nb->nbufs = 0;
    1285         return err;
    1286 }

regards,
dan carpenter

#62 lore raw

Re: [bug report] fs/ntfs3: Add initialization of super block

Quoted 151 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Konstantin Komarov,

Commit 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") from Aug 13, 2021 (linux-next), leads to the following Smatch static checker warning:

fs/ntfs3/fsntfs.c:1260 ntfs_read_run_nb_ra() error: we previously assumed 'run' could be null (see line 1178) fs/ntfs3/fsntfs.c:1259 ntfs_read_run_nb_ra() error: uninitialized symbol 'clen'. fs/ntfs3/fsntfs.c:1260 ntfs_read_run_nb_ra() error: uninitialized symbol 'idx'.

fs/ntfs3/fsntfs.c

     1161 int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
     1162                         u64 vbo, void *buf, u32 bytes, struct ntfs_buffers *nb,
     1163                         struct file_ra_state *ra)
     1164 {
     1165         int err;
     1166         struct super_block *sb = sbi->sb;
     1167         struct address_space *mapping = sb->s_bdev->bd_mapping;
     1168         u32 blocksize = sb->s_blocksize;
     1169         u8 cluster_bits = sbi->cluster_bits;
     1170         u32 off = vbo & sbi->cluster_mask;
     1171         u32 nbh = 0;
     1172         CLST vcn_next, vcn = vbo >> cluster_bits;
     1173         CLST lcn, clen;
     1174         u64 lbo, len;
     1175         size_t idx;
     1176         struct buffer_head *bh;
     1177
     1178         if (!run) {
     1179                 /* First reading of $Volume + $MFTMirr + $LogFile goes here. */
     1180                 if (vbo > MFT_REC_VOL * sbi->record_size) {
     1181                         err = -ENOENT;
     1182                         goto out;
     1183                 }
     1184
     1185                 /* Use absolute boot's 'MFTCluster' to read record. */
     1186                 lbo = vbo + sbi->mft.lbo;
     1187                 len = sbi->record_size;

If run is NULL then "clen" is uninitialized.

     1188         } else if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
     1189                 err = -ENOENT;
     1190                 goto out;
     1191         } else {
     1192                 if (lcn == SPARSE_LCN) {
     1193                         err = -EINVAL;
     1194                         goto out;
     1195                 }
     1196
     1197                 lbo = ((u64)lcn << cluster_bits) + off;
     1198                 len = ((u64)clen << cluster_bits) - off;
     1199         }
     1200
     1201         off = lbo & (blocksize - 1);
     1202         if (nb) {
     1203                 nb->off = off;
     1204                 nb->bytes = bytes;
     1205         }
     1206
     1207         if (ra && !ra->ra_pages)
     1208                 file_ra_state_init(ra, mapping);
     1209
     1210         for (;;) {
     1211                 u32 len32 = len >= bytes ? bytes : len;
     1212                 sector_t block = lbo >> sb->s_blocksize_bits;
     1213
     1214                 if (ra) {
     1215                         pgoff_t index = lbo >> PAGE_SHIFT;
     1216                         if (!ra_has_index(ra, index)) {
     1217                                 page_cache_sync_readahead(mapping, ra, NULL,
     1218                                                           index, 1);
     1219                                 ra->prev_pos = (loff_t)index << PAGE_SHIFT;
     1220                         }
     1221                 }
     1222
     1223                 do {
     1224                         u32 op = blocksize - off;
     1225
     1226                         if (op > len32)
     1227                                 op = len32;
     1228
     1229                         bh = ntfs_bread(sb, block);
     1230                         if (!bh) {
     1231                                 err = -EIO;
     1232                                 goto out;
     1233                         }
     1234
     1235                         if (buf) {
     1236                                 memcpy(buf, bh->b_data + off, op);
     1237                                 buf = Add2Ptr(buf, op);
     1238                         }
     1239
     1240                         if (!nb) {
     1241                                 put_bh(bh);
     1242                         } else if (nbh >= ARRAY_SIZE(nb->bh)) {
     1243                                 err = -EINVAL;
     1244                                 goto out;
     1245                         } else {
     1246                                 nb->bh[nbh++] = bh;
     1247                                 nb->nbufs = nbh;
     1248                         }
     1249
     1250                         bytes -= op;
     1251                         if (!bytes)
     1252                                 return 0;
     1253                         len32 -= op;
     1254                         block += 1;
     1255                         off = 0;
     1256
     1257                 } while (len32);
     1258
--> 1259                 vcn_next = vcn + clen;
                                           ^^^^

Used uninitalized here.

     1260                 if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||

But also if we pass a NULL run to run_get_entry() it will crash. I'm a bit confused by this code.

     1261                     vcn != vcn_next) {
     1262                         err = -ENOENT;
     1263                         goto out;
     1264                 }
     1265
     1266                 if (lcn == SPARSE_LCN) {
     1267                         err = -EINVAL;
     1268                         goto out;
     1269                 }
     1270
     1271                 lbo = ((u64)lcn << cluster_bits);
     1272                 len = ((u64)clen << cluster_bits);
     1273         }
     1274
     1275 out:
     1276         if (!nbh)
     1277                 return err;
     1278
     1279         while (nbh) {
     1280                 put_bh(nb->bh[--nbh]);
     1281                 nb->bh[nbh] = NULL;
     1282         }
     1283
     1284         nb->nbufs = 0;
     1285         return err;
     1286 }
Quoted 2 lines

regards,
dan carpenter

Hello,

Thanks for the Smatch report. I’ll examine the warnings, prepare a fix, and post a patch.

Regards,
Konstantin

#63 lore raw

PATCH 1/1 (resend: correct threading) fs/ntfs3: avoid calling run_get_entry() when run == NULL in ntfs_read_run_nb_ra()

In reply to Dan Carpenter

When ntfs_read_run_nb_ra() is invoked with run == NULL the code later assumes run is valid and may call run_get_entry(NULL, ...), and also uses clen/idx without initializing them. Smatch reported uninitialized variable warnings and this can lead to undefined behaviour. This patch fixes it.

---
 fs/ntfs3/fsntfs.c | 6 ++++++
 1 file changed, 6 insertions(+)
fs/ntfs3/fsntfs.c +6 -0
index e9c39c62aea4..2ef500f1a9fa 100644
@@ -1256,6 +1256,12 @@ int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
 
 		} while (len32);
 
+		if (!run) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		/* Get next fragment to read. */
 		vcn_next = vcn + clen;
 		if (!run_get_entry(run, ++idx, &vcn, &lcn, &clen) ||
 		    vcn != vcn_next) {
Signature · 1 line
2.43.0
#64 lore raw

[bug report] remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Peng Fan,

Commit edd2a9956055 ("remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg") from Jan 9, 2026 (linux-next), leads to the following Smatch static checker warning:

drivers/remoteproc/imx_rproc.c:648 imx_rproc_prepare()
warn: ignoring unreachable code.

drivers/remoteproc/imx_rproc.c

    605 static int imx_rproc_prepare(struct rproc *rproc)
    606 {
    607         struct imx_rproc *priv = rproc->priv;
    608         struct device_node *np = priv->dev->of_node;
    609         struct rproc_mem_entry *mem;
    610         int i = 0;
    611         u32 da;
    612 
    613         /* Register associated reserved memory regions */
    614         while (1) {
    615                 int err;
    616                 struct resource res;
    617 
    618                 err = of_reserved_mem_region_to_resource(np, i++, &res);
    619                 if (err)
    620                         return 0;
    621 
    622                 /*
    623                  * Ignore the first memory region which will be used vdev buffer.
    624                  * No need to do extra handlings, rproc_add_virtio_dev will handle it.
    625                  */
    626                 if (strstarts(res.name, "vdev0buffer"))
    627                         continue;
    628 
    629                 if (strstarts(res.name, "rsc-table"))
    630                         continue;
    631 
    632                 /* No need to translate pa to da, i.MX use same map */
    633                 da = res.start;
    634 
    635                 /* Register memory region */
    636                 mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start,
    637                                            resource_size(&res), da,
    638                                            imx_rproc_mem_alloc, imx_rproc_mem_release,
    639                                            "%.*s", strchrnul(res.name, '@') - res.name,
    640                                            res.name);
    641                 if (!mem)
    642                         return -ENOMEM;
    643 
    644                 rproc_coredump_add_segment(rproc, da, resource_size(&res));
    645                 rproc_add_carveout(rproc, mem);
    646         }
    647 
--> 648         if (priv->ops && priv->ops->prepare)
    649                 return priv->ops->prepare(rproc);

This is unreachable code.

    650 
    651         return 0;
    652 }

regards,
dan carpenter

#65 lore raw

Re: [bug report] remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg

Quoted 59 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Peng Fan,

Commit edd2a9956055 ("remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg") from Jan 9, 2026 (linux-next), leads to the following Smatch static checker warning:

drivers/remoteproc/imx_rproc.c:648 imx_rproc_prepare()
warn: ignoring unreachable code.

drivers/remoteproc/imx_rproc.c

    605 static int imx_rproc_prepare(struct rproc *rproc)
    606 {
    607         struct imx_rproc *priv = rproc->priv;
    608         struct device_node *np = priv->dev->of_node;
    609         struct rproc_mem_entry *mem;
    610         int i = 0;
    611         u32 da;
    612 
    613         /* Register associated reserved memory regions */
    614         while (1) {
    615                 int err;
    616                 struct resource res;
    617 
    618                 err = of_reserved_mem_region_to_resource(np, i++, &res);
    619                 if (err)
    620                         return 0;
    621 
    622                 /*
    623                  * Ignore the first memory region which will be used vdev buffer.
    624                  * No need to do extra handlings, rproc_add_virtio_dev will handle it.
    625                  */
    626                 if (strstarts(res.name, "vdev0buffer"))
    627                         continue;
    628 
    629                 if (strstarts(res.name, "rsc-table"))
    630                         continue;
    631 
    632                 /* No need to translate pa to da, i.MX use same map */
    633                 da = res.start;
    634 
    635                 /* Register memory region */
    636                 mem = rproc_mem_entry_init(priv->dev, NULL, (dma_addr_t)res.start,
    637                                            resource_size(&res), da,
    638                                            imx_rproc_mem_alloc, imx_rproc_mem_release,
    639                                            "%.*s", strchrnul(res.name, '@') - res.name,
    640                                            res.name);
    641                 if (!mem)
    642                         return -ENOMEM;
    643 
    644                 rproc_coredump_add_segment(rproc, da, resource_size(&res));
    645                 rproc_add_carveout(rproc, mem);
    646         }
    647 
--> 648         if (priv->ops && priv->ops->prepare)
    649                 return priv->ops->prepare(rproc);
Quoted 1 line

This is unreachable code.

It looks like Dan (and Smatch) has a point.

Quoted 8 lines
    650 
    651         return 0;
    652 }

regards,
dan carpenter

#66 lore raw

RE: [bug report] remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg

In reply to Dan Carpenter

Hi Dan,

Thanks for your report.

Quoted 13 lines

Subject: [bug report] remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg

Hello Peng Fan,

Commit edd2a9956055 ("remoteproc: imx_rproc: Introduce prepare ops for imx_rproc_dcfg") from Jan 9, 2026 (linux-next), leads to the following Smatch static checker warning:

drivers/remoteproc/imx_rproc.c:648 imx_rproc_prepare()
warn: ignoring unreachable code.

drivers/remoteproc/imx_rproc.c

[...]

Quoted 11 lines
    642                         return -ENOMEM;
    643
    644                 rproc_coredump_add_segment(rproc, da,
resource_size(&res));
    645                 rproc_add_carveout(rproc, mem);
    646         }
    647
--> 648         if (priv->ops && priv->ops->prepare)
    649                 return priv->ops->prepare(rproc);

This is unreachable code.

Indeed.

The i.MX95 patches were developed quite some time ago. Later, there was another change [1] which modified the reserved-memory while-loop logic. When rebasing my changes on top of that, I overlooked this behavior change, which resulted in the early return making the prepare callback unreachable.

Regarding why this was not exposed earlier during testing: NXP U-Boot powers up the M7 (leaving it in reset) and initializes TCM ECC by default. As a result, even without calling the platform prepare ops, Linux can still load the M7 ELF correctly, so no issue was observed.

In hindsight, I should have tested the case where M7 remains powered off when rebasing these changes (:

I have just sent out a fix to address this issue. Thanks again for reporting it.

[1] 67a7bc7f0358b ("remoteproc: Use of_reserved_mem_region_* functions for "memory-region")

Thanks,
Peng

Quoted 6 lines
    650
    651         return 0;
    652 }

regards,
dan carpenter

#67 lore raw

[bug report] irqchip/ls-extirq: Convert to a platform driver to make it work again

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ioana Ciornei,

Commit 05cd654829dd ("irqchip/ls-extirq: Convert to a platform driver to make it work again") from Jan 22, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/irqchip/irq-ls-extirq.c:180 ls_extirq_probe()
	warn: 'priv->intpcr' is an error pointer or valid

drivers/irqchip/irq-ls-extirq.c

    158 static int ls_extirq_probe(struct platform_device *pdev)
    159 {
    160         struct irq_domain *domain, *parent_domain;
    161         struct device_node *node, *parent;
    162         struct device *dev = &pdev->dev;
    163         struct ls_extirq_data *priv;
    164         int ret;
    165 
    166         node = dev->of_node;
    167         parent = of_irq_find_parent(node);
    168         if (!parent)
    169                 return dev_err_probe(dev, -ENODEV, "Failed to get IRQ parent node\n");
    170 
    171         parent_domain = irq_find_host(parent);
    172         if (!parent_domain)
    173                 return dev_err_probe(dev, -EPROBE_DEFER, "Cannot find parent domain\n");
    174 
    175         priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    176         if (!priv)
    177                 return dev_err_probe(dev, -ENOMEM, "Failed to allocate memory\n");
    178 
    179         priv->intpcr = devm_of_iomap(dev, node, 0, NULL);

--> 180 if (!priv->intpcr)

This should be an IS_ERR() check.

    181                 return dev_err_probe(dev, -ENOMEM, "Cannot ioremap OF node %pOF\n", node);
    182 
    183         ret = ls_extirq_parse_map(priv, node);
    184         if (ret)
    185                 return dev_err_probe(dev, ret, "Failed to parse IRQ map\n");
    186 
    187         priv->big_endian = of_device_is_big_endian(node->parent);
    188         priv->is_ls1021a_or_ls1043a = of_device_is_compatible(node, "fsl,ls1021a-extirq") ||
    189                                       of_device_is_compatible(node, "fsl,ls1043a-extirq");
    190         raw_spin_lock_init(&priv->lock);
    191 
    192         domain = irq_domain_create_hierarchy(parent_domain, 0, priv->nirq, of_fwnode_handle(node),
    193                                              &extirq_domain_ops, priv);
    194         if (!domain)
    195                 return dev_err_probe(dev, -ENOMEM, "Failed to add IRQ domain\n");
    196 
    197         return 0;
    198 }

regards,
dan carpenter

#68 lore raw

[bug report] soc: rockchip: grf: Support multiple grf to be handled

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Shawn Lin,

Commit 75fb63ae0312 ("soc: rockchip: grf: Support multiple grf to be handled") from Jan 16, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/soc/rockchip/grf.c:249 rockchip_grf_init()
	warn: inconsistent refcounting 'np->kobj.kref.refcount.refs.counter':

drivers/soc/rockchip/grf.c
212 static int __init rockchip_grf_init(void)
213 {

   214          const struct rockchip_grf_info *grf_info;
   215          const struct of_device_id *match;
   216          struct device_node *np;
   217          struct regmap *grf;
   218          int ret, i;
   219  
   220          for_each_matching_node_and_match(np, rockchip_grf_dt_match, &match) {
   221                  if (!of_device_is_available(np))
   222                          continue;
   223                  if (!match || !match->data) {
   224                          pr_err("%s: missing grf data\n", __func__);
   225                          of_node_put(np);
   226                          return -EINVAL;

227 }
228
229 grf_info = match->data;
230
231 grf = syscon_node_to_regmap(np);
232 if (IS_ERR(grf)) {
233 pr_err("%s: could not get grf syscon\n", __func__);
234 return PTR_ERR(grf);

Missing of_node_put(np) before returning.

   235                  }
   236  
   237                  for (i = 0; i < grf_info->num_values; i++) {
   238                          const struct rockchip_grf_value *val = &grf_info->values[i];
   239  
   240                          pr_debug("%s: adjusting %s in %#6x to %#10x\n", __func__,
   241                                  val->desc, val->reg, val->val);
   242                          ret = regmap_write(grf, val->reg, val->val);
   243                          if (ret < 0)
   244                                  pr_err("%s: write to %#6x failed with %d\n",
   245                                          __func__, val->reg, ret);
   246                  }
   247          }
   248  
   249          return 0;
   250  }

regards,
dan carpenter

#69 lore raw

[bug report] drm/amdgpu: fix possible fence leaks from job structure

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Alex Deucher,

Commit f903b85ed0f1 ("drm/amdgpu: fix possible fence leaks from job structure") from Oct 22, 2025 (linux-next), leads to the following Smatch static checker warning:

drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c:232 amdgpu_ib_schedule()
warn: missing unwind goto?

drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c

    124 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
    125                        struct amdgpu_ib *ibs, struct amdgpu_job *job,
    126                        struct dma_fence **f)
    127 {
    128         struct amdgpu_device *adev = ring->adev;
    129         struct amdgpu_ib *ib = &ibs[0];
    130         struct dma_fence *tmp = NULL;
    131         struct amdgpu_fence *af;
    132         bool need_ctx_switch;
    133         struct amdgpu_vm *vm;
    134         uint64_t fence_ctx;
    135         uint32_t status = 0, alloc_size;
    136         unsigned int fence_flags = 0;
    137         bool secure, init_shadow;
    138         u64 shadow_va, csa_va, gds_va;
    139         int vmid = AMDGPU_JOB_GET_VMID(job);
    140         bool need_pipe_sync = false;
    141         unsigned int cond_exec;
    142         unsigned int i;
    143         int r = 0;
    144 
    145         if (num_ibs == 0)
    146                 return -EINVAL;
    147 
    148         /* ring tests don't use a job */
    149         if (job) {
    150                 vm = job->vm;
    151                 fence_ctx = job->base.s_fence ?
    152                         job->base.s_fence->finished.context : 0;
    153                 shadow_va = job->shadow_va;
    154                 csa_va = job->csa_va;
    155                 gds_va = job->gds_va;
    156                 init_shadow = job->init_shadow;
    157                 af = job->hw_fence;
    158                 /* Save the context of the job for reset handling.
    159                  * The driver needs this so it can skip the ring
    160                  * contents for guilty contexts.
    161                  */
    162                 af->context = fence_ctx;
    163                 /* the vm fence is also part of the job's context */
    164                 job->hw_vm_fence->context = fence_ctx;
    165         } else {
    166                 vm = NULL;
    167                 fence_ctx = 0;
    168                 shadow_va = 0;
    169                 csa_va = 0;
    170                 gds_va = 0;
    171                 init_shadow = false;
    172                 af = kzalloc(sizeof(*af), GFP_ATOMIC);
    173                 if (!af)
    174                         return -ENOMEM;
    175         }
    176 
    177         if (!ring->sched.ready) {
    178                 dev_err(adev->dev, "couldn't schedule ib on ring <%s>\n", ring->name);
    179                 r = -EINVAL;
    180                 goto free_fence;
    181         }
    182 
    183         if (vm && !job->vmid) {
    184                 dev_err(adev->dev, "VM IB without ID\n");
    185                 r = -EINVAL;
    186                 goto free_fence;
    187         }
    188 
    189         if ((ib->flags & AMDGPU_IB_FLAGS_SECURE) &&
    190             (!ring->funcs->secure_submission_supported)) {
    191                 dev_err(adev->dev, "secure submissions not supported on ring <%s>\n", ring->name);
    192                 r = -EINVAL;
    193                 goto free_fence;
    194         }
    195 
    196         alloc_size = ring->funcs->emit_frame_size + num_ibs *
    197                 ring->funcs->emit_ib_size;
    198 
    199         r = amdgpu_ring_alloc(ring, alloc_size);
    200         if (r) {
    201                 dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
    202                 goto free_fence;
    203         }
    204 
    205         need_ctx_switch = ring->current_ctx != fence_ctx;
    206         if (ring->funcs->emit_pipeline_sync && job &&
    207             ((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
    208              need_ctx_switch || amdgpu_vm_need_pipeline_sync(ring, job))) {
    209 
    210                 need_pipe_sync = true;
    211 
    212                 if (tmp)
    213                         trace_amdgpu_ib_pipe_sync(job, tmp);
    214 
    215                 dma_fence_put(tmp);
    216         }
    217 
    218         if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync)
    219                 ring->funcs->emit_mem_sync(ring);
    220 
    221         if (ring->funcs->emit_wave_limit &&
    222             ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
    223                 ring->funcs->emit_wave_limit(ring, true);
    224 
    225         if (ring->funcs->insert_start)
    226                 ring->funcs->insert_start(ring);
    227 
    228         if (job) {
    229                 r = amdgpu_vm_flush(ring, job, need_pipe_sync);
    230                 if (r) {
    231                         amdgpu_ring_undo(ring);

--> 232 return r;

The patch changed the other error paths to goto free_fence but this one was accidentally skipped.

    233                 }
    234         }
    235 
    236         amdgpu_ring_ib_begin(ring);
    237 
    238         if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow)
    239                 amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va,
    240                                             init_shadow, vmid);
    241 
    242         if (ring->funcs->init_cond_exec)
    243                 cond_exec = amdgpu_ring_init_cond_exec(ring,
    244                                                        ring->cond_exe_gpu_addr);
    245 
    246         amdgpu_device_flush_hdp(adev, ring);
    247 
    248         if (need_ctx_switch)
    249                 status |= AMDGPU_HAVE_CTX_SWITCH;
    250 
    251         if (job && ring->funcs->emit_cntxcntl) {
    252                 status |= job->preamble_status;
    253                 status |= job->preemption_status;
    254                 amdgpu_ring_emit_cntxcntl(ring, status);
    255         }
    256 
    257         /* Setup initial TMZiness and send it off.
    258          */
    259         secure = false;
    260         if (job && ring->funcs->emit_frame_cntl) {
    261                 secure = ib->flags & AMDGPU_IB_FLAGS_SECURE;
    262                 amdgpu_ring_emit_frame_cntl(ring, true, secure);
    263         }
    264 
    265         for (i = 0; i < num_ibs; ++i) {
    266                 ib = &ibs[i];
    267 
    268                 if (job && ring->funcs->emit_frame_cntl) {
    269                         if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) {
    270                                 amdgpu_ring_emit_frame_cntl(ring, false, secure);
    271                                 secure = !secure;
    272                                 amdgpu_ring_emit_frame_cntl(ring, true, secure);
    273                         }
    274                 }
    275 
    276                 amdgpu_ring_emit_ib(ring, job, ib, status);
    277                 status &= ~AMDGPU_HAVE_CTX_SWITCH;
    278         }
    279 
    280         if (job && ring->funcs->emit_frame_cntl)
    281                 amdgpu_ring_emit_frame_cntl(ring, false, secure);
    282 
    283         amdgpu_device_invalidate_hdp(adev, ring);
    284 
    285         if (ib->flags & AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE)
    286                 fence_flags |= AMDGPU_FENCE_FLAG_TC_WB_ONLY;
    287 
    288         /* wrap the last IB with fence */
    289         if (job && job->uf_addr) {
    290                 amdgpu_ring_emit_fence(ring, job->uf_addr, job->uf_sequence,
    291                                        fence_flags | AMDGPU_FENCE_FLAG_64BIT);
    292         }
    293 
    294         if (ring->funcs->emit_gfx_shadow && ring->funcs->init_cond_exec &&
    295             adev->gfx.cp_gfx_shadow) {
    296                 amdgpu_ring_emit_gfx_shadow(ring, 0, 0, 0, false, 0);
    297                 amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr);
    298         }
    299 
    300         r = amdgpu_fence_emit(ring, af, fence_flags);
    301         if (r) {
    302                 dev_err(adev->dev, "failed to emit fence (%d)\n", r);
    303                 if (job && job->vmid)
    304                         amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
    305                 amdgpu_ring_undo(ring);
    306                 goto free_fence;
    307         }
    308         *f = &af->base;
    309         /* get a ref for the job */
    310         if (job)
    311                 dma_fence_get(*f);
    312 
    313         if (ring->funcs->insert_end)
    314                 ring->funcs->insert_end(ring);
    315 
    316         amdgpu_ring_patch_cond_exec(ring, cond_exec);
    317 
    318         ring->current_ctx = fence_ctx;
    319         if (job && ring->funcs->emit_switch_buffer)
    320                 amdgpu_ring_emit_switch_buffer(ring);
    321 
    322         if (ring->funcs->emit_wave_limit &&
    323             ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
    324                 ring->funcs->emit_wave_limit(ring, false);
    325 
    326         /* Save the wptr associated with this fence.
    327          * This must be last for resets to work properly
    328          * as we need to save the wptr associated with this
    329          * fence so we know what rings contents to backup
    330          * after we reset the queue.
    331          */
    332         amdgpu_fence_save_wptr(af);
    333 
    334         amdgpu_ring_ib_end(ring);
    335         amdgpu_ring_commit(ring);
    336 
    337         return 0;
    338 
    339 free_fence:
    340         if (!job)
    341                 kfree(af);
    342         return r;
    343 }

regards,
dan carpenter

#70 lore raw

[bug report] bio: add allocation cache abstraction

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Jens Axboe,

Commit be4d234d7aeb ("bio: add allocation cache abstraction") from Mar 8, 2021 (linux-next), leads to the following Smatch static checker warning:

	block/bio.c:790 bio_cpu_dead()
	error: potential null dereference 'bs'.  (hlist_entry_safe() returns null)

block/bio.c

    785 static int bio_cpu_dead(unsigned int cpu, struct hlist_node *node)
    786 {
    787         struct bio_set *bs;
    788 
    789         bs = hlist_entry_safe(node, struct bio_set, cpuhp_dead);

--> 790 if (bs->cache) {

It doesn't really make sense to use hlist_entry_safe() instead of hlist_entry() if we're not going to check for NULL.

    791                 struct bio_alloc_cache *cache = per_cpu_ptr(bs->cache, cpu);
    792 
    793                 bio_alloc_cache_prune(cache, -1U);
    794         }
    795         return 0;
    796 }

regards,
dan carpenter

#71 lore raw

[bug report] ASoC: codecs: ACF bin parsing and check library file for aw88395

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Weidong Wang,

Commit 4345865b003b ("ASoC: codecs: ACF bin parsing and check library file for aw88395") from Jan 13, 2023 (linux-next), leads to the following Smatch static checker warning:

	sound/soc/codecs/aw88395/aw88395_lib.c:712 aw_dev_create_prof_name_list_v1()
	warn: double check that we're allocating correct size: 8 vs 32

sound/soc/codecs/aw88395/aw88395_lib.c

    701 static int aw_dev_create_prof_name_list_v1(struct aw_device *aw_dev)
    702 {
    703         struct aw_prof_info *prof_info = &aw_dev->prof_info;
    704         struct aw_prof_desc *prof_desc = prof_info->prof_desc;
    705         int i;
    706 
    707         if (!prof_desc) {
    708                 dev_err(aw_dev->dev, "prof_desc is NULL");
    709                 return -EINVAL;
    710         }
    711 
--> 712         prof_info->prof_name_list = devm_kzalloc(aw_dev->dev,
    713                                         prof_info->count * PROFILE_STR_MAX,
                                                                   ^^^^^^^^^^^^^^^

PROFILE_STR_MAX this is the maximum length of the string but we only need to allocate a pointer to the string sizeof(char *). So this allocates 32bytes instead of just 8.

It's a small waste of space but otherwise it's harmless.

    714                                         GFP_KERNEL);
    715         if (!prof_info->prof_name_list)
    716                 return -ENOMEM;
    717 
    718         for (i = 0; i < prof_info->count; i++) {
    719                 prof_desc[i].id = i;
    720                 prof_info->prof_name_list[i] = prof_desc[i].prf_str;
    721                 dev_dbg(aw_dev->dev, "prof name is %s", prof_info->prof_name_list[i]);
    722         }
    723 
    724         return 0;
    725 }

regards,
dan carpenter

#72 lore raw

[bug report] xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Tetsuo Handa,

Commit 638361ad7ab2 ("xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()") from Feb 2, 2026 (linux-next), leads to the following Smatch static checker warning:

	net/xfrm/xfrm_state.c:898 xfrm_dev_state_flush_secctx_check()
	warn: was '== (-1)' instead of '='

net/xfrm/xfrm_state.c

    888         int i, err = 0;
    889 
    890         for (i = 0; i <= net->xfrm.state_hmask; i++) {
    891                 struct xfrm_state *x;
    892                 struct xfrm_dev_offload *xso;
    893 
    894                 hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) {
    895                         xso = &x->xso;
    896 
    897                         if (xso->dev == dev &&
--> 898                             (err = -EPERM) != 0) {
                                         ^

= vs == bug.

    899                                 pr_info("%s: LSM policy is rejecting this operation.\n", __func__);
    900                                 dump_stack();
    901                                 xfrm_audit_state_delete(x, 0, task_valid);
    902                                 return err;
    903                         }
    904                 }
    905         }
    906 
    907         return err;
    908 }

regards,
dan carpenter

#73 lore raw

Re: [bug report] xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()

Quoted 11 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Tetsuo Handa,

Commit 638361ad7ab2 ("xfrm: always fail xfrm_dev_{state,policy}_flush_secctx_check()") from Feb 2, 2026 (linux-next), leads to the following Smatch static checker warning:

	net/xfrm/xfrm_state.c:898 xfrm_dev_state_flush_secctx_check()
	warn: was '== (-1)' instead of '='

Thank you, but this change is intended for demonstrating to SELinux people that making xfrm_dev_{state,policy}_flush() no-op results in hung task bug
( https://lkml.kernel.org/r/[email protected] ).

That change is already removed, and we are waiting for
https://lkml.kernel.org/r/[email protected]
to be applied.

#74 lore raw

[bug report] wifi: mwifiex: Allocate dev name earlier for interface workqueue name

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Chen-Yu Tsai,

Commit 7bab5bdb81e3 ("wifi: mwifiex: Allocate dev name earlier for interface workqueue name") from Jan 7, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/net/wireless/marvell/mwifiex/cfg80211.c:3214 mwifiex_add_virtual_intf()
	warn: passing positive error code '(-23)-(-22),(-12),1-64' to 'ERR_PTR'

drivers/net/wireless/marvell/mwifiex/cfg80211.c
3147
3148 SET_NETDEV_DEV(dev, adapter->dev);
3149
3150 ret = dev_alloc_name(dev, name);
3151 if (ret)
3152 goto err_alloc_name;

The dev_alloc_name() function can return 1-64 if the name has a "%d" in it. None of the other nine callers use the positive returns. The only thing it does is cause a crash here. We should probably fix dev_alloc_name() as well as changing this to if (ret < 0) {.

3153
3154 priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC-%s",

  3155                                                    WQ_HIGHPRI |
  3156                                                    WQ_MEM_RECLAIM |
  3157                                                    WQ_UNBOUND, 0, dev->name);
  3158          if (!priv->dfs_cac_workqueue) {
  3159                  mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");
  3160                  ret = -ENOMEM;
  3161                  goto err_alloc_cac;

3162 }
3163

regards,
dan carpenter

#75 lore raw

[bug report] apparmor: add support loading per permission tagging

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello John Johansen,

Commit 3d28e2397af7 ("apparmor: add support loading per permission tagging") from Apr 1, 2025 (linux-next), leads to the following Smatch static checker warning:

	security/apparmor/policy_unpack.c:966 unpack_pdb()
	warn: unsigned 'unpack_tags(e, &pdb->tags, info)' is never less than zero.

security/apparmor/policy_unpack.c

    951 static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
    952                       bool required_dfa, bool required_trans,
    953                       const char **info)
    954 {
    955         struct aa_policydb *pdb;
    956         void *pos = e->pos;
    957         int i, flags, error = -EPROTO;
    958         ssize_t size;
    959         u32 version = 0;
    960 
    961         pdb = aa_alloc_pdb(GFP_KERNEL);
    962         if (!pdb)
    963                 return -ENOMEM;
    964 
    965         AA_DEBUG(DEBUG_UNPACK, "unpacking tags");
--> 966         if (unpack_tags(e, &pdb->tags, info) < 0)
                    ^^^^^^^^^^^

Signedness bug. unpack_tags() is unsigned.

    967                 goto fail;
    968         AA_DEBUG(DEBUG_UNPACK, "done unpacking tags");
    969 
    970         size = unpack_perms_table(e, &pdb->perms);
    971         if (size < 0) {
    972                 error = size;
    973                 pdb->perms = NULL;

regards,
dan carpenter

#76 lore raw

PATCH 1/1 apparmor: fix signedness bug in unpack_tags()

Smatch static checker warning:

    security/apparmor/policy_unpack.c:966 unpack_pdb()
    warn: unsigned 'unpack_tags(e, &pdb->tags, info)' is never less than zero.

unpack_tags() is declared with return type size_t (unsigned) but returns negative errno values on failure. The caller in unpack_pdb() tests the return with < 0, which is always false for an unsigned type, making error handling dead code. Malformed tag data would be silently accepted instead of causing a load failure.

Change return type of unpack_tags() from size_t to int to match the functions's actual semantic.

Fixes 3d28e2397af7 ("apparmor: add support loading per permission tagging")
---
 security/apparmor/policy_unpack.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
security/apparmor/policy_unpack.c +1 -1
index e68adf39771f..dc908e1f5a88 100644
@@ -835,7 +835,7 @@ static int unpack_tag_headers(struct aa_ext *e, struct aa_tags_struct *tags)
 }
 
 
-static size_t unpack_tags(struct aa_ext *e, struct aa_tags_struct *tags,
+static int unpack_tags(struct aa_ext *e, struct aa_tags_struct *tags,
 	const char **info)
 {
 	int error = -EPROTO;
Signature · 1 line
2.51.0
#77 lore raw

[bug report] regulator: s2mps11: add S2MPG10 regulator

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello André Draszik,

Commit a2b8b9f33ce3 ("regulator: s2mps11: add S2MPG10 regulator") from Jan 22, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/regulator/s2mps11.c:483 s2mpg10_of_parse_cb()
	warn: off by one 'ext_control' == ARRAY_SIZE()?

drivers/regulator/s2mps11.c

    458         if (of_property_read_u32(np, "samsung,ext-control", &ext_control))
    459                 return 0;
    460 
    461         switch (s2mps11->dev_type) {
    462         case S2MPG10:
    463                 switch (desc->id) {
    464                 case S2MPG10_BUCK1 ... S2MPG10_BUCK7:
    465                 case S2MPG10_BUCK10:
    466                 case S2MPG10_LDO3 ... S2MPG10_LDO19:
    467                         if (ext_control > S2MPG10_EXTCTRL_TCXO_ON2)
    468                                 return -EINVAL;
    469                         break;
    470 
    471                 case S2MPG10_LDO20:
    472                         if (ext_control < S2MPG10_EXTCTRL_LDO20M_EN2 ||
    473                             ext_control > S2MPG10_EXTCTRL_LDO20M_EN)
    474                                 return -EINVAL;
    475                         break;
    476 
    477                 default:
    478                         return -EINVAL;
    479                 }
    480 
    481                 if (ext_control > ARRAY_SIZE(ext_control_s2mpg10))

This should be >= ARRAY_SIZE(). Although the earlier checks prevent an out of bounds access, it's still worth fixing the sanity check.

    482                         return -EINVAL;
--> 483                 ext_control = ext_control_s2mpg10[ext_control];
    484                 break;
    485 
    486         case S2MPG11:
    487                 switch (desc->id) {
    488                 case S2MPG11_BUCK1 ... S2MPG11_BUCK3:

regards,
dan carpenter

#78 lore raw

Re: [bug report] regulator: s2mps11: add S2MPG10 regulator

Hi Dan,

Quoted 38 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
  https://lore.kernel.org/all/[email protected]/ -dan ]

Hello André Draszik,

Commit a2b8b9f33ce3 ("regulator: s2mps11: add S2MPG10 regulator") from Jan 22, 2026 (linux-next), leads to the following Smatch static checker warning:

	drivers/regulator/s2mps11.c:483 s2mpg10_of_parse_cb()
	warn: off by one 'ext_control' == ARRAY_SIZE()?

drivers/regulator/s2mps11.c
    458         if (of_property_read_u32(np, "samsung,ext-control", &ext_control)) 459                 return 0;
    460
    461         switch (s2mps11->dev_type) {
    462         case S2MPG10:
    463                 switch (desc->id) {
    464                 case S2MPG10_BUCK1 ... S2MPG10_BUCK7:
    465                 case S2MPG10_BUCK10:
    466                 case S2MPG10_LDO3 ... S2MPG10_LDO19:
    467                         if (ext_control > S2MPG10_EXTCTRL_TCXO_ON2) 468                                 return -EINVAL;
    469                         break;
    470
    471                 case S2MPG10_LDO20:
    472                         if (ext_control < S2MPG10_EXTCTRL_LDO20M_EN2 || 473                             ext_control > S2MPG10_EXTCTRL_LDO20M_EN) 474                                 return -EINVAL;
    475                         break;
    476
    477                 default:
    478                         return -EINVAL;
    479                 }
    480
    481                 if (ext_control > ARRAY_SIZE(ext_control_s2mpg10))

Quoted 2 lines

This should be >= ARRAY_SIZE().  Although the earlier checks prevent an out of bounds access, it's still worth fixing the sanity check.

Thanks, yes. Although this was on purpose to avoid duplicated checks. I'd say this test could be removed altogether as it's just confusing and useless.

Cheers,
Andre'

#79 lore raw

[bug report] btrfs: tests: zoned: add tests cases for zoned code

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]
Hello Naohiro Aota,

Commit df321b214f62 ("btrfs: tests: zoned: add tests cases for zoned code") from Feb 4, 2026 (linux-next), leads to the following Smatch static checker warning:

fs/btrfs/tests/zoned-tests.c:68 test_load_zone_info()
warn: duplicate check 'zone_info' (previous on line 62)

fs/btrfs/tests/zoned-tests.c

    40 static int test_load_zone_info(struct btrfs_fs_info *fs_info,
    41                                const struct load_zone_info_test_vector *test)
    42 {
    43         struct btrfs_block_group *bg __free(btrfs_free_dummy_block_group) = NULL;
    44         struct btrfs_chunk_map *map __free(btrfs_free_chunk_map) = NULL;
    45         struct zone_info AUTO_KFREE(zone_info);
    46         unsigned long AUTO_KFREE(active);
    47         int ret;
    48 
    49         bg = btrfs_alloc_dummy_block_group(fs_info, test->bg_length);
    50         if (!bg) {
    51                 test_std_err(TEST_ALLOC_BLOCK_GROUP);
    52                 return -ENOMEM;
    53         }
    54 
    55         map = btrfs_alloc_chunk_map(test->num_stripes, GFP_KERNEL);
    56         if (!map) {
    57                 test_std_err(TEST_ALLOC_EXTENT_MAP);
    58                 return -ENOMEM;
    59         }
    60 
    61         zone_info = kcalloc(test->num_stripes, sizeof(*zone_info), GFP_KERNEL);
    62         if (!zone_info) {
    63                 test_err("cannot allocate zone info");
    64                 return -ENOMEM;
    65         }
    66 
    67         active = bitmap_zalloc(test->num_stripes, GFP_KERNEL);

--> 68 if (!zone_info) {

s/zone_info/active/

    69                 test_err("cannot allocate active bitmap");
    70                 return -ENOMEM;
    71         }
    72 

regards,
dan carpenter

#80 lore raw

Re: [bug report] btrfs: tests: zoned: add tests cases for zoned code

Quoted 40 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]
Hello Naohiro Aota,

Commit df321b214f62 ("btrfs: tests: zoned: add tests cases for zoned code") from Feb 4, 2026 (linux-next), leads to the following Smatch static checker warning:

fs/btrfs/tests/zoned-tests.c:68 test_load_zone_info()
warn: duplicate check 'zone_info' (previous on line 62)

fs/btrfs/tests/zoned-tests.c

    40 static int test_load_zone_info(struct btrfs_fs_info *fs_info,
    41                                const struct load_zone_info_test_vector *test)
    42 {
    43         struct btrfs_block_group *bg __free(btrfs_free_dummy_block_group) = NULL;
    44         struct btrfs_chunk_map *map __free(btrfs_free_chunk_map) = NULL;
    45         struct zone_info AUTO_KFREE(zone_info);
    46         unsigned long AUTO_KFREE(active);
    47         int ret;
    48 
    49         bg = btrfs_alloc_dummy_block_group(fs_info, test->bg_length);
    50         if (!bg) {
    51                 test_std_err(TEST_ALLOC_BLOCK_GROUP);
    52                 return -ENOMEM;
    53         }
    54 
    55         map = btrfs_alloc_chunk_map(test->num_stripes, GFP_KERNEL);
    56         if (!map) {
    57                 test_std_err(TEST_ALLOC_EXTENT_MAP);
    58                 return -ENOMEM;
    59         }
    60 
    61         zone_info = kcalloc(test->num_stripes, sizeof(*zone_info), GFP_KERNEL);
    62         if (!zone_info) {
    63                 test_err("cannot allocate zone info");
    64                 return -ENOMEM;
    65         }
    66 
    67         active = bitmap_zalloc(test->num_stripes, GFP_KERNEL);
Quoted 3 lines

--> 68 if (!zone_info) {

s/zone_info/active/

Thanks for the report, fixed in git.

#81 lore raw

[bug report] ASoC: SOF: sof-audio: Add support for loopback capture

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Ranjani Sridharan,

Commit c4b37c21c75d ("ASoC: SOF: sof-audio: Add support for loopback capture") from Feb 4, 2026 (linux-next), leads to the following Smatch static checker warning:

	sound/soc/sof/sof-audio.c:534 sof_prepare_widgets_in_path()
	error: uninitialized symbol 'widget_ops'.

sound/soc/sof/sof-audio.c

    478 static int
    479 sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
    480                             struct snd_pcm_hw_params *fe_params,
    481                             struct snd_sof_platform_stream_params *platform_params,
    482                             struct snd_pcm_hw_params *pipeline_params, int dir,
    483                             struct snd_soc_dapm_widget_list *list)
    484 {
    485         const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
    486         struct snd_sof_widget *swidget = widget->dobj.private;
    487         const struct sof_ipc_tplg_widget_ops *widget_ops;
    488         struct snd_soc_dapm_path *p;
    489         int ret;
    490 
    491         if (is_virtual_widget(sdev, widget, __func__))
    492                 return 0;
    493 
    494         if (!swidget)
    495                 goto sink_prepare;
                        ^^^^^^^^^^^^^^^^^

widget_ops is uninitialized.

    496 
    497         widget_ops = tplg_ops ? tplg_ops->widget : NULL;
    498         if (!widget_ops)
    499                 return 0;
    500 
    501         if (swidget->spipe && swidget->spipe->direction_valid &&
    502             !sof_widget_in_same_direction(swidget, dir))
    503                 return 0;
    504 
    505         /* skip widgets already prepared or aggregated DAI widgets*/
    506         if (!widget_ops[widget->id].ipc_prepare || swidget->prepared ||
    507             is_aggregated_dai(swidget))
    508                 goto sink_prepare;
    509 
    510         /* prepare the source widget */
    511         ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params,
    512                                              pipeline_params, dir);
    513         if (ret < 0) {
    514                 dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name);
    515                 return ret;
    516         }
    517 
    518         swidget->prepared = true;
    519 
    520 sink_prepare:
    521         /* prepare all widgets in the sink paths */
    522         snd_soc_dapm_widget_for_each_sink_path(widget, p) {
    523                 if (!widget_in_list(list, p->sink))
    524                         continue;
    525 
    526                 if (!p->walking && p->sink->dobj.private) {
    527                         p->walking = true;
    528                         ret = sof_prepare_widgets_in_path(sdev, p->sink,  fe_params,
    529                                                           platform_params, pipeline_params, dir,
    530                                                           list);
    531                         p->walking = false;
    532                         if (ret < 0) {
    533                                 /* unprepare the source widget */
--> 534                                 if (widget_ops[widget->id].ipc_unprepare &&
    535                                     swidget && swidget->prepared && swidget->use_count == 0) {

We need to check that swidget is non-NULL first before checking widget_ops[widget->id].ipc_unprepare, otherwise widget_ops is uninitialized and it leads to a crash.

Wait, the zero day bot already reported this on Jan 5th.
https://lore.kernel.org/all/[email protected]/

    536                                         widget_ops[widget->id].ipc_unprepare(swidget);
    537                                         swidget->prepared = false;
    538                                 }
    539                                 return ret;
    540                         }
    541                 }
    542         }
    543 
    544         return 0;
    545 }

regards,
dan carpenter

#82 lore raw

[bug report] bpf: Fix a potential use-after-free of BTF object

In reply to Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Anton Protopopov,

Commit c81e4322acf0 ("bpf: Fix a potential use-after-free of BTF object") from Feb 9, 2026 (linux-next), leads to the following Smatch static checker warning:

	kernel/bpf/verifier.c:25375 add_fd_from_fd_array()
	warn: double fget(): 'fd'

kernel/bpf/verifier.c

    25360 static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd)
    25361 {
    25362         struct bpf_map *map;
    25363         struct btf *btf;
    25364         CLASS(fd, f)(fd);

This assigns f = fdget(fd);

    25365         int err;
    25366 
    25367         map = __bpf_map_get(f);
    25368         if (!IS_ERR(map)) {
    25369                 err = __add_used_map(env, map);
    25370                 if (err < 0)
    25371                         return err;
    25372                 return 0;
    25373         }
    25374 
--> 25375         btf = btf_get_by_fd(fd);
                                      ^^

This re-uses the fd. The reason behind the warning is that the user could have changed the fd to point to a different file from the start of the function.

    25376         if (!IS_ERR(btf))
    25377                 return __add_used_btf(env, btf);
    25378 
    25379         verbose(env, "fd %d is not pointing to valid bpf_map or btf\n", fd);
    25380         return PTR_ERR(map);
    25381 }

regards,
dan carpenter

#83 lore raw

Re: [bug report] bpf: Fix a potential use-after-free of BTF object

Quoted 33 lines · Dan Carpenter

[ Smatch checking is paused while we raise funding. #SadFace
https://lore.kernel.org/all/[email protected]/ -dan ]

Hello Anton Protopopov,

Commit c81e4322acf0 ("bpf: Fix a potential use-after-free of BTF object") from Feb 9, 2026 (linux-next), leads to the following Smatch static checker warning:

	kernel/bpf/verifier.c:25375 add_fd_from_fd_array()
	warn: double fget(): 'fd'

kernel/bpf/verifier.c

    25360 static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd)
    25361 {
    25362         struct bpf_map *map;
    25363         struct btf *btf;
    25364         CLASS(fd, f)(fd);

This assigns f = fdget(fd);

    25365         int err;
    25366 
    25367         map = __bpf_map_get(f);
    25368         if (!IS_ERR(map)) {
    25369                 err = __add_used_map(env, map);
    25370                 if (err < 0)
    25371                         return err;
    25372                 return 0;
    25373         }
    25374 
--> 25375         btf = btf_get_by_fd(fd);
                                      ^^
Quoted 3 lines

This re-uses the fd. The reason behind the warning is that the user could have changed the fd to point to a different file from the start of the function.

True, this could happen. Not sure this is a real problem (if a user replaced this by a valid BTF, well...)

Quoted 2 lines
    25376         if (!IS_ERR(btf))
    25377                 return __add_used_btf(env, btf);

The problem with this piece of code is that originally I wanted to keep naming/appearance in sync, but the corresponding map/btf functions, historically, behave a bit different...

To keep things working and to address the bug report in this thread, one fix is required:

-       btf = btf_get_by_fd(fd);
-       if (!IS_ERR(btf))
+       btf = __btf_get_by_fd(f);
+       if (!IS_ERR(btf)) {
+               btf_get(btf);
                return __add_used_btf(env, btf);

+ }

I will send this fix later.

Quoted 6 lines
    25379         verbose(env, "fd %d is not pointing to valid bpf_map or btf\n", fd);
    25380         return PTR_ERR(map);
    25381 }

regards,
dan carpenter