]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jul 2012 20:36:19 +0000 (13:36 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jul 2012 20:36:19 +0000 (13:36 -0700)
added patches:
hwmon-applesmc-limit-key-length-in-warning-messages.patch
nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch
udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch
udf-fortify-loading-of-sparing-table.patch
udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch

queue-3.0/hwmon-applesmc-limit-key-length-in-warning-messages.patch [new file with mode: 0644]
queue-3.0/nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch [new file with mode: 0644]
queue-3.0/udf-fortify-loading-of-sparing-table.patch [new file with mode: 0644]
queue-3.0/udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch [new file with mode: 0644]

diff --git a/queue-3.0/hwmon-applesmc-limit-key-length-in-warning-messages.patch b/queue-3.0/hwmon-applesmc-limit-key-length-in-warning-messages.patch
new file mode 100644 (file)
index 0000000..2630fca
--- /dev/null
@@ -0,0 +1,41 @@
+From ac852edb47b15900886ba2564eeeb13b3b526e3e Mon Sep 17 00:00:00 2001
+From: Henrik Rydberg <rydberg@euromail.se>
+Date: Thu, 7 Jun 2012 04:54:29 -0400
+Subject: hwmon: (applesmc) Limit key length in warning messages
+
+From: Henrik Rydberg <rydberg@euromail.se>
+
+commit ac852edb47b15900886ba2564eeeb13b3b526e3e upstream.
+
+Key lookups may call read_smc() with a fixed-length key string,
+and if the lookup fails, trailing stack content may appear in the
+kernel log. Fixed with this patch.
+
+Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hwmon/applesmc.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/hwmon/applesmc.c
++++ b/drivers/hwmon/applesmc.c
+@@ -215,7 +215,7 @@ static int read_smc(u8 cmd, const char *
+       int i;
+       if (send_command(cmd) || send_argument(key)) {
+-              pr_warn("%s: read arg fail\n", key);
++              pr_warn("%.4s: read arg fail\n", key);
+               return -EIO;
+       }
+@@ -223,7 +223,7 @@ static int read_smc(u8 cmd, const char *
+       for (i = 0; i < len; i++) {
+               if (__wait_status(0x05)) {
+-                      pr_warn("%s: read data fail\n", key);
++                      pr_warn("%.4s: read data fail\n", key);
+                       return -EIO;
+               }
+               buffer[i] = inb(APPLESMC_DATA_PORT);
diff --git a/queue-3.0/nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch b/queue-3.0/nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch
new file mode 100644 (file)
index 0000000..f49f987
--- /dev/null
@@ -0,0 +1,67 @@
+From fbb24a3a915f105016f1c828476be11aceac8504 Mon Sep 17 00:00:00 2001
+From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+Date: Wed, 20 Jun 2012 12:52:57 -0700
+Subject: nilfs2: ensure proper cache clearing for gc-inodes
+
+From: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+
+commit fbb24a3a915f105016f1c828476be11aceac8504 upstream.
+
+A gc-inode is a pseudo inode used to buffer the blocks to be moved by
+garbage collection.
+
+Block caches of gc-inodes must be cleared every time a garbage collection
+function (nilfs_clean_segments) completes.  Otherwise, stale blocks
+buffered in the caches may be wrongly reused in successive calls of the GC
+function.
+
+For user files, this is not a problem because their gc-inodes are
+distinguished by a checkpoint number as well as an inode number.  They
+never buffer different blocks if either an inode number, a checkpoint
+number, or a block offset differs.
+
+However, gc-inodes of sufile, cpfile and DAT file can store different data
+for the same block offset.  Thus, the nilfs_clean_segments function can
+move incorrect block for these meta-data files if an old block is cached.
+I found this is really causing meta-data corruption in nilfs.
+
+This fixes the issue by ensuring cache clear of gc-inodes and resolves
+reported GC problems including checkpoint file corruption, b-tree
+corruption, and the following warning during GC.
+
+  nilfs_palloc_freev: entry number 307234 already freed.
+  ...
+
+Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+Tested-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nilfs2/gcinode.c |    2 ++
+ fs/nilfs2/segment.c |    2 ++
+ 2 files changed, 4 insertions(+)
+
+--- a/fs/nilfs2/gcinode.c
++++ b/fs/nilfs2/gcinode.c
+@@ -191,6 +191,8 @@ void nilfs_remove_all_gcinodes(struct th
+       while (!list_empty(head)) {
+               ii = list_first_entry(head, struct nilfs_inode_info, i_dirty);
+               list_del_init(&ii->i_dirty);
++              truncate_inode_pages(&ii->vfs_inode.i_data, 0);
++              nilfs_btnode_cache_clear(&ii->i_btnode_cache);
+               iput(&ii->vfs_inode);
+       }
+ }
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -2309,6 +2309,8 @@ nilfs_remove_written_gcinodes(struct the
+               if (!test_bit(NILFS_I_UPDATED, &ii->i_state))
+                       continue;
+               list_del_init(&ii->i_dirty);
++              truncate_inode_pages(&ii->vfs_inode.i_data, 0);
++              nilfs_btnode_cache_clear(&ii->i_btnode_cache);
+               iput(&ii->vfs_inode);
+       }
+ }
index 245f658caa262567369a0cff7c0178477208a37d..5f73c46fa1cdcc7413e041b5014d8dd6714f239a 100644 (file)
@@ -13,3 +13,8 @@ ipv6-move-ipv6-proc-file-registration-to-end-of-init-order.patch
 sky2-fix-checksum-bit-management-on-some-chips.patch
 be2net-fix-a-race-in-be_xmit.patch
 netpoll-fix-netpoll_send_udp-bugs.patch
+hwmon-applesmc-limit-key-length-in-warning-messages.patch
+nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch
+udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch
+udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch
+udf-fortify-loading-of-sparing-table.patch
diff --git a/queue-3.0/udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch b/queue-3.0/udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch
new file mode 100644 (file)
index 0000000..fd49b10
--- /dev/null
@@ -0,0 +1,51 @@
+From adee11b2085bee90bd8f4f52123ffb07882d6256 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 27 Jun 2012 20:20:22 +0200
+Subject: udf: Avoid run away loop when partition table length is corrupted
+
+From: Jan Kara <jack@suse.cz>
+
+commit adee11b2085bee90bd8f4f52123ffb07882d6256 upstream.
+
+Check provided length of partition table so that (possibly maliciously)
+corrupted partition table cannot cause accessing data beyond current buffer.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/udf/super.c |   10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -1254,6 +1254,7 @@ static int udf_load_logicalvol(struct su
+       struct genericPartitionMap *gpm;
+       uint16_t ident;
+       struct buffer_head *bh;
++      unsigned int table_len;
+       int ret = 0;
+       bh = udf_read_tagged(sb, block, block, &ident);
+@@ -1261,13 +1262,20 @@ static int udf_load_logicalvol(struct su
+               return 1;
+       BUG_ON(ident != TAG_IDENT_LVD);
+       lvd = (struct logicalVolDesc *)bh->b_data;
++      table_len = le32_to_cpu(lvd->mapTableLength);
++      if (sizeof(*lvd) + table_len > sb->s_blocksize) {
++              udf_error(sb, "error loading logical volume descriptor: "
++                      "Partition table too long (%u > %lu)\n", table_len,
++                      sb->s_blocksize - sizeof(*lvd));
++              goto out_bh;
++      }
+       ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+       if (ret)
+               goto out_bh;
+       for (i = 0, offset = 0;
+-           i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);
++           i < sbi->s_partitions && offset < table_len;
+            i++, offset += gpm->partitionMapLength) {
+               struct udf_part_map *map = &sbi->s_partmaps[i];
+               gpm = (struct genericPartitionMap *)
diff --git a/queue-3.0/udf-fortify-loading-of-sparing-table.patch b/queue-3.0/udf-fortify-loading-of-sparing-table.patch
new file mode 100644 (file)
index 0000000..4be165a
--- /dev/null
@@ -0,0 +1,132 @@
+From 1df2ae31c724e57be9d7ac00d78db8a5dabdd050 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 27 Jun 2012 21:23:07 +0200
+Subject: udf: Fortify loading of sparing table
+
+From: Jan Kara <jack@suse.cz>
+
+commit 1df2ae31c724e57be9d7ac00d78db8a5dabdd050 upstream.
+
+Add sanity checks when loading sparing table from disk to avoid accessing
+unallocated memory or writing to it.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/udf/super.c |   86 +++++++++++++++++++++++++++++++++++----------------------
+ 1 file changed, 53 insertions(+), 33 deletions(-)
+
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -56,6 +56,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/bitmap.h>
+ #include <linux/crc-itu-t.h>
++#include <linux/log2.h>
+ #include <asm/byteorder.h>
+ #include "udf_sb.h"
+@@ -1244,11 +1245,59 @@ out_bh:
+       return ret;
+ }
++static int udf_load_sparable_map(struct super_block *sb,
++                               struct udf_part_map *map,
++                               struct sparablePartitionMap *spm)
++{
++      uint32_t loc;
++      uint16_t ident;
++      struct sparingTable *st;
++      struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing;
++      int i;
++      struct buffer_head *bh;
++
++      map->s_partition_type = UDF_SPARABLE_MAP15;
++      sdata->s_packet_len = le16_to_cpu(spm->packetLength);
++      if (!is_power_of_2(sdata->s_packet_len)) {
++              udf_error(sb, __func__, "error loading logical volume descriptor: "
++                      "Invalid packet length %u\n",
++                      (unsigned)sdata->s_packet_len);
++              return -EIO;
++      }
++      if (spm->numSparingTables > 4) {
++              udf_error(sb, __func__, "error loading logical volume descriptor: "
++                      "Too many sparing tables (%d)\n",
++                      (int)spm->numSparingTables);
++              return -EIO;
++      }
++
++      for (i = 0; i < spm->numSparingTables; i++) {
++              loc = le32_to_cpu(spm->locSparingTable[i]);
++              bh = udf_read_tagged(sb, loc, loc, &ident);
++              if (!bh)
++                      continue;
++
++              st = (struct sparingTable *)bh->b_data;
++              if (ident != 0 ||
++                  strncmp(st->sparingIdent.ident, UDF_ID_SPARING,
++                          strlen(UDF_ID_SPARING)) ||
++                  sizeof(*st) + le16_to_cpu(st->reallocationTableLen) >
++                                                      sb->s_blocksize) {
++                      brelse(bh);
++                      continue;
++              }
++
++              sdata->s_spar_map[i] = bh;
++      }
++      map->s_partition_func = udf_get_pblock_spar15;
++      return 0;
++}
++
+ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
+                              struct kernel_lb_addr *fileset)
+ {
+       struct logicalVolDesc *lvd;
+-      int i, j, offset;
++      int i, offset;
+       uint8_t type;
+       struct udf_sb_info *sbi = UDF_SB(sb);
+       struct genericPartitionMap *gpm;
+@@ -1310,38 +1359,9 @@ static int udf_load_logicalvol(struct su
+                       } else if (!strncmp(upm2->partIdent.ident,
+                                               UDF_ID_SPARABLE,
+                                               strlen(UDF_ID_SPARABLE))) {
+-                              uint32_t loc;
+-                              struct sparingTable *st;
+-                              struct sparablePartitionMap *spm =
+-                                      (struct sparablePartitionMap *)gpm;
+-
+-                              map->s_partition_type = UDF_SPARABLE_MAP15;
+-                              map->s_type_specific.s_sparing.s_packet_len =
+-                                              le16_to_cpu(spm->packetLength);
+-                              for (j = 0; j < spm->numSparingTables; j++) {
+-                                      struct buffer_head *bh2;
+-
+-                                      loc = le32_to_cpu(
+-                                              spm->locSparingTable[j]);
+-                                      bh2 = udf_read_tagged(sb, loc, loc,
+-                                                           &ident);
+-                                      map->s_type_specific.s_sparing.
+-                                                      s_spar_map[j] = bh2;
+-
+-                                      if (bh2 == NULL)
+-                                              continue;
+-
+-                                      st = (struct sparingTable *)bh2->b_data;
+-                                      if (ident != 0 || strncmp(
+-                                              st->sparingIdent.ident,
+-                                              UDF_ID_SPARING,
+-                                              strlen(UDF_ID_SPARING))) {
+-                                              brelse(bh2);
+-                                              map->s_type_specific.s_sparing.
+-                                                      s_spar_map[j] = NULL;
+-                                      }
+-                              }
+-                              map->s_partition_func = udf_get_pblock_spar15;
++                              if (udf_load_sparable_map(sb, map,
++                                  (struct sparablePartitionMap *)gpm) < 0)
++                                      goto out_bh;
+                       } else if (!strncmp(upm2->partIdent.ident,
+                                               UDF_ID_METADATA,
+                                               strlen(UDF_ID_METADATA))) {
diff --git a/queue-3.0/udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch b/queue-3.0/udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch
new file mode 100644 (file)
index 0000000..00a0bcc
--- /dev/null
@@ -0,0 +1,32 @@
+From cb14d340ef1737c24125dd663eff77734a482d47 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 27 Jun 2012 20:08:44 +0200
+Subject: udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol()
+
+From: Jan Kara <jack@suse.cz>
+
+commit cb14d340ef1737c24125dd663eff77734a482d47 upstream.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/udf/super.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/fs/udf/super.c
++++ b/fs/udf/super.c
+@@ -1262,11 +1262,9 @@ static int udf_load_logicalvol(struct su
+       BUG_ON(ident != TAG_IDENT_LVD);
+       lvd = (struct logicalVolDesc *)bh->b_data;
+-      i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
+-      if (i != 0) {
+-              ret = i;
++      ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps));
++      if (ret)
+               goto out_bh;
+-      }
+       for (i = 0, offset = 0;
+            i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength);