1 /* 2 * Copyright (C) 2017 Oracle. All Rights Reserved. 3 * 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it would be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 #include "xfs.h" 21 #include "xfs_fs.h" 22 #include "xfs_shared.h" 23 #include "xfs_format.h" 24 #include "xfs_trans_resv.h" 25 #include "xfs_mount.h" 26 #include "xfs_defer.h" 27 #include "xfs_btree.h" 28 #include "xfs_bit.h" 29 #include "xfs_log_format.h" 30 #include "xfs_trans.h" 31 #include "xfs_sb.h" 32 #include "xfs_inode.h" 33 #include "xfs_da_format.h" 34 #include "xfs_da_btree.h" 35 #include "xfs_dir2.h" 36 #include "xfs_attr.h" 37 #include "xfs_attr_leaf.h" 38 #include "scrub/xfs_scrub.h" 39 #include "scrub/scrub.h" 40 #include "scrub/common.h" 41 #include "scrub/dabtree.h" 42 #include "scrub/trace.h" 43 44 #include <linux/posix_acl_xattr.h> 45 #include <linux/xattr.h> 46 47 /* Set us up to scrub an inode's extended attributes. */ 48 int 49 xfs_scrub_setup_xattr( 50 struct xfs_scrub_context *sc, 51 struct xfs_inode *ip) 52 { 53 size_t sz; 54 55 /* 56 * Allocate the buffer without the inode lock held. We need enough 57 * space to read every xattr value in the file or enough space to 58 * hold three copies of the xattr free space bitmap. (Not both at 59 * the same time.) 60 */ 61 sz = max_t(size_t, XATTR_SIZE_MAX, 3 * sizeof(long) * 62 BITS_TO_LONGS(sc->mp->m_attr_geo->blksize)); 63 sc->buf = kmem_zalloc_large(sz, KM_SLEEP); 64 if (!sc->buf) 65 return -ENOMEM; 66 67 return xfs_scrub_setup_inode_contents(sc, ip, 0); 68 } 69 70 /* Extended Attributes */ 71 72 struct xfs_scrub_xattr { 73 struct xfs_attr_list_context context; 74 struct xfs_scrub_context *sc; 75 }; 76 77 /* 78 * Check that an extended attribute key can be looked up by hash. 79 * 80 * We use the XFS attribute list iterator (i.e. xfs_attr_list_int_ilocked) 81 * to call this function for every attribute key in an inode. Once 82 * we're here, we load the attribute value to see if any errors happen, 83 * or if we get more or less data than we expected. 84 */ 85 static void 86 xfs_scrub_xattr_listent( 87 struct xfs_attr_list_context *context, 88 int flags, 89 unsigned char *name, 90 int namelen, 91 int valuelen) 92 { 93 struct xfs_scrub_xattr *sx; 94 struct xfs_da_args args = { NULL }; 95 int error = 0; 96 97 sx = container_of(context, struct xfs_scrub_xattr, context); 98 99 if (flags & XFS_ATTR_INCOMPLETE) { 100 /* Incomplete attr key, just mark the inode for preening. */ 101 xfs_scrub_ino_set_preen(sx->sc, context->dp->i_ino); 102 return; 103 } 104 105 args.flags = ATTR_KERNOTIME; 106 if (flags & XFS_ATTR_ROOT) 107 args.flags |= ATTR_ROOT; 108 else if (flags & XFS_ATTR_SECURE) 109 args.flags |= ATTR_SECURE; 110 args.geo = context->dp->i_mount->m_attr_geo; 111 args.whichfork = XFS_ATTR_FORK; 112 args.dp = context->dp; 113 args.name = name; 114 args.namelen = namelen; 115 args.hashval = xfs_da_hashname(args.name, args.namelen); 116 args.trans = context->tp; 117 args.value = sx->sc->buf; 118 args.valuelen = XATTR_SIZE_MAX; 119 120 error = xfs_attr_get_ilocked(context->dp, &args); 121 if (error == -EEXIST) 122 error = 0; 123 if (!xfs_scrub_fblock_process_error(sx->sc, XFS_ATTR_FORK, args.blkno, 124 &error)) 125 goto fail_xref; 126 if (args.valuelen != valuelen) 127 xfs_scrub_fblock_set_corrupt(sx->sc, XFS_ATTR_FORK, 128 args.blkno); 129 fail_xref: 130 if (sx->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 131 context->seen_enough = 1; 132 return; 133 } 134 135 /* 136 * Mark a range [start, start+len) in this map. Returns true if the 137 * region was free, and false if there's a conflict or a problem. 138 * 139 * Within a char, the lowest bit of the char represents the byte with 140 * the smallest address 141 */ 142 STATIC bool 143 xfs_scrub_xattr_set_map( 144 struct xfs_scrub_context *sc, 145 unsigned long *map, 146 unsigned int start, 147 unsigned int len) 148 { 149 unsigned int mapsize = sc->mp->m_attr_geo->blksize; 150 bool ret = true; 151 152 if (start >= mapsize) 153 return false; 154 if (start + len > mapsize) { 155 len = mapsize - start; 156 ret = false; 157 } 158 159 if (find_next_bit(map, mapsize, start) < start + len) 160 ret = false; 161 bitmap_set(map, start, len); 162 163 return ret; 164 } 165 166 /* 167 * Check the leaf freemap from the usage bitmap. Returns false if the 168 * attr freemap has problems or points to used space. 169 */ 170 STATIC bool 171 xfs_scrub_xattr_check_freemap( 172 struct xfs_scrub_context *sc, 173 unsigned long *map, 174 struct xfs_attr3_icleaf_hdr *leafhdr) 175 { 176 unsigned long *freemap; 177 unsigned long *dstmap; 178 unsigned int mapsize = sc->mp->m_attr_geo->blksize; 179 int i; 180 181 /* Construct bitmap of freemap contents. */ 182 freemap = (unsigned long *)sc->buf + BITS_TO_LONGS(mapsize); 183 bitmap_zero(freemap, mapsize); 184 for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) { 185 if (!xfs_scrub_xattr_set_map(sc, freemap, 186 leafhdr->freemap[i].base, 187 leafhdr->freemap[i].size)) 188 return false; 189 } 190 191 /* Look for bits that are set in freemap and are marked in use. */ 192 dstmap = freemap + BITS_TO_LONGS(mapsize); 193 return bitmap_and(dstmap, freemap, map, mapsize) == 0; 194 } 195 196 /* 197 * Check this leaf entry's relations to everything else. 198 * Returns the number of bytes used for the name/value data. 199 */ 200 STATIC void 201 xfs_scrub_xattr_entry( 202 struct xfs_scrub_da_btree *ds, 203 int level, 204 char *buf_end, 205 struct xfs_attr_leafblock *leaf, 206 struct xfs_attr3_icleaf_hdr *leafhdr, 207 unsigned long *usedmap, 208 struct xfs_attr_leaf_entry *ent, 209 int idx, 210 unsigned int *usedbytes, 211 __u32 *last_hashval) 212 { 213 struct xfs_mount *mp = ds->state->mp; 214 char *name_end; 215 struct xfs_attr_leaf_name_local *lentry; 216 struct xfs_attr_leaf_name_remote *rentry; 217 unsigned int nameidx; 218 unsigned int namesize; 219 220 if (ent->pad2 != 0) 221 xfs_scrub_da_set_corrupt(ds, level); 222 223 /* Hash values in order? */ 224 if (be32_to_cpu(ent->hashval) < *last_hashval) 225 xfs_scrub_da_set_corrupt(ds, level); 226 *last_hashval = be32_to_cpu(ent->hashval); 227 228 nameidx = be16_to_cpu(ent->nameidx); 229 if (nameidx < leafhdr->firstused || 230 nameidx >= mp->m_attr_geo->blksize) { 231 xfs_scrub_da_set_corrupt(ds, level); 232 return; 233 } 234 235 /* Check the name information. */ 236 if (ent->flags & XFS_ATTR_LOCAL) { 237 lentry = xfs_attr3_leaf_name_local(leaf, idx); 238 namesize = xfs_attr_leaf_entsize_local(lentry->namelen, 239 be16_to_cpu(lentry->valuelen)); 240 name_end = (char *)lentry + namesize; 241 if (lentry->namelen == 0) 242 xfs_scrub_da_set_corrupt(ds, level); 243 } else { 244 rentry = xfs_attr3_leaf_name_remote(leaf, idx); 245 namesize = xfs_attr_leaf_entsize_remote(rentry->namelen); 246 name_end = (char *)rentry + namesize; 247 if (rentry->namelen == 0 || rentry->valueblk == 0) 248 xfs_scrub_da_set_corrupt(ds, level); 249 } 250 if (name_end > buf_end) 251 xfs_scrub_da_set_corrupt(ds, level); 252 253 if (!xfs_scrub_xattr_set_map(ds->sc, usedmap, nameidx, namesize)) 254 xfs_scrub_da_set_corrupt(ds, level); 255 if (!(ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 256 *usedbytes += namesize; 257 } 258 259 /* Scrub an attribute leaf. */ 260 STATIC int 261 xfs_scrub_xattr_block( 262 struct xfs_scrub_da_btree *ds, 263 int level) 264 { 265 struct xfs_attr3_icleaf_hdr leafhdr; 266 struct xfs_mount *mp = ds->state->mp; 267 struct xfs_da_state_blk *blk = &ds->state->path.blk[level]; 268 struct xfs_buf *bp = blk->bp; 269 xfs_dablk_t *last_checked = ds->private; 270 struct xfs_attr_leafblock *leaf = bp->b_addr; 271 struct xfs_attr_leaf_entry *ent; 272 struct xfs_attr_leaf_entry *entries; 273 unsigned long *usedmap = ds->sc->buf; 274 char *buf_end; 275 size_t off; 276 __u32 last_hashval = 0; 277 unsigned int usedbytes = 0; 278 unsigned int hdrsize; 279 int i; 280 281 if (*last_checked == blk->blkno) 282 return 0; 283 *last_checked = blk->blkno; 284 bitmap_zero(usedmap, mp->m_attr_geo->blksize); 285 286 /* Check all the padding. */ 287 if (xfs_sb_version_hascrc(&ds->sc->mp->m_sb)) { 288 struct xfs_attr3_leafblock *leaf = bp->b_addr; 289 290 if (leaf->hdr.pad1 != 0 || leaf->hdr.pad2 != 0 || 291 leaf->hdr.info.hdr.pad != 0) 292 xfs_scrub_da_set_corrupt(ds, level); 293 } else { 294 if (leaf->hdr.pad1 != 0 || leaf->hdr.info.pad != 0) 295 xfs_scrub_da_set_corrupt(ds, level); 296 } 297 298 /* Check the leaf header */ 299 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf); 300 hdrsize = xfs_attr3_leaf_hdr_size(leaf); 301 302 if (leafhdr.usedbytes > mp->m_attr_geo->blksize) 303 xfs_scrub_da_set_corrupt(ds, level); 304 if (leafhdr.firstused > mp->m_attr_geo->blksize) 305 xfs_scrub_da_set_corrupt(ds, level); 306 if (leafhdr.firstused < hdrsize) 307 xfs_scrub_da_set_corrupt(ds, level); 308 if (!xfs_scrub_xattr_set_map(ds->sc, usedmap, 0, hdrsize)) 309 xfs_scrub_da_set_corrupt(ds, level); 310 311 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 312 goto out; 313 314 entries = xfs_attr3_leaf_entryp(leaf); 315 if ((char *)&entries[leafhdr.count] > (char *)leaf + leafhdr.firstused) 316 xfs_scrub_da_set_corrupt(ds, level); 317 318 buf_end = (char *)bp->b_addr + mp->m_attr_geo->blksize; 319 for (i = 0, ent = entries; i < leafhdr.count; ent++, i++) { 320 /* Mark the leaf entry itself. */ 321 off = (char *)ent - (char *)leaf; 322 if (!xfs_scrub_xattr_set_map(ds->sc, usedmap, off, 323 sizeof(xfs_attr_leaf_entry_t))) { 324 xfs_scrub_da_set_corrupt(ds, level); 325 goto out; 326 } 327 328 /* Check the entry and nameval. */ 329 xfs_scrub_xattr_entry(ds, level, buf_end, leaf, &leafhdr, 330 usedmap, ent, i, &usedbytes, &last_hashval); 331 332 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 333 goto out; 334 } 335 336 if (!xfs_scrub_xattr_check_freemap(ds->sc, usedmap, &leafhdr)) 337 xfs_scrub_da_set_corrupt(ds, level); 338 339 if (leafhdr.usedbytes != usedbytes) 340 xfs_scrub_da_set_corrupt(ds, level); 341 342 out: 343 return 0; 344 } 345 346 /* Scrub a attribute btree record. */ 347 STATIC int 348 xfs_scrub_xattr_rec( 349 struct xfs_scrub_da_btree *ds, 350 int level, 351 void *rec) 352 { 353 struct xfs_mount *mp = ds->state->mp; 354 struct xfs_attr_leaf_entry *ent = rec; 355 struct xfs_da_state_blk *blk; 356 struct xfs_attr_leaf_name_local *lentry; 357 struct xfs_attr_leaf_name_remote *rentry; 358 struct xfs_buf *bp; 359 xfs_dahash_t calc_hash; 360 xfs_dahash_t hash; 361 int nameidx; 362 int hdrsize; 363 unsigned int badflags; 364 int error; 365 366 blk = &ds->state->path.blk[level]; 367 368 /* Check the whole block, if necessary. */ 369 error = xfs_scrub_xattr_block(ds, level); 370 if (error) 371 goto out; 372 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 373 goto out; 374 375 /* Check the hash of the entry. */ 376 error = xfs_scrub_da_btree_hash(ds, level, &ent->hashval); 377 if (error) 378 goto out; 379 380 /* Find the attr entry's location. */ 381 bp = blk->bp; 382 hdrsize = xfs_attr3_leaf_hdr_size(bp->b_addr); 383 nameidx = be16_to_cpu(ent->nameidx); 384 if (nameidx < hdrsize || nameidx >= mp->m_attr_geo->blksize) { 385 xfs_scrub_da_set_corrupt(ds, level); 386 goto out; 387 } 388 389 /* Retrieve the entry and check it. */ 390 hash = be32_to_cpu(ent->hashval); 391 badflags = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_SECURE | 392 XFS_ATTR_INCOMPLETE); 393 if ((ent->flags & badflags) != 0) 394 xfs_scrub_da_set_corrupt(ds, level); 395 if (ent->flags & XFS_ATTR_LOCAL) { 396 lentry = (struct xfs_attr_leaf_name_local *) 397 (((char *)bp->b_addr) + nameidx); 398 if (lentry->namelen <= 0) { 399 xfs_scrub_da_set_corrupt(ds, level); 400 goto out; 401 } 402 calc_hash = xfs_da_hashname(lentry->nameval, lentry->namelen); 403 } else { 404 rentry = (struct xfs_attr_leaf_name_remote *) 405 (((char *)bp->b_addr) + nameidx); 406 if (rentry->namelen <= 0) { 407 xfs_scrub_da_set_corrupt(ds, level); 408 goto out; 409 } 410 calc_hash = xfs_da_hashname(rentry->name, rentry->namelen); 411 } 412 if (calc_hash != hash) 413 xfs_scrub_da_set_corrupt(ds, level); 414 415 out: 416 return error; 417 } 418 419 /* Scrub the extended attribute metadata. */ 420 int 421 xfs_scrub_xattr( 422 struct xfs_scrub_context *sc) 423 { 424 struct xfs_scrub_xattr sx; 425 struct attrlist_cursor_kern cursor = { 0 }; 426 xfs_dablk_t last_checked = -1U; 427 int error = 0; 428 429 if (!xfs_inode_hasattr(sc->ip)) 430 return -ENOENT; 431 432 memset(&sx, 0, sizeof(sx)); 433 /* Check attribute tree structure */ 434 error = xfs_scrub_da_btree(sc, XFS_ATTR_FORK, xfs_scrub_xattr_rec, 435 &last_checked); 436 if (error) 437 goto out; 438 439 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 440 goto out; 441 442 /* Check that every attr key can also be looked up by hash. */ 443 sx.context.dp = sc->ip; 444 sx.context.cursor = &cursor; 445 sx.context.resynch = 1; 446 sx.context.put_listent = xfs_scrub_xattr_listent; 447 sx.context.tp = sc->tp; 448 sx.context.flags = ATTR_INCOMPLETE; 449 sx.sc = sc; 450 451 /* 452 * Look up every xattr in this file by name. 453 * 454 * Use the backend implementation of xfs_attr_list to call 455 * xfs_scrub_xattr_listent on every attribute key in this inode. 456 * In other words, we use the same iterator/callback mechanism 457 * that listattr uses to scrub extended attributes, though in our 458 * _listent function, we check the value of the attribute. 459 * 460 * The VFS only locks i_rwsem when modifying attrs, so keep all 461 * three locks held because that's the only way to ensure we're 462 * the only thread poking into the da btree. We traverse the da 463 * btree while holding a leaf buffer locked for the xattr name 464 * iteration, which doesn't really follow the usual buffer 465 * locking order. 466 */ 467 error = xfs_attr_list_int_ilocked(&sx.context); 468 if (!xfs_scrub_fblock_process_error(sc, XFS_ATTR_FORK, 0, &error)) 469 goto out; 470 out: 471 return error; 472 } 473