]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Aug 2017 20:04:07 +0000 (13:04 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Aug 2017 20:04:07 +0000 (13:04 -0700)
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
queue-4.4/tpm-fix-a-kernel-memory-leak-in-tpm-sysfs.c.patch [new file with mode: 0644]
queue-4.4/tpm-replace-device-number-bitmap-with-idr.patch [new file with mode: 0644]
queue-4.4/xen-blkback-don-t-free-be-structure-too-early.patch [new file with mode: 0644]
queue-4.4/xen-blkback-don-t-use-xen_blkif_get-in-xen-blkback-kthread.patch [new file with mode: 0644]

index 40931a9274c2700b6a25164096e5a55f81069def..1e3fa02114a15a38b3e6d9437e852e7f72313971 100644 (file)
@@ -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 (file)
index 0000000..804f288
--- /dev/null
@@ -0,0 +1,39 @@
+From 13b47cfcfc60495cde216eef4c01040d76174cbe Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Date: Tue, 20 Jun 2017 11:38:02 +0200
+Subject: tpm: fix a kernel memory leak in tpm-sysfs.c
+
+From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+
+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 <jgunthorpe@obsidianresearch.com>
+Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ 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 (file)
index 0000000..cc04d80
--- /dev/null
@@ -0,0 +1,222 @@
+From 15516788e581eb32ec1c50e5f00aba3faf95d817 Mon Sep 17 00:00:00 2001
+From: Stefan Berger <stefanb@linux.vnet.ibm.com>
+Date: Mon, 29 Feb 2016 08:53:02 -0500
+Subject: tpm: Replace device number bitmap with IDR
+
+From: Stefan Berger <stefanb@linux.vnet.ibm.com>
+
+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 <stefanb@linux.vnet.ibm.com>
+Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d7af6f5
--- /dev/null
@@ -0,0 +1,52 @@
+From 71df1d7ccad1c36f7321d6b3b48f2ea42681c363 Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+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 <jgross@suse.com>
+
+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 <jgross@suse.com>
+Tested-by: Steven Haigh <netwiz@crc.id.au>
+Acked-by: Roger Pau MonnĂ© <roger.pau@citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..df14c0d
--- /dev/null
@@ -0,0 +1,61 @@
+From a24fa22ce22ae302b3bf8f7008896d52d5d57b8d Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+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 <jgross@suse.com>
+
+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 <jgross@suse.com>
+Tested-by: Steven Haigh <netwiz@crc.id.au>
+Acked-by: Roger Pau MonnĂ© <roger.pau@citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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