From 03a39b990470257e86a2f6974f939637fa0a6059 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mar 01 2023 08:27:05 +0000 Subject: - Delete patches.suse/char-pcmcia-cm4000_cs-Fix-use-after-free-in-cm4000_f.patch. - Delete patches.suse/char-pcmcia-cm4040_cs-Fix-use-after-free-in-reader_f.patch. - Delete patches.suse/char-pcmcia-scr24x_cs-Fix-use-after-free-in-scr24x_f.patch. These drivers are now disabled, so remove the non-upstream patches. See bsc#1208775. --- diff --git a/patches.suse/char-pcmcia-cm4000_cs-Fix-use-after-free-in-cm4000_f.patch b/patches.suse/char-pcmcia-cm4000_cs-Fix-use-after-free-in-cm4000_f.patch deleted file mode 100644 index 235660a..0000000 --- a/patches.suse/char-pcmcia-cm4000_cs-Fix-use-after-free-in-cm4000_f.patch +++ /dev/null @@ -1,147 +0,0 @@ -From: Hyunwoo Kim -Date: Sun, 18 Sep 2022 21:07:01 -0700 -Subject: char: pcmcia: cm4000_cs: Fix use-after-free in cm4000_fops -Patch-mainline: Submitted, 20220919040701.GA302806@ubuntu -References: bsc#1204894 CVE-2022-44032 - -A race condition may occur if the user physically removes the pcmcia -device while calling open() for this char device node. - -This is a race condition between the cmm_open() function and the -cm4000_detach() function, which may eventually result in UAF. - -So, add a refcount check to cm4000_detach() to free the "dev" structure -after the char device node is close()d. - -Signed-off-by: Hyunwoo Kim -Signed-off-by: Jiri Slaby ---- - drivers/char/pcmcia/cm4000_cs.c | 58 ++++++++++++++++++++++++++++------------ - 1 file changed, 41 insertions(+), 17 deletions(-) - ---- a/drivers/char/pcmcia/cm4000_cs.c -+++ b/drivers/char/pcmcia/cm4000_cs.c -@@ -55,6 +55,7 @@ - } while (0) - - static DEFINE_MUTEX(cmm_mutex); -+static DEFINE_MUTEX(remove_mutex); - - #define T_1SEC (HZ) - #define T_10MSEC msecs_to_jiffies(10) -@@ -103,7 +104,8 @@ static int major; /* major number we ge - #define REG_STOPBITS(x) (x + 7) - - struct cm4000_dev { -- struct pcmcia_device *p_dev; -+ struct pcmcia_device *p_dev; -+ struct kref refcnt; - - unsigned char atr[MAX_ATR]; - unsigned char rbuf[512]; -@@ -146,6 +148,9 @@ struct cm4000_dev { - - #define ZERO_DEV(dev) memset(&((dev)->init), 0, sizeof((dev)->init)) - -+static void stop_monitor(struct cm4000_dev *dev); -+static void cm4000_delete(struct kref *kref); -+ - static struct pcmcia_device *dev_table[CM4000_MAX_DEV]; - static struct class *cmm_class; - -@@ -416,6 +421,30 @@ static struct card_fixup card_fixups[] = - }, - }; - -+ -+static void cm4000_delete(struct kref *kref) -+{ -+ struct cm4000_dev *dev = container_of(kref, struct cm4000_dev, refcnt); -+ struct pcmcia_device *link = dev->p_dev; -+ int devno; -+ -+ /* find device */ -+ for (devno = 0; devno < CM4000_MAX_DEV; devno++) -+ if (dev_table[devno] == link) -+ break; -+ if (devno == CM4000_MAX_DEV) -+ return; -+ -+ stop_monitor(dev); -+ -+ cm4000_release(link); -+ -+ dev_table[devno] = NULL; -+ kfree(dev); -+ -+ device_destroy(cmm_class, MKDEV(major, devno)); -+} -+ - static void set_cardparameter(struct cm4000_dev *dev) - { - int i; -@@ -1629,6 +1658,7 @@ static int cmm_open(struct inode *inode, - if (minor >= CM4000_MAX_DEV) - return -ENODEV; - -+ mutex_lock(&remove_mutex); - mutex_lock(&cmm_mutex); - link = dev_table[minor]; - if (link == NULL || !pcmcia_dev_present(link)) { -@@ -1673,8 +1703,12 @@ static int cmm_open(struct inode *inode, - - DEBUGP(2, dev, "<- cmm_open\n"); - ret = stream_open(inode, filp); -+ -+ kref_get(&dev->refcnt); - out: - mutex_unlock(&cmm_mutex); -+ mutex_unlock(&remove_mutex); -+ - return ret; - } - -@@ -1703,6 +1737,8 @@ static int cmm_close(struct inode *inode - link->open = 0; /* only one open per device */ - wake_up(&dev->devq); /* socket removed? */ - -+ kref_put(&dev->refcnt, cm4000_delete); -+ - DEBUGP(2, dev, "cmm_close\n"); - return 0; - } -@@ -1808,6 +1844,7 @@ static int cm4000_probe(struct pcmcia_de - init_waitqueue_head(&dev->ioq); - init_waitqueue_head(&dev->atrq); - init_waitqueue_head(&dev->readq); -+ kref_init(&dev->refcnt); - - ret = cm4000_config(link, i); - if (ret) { -@@ -1824,23 +1861,10 @@ static int cm4000_probe(struct pcmcia_de - static void cm4000_detach(struct pcmcia_device *link) - { - struct cm4000_dev *dev = link->priv; -- int devno; -- -- /* find device */ -- for (devno = 0; devno < CM4000_MAX_DEV; devno++) -- if (dev_table[devno] == link) -- break; -- if (devno == CM4000_MAX_DEV) -- return; -- -- stop_monitor(dev); -- -- cm4000_release(link); - -- dev_table[devno] = NULL; -- kfree(dev); -- -- device_destroy(cmm_class, MKDEV(major, devno)); -+ mutex_lock(&remove_mutex); -+ kref_put(&dev->refcnt, cm4000_delete); -+ mutex_unlock(&remove_mutex); - - return; - } diff --git a/patches.suse/char-pcmcia-cm4040_cs-Fix-use-after-free-in-reader_f.patch b/patches.suse/char-pcmcia-cm4040_cs-Fix-use-after-free-in-reader_f.patch deleted file mode 100644 index 8adebc8..0000000 --- a/patches.suse/char-pcmcia-cm4040_cs-Fix-use-after-free-in-reader_f.patch +++ /dev/null @@ -1,132 +0,0 @@ -From: Hyunwoo Kim -Date: Sun, 18 Sep 2022 21:04:57 -0700 -Subject: char: pcmcia: cm4040_cs: Fix use-after-free in reader_fops -Patch-mainline: Submitted, 20220919040457.GA302681@ubuntu -References: bsc#1204922 CVE-2022-44033 - -A race condition may occur if the user physically removes the pcmcia -device while calling open() for this char device node. - -This is a race condition between the cm4040_open() function and the -reader_detach() function, which may eventually result in UAF. - -So, add a refcount check to reader_detach() to free the "dev" structure -after the char device node is close()d. - -Signed-off-by: Hyunwoo Kim -Signed-off-by: Jiri Slaby ---- - drivers/char/pcmcia/cm4040_cs.c | 50 ++++++++++++++++++++++++++++------------ - 1 file changed, 35 insertions(+), 15 deletions(-) - ---- a/drivers/char/pcmcia/cm4040_cs.c -+++ b/drivers/char/pcmcia/cm4040_cs.c -@@ -59,6 +59,7 @@ static DEFINE_MUTEX(cm4040_mutex); - /* how often to poll for fifo status change */ - #define POLL_PERIOD msecs_to_jiffies(10) - -+static void cm4040_delete(struct kref *kref); - static void reader_release(struct pcmcia_device *link); - - static int major; -@@ -73,6 +74,7 @@ struct reader_dev { - wait_queue_head_t poll_wait; - wait_queue_head_t read_wait; - wait_queue_head_t write_wait; -+ struct kref refcnt; - unsigned long buffer_status; - unsigned long timeout; - unsigned char s_buf[READ_WRITE_BUFFER_SIZE]; -@@ -102,6 +104,28 @@ static inline unsigned char xinb(unsigne - } - #endif - -+static void cm4040_delete(struct kref *kref) -+{ -+ struct reader_dev *dev = container_of(kref, struct reader_dev, refcnt); -+ struct pcmcia_device *link = dev->p_dev; -+ int devno; -+ -+ /* find device */ -+ for (devno = 0; devno < CM_MAX_DEV; devno++) { -+ if (dev_table[devno] == link) -+ break; -+ } -+ if (devno == CM_MAX_DEV) -+ return; -+ -+ reader_release(link); -+ -+ dev_table[devno] = NULL; -+ kfree(dev); -+ -+ device_destroy(cmx_class, MKDEV(major, devno)); -+} -+ - /* poll the device fifo status register. not to be confused with - * the poll syscall. */ - static void cm4040_do_poll(struct timer_list *t) -@@ -442,6 +466,7 @@ static int cm4040_open(struct inode *ino - return -ENODEV; - - mutex_lock(&cm4040_mutex); -+ - link = dev_table[minor]; - if (link == NULL || !pcmcia_dev_present(link)) { - ret = -ENODEV; -@@ -468,8 +493,11 @@ static int cm4040_open(struct inode *ino - - DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); - ret = nonseekable_open(inode, filp); -+ -+ kref_get(&dev->refcnt); - out: - mutex_unlock(&cm4040_mutex); -+ - return ret; - } - -@@ -495,6 +523,9 @@ static int cm4040_close(struct inode *in - wake_up(&dev->devq); - - DEBUGP(2, dev, "<- cm4040_close\n"); -+ -+ kref_put(&dev->refcnt, cm4040_delete); -+ - return 0; - } - -@@ -584,6 +615,7 @@ static int reader_probe(struct pcmcia_de - init_waitqueue_head(&dev->read_wait); - init_waitqueue_head(&dev->write_wait); - timer_setup(&dev->poll_timer, cm4040_do_poll, 0); -+ kref_init(&dev->refcnt); - - ret = reader_config(link, i); - if (ret) { -@@ -600,22 +632,10 @@ static int reader_probe(struct pcmcia_de - static void reader_detach(struct pcmcia_device *link) - { - struct reader_dev *dev = link->priv; -- int devno; -- -- /* find device */ -- for (devno = 0; devno < CM_MAX_DEV; devno++) { -- if (dev_table[devno] == link) -- break; -- } -- if (devno == CM_MAX_DEV) -- return; -- -- reader_release(link); -- -- dev_table[devno] = NULL; -- kfree(dev); - -- device_destroy(cmx_class, MKDEV(major, devno)); -+ mutex_lock(&cm4040_mutex); -+ kref_put(&dev->refcnt, cm4040_delete); -+ mutex_unlock(&cm4040_mutex); - - return; - } diff --git a/patches.suse/char-pcmcia-scr24x_cs-Fix-use-after-free-in-scr24x_f.patch b/patches.suse/char-pcmcia-scr24x_cs-Fix-use-after-free-in-scr24x_f.patch deleted file mode 100644 index 1006cff..0000000 --- a/patches.suse/char-pcmcia-scr24x_cs-Fix-use-after-free-in-scr24x_f.patch +++ /dev/null @@ -1,161 +0,0 @@ -From: Hyunwoo Kim -Date: Mon, 19 Sep 2022 03:18:25 -0700 -Subject: char: pcmcia: scr24x_cs: Fix use-after-free in scr24x_fops -Patch-mainline: Submitted, 20220919101825.GA313940@ubuntu -References: bsc#1204901 CVE-2022-44034 - -A race condition may occur if the user physically removes the -pcmcia device while calling open() for this char device node. - -This is a race condition between the scr24x_open() function and -the scr24x_remove() function, which may eventually result in UAF. - -So, add a mutex to the scr24x_open() and scr24x_remove() functions -to avoid race contidion of krefs. - -Signed-off-by: Hyunwoo Kim -Reported-by: kernel test robot -Signed-off-by: Jiri Slaby ---- - drivers/char/pcmcia/scr24x_cs.c | 73 ++++++++++++++++++++++++++++------------ - 1 file changed, 52 insertions(+), 21 deletions(-) - ---- a/drivers/char/pcmcia/scr24x_cs.c -+++ b/drivers/char/pcmcia/scr24x_cs.c -@@ -33,6 +33,7 @@ - - struct scr24x_dev { - struct device *dev; -+ struct pcmcia_device *p_dev; - struct cdev c_dev; - unsigned char buf[CCID_MAX_LEN]; - int devno; -@@ -42,15 +43,31 @@ struct scr24x_dev { - }; - - #define SCR24X_DEVS 8 --static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS); -+static struct pcmcia_device *dev_table[SCR24X_DEVS]; -+static DEFINE_MUTEX(remove_mutex); - - static struct class *scr24x_class; - static dev_t scr24x_devt; - - static void scr24x_delete(struct kref *kref) - { -- struct scr24x_dev *dev = container_of(kref, struct scr24x_dev, -- refcnt); -+ struct scr24x_dev *dev = container_of(kref, struct scr24x_dev, refcnt); -+ struct pcmcia_device *link = dev->p_dev; -+ int devno; -+ -+ for (devno = 0; devno < SCR24X_DEVS; devno++) { -+ if (dev_table[devno] == link) -+ break; -+ } -+ if (devno == SCR24X_DEVS) -+ return; -+ -+ device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno)); -+ mutex_lock(&dev->lock); -+ pcmcia_disable_device(link); -+ cdev_del(&dev->c_dev); -+ dev->dev = NULL; -+ mutex_unlock(&dev->lock); - - kfree(dev); - } -@@ -73,11 +90,24 @@ static int scr24x_wait_ready(struct scr2 - - static int scr24x_open(struct inode *inode, struct file *filp) - { -- struct scr24x_dev *dev = container_of(inode->i_cdev, -- struct scr24x_dev, c_dev); -+ struct scr24x_dev *dev; -+ struct pcmcia_device *link; -+ int minor = iminor(inode); -+ -+ if (minor >= SCR24X_DEVS) -+ return -ENODEV; -+ -+ mutex_lock(&remove_mutex); -+ link = dev_table[minor]; -+ if (link == NULL) { -+ mutex_unlock(&remove_mutex); -+ return -ENODEV; -+ } - -+ dev = link->priv; - kref_get(&dev->refcnt); - filp->private_data = dev; -+ mutex_unlock(&remove_mutex); - - return stream_open(inode, filp); - } -@@ -232,24 +262,31 @@ static int scr24x_config_check(struct pc - static int scr24x_probe(struct pcmcia_device *link) - { - struct scr24x_dev *dev; -- int ret; -+ int i, ret; -+ -+ for (i = 0; i < SCR24X_DEVS; i++) { -+ if (dev_table[i] == NULL) -+ break; -+ } -+ -+ if (i == SCR24X_DEVS) -+ return -ENODEV; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - -- dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS); -- if (dev->devno >= SCR24X_DEVS) { -- ret = -EBUSY; -- goto err; -- } -+ dev->devno = i; - - mutex_init(&dev->lock); - kref_init(&dev->refcnt); - - link->priv = dev; -+ dev->p_dev = link; - link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - -+ dev_table[i] = link; -+ - ret = pcmcia_loop_config(link, scr24x_config_check, NULL); - if (ret < 0) - goto err; -@@ -282,8 +319,8 @@ static int scr24x_probe(struct pcmcia_de - return 0; - - err: -- if (dev->devno < SCR24X_DEVS) -- clear_bit(dev->devno, scr24x_minors); -+ dev_table[i] = NULL; -+ - kfree (dev); - return ret; - } -@@ -292,15 +329,9 @@ static void scr24x_remove(struct pcmcia_ - { - struct scr24x_dev *dev = (struct scr24x_dev *)link->priv; - -- device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno)); -- mutex_lock(&dev->lock); -- pcmcia_disable_device(link); -- cdev_del(&dev->c_dev); -- clear_bit(dev->devno, scr24x_minors); -- dev->dev = NULL; -- mutex_unlock(&dev->lock); -- -+ mutex_lock(&remove_mutex); - kref_put(&dev->refcnt, scr24x_delete); -+ mutex_unlock(&remove_mutex); - } - - static const struct pcmcia_device_id scr24x_ids[] = { diff --git a/series.conf b/series.conf index 38443a0..9ec5728 100644 --- a/series.conf +++ b/series.conf @@ -86,9 +86,6 @@ # to get into mainline any time soon (or ever) belong # to area specific sections below. ######################################################## - patches.suse/char-pcmcia-cm4000_cs-Fix-use-after-free-in-cm4000_f.patch - patches.suse/char-pcmcia-cm4040_cs-Fix-use-after-free-in-reader_f.patch - patches.suse/char-pcmcia-scr24x_cs-Fix-use-after-free-in-scr24x_f.patch ######################################################## # kbuild/module infrastructure fixes