1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2022-2024 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <djwong@kernel.org> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_log_format.h" 11 #include "xfs_trans_resv.h" 12 #include "xfs_mount.h" 13 #include "xfs_inode.h" 14 #include "xfs_da_format.h" 15 #include "xfs_da_btree.h" 16 #include "xfs_attr.h" 17 #include "xfs_attr_leaf.h" 18 #include "xfs_attr_sf.h" 19 #include "xfs_trans.h" 20 #include "scrub/scrub.h" 21 #include "scrub/bitmap.h" 22 #include "scrub/dab_bitmap.h" 23 #include "scrub/listxattr.h" 24 25 /* Call a function for every entry in a shortform xattr structure. */ 26 STATIC int 27 xchk_xattr_walk_sf( 28 struct xfs_scrub *sc, 29 struct xfs_inode *ip, 30 xchk_xattr_fn attr_fn, 31 void *priv) 32 { 33 struct xfs_attr_sf_hdr *hdr = ip->i_af.if_data; 34 struct xfs_attr_sf_entry *sfe; 35 unsigned int i; 36 int error; 37 38 sfe = xfs_attr_sf_firstentry(hdr); 39 for (i = 0; i < hdr->count; i++) { 40 error = attr_fn(sc, ip, sfe->flags, sfe->nameval, sfe->namelen, 41 &sfe->nameval[sfe->namelen], sfe->valuelen, 42 priv); 43 if (error) 44 return error; 45 46 sfe = xfs_attr_sf_nextentry(sfe); 47 } 48 49 return 0; 50 } 51 52 /* Call a function for every entry in this xattr leaf block. */ 53 STATIC int 54 xchk_xattr_walk_leaf_entries( 55 struct xfs_scrub *sc, 56 struct xfs_inode *ip, 57 xchk_xattr_fn attr_fn, 58 struct xfs_buf *bp, 59 void *priv) 60 { 61 struct xfs_attr3_icleaf_hdr ichdr; 62 struct xfs_mount *mp = sc->mp; 63 struct xfs_attr_leafblock *leaf = bp->b_addr; 64 struct xfs_attr_leaf_entry *entry; 65 unsigned int i; 66 int error; 67 68 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf); 69 entry = xfs_attr3_leaf_entryp(leaf); 70 71 for (i = 0; i < ichdr.count; entry++, i++) { 72 void *value; 73 unsigned char *name; 74 unsigned int namelen, valuelen; 75 76 if (entry->flags & XFS_ATTR_LOCAL) { 77 struct xfs_attr_leaf_name_local *name_loc; 78 79 name_loc = xfs_attr3_leaf_name_local(leaf, i); 80 name = name_loc->nameval; 81 namelen = name_loc->namelen; 82 value = &name_loc->nameval[name_loc->namelen]; 83 valuelen = be16_to_cpu(name_loc->valuelen); 84 } else { 85 struct xfs_attr_leaf_name_remote *name_rmt; 86 87 name_rmt = xfs_attr3_leaf_name_remote(leaf, i); 88 name = name_rmt->name; 89 namelen = name_rmt->namelen; 90 value = NULL; 91 valuelen = be32_to_cpu(name_rmt->valuelen); 92 } 93 94 error = attr_fn(sc, ip, entry->flags, name, namelen, value, 95 valuelen, priv); 96 if (error) 97 return error; 98 99 } 100 101 return 0; 102 } 103 104 /* 105 * Call a function for every entry in a leaf-format xattr structure. Avoid 106 * memory allocations for the loop detector since there's only one block. 107 */ 108 STATIC int 109 xchk_xattr_walk_leaf( 110 struct xfs_scrub *sc, 111 struct xfs_inode *ip, 112 xchk_xattr_fn attr_fn, 113 void *priv) 114 { 115 struct xfs_buf *leaf_bp; 116 int error; 117 118 error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino, 0, &leaf_bp); 119 if (error) 120 return error; 121 122 error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp, priv); 123 xfs_trans_brelse(sc->tp, leaf_bp); 124 return error; 125 } 126 127 /* Find the leftmost leaf in the xattr dabtree. */ 128 STATIC int 129 xchk_xattr_find_leftmost_leaf( 130 struct xfs_scrub *sc, 131 struct xfs_inode *ip, 132 struct xdab_bitmap *seen_dablks, 133 struct xfs_buf **leaf_bpp) 134 { 135 struct xfs_da3_icnode_hdr nodehdr; 136 struct xfs_mount *mp = sc->mp; 137 struct xfs_trans *tp = sc->tp; 138 struct xfs_da_intnode *node; 139 struct xfs_da_node_entry *btree; 140 struct xfs_buf *bp; 141 xfs_failaddr_t fa; 142 xfs_dablk_t blkno = 0; 143 unsigned int expected_level = 0; 144 int error; 145 146 for (;;) { 147 xfs_extlen_t len = 1; 148 uint16_t magic; 149 150 /* Make sure we haven't seen this new block already. */ 151 if (xdab_bitmap_test(seen_dablks, blkno, &len)) 152 return -EFSCORRUPTED; 153 154 error = xfs_da3_node_read(tp, ip, blkno, &bp, XFS_ATTR_FORK); 155 if (error) 156 return error; 157 158 node = bp->b_addr; 159 magic = be16_to_cpu(node->hdr.info.magic); 160 if (magic == XFS_ATTR_LEAF_MAGIC || 161 magic == XFS_ATTR3_LEAF_MAGIC) 162 break; 163 164 error = -EFSCORRUPTED; 165 if (magic != XFS_DA_NODE_MAGIC && 166 magic != XFS_DA3_NODE_MAGIC) 167 goto out_buf; 168 169 fa = xfs_da3_node_header_check(bp, ip->i_ino); 170 if (fa) 171 goto out_buf; 172 173 xfs_da3_node_hdr_from_disk(mp, &nodehdr, node); 174 175 if (nodehdr.count == 0 || nodehdr.level >= XFS_DA_NODE_MAXDEPTH) 176 goto out_buf; 177 178 /* Check the level from the root node. */ 179 if (blkno == 0) 180 expected_level = nodehdr.level - 1; 181 else if (expected_level != nodehdr.level) 182 goto out_buf; 183 else 184 expected_level--; 185 186 /* Remember that we've seen this node. */ 187 error = xdab_bitmap_set(seen_dablks, blkno, 1); 188 if (error) 189 goto out_buf; 190 191 /* Find the next level towards the leaves of the dabtree. */ 192 btree = nodehdr.btree; 193 blkno = be32_to_cpu(btree->before); 194 xfs_trans_brelse(tp, bp); 195 } 196 197 error = -EFSCORRUPTED; 198 fa = xfs_attr3_leaf_header_check(bp, ip->i_ino); 199 if (fa) 200 goto out_buf; 201 202 if (expected_level != 0) 203 goto out_buf; 204 205 /* Remember that we've seen this leaf. */ 206 error = xdab_bitmap_set(seen_dablks, blkno, 1); 207 if (error) 208 goto out_buf; 209 210 *leaf_bpp = bp; 211 return 0; 212 213 out_buf: 214 xfs_trans_brelse(tp, bp); 215 return error; 216 } 217 218 /* Call a function for every entry in a node-format xattr structure. */ 219 STATIC int 220 xchk_xattr_walk_node( 221 struct xfs_scrub *sc, 222 struct xfs_inode *ip, 223 xchk_xattr_fn attr_fn, 224 xchk_xattrleaf_fn leaf_fn, 225 void *priv) 226 { 227 struct xfs_attr3_icleaf_hdr leafhdr; 228 struct xdab_bitmap seen_dablks; 229 struct xfs_mount *mp = sc->mp; 230 struct xfs_attr_leafblock *leaf; 231 struct xfs_buf *leaf_bp; 232 int error; 233 234 xdab_bitmap_init(&seen_dablks); 235 236 error = xchk_xattr_find_leftmost_leaf(sc, ip, &seen_dablks, &leaf_bp); 237 if (error) 238 goto out_bitmap; 239 240 for (;;) { 241 xfs_extlen_t len; 242 243 error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp, 244 priv); 245 if (error) 246 goto out_leaf; 247 248 /* Find the right sibling of this leaf block. */ 249 leaf = leaf_bp->b_addr; 250 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); 251 if (leafhdr.forw == 0) 252 goto out_leaf; 253 254 xfs_trans_brelse(sc->tp, leaf_bp); 255 256 if (leaf_fn) { 257 error = leaf_fn(sc, priv); 258 if (error) 259 goto out_bitmap; 260 } 261 262 /* Make sure we haven't seen this new leaf already. */ 263 len = 1; 264 if (xdab_bitmap_test(&seen_dablks, leafhdr.forw, &len)) { 265 error = -EFSCORRUPTED; 266 goto out_bitmap; 267 } 268 269 error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino, 270 leafhdr.forw, &leaf_bp); 271 if (error) 272 goto out_bitmap; 273 274 /* Remember that we've seen this new leaf. */ 275 error = xdab_bitmap_set(&seen_dablks, leafhdr.forw, 1); 276 if (error) 277 goto out_leaf; 278 } 279 280 out_leaf: 281 xfs_trans_brelse(sc->tp, leaf_bp); 282 out_bitmap: 283 xdab_bitmap_destroy(&seen_dablks); 284 return error; 285 } 286 287 /* 288 * Call a function for every extended attribute in a file. 289 * 290 * Callers must hold the ILOCK. No validation or cursor restarts allowed. 291 * Returns -EFSCORRUPTED on any problem, including loops in the dabtree. 292 */ 293 int 294 xchk_xattr_walk( 295 struct xfs_scrub *sc, 296 struct xfs_inode *ip, 297 xchk_xattr_fn attr_fn, 298 xchk_xattrleaf_fn leaf_fn, 299 void *priv) 300 { 301 int error; 302 303 xfs_assert_ilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL); 304 305 if (!xfs_inode_hasattr(ip)) 306 return 0; 307 308 if (ip->i_af.if_format == XFS_DINODE_FMT_LOCAL) 309 return xchk_xattr_walk_sf(sc, ip, attr_fn, priv); 310 311 /* attr functions require that the attr fork is loaded */ 312 error = xfs_iread_extents(sc->tp, ip, XFS_ATTR_FORK); 313 if (error) 314 return error; 315 316 if (xfs_attr_is_leaf(ip)) 317 return xchk_xattr_walk_leaf(sc, ip, attr_fn, priv); 318 319 return xchk_xattr_walk_node(sc, ip, attr_fn, leaf_fn, priv); 320 } 321