Re: UBSAN: shift-out-of-bounds in sound/pci/ctxfi/cthw20k2.c:956:31

From: Takashi Iwai

Date: Mon Mar 16 2026 - 04:46:39 EST


On Sun, 15 Mar 2026 16:50:04 +0100,
Karsten Hohmeier wrote:
>
> Hello Takashi,
>
> Updated to 6.19.8 and got some more UBSAN errors.
> Care to take a look?

Through a quick glance, the patch below should paper over it, but we'd
need to check the printed error values. You can uncomment
"//dump_stack();" lines to show the stack traces for further
investigation, too.


Takashi

-- 8< --
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index b8bde27f3a1d..ad465f66e5bc 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -99,7 +99,7 @@ static const struct rsc_ops daio_in_rsc_ops_20k2 = {
.output_slot = daio_index,
};

-static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
+static int daio_device_index(enum DAIOTYP type, struct hw *hw)
{
switch (hw->chip_type) {
case ATC20K1:
@@ -112,7 +112,10 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
case LINEO3: return 5;
case LINEO4: return 6;
case LINEIM: return 7;
- default: return -EINVAL;
+ default:
+ pr_err("XXX invalid type %d for hw20k1\n", type);
+ //dump_stack();
+ return -EINVAL;
}
case ATC20K2:
switch (type) {
@@ -125,9 +128,14 @@ static unsigned int daio_device_index(enum DAIOTYP type, struct hw *hw)
case LINEIM: return 4;
case MIC: return 5;
case RCA: return 3;
- default: return -EINVAL;
+ default:
+ pr_err("XXX invalid type %d for hw20k2\n", type);
+ //dump_stack();
+ return -EINVAL;
}
default:
+ pr_err("XXX invalid chip type %d\n", hw->chip_type);
+ //dump_stack();
return -EINVAL;
}
}
@@ -148,8 +156,11 @@ static int dao_spdif_set_spos(struct dao *dao, unsigned int spos)

static int dao_commit_write(struct dao *dao)
{
- dao->hw->dao_commit_write(dao->hw,
- daio_device_index(dao->daio.type, dao->hw), dao->ctrl_blk);
+ int idx = daio_device_index(dao->daio.type, dao->hw);
+
+ if (idx < 0)
+ return idx;
+ dao->hw->dao_commit_write(dao->hw, idx, dao->ctrl_blk);
return 0;
}

@@ -287,8 +298,11 @@ static int dai_set_enb_srt(struct dai *dai, unsigned int enb)

static int dai_commit_write(struct dai *dai)
{
- dai->hw->dai_commit_write(dai->hw,
- daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
+ int idx = daio_device_index(dai->daio.type, dai->hw);
+
+ if (idx < 0)
+ return idx;
+ dai->hw->dai_commit_write(dai->hw, idx, dai->ctrl_blk);
return 0;
}

@@ -367,7 +381,7 @@ static int dao_rsc_init(struct dao *dao,
{
struct hw *hw = mgr->mgr.hw;
unsigned int conf;
- int err;
+ int idx, err;

err = daio_rsc_init(&dao->daio, desc, mgr->mgr.hw);
if (err)
@@ -386,15 +400,18 @@ static int dao_rsc_init(struct dao *dao,
if (err)
goto error2;

- hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
- daio_device_index(dao->daio.type, hw));
+ idx = daio_device_index(dao->daio.type, hw);
+ if (idx < 0) {
+ err = idx;
+ goto error2;
+ }
+
+ hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, idx);
hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);

conf = (desc->msr & 0x7) | (desc->passthru << 3);
- hw->daio_mgr_dao_init(hw, mgr->mgr.ctrl_blk,
- daio_device_index(dao->daio.type, hw), conf);
- hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
- daio_device_index(dao->daio.type, hw));
+ hw->daio_mgr_dao_init(hw, mgr->mgr.ctrl_blk, idx, conf);
+ hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, idx);
hw->daio_mgr_commit_write(hw, mgr->mgr.ctrl_blk);

return 0;
@@ -443,7 +460,7 @@ static int dai_rsc_init(struct dai *dai,
const struct daio_desc *desc,
struct daio_mgr *mgr)
{
- int err;
+ int idx, err;
struct hw *hw = mgr->mgr.hw;
unsigned int rsr, msr;

@@ -457,6 +474,12 @@ static int dai_rsc_init(struct dai *dai,
if (err)
goto error1;

+ idx = daio_device_index(dai->daio.type, dai->hw);
+ if (idx < 0) {
+ err = idx;
+ goto error1;
+ }
+
for (rsr = 0, msr = desc->msr; msr > 1; msr >>= 1)
rsr++;

@@ -465,8 +488,7 @@ static int dai_rsc_init(struct dai *dai,
/* default to disabling control of a SRC */
hw->dai_srt_set_ec(dai->ctrl_blk, 0);
hw->dai_srt_set_et(dai->ctrl_blk, 0); /* default to disabling SRT */
- hw->dai_commit_write(hw,
- daio_device_index(dai->daio.type, dai->hw), dai->ctrl_blk);
+ hw->dai_commit_write(hw, idx, dai->ctrl_blk);

return 0;

@@ -581,28 +603,28 @@ static int put_daio_rsc(struct daio_mgr *mgr, struct daio *daio)
static int daio_mgr_enb_daio(struct daio_mgr *mgr, struct daio *daio)
{
struct hw *hw = mgr->mgr.hw;
+ int idx = daio_device_index(daio->type, hw);

- if (daio->output) {
- hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk,
- daio_device_index(daio->type, hw));
- } else {
- hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk,
- daio_device_index(daio->type, hw));
- }
+ if (idx < 0)
+ return idx;
+ if (daio->output)
+ hw->daio_mgr_enb_dao(mgr->mgr.ctrl_blk, idx);
+ else
+ hw->daio_mgr_enb_dai(mgr->mgr.ctrl_blk, idx);
return 0;
}

static int daio_mgr_dsb_daio(struct daio_mgr *mgr, struct daio *daio)
{
struct hw *hw = mgr->mgr.hw;
+ int idx = daio_device_index(daio->type, hw);

- if (daio->output) {
- hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk,
- daio_device_index(daio->type, hw));
- } else {
- hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk,
- daio_device_index(daio->type, hw));
- }
+ if (idx < 0)
+ return idx;
+ if (daio->output)
+ hw->daio_mgr_dsb_dao(mgr->mgr.ctrl_blk, idx);
+ else
+ hw->daio_mgr_dsb_dai(mgr->mgr.ctrl_blk, idx);
return 0;
}