]> Git Repo - linux.git/blob - fs/xfs/scrub/attr.c
Merge tag 'char-misc-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[linux.git] / fs / xfs / scrub / attr.c
1 /*
2  * Copyright (C) 2017 Oracle.  All Rights Reserved.
3  *
4  * Author: Darrick J. Wong <[email protected]>
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 }
This page took 0.073135 seconds and 4 git commands to generate.