diff options
author | Dave Chinner <dchinner@redhat.com> | 2013-08-26 00:13:30 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-08-30 10:48:59 -0400 |
commit | 37804376121de1a25fb582bdd8970f139c4d9685 (patch) | |
tree | d475f98cdb8fc0548a7e14f8eb480a58c855a1b3 | |
parent | 0f0d334595105d982ea22ae1d5947723e462344f (diff) |
XFS: Assertion failed: first <= last && last < BBTOB(bp->b_length), file: fs/xfs/xfs_trans_buf.c, line: 568
The calculation doesn't take into account the size of the dir v3
header, so overestimates the hash entries in a node. This causes
directory buffer overruns when splitting and merging nodes.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Tested-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 16 |
2 files changed, 19 insertions, 8 deletions
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 8cdc77b2e58d..b1f267995dea 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -133,12 +133,19 @@ extern void xfs_da3_node_hdr_to_disk(struct xfs_da_intnode *to, | |||
133 | struct xfs_da3_icnode_hdr *from); | 133 | struct xfs_da3_icnode_hdr *from); |
134 | 134 | ||
135 | static inline int | 135 | static inline int |
136 | xfs_da3_node_hdr_size(struct xfs_da_intnode *dap) | 136 | __xfs_da3_node_hdr_size(bool v3) |
137 | { | 137 | { |
138 | if (dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) | 138 | if (v3) |
139 | return sizeof(struct xfs_da3_node_hdr); | 139 | return sizeof(struct xfs_da3_node_hdr); |
140 | return sizeof(struct xfs_da_node_hdr); | 140 | return sizeof(struct xfs_da_node_hdr); |
141 | } | 141 | } |
142 | static inline int | ||
143 | xfs_da3_node_hdr_size(struct xfs_da_intnode *dap) | ||
144 | { | ||
145 | bool v3 = dap->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC); | ||
146 | |||
147 | return __xfs_da3_node_hdr_size(v3); | ||
148 | } | ||
142 | 149 | ||
143 | static inline struct xfs_da_node_entry * | 150 | static inline struct xfs_da_node_entry * |
144 | xfs_da3_node_tree_p(struct xfs_da_intnode *dap) | 151 | xfs_da3_node_tree_p(struct xfs_da_intnode *dap) |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index d3ff96c321f9..edf203ab50af 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -90,6 +90,9 @@ void | |||
90 | xfs_dir_mount( | 90 | xfs_dir_mount( |
91 | xfs_mount_t *mp) | 91 | xfs_mount_t *mp) |
92 | { | 92 | { |
93 | int nodehdr_size; | ||
94 | |||
95 | |||
93 | ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); | 96 | ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); |
94 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= | 97 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= |
95 | XFS_MAX_BLOCKSIZE); | 98 | XFS_MAX_BLOCKSIZE); |
@@ -98,12 +101,13 @@ xfs_dir_mount( | |||
98 | mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); | 101 | mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); |
99 | mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); | 102 | mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); |
100 | mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); | 103 | mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); |
101 | mp->m_attr_node_ents = | 104 | |
102 | (mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) / | 105 | nodehdr_size = __xfs_da3_node_hdr_size(xfs_sb_version_hascrc(&mp->m_sb)); |
103 | (uint)sizeof(xfs_da_node_entry_t); | 106 | mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / |
104 | mp->m_dir_node_ents = | 107 | (uint)sizeof(xfs_da_node_entry_t); |
105 | (mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) / | 108 | mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / |
106 | (uint)sizeof(xfs_da_node_entry_t); | 109 | (uint)sizeof(xfs_da_node_entry_t); |
110 | |||
107 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; | 111 | mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; |
108 | if (xfs_sb_version_hasasciici(&mp->m_sb)) | 112 | if (xfs_sb_version_hasasciici(&mp->m_sb)) |
109 | mp->m_dirnameops = &xfs_ascii_ci_nameops; | 113 | mp->m_dirnameops = &xfs_ascii_ci_nameops; |