summaryrefslogtreecommitdiffstats
path: root/master/debian/xfs_invalid_bmap.patch
diff options
context:
space:
mode:
Diffstat (limited to 'master/debian/xfs_invalid_bmap.patch')
-rw-r--r--master/debian/xfs_invalid_bmap.patch188
1 files changed, 188 insertions, 0 deletions
diff --git a/master/debian/xfs_invalid_bmap.patch b/master/debian/xfs_invalid_bmap.patch
new file mode 100644
index 0000000..71d04de
--- /dev/null
+++ b/master/debian/xfs_invalid_bmap.patch
@@ -0,0 +1,188 @@
+Description: Rewrite XFS btree parsing; fixes invalid BMAP
+Author: Vladimir Serbinenko <phcoder@gmail.com>
+Bug: http://savannah.gnu.org/bugs/?34213
+Bug-Debian: http://bugs.debian.org/657776
+Applied-Upstream: http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3443
+Last-Update: 2012-01-29
+
+Index: b/grub-core/fs/xfs.c
+===================================================================
+--- a/grub-core/fs/xfs.c
++++ b/grub-core/fs/xfs.c
+@@ -111,7 +111,9 @@
+ grub_uint64_t nblocks;
+ grub_uint32_t extsize;
+ grub_uint32_t nextents;
+- grub_uint8_t unused3[20];
++ grub_uint16_t unused3;
++ grub_uint8_t fork_offset;
++ grub_uint8_t unused4[17];
+ union
+ {
+ char raw[156];
+@@ -145,7 +147,7 @@
+ grub_disk_t disk;
+ int pos;
+ int bsize;
+- int agsize;
++ grub_uint32_t agsize;
+ struct grub_fshelp_node diropen;
+ };
+
+@@ -159,33 +161,67 @@
+ #define FILETYPE_INO_DIRECTORY 0040000
+ #define FILETYPE_INO_SYMLINK 0120000
+
+-#define GRUB_XFS_INO_AGBITS(data) \
+- ((data)->sblock.log2_agblk + (data)->sblock.log2_inop)
+-#define GRUB_XFS_INO_INOINAG(data, ino) \
+- (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1))
+-#define GRUB_XFS_INO_AG(data,ino) \
+- (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data))
+-
+-#define GRUB_XFS_FSB_TO_BLOCK(data, fsb) \
+- (((fsb) >> (data)->sblock.log2_agblk) * (data)->agsize \
+- + ((fsb) & ((1LL << (data)->sblock.log2_agblk) - 1)))
+-
+-#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \
+- ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \
+- | grub_be_to_cpu32 (exts[ex][1]) >> 9)
+-
+-#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \
+- ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \
+- & (0x1ff)) << 43 \
+- | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \
+- | grub_be_to_cpu32 (exts[ex][3]) >> 21)
+-
+-#define GRUB_XFS_EXTENT_SIZE(exts,ex) \
+- (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1))
+-
+-#define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8)
+-#define GRUB_XFS_NEXT_DIRENT(pos,len) \
+- (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2)
++static inline int
++GRUB_XFS_INO_AGBITS(struct grub_xfs_data *data)
++{
++ return ((data)->sblock.log2_agblk + (data)->sblock.log2_inop);
++}
++
++static inline grub_uint64_t
++GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data,
++ grub_uint64_t ino)
++{
++ return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1));
++}
++
++static inline grub_uint64_t
++GRUB_XFS_INO_AG (struct grub_xfs_data *data,
++ grub_uint64_t ino)
++{
++ return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data));
++}
++
++static inline grub_disk_addr_t
++GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb)
++{
++ return ((fsb >> data->sblock.log2_agblk) * data->agsize
++ + (fsb & ((1LL << data->sblock.log2_agblk) - 1)));
++}
++
++static inline grub_uint64_t
++GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex)
++{
++ return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23
++ | grub_be_to_cpu32 (exts[ex][1]) >> 9);
++}
++
++static inline grub_uint64_t
++GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex)
++{
++ return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1])
++ & (0x1ff)) << 43
++ | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11
++ | grub_be_to_cpu32 (exts[ex][3]) >> 21);
++}
++
++static inline grub_uint64_t
++GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex)
++{
++ return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1));
++}
++
++static inline int
++GRUB_XFS_ROUND_TO_DIRENT (int pos)
++{
++ return ((((pos) + 8 - 1) / 8) * 8);
++}
++
++static inline int
++GRUB_XFS_NEXT_DIRENT (int pos, int len)
++{
++ return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2);
++}
++
+
+ static inline grub_uint64_t
+ grub_xfs_inode_block (struct grub_xfs_data *data,
+@@ -241,13 +277,23 @@
+ if (node->inode.format == XFS_INODE_FORMAT_BTREE)
+ {
+ grub_uint64_t *keys;
++ int recoffset;
+
+- leaf = grub_malloc (node->data->sblock.bsize);
++ leaf = grub_malloc (node->data->bsize);
+ if (leaf == 0)
+ return 0;
+
+ nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
+ keys = &node->inode.data.btree.keys[0];
++ if (node->inode.fork_offset)
++ recoffset = (node->inode.fork_offset
++ - ((char *) &node->inode.data.btree.keys - (char *) &node->inode))
++ / (2 * sizeof (grub_uint64_t));
++ else
++ recoffset = ((1 << node->data->sblock.log2_inode)
++ - ((char *) &node->inode.data.btree.keys
++ - (char *) &node->inode))
++ / (2 * sizeof (grub_uint64_t));
+ do
+ {
+ int i;
+@@ -264,12 +310,9 @@
+ grub_free (leaf);
+ return 0;
+ }
+-
+ if (grub_disk_read (node->data->disk,
+- grub_be_to_cpu64 (keys[i - 1 + nrec])
+- << (node->data->sblock.log2_bsize
+- - GRUB_DISK_SECTOR_BITS),
+- 0, node->data->sblock.bsize, leaf))
++ GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
++ 0, node->data->bsize, leaf))
+ return 0;
+
+ if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
+@@ -281,7 +324,11 @@
+
+ nrec = grub_be_to_cpu16 (leaf->numrecs);
+ keys = &leaf->keys[0];
+- } while (leaf->level);
++ recoffset = ((node->data->bsize - ((char *) &leaf->keys
++ - (char *) leaf))
++ / (2 * sizeof (grub_uint64_t)));
++ }
++ while (leaf->level);
+ exts = (grub_xfs_extent *) keys;
+ }
+ else if (node->inode.format == XFS_INODE_FORMAT_EXT)
+@@ -328,7 +375,7 @@
+ grub_xfs_read_file (grub_fshelp_node_t node,
+ void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
+ unsigned offset, unsigned length),
+- int pos, grub_size_t len, char *buf)
++ grub_off_t pos, grub_size_t len, char *buf)
+ {
+ return grub_fshelp_read_file (node->data->disk, node, read_hook,
+ pos, len, buf, grub_xfs_read_block,