Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2017 Oracle.  All Rights Reserved.
0004  * Author: Darrick J. Wong <darrick.wong@oracle.com>
0005  */
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_log_format.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_da_format.h"
0015 #include "xfs_da_btree.h"
0016 #include "xfs_attr.h"
0017 #include "xfs_attr_leaf.h"
0018 #include "scrub/scrub.h"
0019 #include "scrub/common.h"
0020 #include "scrub/dabtree.h"
0021 #include "scrub/attr.h"
0022 
0023 /*
0024  * Allocate enough memory to hold an attr value and attr block bitmaps,
0025  * reallocating the buffer if necessary.  Buffer contents are not preserved
0026  * across a reallocation.
0027  */
0028 static int
0029 xchk_setup_xattr_buf(
0030     struct xfs_scrub    *sc,
0031     size_t          value_size,
0032     gfp_t           flags)
0033 {
0034     size_t          sz;
0035     struct xchk_xattr_buf   *ab = sc->buf;
0036 
0037     /*
0038      * We need enough space to read an xattr value from the file or enough
0039      * space to hold three copies of the xattr free space bitmap.  We don't
0040      * need the buffer space for both purposes at the same time.
0041      */
0042     sz = 3 * sizeof(long) * BITS_TO_LONGS(sc->mp->m_attr_geo->blksize);
0043     sz = max_t(size_t, sz, value_size);
0044 
0045     /*
0046      * If there's already a buffer, figure out if we need to reallocate it
0047      * to accommodate a larger size.
0048      */
0049     if (ab) {
0050         if (sz <= ab->sz)
0051             return 0;
0052         kmem_free(ab);
0053         sc->buf = NULL;
0054     }
0055 
0056     /*
0057      * Don't zero the buffer upon allocation to avoid runtime overhead.
0058      * All users must be careful never to read uninitialized contents.
0059      */
0060     ab = kvmalloc(sizeof(*ab) + sz, flags);
0061     if (!ab)
0062         return -ENOMEM;
0063 
0064     ab->sz = sz;
0065     sc->buf = ab;
0066     return 0;
0067 }
0068 
0069 /* Set us up to scrub an inode's extended attributes. */
0070 int
0071 xchk_setup_xattr(
0072     struct xfs_scrub    *sc)
0073 {
0074     int         error;
0075 
0076     /*
0077      * We failed to get memory while checking attrs, so this time try to
0078      * get all the memory we're ever going to need.  Allocate the buffer
0079      * without the inode lock held, which means we can sleep.
0080      */
0081     if (sc->flags & XCHK_TRY_HARDER) {
0082         error = xchk_setup_xattr_buf(sc, XATTR_SIZE_MAX, GFP_KERNEL);
0083         if (error)
0084             return error;
0085     }
0086 
0087     return xchk_setup_inode_contents(sc, 0);
0088 }
0089 
0090 /* Extended Attributes */
0091 
0092 struct xchk_xattr {
0093     struct xfs_attr_list_context    context;
0094     struct xfs_scrub        *sc;
0095 };
0096 
0097 /*
0098  * Check that an extended attribute key can be looked up by hash.
0099  *
0100  * We use the XFS attribute list iterator (i.e. xfs_attr_list_ilocked)
0101  * to call this function for every attribute key in an inode.  Once
0102  * we're here, we load the attribute value to see if any errors happen,
0103  * or if we get more or less data than we expected.
0104  */
0105 static void
0106 xchk_xattr_listent(
0107     struct xfs_attr_list_context    *context,
0108     int             flags,
0109     unsigned char           *name,
0110     int             namelen,
0111     int             valuelen)
0112 {
0113     struct xchk_xattr       *sx;
0114     struct xfs_da_args      args = { NULL };
0115     int             error = 0;
0116 
0117     sx = container_of(context, struct xchk_xattr, context);
0118 
0119     if (xchk_should_terminate(sx->sc, &error)) {
0120         context->seen_enough = error;
0121         return;
0122     }
0123 
0124     if (flags & XFS_ATTR_INCOMPLETE) {
0125         /* Incomplete attr key, just mark the inode for preening. */
0126         xchk_ino_set_preen(sx->sc, context->dp->i_ino);
0127         return;
0128     }
0129 
0130     /* Does this name make sense? */
0131     if (!xfs_attr_namecheck(name, namelen)) {
0132         xchk_fblock_set_corrupt(sx->sc, XFS_ATTR_FORK, args.blkno);
0133         return;
0134     }
0135 
0136     /*
0137      * Try to allocate enough memory to extrat the attr value.  If that
0138      * doesn't work, we overload the seen_enough variable to convey
0139      * the error message back to the main scrub function.
0140      */
0141     error = xchk_setup_xattr_buf(sx->sc, valuelen,
0142             GFP_KERNEL | __GFP_RETRY_MAYFAIL);
0143     if (error == -ENOMEM)
0144         error = -EDEADLOCK;
0145     if (error) {
0146         context->seen_enough = error;
0147         return;
0148     }
0149 
0150     args.op_flags = XFS_DA_OP_NOTIME;
0151     args.attr_filter = flags & XFS_ATTR_NSP_ONDISK_MASK;
0152     args.geo = context->dp->i_mount->m_attr_geo;
0153     args.whichfork = XFS_ATTR_FORK;
0154     args.dp = context->dp;
0155     args.name = name;
0156     args.namelen = namelen;
0157     args.hashval = xfs_da_hashname(args.name, args.namelen);
0158     args.trans = context->tp;
0159     args.value = xchk_xattr_valuebuf(sx->sc);
0160     args.valuelen = valuelen;
0161 
0162     error = xfs_attr_get_ilocked(&args);
0163     /* ENODATA means the hash lookup failed and the attr is bad */
0164     if (error == -ENODATA)
0165         error = -EFSCORRUPTED;
0166     if (!xchk_fblock_process_error(sx->sc, XFS_ATTR_FORK, args.blkno,
0167             &error))
0168         goto fail_xref;
0169     if (args.valuelen != valuelen)
0170         xchk_fblock_set_corrupt(sx->sc, XFS_ATTR_FORK,
0171                          args.blkno);
0172 fail_xref:
0173     if (sx->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0174         context->seen_enough = 1;
0175     return;
0176 }
0177 
0178 /*
0179  * Mark a range [start, start+len) in this map.  Returns true if the
0180  * region was free, and false if there's a conflict or a problem.
0181  *
0182  * Within a char, the lowest bit of the char represents the byte with
0183  * the smallest address
0184  */
0185 STATIC bool
0186 xchk_xattr_set_map(
0187     struct xfs_scrub    *sc,
0188     unsigned long       *map,
0189     unsigned int        start,
0190     unsigned int        len)
0191 {
0192     unsigned int        mapsize = sc->mp->m_attr_geo->blksize;
0193     bool            ret = true;
0194 
0195     if (start >= mapsize)
0196         return false;
0197     if (start + len > mapsize) {
0198         len = mapsize - start;
0199         ret = false;
0200     }
0201 
0202     if (find_next_bit(map, mapsize, start) < start + len)
0203         ret = false;
0204     bitmap_set(map, start, len);
0205 
0206     return ret;
0207 }
0208 
0209 /*
0210  * Check the leaf freemap from the usage bitmap.  Returns false if the
0211  * attr freemap has problems or points to used space.
0212  */
0213 STATIC bool
0214 xchk_xattr_check_freemap(
0215     struct xfs_scrub        *sc,
0216     unsigned long           *map,
0217     struct xfs_attr3_icleaf_hdr *leafhdr)
0218 {
0219     unsigned long           *freemap = xchk_xattr_freemap(sc);
0220     unsigned long           *dstmap = xchk_xattr_dstmap(sc);
0221     unsigned int            mapsize = sc->mp->m_attr_geo->blksize;
0222     int             i;
0223 
0224     /* Construct bitmap of freemap contents. */
0225     bitmap_zero(freemap, mapsize);
0226     for (i = 0; i < XFS_ATTR_LEAF_MAPSIZE; i++) {
0227         if (!xchk_xattr_set_map(sc, freemap,
0228                 leafhdr->freemap[i].base,
0229                 leafhdr->freemap[i].size))
0230             return false;
0231     }
0232 
0233     /* Look for bits that are set in freemap and are marked in use. */
0234     return bitmap_and(dstmap, freemap, map, mapsize) == 0;
0235 }
0236 
0237 /*
0238  * Check this leaf entry's relations to everything else.
0239  * Returns the number of bytes used for the name/value data.
0240  */
0241 STATIC void
0242 xchk_xattr_entry(
0243     struct xchk_da_btree        *ds,
0244     int             level,
0245     char                *buf_end,
0246     struct xfs_attr_leafblock   *leaf,
0247     struct xfs_attr3_icleaf_hdr *leafhdr,
0248     struct xfs_attr_leaf_entry  *ent,
0249     int             idx,
0250     unsigned int            *usedbytes,
0251     __u32               *last_hashval)
0252 {
0253     struct xfs_mount        *mp = ds->state->mp;
0254     unsigned long           *usedmap = xchk_xattr_usedmap(ds->sc);
0255     char                *name_end;
0256     struct xfs_attr_leaf_name_local *lentry;
0257     struct xfs_attr_leaf_name_remote *rentry;
0258     unsigned int            nameidx;
0259     unsigned int            namesize;
0260 
0261     if (ent->pad2 != 0)
0262         xchk_da_set_corrupt(ds, level);
0263 
0264     /* Hash values in order? */
0265     if (be32_to_cpu(ent->hashval) < *last_hashval)
0266         xchk_da_set_corrupt(ds, level);
0267     *last_hashval = be32_to_cpu(ent->hashval);
0268 
0269     nameidx = be16_to_cpu(ent->nameidx);
0270     if (nameidx < leafhdr->firstused ||
0271         nameidx >= mp->m_attr_geo->blksize) {
0272         xchk_da_set_corrupt(ds, level);
0273         return;
0274     }
0275 
0276     /* Check the name information. */
0277     if (ent->flags & XFS_ATTR_LOCAL) {
0278         lentry = xfs_attr3_leaf_name_local(leaf, idx);
0279         namesize = xfs_attr_leaf_entsize_local(lentry->namelen,
0280                 be16_to_cpu(lentry->valuelen));
0281         name_end = (char *)lentry + namesize;
0282         if (lentry->namelen == 0)
0283             xchk_da_set_corrupt(ds, level);
0284     } else {
0285         rentry = xfs_attr3_leaf_name_remote(leaf, idx);
0286         namesize = xfs_attr_leaf_entsize_remote(rentry->namelen);
0287         name_end = (char *)rentry + namesize;
0288         if (rentry->namelen == 0 || rentry->valueblk == 0)
0289             xchk_da_set_corrupt(ds, level);
0290     }
0291     if (name_end > buf_end)
0292         xchk_da_set_corrupt(ds, level);
0293 
0294     if (!xchk_xattr_set_map(ds->sc, usedmap, nameidx, namesize))
0295         xchk_da_set_corrupt(ds, level);
0296     if (!(ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
0297         *usedbytes += namesize;
0298 }
0299 
0300 /* Scrub an attribute leaf. */
0301 STATIC int
0302 xchk_xattr_block(
0303     struct xchk_da_btree        *ds,
0304     int             level)
0305 {
0306     struct xfs_attr3_icleaf_hdr leafhdr;
0307     struct xfs_mount        *mp = ds->state->mp;
0308     struct xfs_da_state_blk     *blk = &ds->state->path.blk[level];
0309     struct xfs_buf          *bp = blk->bp;
0310     xfs_dablk_t         *last_checked = ds->private;
0311     struct xfs_attr_leafblock   *leaf = bp->b_addr;
0312     struct xfs_attr_leaf_entry  *ent;
0313     struct xfs_attr_leaf_entry  *entries;
0314     unsigned long           *usedmap;
0315     char                *buf_end;
0316     size_t              off;
0317     __u32               last_hashval = 0;
0318     unsigned int            usedbytes = 0;
0319     unsigned int            hdrsize;
0320     int             i;
0321     int             error;
0322 
0323     if (*last_checked == blk->blkno)
0324         return 0;
0325 
0326     /* Allocate memory for block usage checking. */
0327     error = xchk_setup_xattr_buf(ds->sc, 0,
0328             GFP_KERNEL | __GFP_RETRY_MAYFAIL);
0329     if (error == -ENOMEM)
0330         return -EDEADLOCK;
0331     if (error)
0332         return error;
0333     usedmap = xchk_xattr_usedmap(ds->sc);
0334 
0335     *last_checked = blk->blkno;
0336     bitmap_zero(usedmap, mp->m_attr_geo->blksize);
0337 
0338     /* Check all the padding. */
0339     if (xfs_has_crc(ds->sc->mp)) {
0340         struct xfs_attr3_leafblock  *leaf = bp->b_addr;
0341 
0342         if (leaf->hdr.pad1 != 0 || leaf->hdr.pad2 != 0 ||
0343             leaf->hdr.info.hdr.pad != 0)
0344             xchk_da_set_corrupt(ds, level);
0345     } else {
0346         if (leaf->hdr.pad1 != 0 || leaf->hdr.info.pad != 0)
0347             xchk_da_set_corrupt(ds, level);
0348     }
0349 
0350     /* Check the leaf header */
0351     xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
0352     hdrsize = xfs_attr3_leaf_hdr_size(leaf);
0353 
0354     if (leafhdr.usedbytes > mp->m_attr_geo->blksize)
0355         xchk_da_set_corrupt(ds, level);
0356     if (leafhdr.firstused > mp->m_attr_geo->blksize)
0357         xchk_da_set_corrupt(ds, level);
0358     if (leafhdr.firstused < hdrsize)
0359         xchk_da_set_corrupt(ds, level);
0360     if (!xchk_xattr_set_map(ds->sc, usedmap, 0, hdrsize))
0361         xchk_da_set_corrupt(ds, level);
0362 
0363     if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0364         goto out;
0365 
0366     entries = xfs_attr3_leaf_entryp(leaf);
0367     if ((char *)&entries[leafhdr.count] > (char *)leaf + leafhdr.firstused)
0368         xchk_da_set_corrupt(ds, level);
0369 
0370     buf_end = (char *)bp->b_addr + mp->m_attr_geo->blksize;
0371     for (i = 0, ent = entries; i < leafhdr.count; ent++, i++) {
0372         /* Mark the leaf entry itself. */
0373         off = (char *)ent - (char *)leaf;
0374         if (!xchk_xattr_set_map(ds->sc, usedmap, off,
0375                 sizeof(xfs_attr_leaf_entry_t))) {
0376             xchk_da_set_corrupt(ds, level);
0377             goto out;
0378         }
0379 
0380         /* Check the entry and nameval. */
0381         xchk_xattr_entry(ds, level, buf_end, leaf, &leafhdr,
0382                 ent, i, &usedbytes, &last_hashval);
0383 
0384         if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0385             goto out;
0386     }
0387 
0388     if (!xchk_xattr_check_freemap(ds->sc, usedmap, &leafhdr))
0389         xchk_da_set_corrupt(ds, level);
0390 
0391     if (leafhdr.usedbytes != usedbytes)
0392         xchk_da_set_corrupt(ds, level);
0393 
0394 out:
0395     return 0;
0396 }
0397 
0398 /* Scrub a attribute btree record. */
0399 STATIC int
0400 xchk_xattr_rec(
0401     struct xchk_da_btree        *ds,
0402     int             level)
0403 {
0404     struct xfs_mount        *mp = ds->state->mp;
0405     struct xfs_da_state_blk     *blk = &ds->state->path.blk[level];
0406     struct xfs_attr_leaf_name_local *lentry;
0407     struct xfs_attr_leaf_name_remote    *rentry;
0408     struct xfs_buf          *bp;
0409     struct xfs_attr_leaf_entry  *ent;
0410     xfs_dahash_t            calc_hash;
0411     xfs_dahash_t            hash;
0412     int             nameidx;
0413     int             hdrsize;
0414     unsigned int            badflags;
0415     int             error;
0416 
0417     ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
0418 
0419     ent = xfs_attr3_leaf_entryp(blk->bp->b_addr) + blk->index;
0420 
0421     /* Check the whole block, if necessary. */
0422     error = xchk_xattr_block(ds, level);
0423     if (error)
0424         goto out;
0425     if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0426         goto out;
0427 
0428     /* Check the hash of the entry. */
0429     error = xchk_da_btree_hash(ds, level, &ent->hashval);
0430     if (error)
0431         goto out;
0432 
0433     /* Find the attr entry's location. */
0434     bp = blk->bp;
0435     hdrsize = xfs_attr3_leaf_hdr_size(bp->b_addr);
0436     nameidx = be16_to_cpu(ent->nameidx);
0437     if (nameidx < hdrsize || nameidx >= mp->m_attr_geo->blksize) {
0438         xchk_da_set_corrupt(ds, level);
0439         goto out;
0440     }
0441 
0442     /* Retrieve the entry and check it. */
0443     hash = be32_to_cpu(ent->hashval);
0444     badflags = ~(XFS_ATTR_LOCAL | XFS_ATTR_ROOT | XFS_ATTR_SECURE |
0445             XFS_ATTR_INCOMPLETE);
0446     if ((ent->flags & badflags) != 0)
0447         xchk_da_set_corrupt(ds, level);
0448     if (ent->flags & XFS_ATTR_LOCAL) {
0449         lentry = (struct xfs_attr_leaf_name_local *)
0450                 (((char *)bp->b_addr) + nameidx);
0451         if (lentry->namelen <= 0) {
0452             xchk_da_set_corrupt(ds, level);
0453             goto out;
0454         }
0455         calc_hash = xfs_da_hashname(lentry->nameval, lentry->namelen);
0456     } else {
0457         rentry = (struct xfs_attr_leaf_name_remote *)
0458                 (((char *)bp->b_addr) + nameidx);
0459         if (rentry->namelen <= 0) {
0460             xchk_da_set_corrupt(ds, level);
0461             goto out;
0462         }
0463         calc_hash = xfs_da_hashname(rentry->name, rentry->namelen);
0464     }
0465     if (calc_hash != hash)
0466         xchk_da_set_corrupt(ds, level);
0467 
0468 out:
0469     return error;
0470 }
0471 
0472 /* Scrub the extended attribute metadata. */
0473 int
0474 xchk_xattr(
0475     struct xfs_scrub        *sc)
0476 {
0477     struct xchk_xattr       sx;
0478     xfs_dablk_t         last_checked = -1U;
0479     int             error = 0;
0480 
0481     if (!xfs_inode_hasattr(sc->ip))
0482         return -ENOENT;
0483 
0484     memset(&sx, 0, sizeof(sx));
0485     /* Check attribute tree structure */
0486     error = xchk_da_btree(sc, XFS_ATTR_FORK, xchk_xattr_rec,
0487             &last_checked);
0488     if (error)
0489         goto out;
0490 
0491     if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
0492         goto out;
0493 
0494     /* Check that every attr key can also be looked up by hash. */
0495     sx.context.dp = sc->ip;
0496     sx.context.resynch = 1;
0497     sx.context.put_listent = xchk_xattr_listent;
0498     sx.context.tp = sc->tp;
0499     sx.context.allow_incomplete = true;
0500     sx.sc = sc;
0501 
0502     /*
0503      * Look up every xattr in this file by name.
0504      *
0505      * Use the backend implementation of xfs_attr_list to call
0506      * xchk_xattr_listent on every attribute key in this inode.
0507      * In other words, we use the same iterator/callback mechanism
0508      * that listattr uses to scrub extended attributes, though in our
0509      * _listent function, we check the value of the attribute.
0510      *
0511      * The VFS only locks i_rwsem when modifying attrs, so keep all
0512      * three locks held because that's the only way to ensure we're
0513      * the only thread poking into the da btree.  We traverse the da
0514      * btree while holding a leaf buffer locked for the xattr name
0515      * iteration, which doesn't really follow the usual buffer
0516      * locking order.
0517      */
0518     error = xfs_attr_list_ilocked(&sx.context);
0519     if (!xchk_fblock_process_error(sc, XFS_ATTR_FORK, 0, &error))
0520         goto out;
0521 
0522     /* Did our listent function try to return any errors? */
0523     if (sx.context.seen_enough < 0)
0524         error = sx.context.seen_enough;
0525 out:
0526     return error;
0527 }