Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2022-2023 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 "xfs_parent.h"
21 : #include "scrub/scrub.h"
22 : #include "scrub/bitmap.h"
23 : #include "scrub/listxattr.h"
24 :
25 : /* Call a function for every entry in a shortform xattr structure. */
26 : STATIC int
27 6195779693 : 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 6195779693 : struct xfs_attr_shortform *sf;
34 6195779693 : struct xfs_attr_sf_entry *sfe;
35 6195779693 : unsigned int i;
36 6195779693 : int error;
37 :
38 6195779693 : sf = (struct xfs_attr_shortform *)ip->i_af.if_u1.if_data;
39 14602383534 : for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
40 8473446268 : error = attr_fn(sc, ip, sfe->flags, sfe->nameval, sfe->namelen,
41 8473446268 : &sfe->nameval[sfe->namelen], sfe->valuelen,
42 : priv);
43 8427331302 : if (error)
44 20727461 : return error;
45 :
46 8406603841 : 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 250549285 : 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 250549285 : struct xfs_attr3_icleaf_hdr ichdr;
62 250549285 : struct xfs_mount *mp = sc->mp;
63 250549285 : struct xfs_attr_leafblock *leaf = bp->b_addr;
64 250549285 : struct xfs_attr_leaf_entry *entry;
65 250549285 : unsigned int i;
66 250549285 : int error;
67 :
68 250549285 : xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
69 250603004 : entry = xfs_attr3_leaf_entryp(leaf);
70 :
71 2400130331 : for (i = 0; i < ichdr.count; entry++, i++) {
72 2149752815 : void *value;
73 2149752815 : unsigned char *name;
74 2149752815 : unsigned int namelen, valuelen;
75 :
76 2149752815 : if (entry->flags & XFS_ATTR_LOCAL) {
77 2149746881 : struct xfs_attr_leaf_name_local *name_loc;
78 :
79 2149746881 : name_loc = xfs_attr3_leaf_name_local(leaf, i);
80 2149746881 : name = name_loc->nameval;
81 2149746881 : namelen = name_loc->namelen;
82 2149746881 : value = &name_loc->nameval[name_loc->namelen];
83 2149746881 : valuelen = be16_to_cpu(name_loc->valuelen);
84 : } else {
85 5934 : struct xfs_attr_leaf_name_remote *name_rmt;
86 :
87 5934 : name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
88 5934 : name = name_rmt->name;
89 5934 : namelen = name_rmt->namelen;
90 5934 : value = NULL;
91 5934 : valuelen = be32_to_cpu(name_rmt->valuelen);
92 : }
93 :
94 2149752815 : error = attr_fn(sc, ip, entry->flags, name, namelen, value,
95 : valuelen, priv);
96 2149650985 : if (error)
97 123658 : 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 248944430 : 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 248944430 : struct xfs_buf *leaf_bp;
116 248944430 : int error;
117 :
118 248944430 : error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino, 0, &leaf_bp);
119 248842196 : if (error)
120 : return error;
121 :
122 248844820 : error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp, priv);
123 248898114 : xfs_trans_brelse(sc->tp, leaf_bp);
124 248898114 : return error;
125 : }
126 :
127 : /* Find the leftmost leaf in the xattr dabtree. */
128 : STATIC int
129 91299 : xchk_xattr_find_leftmost_leaf(
130 : struct xfs_scrub *sc,
131 : struct xfs_inode *ip,
132 : struct xbitmap *seen_blocks,
133 : struct xfs_buf **leaf_bpp)
134 : {
135 91299 : struct xfs_da3_icnode_hdr nodehdr;
136 91299 : struct xfs_mount *mp = sc->mp;
137 91299 : struct xfs_trans *tp = sc->tp;
138 91299 : struct xfs_da_intnode *node;
139 91299 : struct xfs_da_node_entry *btree;
140 91299 : struct xfs_buf *bp;
141 91299 : xfs_failaddr_t fa;
142 91299 : xfs_dablk_t blkno = 0;
143 91299 : unsigned int expected_level = 0;
144 177303 : int error;
145 :
146 86004 : for (;;) {
147 177303 : uint64_t len = 1;
148 177303 : uint16_t magic;
149 :
150 : /* Make sure we haven't seen this new block already. */
151 177303 : if (xbitmap_test(seen_blocks, blkno, &len))
152 0 : return -EFSCORRUPTED;
153 :
154 177297 : error = xfs_da3_node_read(tp, ip, blkno, &bp, XFS_ATTR_FORK);
155 177299 : if (error)
156 0 : return error;
157 :
158 177299 : node = bp->b_addr;
159 177299 : magic = be16_to_cpu(node->hdr.info.magic);
160 177299 : if (magic == XFS_ATTR_LEAF_MAGIC ||
161 177299 : magic == XFS_ATTR3_LEAF_MAGIC)
162 : break;
163 :
164 85995 : error = -EFSCORRUPTED;
165 85995 : if (magic != XFS_DA_NODE_MAGIC &&
166 85995 : magic != XFS_DA3_NODE_MAGIC)
167 0 : goto out_buf;
168 :
169 85995 : fa = xfs_da3_node_header_check(bp, ip->i_ino);
170 85990 : if (fa)
171 0 : goto out_buf;
172 :
173 85990 : xfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
174 :
175 85986 : if (nodehdr.count == 0 || nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
176 0 : goto out_buf;
177 :
178 : /* Check the level from the root node. */
179 85986 : if (blkno == 0)
180 85695 : expected_level = nodehdr.level - 1;
181 291 : else if (expected_level != nodehdr.level)
182 0 : goto out_buf;
183 : else
184 291 : expected_level--;
185 :
186 : /* Remember that we've seen this node. */
187 85986 : error = xbitmap_set(seen_blocks, blkno, 1);
188 85991 : if (error)
189 0 : goto out_buf;
190 :
191 : /* Find the next level towards the leaves of the dabtree. */
192 85991 : btree = nodehdr.btree;
193 85991 : blkno = be32_to_cpu(btree->before);
194 85991 : xfs_trans_brelse(tp, bp);
195 : }
196 :
197 91304 : error = -EFSCORRUPTED;
198 91304 : fa = xfs_attr3_leaf_header_check(bp, ip->i_ino);
199 91295 : if (fa)
200 0 : goto out_buf;
201 :
202 91295 : if (expected_level != 0)
203 0 : goto out_buf;
204 :
205 : /* Remember that we've seen this leaf. */
206 91295 : error = xbitmap_set(seen_blocks, blkno, 1);
207 91283 : if (error)
208 0 : goto out_buf;
209 :
210 91283 : *leaf_bpp = bp;
211 91283 : return 0;
212 :
213 0 : out_buf:
214 0 : xfs_trans_brelse(tp, bp);
215 0 : return error;
216 : }
217 :
218 : /* Call a function for every entry in a node-format xattr structure. */
219 : STATIC int
220 91296 : 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 91296 : struct xfs_attr3_icleaf_hdr leafhdr;
228 91296 : struct xbitmap seen_blocks;
229 91296 : struct xfs_mount *mp = sc->mp;
230 91296 : struct xfs_attr_leafblock *leaf;
231 91296 : struct xfs_buf *leaf_bp;
232 91296 : int error;
233 :
234 91296 : xbitmap_init(&seen_blocks);
235 :
236 91296 : error = xchk_xattr_find_leftmost_leaf(sc, ip, &seen_blocks, &leaf_bp);
237 91290 : if (error)
238 0 : goto out_bitmap;
239 :
240 1553940 : for (;;) {
241 1645230 : uint64_t len;
242 :
243 1645230 : error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp,
244 : priv);
245 1645262 : if (error)
246 38 : goto out_leaf;
247 :
248 : /* Find the right sibling of this leaf block. */
249 1645224 : leaf = leaf_bp->b_addr;
250 1645224 : xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
251 1645226 : if (leafhdr.forw == 0)
252 91269 : goto out_leaf;
253 :
254 1553957 : xfs_trans_brelse(sc->tp, leaf_bp);
255 :
256 1553988 : if (leaf_fn) {
257 5736 : error = leaf_fn(sc, priv);
258 5736 : if (error)
259 0 : goto out_bitmap;
260 : }
261 :
262 : /* Make sure we haven't seen this new leaf already. */
263 1553988 : len = 1;
264 1553988 : if (xbitmap_test(&seen_blocks, leafhdr.forw, &len))
265 0 : goto out_bitmap;
266 :
267 1553978 : error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino,
268 : leafhdr.forw, &leaf_bp);
269 1553877 : if (error)
270 0 : goto out_bitmap;
271 :
272 : /* Remember that we've seen this new leaf. */
273 1553877 : error = xbitmap_set(&seen_blocks, leafhdr.forw, 1);
274 1553940 : if (error)
275 0 : goto out_leaf;
276 : }
277 :
278 : out_leaf:
279 91307 : xfs_trans_brelse(sc->tp, leaf_bp);
280 91308 : out_bitmap:
281 91308 : xbitmap_destroy(&seen_blocks);
282 91301 : return error;
283 : }
284 :
285 : /*
286 : * Call a function for every extended attribute in a file.
287 : *
288 : * Callers must hold the ILOCK. No validation or cursor restarts allowed.
289 : * Returns -EFSCORRUPTED on any problem, including loops in the dabtree.
290 : */
291 : int
292 6454571526 : xchk_xattr_walk(
293 : struct xfs_scrub *sc,
294 : struct xfs_inode *ip,
295 : xchk_xattr_fn attr_fn,
296 : xchk_xattrleaf_fn leaf_fn,
297 : void *priv)
298 : {
299 6454571526 : int error;
300 :
301 6454571526 : ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
302 :
303 6427844936 : if (!xfs_inode_hasattr(ip))
304 : return 0;
305 :
306 6428691666 : if (ip->i_af.if_format == XFS_DINODE_FMT_LOCAL)
307 6179666358 : return xchk_xattr_walk_sf(sc, ip, attr_fn, priv);
308 :
309 : /* attr functions require that the attr fork is loaded */
310 249025308 : error = xfs_iread_extents(sc->tp, ip, XFS_ATTR_FORK);
311 248989508 : if (error)
312 : return error;
313 :
314 248996484 : if (xfs_attr_is_leaf(ip))
315 248949143 : return xchk_xattr_walk_leaf(sc, ip, attr_fn, priv);
316 :
317 91297 : return xchk_xattr_walk_node(sc, ip, attr_fn, leaf_fn, priv);
318 : }
319 :
320 : struct xchk_pptr_walk {
321 : struct xfs_parent_name_irec *pptr_buf;
322 : xchk_pptr_fn fn;
323 : void *priv;
324 : };
325 :
326 : STATIC int
327 10225841135 : xchk_pptr_walk_attr(
328 : struct xfs_scrub *sc,
329 : struct xfs_inode *ip,
330 : unsigned int attr_flags,
331 : const unsigned char *name,
332 : unsigned int namelen,
333 : const void *value,
334 : unsigned int valuelen,
335 : void *priv)
336 : {
337 10225841135 : struct xchk_pptr_walk *pw = priv;
338 10225841135 : const struct xfs_parent_name_rec *rec = (const void *)name;
339 :
340 : /* Ignore anything that isn't a parent pointer. */
341 10225841135 : if (!(attr_flags & XFS_ATTR_PARENT))
342 : return 0;
343 :
344 : /* Does the ondisk parent pointer structure make sense? */
345 13116645868 : if (!xfs_parent_namecheck(sc->mp, rec, namelen, attr_flags) ||
346 6572828786 : !xfs_parent_valuecheck(sc->mp, value, valuelen))
347 0 : return -EFSCORRUPTED;
348 :
349 6547635981 : xfs_parent_irec_from_disk(pw->pptr_buf, rec, value, valuelen);
350 6537323573 : return pw->fn(sc, ip, pw->pptr_buf, pw->priv);
351 : }
352 :
353 : /*
354 : * Walk every parent pointer of this file. The parent pointer will be
355 : * formatted into the provided pptr_buf, which is then passed to the callback
356 : * function.
357 : */
358 : int
359 6198895073 : xchk_pptr_walk(
360 : struct xfs_scrub *sc,
361 : struct xfs_inode *ip,
362 : xchk_pptr_fn pptr_fn,
363 : struct xfs_parent_name_irec *pptr_buf,
364 : void *priv)
365 : {
366 6198895073 : struct xchk_pptr_walk pw = {
367 : .fn = pptr_fn,
368 : .pptr_buf = pptr_buf,
369 : .priv = priv,
370 : };
371 :
372 6198895073 : ASSERT(xfs_has_parent(sc->mp));
373 :
374 6198895073 : return xchk_xattr_walk(sc, ip, xchk_pptr_walk_attr, NULL, &pw);
375 : }
|