From 8149fc452f1389591e9a22fa924e12e1e137467c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 27 Apr 2021 10:25:22 +0200 Subject: [PATCH] Revert "drop net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch from 4.4, 4.9, and 4.14" This reverts commit 7adde284e07ec510c91fcca1112b05d41319ab43 and brings these patches back as we now have a fix. --- ...ref-during-tty-device-unregistration.patch | 146 ++++++++++++++++++ queue-4.14/series | 1 + ...ref-during-tty-device-unregistration.patch | 146 ++++++++++++++++++ queue-4.4/series | 1 + ...ref-during-tty-device-unregistration.patch | 146 ++++++++++++++++++ queue-4.9/series | 1 + 6 files changed, 441 insertions(+) create mode 100644 queue-4.14/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch create mode 100644 queue-4.4/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch create mode 100644 queue-4.9/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch diff --git a/queue-4.14/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch b/queue-4.14/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch new file mode 100644 index 00000000000..bba0ece6170 --- /dev/null +++ b/queue-4.14/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch @@ -0,0 +1,146 @@ +From foo@baz Sat Apr 24 04:46:10 PM CEST 2021 +From: Anirudh Rayabharam +Date: Wed, 7 Apr 2021 22:57:22 +0530 +Subject: net: hso: fix null-ptr-deref during tty device unregistration + +From: Anirudh Rayabharam + +commit 8a12f8836145ffe37e9c8733dce18c22fb668b66 upstream + +Multiple ttys try to claim the same the minor number causing a double +unregistration of the same device. The first unregistration succeeds +but the next one results in a null-ptr-deref. + +The get_free_serial_index() function returns an available minor number +but doesn't assign it immediately. The assignment is done by the caller +later. But before this assignment, calls to get_free_serial_index() +would return the same minor number. + +Fix this by modifying get_free_serial_index to assign the minor number +immediately after one is found to be and rename it to obtain_minor() +to better reflect what it does. Similary, rename set_serial_by_index() +to release_minor() and modify it to free up the minor number of the +given hso_serial. Every obtain_minor() should have corresponding +release_minor() call. + +Fixes: 72dc1c096c705 ("HSO: add option hso driver") +Reported-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Tested-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Anirudh Rayabharam +Signed-off-by: David S. Miller +[sudip: adjust context] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 33 ++++++++++++--------------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -626,7 +626,7 @@ static struct hso_serial *get_serial_by_ + return serial; + } + +-static int get_free_serial_index(void) ++static int obtain_minor(struct hso_serial *serial) + { + int index; + unsigned long flags; +@@ -634,8 +634,10 @@ static int get_free_serial_index(void) + spin_lock_irqsave(&serial_table_lock, flags); + for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { + if (serial_table[index] == NULL) { ++ serial_table[index] = serial->parent; ++ serial->minor = index; + spin_unlock_irqrestore(&serial_table_lock, flags); +- return index; ++ return 0; + } + } + spin_unlock_irqrestore(&serial_table_lock, flags); +@@ -644,15 +646,12 @@ static int get_free_serial_index(void) + return -1; + } + +-static void set_serial_by_index(unsigned index, struct hso_serial *serial) ++static void release_minor(struct hso_serial *serial) + { + unsigned long flags; + + spin_lock_irqsave(&serial_table_lock, flags); +- if (serial) +- serial_table[index] = serial->parent; +- else +- serial_table[index] = NULL; ++ serial_table[serial->minor] = NULL; + spin_unlock_irqrestore(&serial_table_lock, flags); + } + +@@ -2241,6 +2240,7 @@ static int hso_stop_serial_device(struct + static void hso_serial_tty_unregister(struct hso_serial *serial) + { + tty_unregister_device(tty_drv, serial->minor); ++ release_minor(serial); + } + + static void hso_serial_common_free(struct hso_serial *serial) +@@ -2265,25 +2265,23 @@ static int hso_serial_common_create(stru + int rx_size, int tx_size) + { + struct device *dev; +- int minor; + int i; + + tty_port_init(&serial->port); + +- minor = get_free_serial_index(); +- if (minor < 0) ++ if (obtain_minor(serial)) + goto exit2; + + /* register our minor number */ + serial->parent->dev = tty_port_register_device_attr(&serial->port, +- tty_drv, minor, &serial->parent->interface->dev, ++ tty_drv, serial->minor, &serial->parent->interface->dev, + serial->parent, hso_serial_dev_groups); +- if (IS_ERR(serial->parent->dev)) ++ if (IS_ERR(serial->parent->dev)) { ++ release_minor(serial); + goto exit2; ++ } + dev = serial->parent->dev; + +- /* fill in specific data for later use */ +- serial->minor = minor; + serial->magic = HSO_SERIAL_MAGIC; + spin_lock_init(&serial->serial_lock); + serial->num_rx_urbs = num_urbs; +@@ -2676,9 +2674,6 @@ static struct hso_device *hso_create_bul + + serial->write_data = hso_std_serial_write_data; + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -2735,9 +2730,6 @@ struct hso_device *hso_create_mux_serial + serial->shared_int->ref_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -3122,7 +3114,6 @@ static void hso_free_interface(struct us + cancel_work_sync(&serial_table[i]->async_get_intf); + hso_serial_tty_unregister(serial); + kref_put(&serial_table[i]->ref, hso_serial_ref_free); +- set_serial_by_index(i, NULL); + } + } + diff --git a/queue-4.14/series b/queue-4.14/series index df8b6ae5e87..48d3ba30f3a 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -34,6 +34,7 @@ ibmvnic-remove-duplicate-napi_schedule-call-in-open-function.patch arm-footbridge-fix-pci-interrupt-mapping.patch arm-9071-1-uprobes-don-t-hook-on-thumb-instructions.patch gup-document-and-work-around-cow-can-break-either-way-issue.patch +net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch ext4-correct-error-label-in-ext4_rename.patch pinctrl-lewisburg-update-number-of-pins-in-community.patch hid-alps-fix-error-return-code-in-alps_input_configu.patch diff --git a/queue-4.4/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch b/queue-4.4/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch new file mode 100644 index 00000000000..fcb835fb109 --- /dev/null +++ b/queue-4.4/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch @@ -0,0 +1,146 @@ +From foo@baz Sat Apr 24 04:46:05 PM CEST 2021 +From: Anirudh Rayabharam +Date: Wed, 7 Apr 2021 22:57:22 +0530 +Subject: net: hso: fix null-ptr-deref during tty device unregistration + +From: Anirudh Rayabharam + +commit 8a12f8836145ffe37e9c8733dce18c22fb668b66 upstream + +Multiple ttys try to claim the same the minor number causing a double +unregistration of the same device. The first unregistration succeeds +but the next one results in a null-ptr-deref. + +The get_free_serial_index() function returns an available minor number +but doesn't assign it immediately. The assignment is done by the caller +later. But before this assignment, calls to get_free_serial_index() +would return the same minor number. + +Fix this by modifying get_free_serial_index to assign the minor number +immediately after one is found to be and rename it to obtain_minor() +to better reflect what it does. Similary, rename set_serial_by_index() +to release_minor() and modify it to free up the minor number of the +given hso_serial. Every obtain_minor() should have corresponding +release_minor() call. + +Fixes: 72dc1c096c705 ("HSO: add option hso driver") +Reported-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Tested-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Anirudh Rayabharam +Signed-off-by: David S. Miller +[sudip: adjust context] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 33 ++++++++++++--------------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -635,7 +635,7 @@ static struct hso_serial *get_serial_by_ + return serial; + } + +-static int get_free_serial_index(void) ++static int obtain_minor(struct hso_serial *serial) + { + int index; + unsigned long flags; +@@ -643,8 +643,10 @@ static int get_free_serial_index(void) + spin_lock_irqsave(&serial_table_lock, flags); + for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { + if (serial_table[index] == NULL) { ++ serial_table[index] = serial->parent; ++ serial->minor = index; + spin_unlock_irqrestore(&serial_table_lock, flags); +- return index; ++ return 0; + } + } + spin_unlock_irqrestore(&serial_table_lock, flags); +@@ -653,15 +655,12 @@ static int get_free_serial_index(void) + return -1; + } + +-static void set_serial_by_index(unsigned index, struct hso_serial *serial) ++static void release_minor(struct hso_serial *serial) + { + unsigned long flags; + + spin_lock_irqsave(&serial_table_lock, flags); +- if (serial) +- serial_table[index] = serial->parent; +- else +- serial_table[index] = NULL; ++ serial_table[serial->minor] = NULL; + spin_unlock_irqrestore(&serial_table_lock, flags); + } + +@@ -2249,6 +2248,7 @@ static int hso_stop_serial_device(struct + static void hso_serial_tty_unregister(struct hso_serial *serial) + { + tty_unregister_device(tty_drv, serial->minor); ++ release_minor(serial); + } + + static void hso_serial_common_free(struct hso_serial *serial) +@@ -2273,25 +2273,23 @@ static int hso_serial_common_create(stru + int rx_size, int tx_size) + { + struct device *dev; +- int minor; + int i; + + tty_port_init(&serial->port); + +- minor = get_free_serial_index(); +- if (minor < 0) ++ if (obtain_minor(serial)) + goto exit2; + + /* register our minor number */ + serial->parent->dev = tty_port_register_device_attr(&serial->port, +- tty_drv, minor, &serial->parent->interface->dev, ++ tty_drv, serial->minor, &serial->parent->interface->dev, + serial->parent, hso_serial_dev_groups); +- if (IS_ERR(serial->parent->dev)) ++ if (IS_ERR(serial->parent->dev)) { ++ release_minor(serial); + goto exit2; ++ } + dev = serial->parent->dev; + +- /* fill in specific data for later use */ +- serial->minor = minor; + serial->magic = HSO_SERIAL_MAGIC; + spin_lock_init(&serial->serial_lock); + serial->num_rx_urbs = num_urbs; +@@ -2692,9 +2690,6 @@ static struct hso_device *hso_create_bul + + serial->write_data = hso_std_serial_write_data; + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -2751,9 +2746,6 @@ struct hso_device *hso_create_mux_serial + serial->shared_int->ref_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -3140,7 +3132,6 @@ static void hso_free_interface(struct us + cancel_work_sync(&serial_table[i]->async_get_intf); + hso_serial_tty_unregister(serial); + kref_put(&serial_table[i]->ref, hso_serial_ref_free); +- set_serial_by_index(i, NULL); + } + } + diff --git a/queue-4.4/series b/queue-4.4/series index 82a8eb60181..56448aeccb3 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -19,6 +19,7 @@ scsi-libsas-reset-num_scatter-if-libata-marks-qc-as-nodata.patch net-davicom-fix-regulator-not-turned-off-on-failed-probe.patch i40e-fix-the-panic-when-running-bpf-in-xdpdrv-mode.patch arm-9071-1-uprobes-don-t-hook-on-thumb-instructions.patch +net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch ext4-correct-error-label-in-ext4_rename.patch arm-dts-fix-swapped-mmc-order-for-omap3.patch s390-entry-save-the-caller-of-psw_idle.patch diff --git a/queue-4.9/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch b/queue-4.9/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch new file mode 100644 index 00000000000..f0e9c84d1bf --- /dev/null +++ b/queue-4.9/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch @@ -0,0 +1,146 @@ +From foo@baz Sat Apr 24 04:46:08 PM CEST 2021 +From: Anirudh Rayabharam +Date: Wed, 7 Apr 2021 22:57:22 +0530 +Subject: net: hso: fix null-ptr-deref during tty device unregistration + +From: Anirudh Rayabharam + +commit 8a12f8836145ffe37e9c8733dce18c22fb668b66 upstream + +Multiple ttys try to claim the same the minor number causing a double +unregistration of the same device. The first unregistration succeeds +but the next one results in a null-ptr-deref. + +The get_free_serial_index() function returns an available minor number +but doesn't assign it immediately. The assignment is done by the caller +later. But before this assignment, calls to get_free_serial_index() +would return the same minor number. + +Fix this by modifying get_free_serial_index to assign the minor number +immediately after one is found to be and rename it to obtain_minor() +to better reflect what it does. Similary, rename set_serial_by_index() +to release_minor() and modify it to free up the minor number of the +given hso_serial. Every obtain_minor() should have corresponding +release_minor() call. + +Fixes: 72dc1c096c705 ("HSO: add option hso driver") +Reported-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Tested-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Anirudh Rayabharam +Signed-off-by: David S. Miller +[sudip: adjust context] +Signed-off-by: Sudip Mukherjee +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 33 ++++++++++++--------------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -626,7 +626,7 @@ static struct hso_serial *get_serial_by_ + return serial; + } + +-static int get_free_serial_index(void) ++static int obtain_minor(struct hso_serial *serial) + { + int index; + unsigned long flags; +@@ -634,8 +634,10 @@ static int get_free_serial_index(void) + spin_lock_irqsave(&serial_table_lock, flags); + for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { + if (serial_table[index] == NULL) { ++ serial_table[index] = serial->parent; ++ serial->minor = index; + spin_unlock_irqrestore(&serial_table_lock, flags); +- return index; ++ return 0; + } + } + spin_unlock_irqrestore(&serial_table_lock, flags); +@@ -644,15 +646,12 @@ static int get_free_serial_index(void) + return -1; + } + +-static void set_serial_by_index(unsigned index, struct hso_serial *serial) ++static void release_minor(struct hso_serial *serial) + { + unsigned long flags; + + spin_lock_irqsave(&serial_table_lock, flags); +- if (serial) +- serial_table[index] = serial->parent; +- else +- serial_table[index] = NULL; ++ serial_table[serial->minor] = NULL; + spin_unlock_irqrestore(&serial_table_lock, flags); + } + +@@ -2243,6 +2242,7 @@ static int hso_stop_serial_device(struct + static void hso_serial_tty_unregister(struct hso_serial *serial) + { + tty_unregister_device(tty_drv, serial->minor); ++ release_minor(serial); + } + + static void hso_serial_common_free(struct hso_serial *serial) +@@ -2267,25 +2267,23 @@ static int hso_serial_common_create(stru + int rx_size, int tx_size) + { + struct device *dev; +- int minor; + int i; + + tty_port_init(&serial->port); + +- minor = get_free_serial_index(); +- if (minor < 0) ++ if (obtain_minor(serial)) + goto exit2; + + /* register our minor number */ + serial->parent->dev = tty_port_register_device_attr(&serial->port, +- tty_drv, minor, &serial->parent->interface->dev, ++ tty_drv, serial->minor, &serial->parent->interface->dev, + serial->parent, hso_serial_dev_groups); +- if (IS_ERR(serial->parent->dev)) ++ if (IS_ERR(serial->parent->dev)) { ++ release_minor(serial); + goto exit2; ++ } + dev = serial->parent->dev; + +- /* fill in specific data for later use */ +- serial->minor = minor; + serial->magic = HSO_SERIAL_MAGIC; + spin_lock_init(&serial->serial_lock); + serial->num_rx_urbs = num_urbs; +@@ -2678,9 +2676,6 @@ static struct hso_device *hso_create_bul + + serial->write_data = hso_std_serial_write_data; + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -2737,9 +2732,6 @@ struct hso_device *hso_create_mux_serial + serial->shared_int->ref_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -3124,7 +3116,6 @@ static void hso_free_interface(struct us + cancel_work_sync(&serial_table[i]->async_get_intf); + hso_serial_tty_unregister(serial); + kref_put(&serial_table[i]->ref, hso_serial_ref_free); +- set_serial_by_index(i, NULL); + } + } + diff --git a/queue-4.9/series b/queue-4.9/series index 10c12948b19..9845ea3d649 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -25,6 +25,7 @@ usbip-add-sysfs_lock-to-synchronize-sysfs-code-paths.patch usbip-stub-dev-synchronize-sysfs-code-paths.patch usbip-vudc-synchronize-sysfs-code-paths.patch usbip-synchronize-event-handler-with-sysfs-code-paths.patch +net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch ext4-correct-error-label-in-ext4_rename.patch hid-alps-fix-error-return-code-in-alps_input_configu.patch arm-dts-fix-swapped-mmc-order-for-omap3.patch -- 2.47.3