From: Greg Kroah-Hartman Date: Tue, 10 Jul 2012 20:36:19 +0000 (-0700) Subject: 3.0-stable patches X-Git-Tag: v3.0.37~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5d84d673444d8c58af640570b8b5abb906995963;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches 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 --- 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 index 00000000000..2630fcac240 --- /dev/null +++ b/queue-3.0/hwmon-applesmc-limit-key-length-in-warning-messages.patch @@ -0,0 +1,41 @@ +From ac852edb47b15900886ba2564eeeb13b3b526e3e Mon Sep 17 00:00:00 2001 +From: Henrik Rydberg +Date: Thu, 7 Jun 2012 04:54:29 -0400 +Subject: hwmon: (applesmc) Limit key length in warning messages + +From: Henrik Rydberg + +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 +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..f49f9873749 --- /dev/null +++ b/queue-3.0/nilfs2-ensure-proper-cache-clearing-for-gc-inodes.patch @@ -0,0 +1,67 @@ +From fbb24a3a915f105016f1c828476be11aceac8504 Mon Sep 17 00:00:00 2001 +From: Ryusuke Konishi +Date: Wed, 20 Jun 2012 12:52:57 -0700 +Subject: nilfs2: ensure proper cache clearing for gc-inodes + +From: Ryusuke Konishi + +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 +Tested-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + } diff --git a/queue-3.0/series b/queue-3.0/series index 245f658caa2..5f73c46fa1c 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 00000000000..fd49b104a9c --- /dev/null +++ b/queue-3.0/udf-avoid-run-away-loop-when-partition-table-length-is-corrupted.patch @@ -0,0 +1,51 @@ +From adee11b2085bee90bd8f4f52123ffb07882d6256 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 27 Jun 2012 20:20:22 +0200 +Subject: udf: Avoid run away loop when partition table length is corrupted + +From: Jan Kara + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4be165a3b01 --- /dev/null +++ b/queue-3.0/udf-fortify-loading-of-sparing-table.patch @@ -0,0 +1,132 @@ +From 1df2ae31c724e57be9d7ac00d78db8a5dabdd050 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 27 Jun 2012 21:23:07 +0200 +Subject: udf: Fortify loading of sparing table + +From: Jan Kara + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include + #include + + #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 index 00000000000..00a0bcc02e8 --- /dev/null +++ b/queue-3.0/udf-use-ret-instead-of-abusing-i-in-udf_load_logicalvol.patch @@ -0,0 +1,32 @@ +From cb14d340ef1737c24125dd663eff77734a482d47 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 27 Jun 2012 20:08:44 +0200 +Subject: udf: Use 'ret' instead of abusing 'i' in udf_load_logicalvol() + +From: Jan Kara + +commit cb14d340ef1737c24125dd663eff77734a482d47 upstream. + +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + 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);