On Wed, Nov 4, 2026 at 6:30 PM Christian Brauner <[email protected]> wrote: > > isapnp_cfg_begin() refuses a logical device number above 10 and a bad > card number with -EINVAL before it takes isapnp_cfg_mutex. The callers > that read and write the device's configuration, the proc file included, > don't look at that: they go on talking to whatever device the card > currently has selected and then unlock a mutex they never took in > isapnp_cfg_end(). isapnp_create_device() hands out logical device > numbers without a bound, so a card with twelve or more logical devices > gets there. Return the error instead. > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Cc: [email protected] > Signed-off-by: Christian Brauner (Amutable) <[email protected]>
Acked-by: Rafael J. Wysocki (Intel) <[email protected]> > --- > drivers/pnp/isapnp/core.c | 16 ++++++++++++---- > drivers/pnp/isapnp/proc.c | 5 ++++- > sound/isa/es18xx.c | 6 +++++- > 3 files changed, 21 insertions(+), 6 deletions(-) > > diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c > index 219f96f2aaaf..3591a2791c1a 100644 > --- a/drivers/pnp/isapnp/core.c > +++ b/drivers/pnp/isapnp/core.c > @@ -853,7 +853,9 @@ static int isapnp_get_resources(struct pnp_dev *dev) > > pnp_dbg(&dev->dev, "get resources\n"); > pnp_init_resources(dev); > - isapnp_cfg_begin(dev->card->number, dev->number); > + ret = isapnp_cfg_begin(dev->card->number, dev->number); > + if (ret) > + return ret; > dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); > if (!dev->active) > goto __end; > @@ -887,10 +889,12 @@ __end: > static int isapnp_set_resources(struct pnp_dev *dev) > { > struct resource *res; > - int tmp; > + int tmp, ret; > > pnp_dbg(&dev->dev, "set resources\n"); > - isapnp_cfg_begin(dev->card->number, dev->number); > + ret = isapnp_cfg_begin(dev->card->number, dev->number); > + if (ret) > + return ret; > dev->active = 1; > for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { > res = pnp_get_resource(dev, IORESOURCE_IO, tmp); > @@ -936,9 +940,13 @@ static int isapnp_set_resources(struct pnp_dev *dev) > > static int isapnp_disable_resources(struct pnp_dev *dev) > { > + int ret; > + > if (!dev->active) > return -EINVAL; > - isapnp_cfg_begin(dev->card->number, dev->number); > + ret = isapnp_cfg_begin(dev->card->number, dev->number); > + if (ret) > + return ret; > isapnp_deactivate(dev->number); > dev->active = 0; > isapnp_cfg_end(); > diff --git a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c > index c1f6e6bd0eb2..b3abab24050b 100644 > --- a/drivers/pnp/isapnp/proc.c > +++ b/drivers/pnp/isapnp/proc.c > @@ -25,6 +25,7 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char > __user * buf, > struct pnp_dev *dev = pde_data(file_inode(file)); > int pos = *ppos; > int cnt, size = 256; > + int ret; > > if (pos >= size) > return 0; > @@ -37,7 +38,9 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char > __user * buf, > if (!access_ok(buf, cnt)) > return -EINVAL; > > - isapnp_cfg_begin(dev->card->number, dev->number); > + ret = isapnp_cfg_begin(dev->card->number, dev->number); > + if (ret) > + return ret; > for (; pos < 256 && cnt > 0; pos++, buf++, cnt--) { > unsigned char val; > val = isapnp_read_byte(pos); > diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c > index 3cadbf7cf238..de1eda5a0656 100644 > --- a/sound/isa/es18xx.c > +++ b/sound/isa/es18xx.c > @@ -1950,7 +1950,11 @@ static int snd_audiodrive_pnp_init_main(int dev, > struct pnp_dev *pdev) > /* ok. hack using Vendor-Defined Card-Level registers */ > /* skip csn and logdev initialization - already done in > isapnp_configure */ > if (pnp_device_is_isapnp(pdev)) { > - isapnp_cfg_begin(isapnp_card_number(pdev), > isapnp_csn_number(pdev)); > + int ret = isapnp_cfg_begin(isapnp_card_number(pdev), > + isapnp_csn_number(pdev)); > + > + if (ret) > + return ret; > isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware > Volume IRQ Number */ > if (mpu_port[dev] != SNDRV_AUTO_PORT) > isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 > IRQ Number */ > > -- > 2.53.0 > >
