From 1855e63327f2a5fbc0ee6c2ca7af661524d78a4d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Aug 2017 13:04:07 -0700 Subject: [PATCH] 4.4-stable patches added patches: tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch tpm-replace-device-number-bitmap-with-idr.patch xen-blkback-don-t-free-be-structure-too-early.patch xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch --- queue-4.4/series | 4 + ...-a-kernel-memory-leak-in-tpm-sysfs.c.patch | 39 +++ ...eplace-device-number-bitmap-with-idr.patch | 222 ++++++++++++++++++ ...ck-don-t-free-be-structure-too-early.patch | 52 ++++ ...xen_blkif_get-in-xen-blkback-kthread.patch | 61 +++++ 5 files changed, 378 insertions(+) create mode 100644 queue-4.4/tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch create mode 100644 queue-4.4/tpm-replace-device-number-bitmap-with-idr.patch create mode 100644 queue-4.4/xen-blkback-don-t-free-be-structure-too-early.patch create mode 100644 queue-4.4/xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch diff --git a/queue-4.4/series b/queue-4.4/series index 40931a9274c..1e3fa02114a 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -48,3 +48,7 @@ pstore-use-dynamic-spinlock-initializer.patch staging-sm750fb-avoid-conflicting-vesafb.patch net-skb_needs_check-accepts-checksum_none-for-tx.patch sched-cputime-fix-prev-steal-time-accouting-during-cpu-hotplug.patch +xen-blkback-don-t-free-be-structure-too-early.patch +xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch +tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch +tpm-replace-device-number-bitmap-with-idr.patch diff --git a/queue-4.4/tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch b/queue-4.4/tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch new file mode 100644 index 00000000000..804f288dc51 --- /dev/null +++ b/queue-4.4/tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch @@ -0,0 +1,39 @@ +From 13b47cfcfc60495cde216eef4c01040d76174cbe Mon Sep 17 00:00:00 2001 +From: Jarkko Sakkinen +Date: Tue, 20 Jun 2017 11:38:02 +0200 +Subject: tpm: fix a kernel memory leak in tpm-sysfs.c + +From: Jarkko Sakkinen + +commit 13b47cfcfc60495cde216eef4c01040d76174cbe upstream. + +While cleaning up sysfs callback that prints EK we discovered a kernel +memory leak. This commit fixes the issue by zeroing the buffer used for +TPM command/response. + +The leak happen when we use either tpm_vtpm_proxy, tpm_ibmvtpm or +xen-tpmfront. + +Fixes: 0883743825e3 ("TPM: sysfs functions consolidation") +Reported-by: Jason Gunthorpe +Tested-by: Stefan Berger +Signed-off-by: Jarkko Sakkinen +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/char/tpm/tpm-sysfs.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/char/tpm/tpm-sysfs.c ++++ b/drivers/char/tpm/tpm-sysfs.c +@@ -38,6 +38,8 @@ static ssize_t pubek_show(struct device + + struct tpm_chip *chip = dev_get_drvdata(dev); + ++ memset(&tpm_cmd, 0, sizeof(tpm_cmd)); ++ + tpm_cmd.header.in = tpm_readpubek_header; + err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0, + "attempting to read the PUBEK"); diff --git a/queue-4.4/tpm-replace-device-number-bitmap-with-idr.patch b/queue-4.4/tpm-replace-device-number-bitmap-with-idr.patch new file mode 100644 index 00000000000..cc04d805a66 --- /dev/null +++ b/queue-4.4/tpm-replace-device-number-bitmap-with-idr.patch @@ -0,0 +1,222 @@ +From 15516788e581eb32ec1c50e5f00aba3faf95d817 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 29 Feb 2016 08:53:02 -0500 +Subject: tpm: Replace device number bitmap with IDR + +From: Stefan Berger + +commit 15516788e581eb32ec1c50e5f00aba3faf95d817 upstream. + +Replace the device number bitmap with IDR. Extend the number of devices we +can create to 64k. +Since an IDR allows us to associate a pointer with an ID, we use this now +to rewrite tpm_chip_find_get() to simply look up the chip pointer by the +given device ID. + +Protect the IDR calls with a mutex. + +Signed-off-by: Stefan Berger +Reviewed-by: Jason Gunthorpe +Reviewed-by: Jarkko Sakkinen +Tested-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tpm/tpm-chip.c | 84 ++++++++++++++++++++------------------- + drivers/char/tpm/tpm-interface.c | 1 + drivers/char/tpm/tpm.h | 5 -- + 3 files changed, 48 insertions(+), 42 deletions(-) + +--- a/drivers/char/tpm/tpm-chip.c ++++ b/drivers/char/tpm/tpm-chip.c +@@ -29,9 +29,8 @@ + #include "tpm.h" + #include "tpm_eventlog.h" + +-static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); +-static LIST_HEAD(tpm_chip_list); +-static DEFINE_SPINLOCK(driver_lock); ++DEFINE_IDR(dev_nums_idr); ++static DEFINE_MUTEX(idr_lock); + + struct class *tpm_class; + dev_t tpm_devt; +@@ -92,20 +91,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops); + */ + struct tpm_chip *tpm_chip_find_get(int chip_num) + { +- struct tpm_chip *pos, *chip = NULL; ++ struct tpm_chip *chip, *res = NULL; ++ int chip_prev; + +- rcu_read_lock(); +- list_for_each_entry_rcu(pos, &tpm_chip_list, list) { +- if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) +- continue; +- +- /* rcu prevents chip from being free'd */ +- if (!tpm_try_get_ops(pos)) +- chip = pos; +- break; ++ mutex_lock(&idr_lock); ++ ++ if (chip_num == TPM_ANY_NUM) { ++ chip_num = 0; ++ do { ++ chip_prev = chip_num; ++ chip = idr_get_next(&dev_nums_idr, &chip_num); ++ if (chip && !tpm_try_get_ops(chip)) { ++ res = chip; ++ break; ++ } ++ } while (chip_prev != chip_num); ++ } else { ++ chip = idr_find_slowpath(&dev_nums_idr, chip_num); ++ if (chip && !tpm_try_get_ops(chip)) ++ res = chip; + } +- rcu_read_unlock(); +- return chip; ++ ++ mutex_unlock(&idr_lock); ++ ++ return res; + } + + /** +@@ -118,9 +127,10 @@ static void tpm_dev_release(struct devic + { + struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); + +- spin_lock(&driver_lock); +- clear_bit(chip->dev_num, dev_mask); +- spin_unlock(&driver_lock); ++ mutex_lock(&idr_lock); ++ idr_remove(&dev_nums_idr, chip->dev_num); ++ mutex_unlock(&idr_lock); ++ + kfree(chip); + } + +@@ -180,21 +190,18 @@ struct tpm_chip *tpmm_chip_alloc(struct + + mutex_init(&chip->tpm_mutex); + init_rwsem(&chip->ops_sem); +- INIT_LIST_HEAD(&chip->list); + + chip->ops = ops; + +- spin_lock(&driver_lock); +- chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); +- spin_unlock(&driver_lock); +- +- if (chip->dev_num >= TPM_NUM_DEVICES) { ++ mutex_lock(&idr_lock); ++ rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL); ++ mutex_unlock(&idr_lock); ++ if (rc < 0) { + dev_err(dev, "No available tpm device numbers\n"); + kfree(chip); +- return ERR_PTR(-ENOMEM); ++ return ERR_PTR(rc); + } +- +- set_bit(chip->dev_num, dev_mask); ++ chip->dev_num = rc; + + scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); + +@@ -252,19 +259,28 @@ static int tpm_add_char_device(struct tp + return rc; + } + ++ /* Make the chip available. */ ++ mutex_lock(&idr_lock); ++ idr_replace(&dev_nums_idr, chip, chip->dev_num); ++ mutex_unlock(&idr_lock); ++ + return rc; + } + + static void tpm_del_char_device(struct tpm_chip *chip) + { + cdev_del(&chip->cdev); ++ device_del(&chip->dev); ++ ++ /* Make the chip unavailable. */ ++ mutex_lock(&idr_lock); ++ idr_replace(&dev_nums_idr, NULL, chip->dev_num); ++ mutex_unlock(&idr_lock); + + /* Make the driver uncallable. */ + down_write(&chip->ops_sem); + chip->ops = NULL; + up_write(&chip->ops_sem); +- +- device_del(&chip->dev); + } + + static int tpm1_chip_register(struct tpm_chip *chip) +@@ -319,11 +335,6 @@ int tpm_chip_register(struct tpm_chip *c + if (rc) + goto out_err; + +- /* Make the chip available. */ +- spin_lock(&driver_lock); +- list_add_tail_rcu(&chip->list, &tpm_chip_list); +- spin_unlock(&driver_lock); +- + chip->flags |= TPM_CHIP_FLAG_REGISTERED; + + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { +@@ -360,11 +371,6 @@ void tpm_chip_unregister(struct tpm_chip + if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED)) + return; + +- spin_lock(&driver_lock); +- list_del_rcu(&chip->list); +- spin_unlock(&driver_lock); +- synchronize_rcu(); +- + if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) + sysfs_remove_link(&chip->dev.parent->kobj, "ppi"); + +--- a/drivers/char/tpm/tpm-interface.c ++++ b/drivers/char/tpm/tpm-interface.c +@@ -1127,6 +1127,7 @@ static int __init tpm_init(void) + + static void __exit tpm_exit(void) + { ++ idr_destroy(&dev_nums_idr); + class_destroy(tpm_class); + unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); + } +--- a/drivers/char/tpm/tpm.h ++++ b/drivers/char/tpm/tpm.h +@@ -34,7 +34,7 @@ + enum tpm_const { + TPM_MINOR = 224, /* officially assigned */ + TPM_BUFSIZE = 4096, +- TPM_NUM_DEVICES = 256, ++ TPM_NUM_DEVICES = 65536, + TPM_RETRY = 50, /* 5 seconds */ + }; + +@@ -200,8 +200,6 @@ struct tpm_chip { + acpi_handle acpi_dev_handle; + char ppi_version[TPM_PPI_VERSION_LEN + 1]; + #endif /* CONFIG_ACPI */ +- +- struct list_head list; + }; + + #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) +@@ -497,6 +495,7 @@ static inline void tpm_buf_append_u32(st + extern struct class *tpm_class; + extern dev_t tpm_devt; + extern const struct file_operations tpm_fops; ++extern struct idr dev_nums_idr; + + enum tpm_transmit_flags { + TPM_TRANSMIT_UNLOCKED = BIT(0), diff --git a/queue-4.4/xen-blkback-don-t-free-be-structure-too-early.patch b/queue-4.4/xen-blkback-don-t-free-be-structure-too-early.patch new file mode 100644 index 00000000000..d7af6f5fd46 --- /dev/null +++ b/queue-4.4/xen-blkback-don-t-free-be-structure-too-early.patch @@ -0,0 +1,52 @@ +From 71df1d7ccad1c36f7321d6b3b48f2ea42681c363 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 18 May 2017 17:28:48 +0200 +Subject: xen/blkback: don't free be structure too early +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Juergen Gross + +commit 71df1d7ccad1c36f7321d6b3b48f2ea42681c363 upstream. + +The be structure must not be freed when freeing the blkif structure +isn't done. Otherwise a use-after-free of be when unmapping the ring +used for communicating with the frontend will occur in case of a +late call of xenblk_disconnect() (e.g. due to an I/O still active +when trying to disconnect). + +Signed-off-by: Juergen Gross +Tested-by: Steven Haigh +Acked-by: Roger Pau Monné +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkback/xenbus.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/block/xen-blkback/xenbus.c ++++ b/drivers/block/xen-blkback/xenbus.c +@@ -266,9 +266,10 @@ static int xen_blkif_disconnect(struct x + + static void xen_blkif_free(struct xen_blkif *blkif) + { +- +- xen_blkif_disconnect(blkif); ++ WARN_ON(xen_blkif_disconnect(blkif)); + xen_vbd_free(&blkif->vbd); ++ kfree(blkif->be->mode); ++ kfree(blkif->be); + + /* Make sure everything is drained before shutting down */ + BUG_ON(blkif->persistent_gnt_c != 0); +@@ -445,8 +446,6 @@ static int xen_blkbk_remove(struct xenbu + xen_blkif_put(be->blkif); + } + +- kfree(be->mode); +- kfree(be); + return 0; + } + diff --git a/queue-4.4/xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch b/queue-4.4/xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch new file mode 100644 index 00000000000..df14c0d48ce --- /dev/null +++ b/queue-4.4/xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch @@ -0,0 +1,61 @@ +From a24fa22ce22ae302b3bf8f7008896d52d5d57b8d Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 18 May 2017 17:28:49 +0200 +Subject: xen/blkback: don't use xen_blkif_get() in xen-blkback kthread +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Juergen Gross + +commit a24fa22ce22ae302b3bf8f7008896d52d5d57b8d upstream. + +There is no need to use xen_blkif_get()/xen_blkif_put() in the kthread +of xen-blkback. Thread stopping is synchronous and using the blkif +reference counting in the kthread will avoid to ever let the reference +count drop to zero at the end of an I/O running concurrent to +disconnecting and multiple rings. + +Setting ring->xenblkd to NULL after stopping the kthread isn't needed +as the kthread does this already. + +Signed-off-by: Juergen Gross +Tested-by: Steven Haigh +Acked-by: Roger Pau Monné +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkback/blkback.c | 3 --- + drivers/block/xen-blkback/xenbus.c | 1 - + 2 files changed, 4 deletions(-) + +--- a/drivers/block/xen-blkback/blkback.c ++++ b/drivers/block/xen-blkback/blkback.c +@@ -595,8 +595,6 @@ int xen_blkif_schedule(void *arg) + unsigned long timeout; + int ret; + +- xen_blkif_get(blkif); +- + while (!kthread_should_stop()) { + if (try_to_freeze()) + continue; +@@ -650,7 +648,6 @@ purge_gnt_list: + print_stats(blkif); + + blkif->xenblkd = NULL; +- xen_blkif_put(blkif); + + return 0; + } +--- a/drivers/block/xen-blkback/xenbus.c ++++ b/drivers/block/xen-blkback/xenbus.c +@@ -221,7 +221,6 @@ static int xen_blkif_disconnect(struct x + if (blkif->xenblkd) { + kthread_stop(blkif->xenblkd); + wake_up(&blkif->shutdown_wq); +- blkif->xenblkd = NULL; + } + + /* The above kthread_stop() guarantees that at this point we -- 2.47.3