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 5192861571 : 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 5192861571 : struct xfs_attr_shortform *sf;
34 5192861571 : struct xfs_attr_sf_entry *sfe;
35 5192861571 : unsigned int i;
36 5192861571 : int error;
37 :
38 5192861571 : sf = (struct xfs_attr_shortform *)ip->i_af.if_u1.if_data;
39 11538533554 : for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
40 6377353302 : error = attr_fn(sc, ip, sfe->flags, sfe->nameval, sfe->namelen,
41 6377353302 : &sfe->nameval[sfe->namelen], sfe->valuelen,
42 : priv);
43 6370020387 : if (error)
44 24348404 : return error;
45 :
46 6345671983 : 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 128580764 : 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 128580764 : struct xfs_attr3_icleaf_hdr ichdr;
62 128580764 : struct xfs_mount *mp = sc->mp;
63 128580764 : struct xfs_attr_leafblock *leaf = bp->b_addr;
64 128580764 : struct xfs_attr_leaf_entry *entry;
65 128580764 : unsigned int i;
66 128580764 : int error;
67 :
68 128580764 : xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
69 128604707 : entry = xfs_attr3_leaf_entryp(leaf);
70 :
71 1250273422 : for (i = 0; i < ichdr.count; entry++, i++) {
72 1121830773 : void *value;
73 1121830773 : unsigned char *name;
74 1121830773 : unsigned int namelen, valuelen;
75 :
76 1121830773 : if (entry->flags & XFS_ATTR_LOCAL) {
77 1121826807 : struct xfs_attr_leaf_name_local *name_loc;
78 :
79 1121826807 : name_loc = xfs_attr3_leaf_name_local(leaf, i);
80 1121826807 : name = name_loc->nameval;
81 1121826807 : namelen = name_loc->namelen;
82 1121826807 : value = &name_loc->nameval[name_loc->namelen];
83 1121826807 : valuelen = be16_to_cpu(name_loc->valuelen);
84 : } else {
85 3966 : struct xfs_attr_leaf_name_remote *name_rmt;
86 :
87 3966 : name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
88 3966 : name = name_rmt->name;
89 3966 : namelen = name_rmt->namelen;
90 3966 : value = NULL;
91 3966 : valuelen = be32_to_cpu(name_rmt->valuelen);
92 : }
93 :
94 1121830773 : error = attr_fn(sc, ip, entry->flags, name, namelen, value,
95 : valuelen, priv);
96 1121784384 : if (error)
97 115669 : 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 127438454 : 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 127438454 : struct xfs_buf *leaf_bp;
116 127438454 : int error;
117 :
118 127438454 : error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino, 0, &leaf_bp);
119 127380471 : if (error)
120 : return error;
121 :
122 127381397 : error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp, priv);
123 127407364 : xfs_trans_brelse(sc->tp, leaf_bp);
124 127407364 : return error;
125 : }
126 :
127 : /* Find the leftmost leaf in the xattr dabtree. */
128 : STATIC int
129 52267 : 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 52267 : struct xfs_da3_icnode_hdr nodehdr;
136 52267 : struct xfs_mount *mp = sc->mp;
137 52267 : struct xfs_trans *tp = sc->tp;
138 52267 : struct xfs_da_intnode *node;
139 52267 : struct xfs_da_node_entry *btree;
140 52267 : struct xfs_buf *bp;
141 52267 : xfs_failaddr_t fa;
142 52267 : xfs_dablk_t blkno = 0;
143 52267 : unsigned int expected_level = 0;
144 101120 : int error;
145 :
146 48853 : for (;;) {
147 101120 : uint64_t len = 1;
148 101120 : uint16_t magic;
149 :
150 : /* Make sure we haven't seen this new block already. */
151 101120 : if (xbitmap_test(seen_blocks, blkno, &len))
152 0 : return -EFSCORRUPTED;
153 :
154 101117 : error = xfs_da3_node_read(tp, ip, blkno, &bp, XFS_ATTR_FORK);
155 101122 : if (error)
156 0 : return error;
157 :
158 101122 : node = bp->b_addr;
159 101122 : magic = be16_to_cpu(node->hdr.info.magic);
160 101122 : if (magic == XFS_ATTR_LEAF_MAGIC ||
161 101122 : magic == XFS_ATTR3_LEAF_MAGIC)
162 : break;
163 :
164 48849 : error = -EFSCORRUPTED;
165 48849 : if (magic != XFS_DA_NODE_MAGIC &&
166 48849 : magic != XFS_DA3_NODE_MAGIC)
167 0 : goto out_buf;
168 :
169 48849 : fa = xfs_da3_node_header_check(bp, ip->i_ino);
170 48848 : if (fa)
171 0 : goto out_buf;
172 :
173 48848 : xfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
174 :
175 48844 : 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 48844 : if (blkno == 0)
180 48565 : expected_level = nodehdr.level - 1;
181 279 : else if (expected_level != nodehdr.level)
182 0 : goto out_buf;
183 : else
184 279 : expected_level--;
185 :
186 : /* Remember that we've seen this node. */
187 48844 : error = xbitmap_set(seen_blocks, blkno, 1);
188 48845 : if (error)
189 0 : goto out_buf;
190 :
191 : /* Find the next level towards the leaves of the dabtree. */
192 48845 : btree = nodehdr.btree;
193 48845 : blkno = be32_to_cpu(btree->before);
194 48845 : xfs_trans_brelse(tp, bp);
195 : }
196 :
197 52273 : error = -EFSCORRUPTED;
198 52273 : fa = xfs_attr3_leaf_header_check(bp, ip->i_ino);
199 52266 : if (fa)
200 0 : goto out_buf;
201 :
202 52266 : if (expected_level != 0)
203 0 : goto out_buf;
204 :
205 : /* Remember that we've seen this leaf. */
206 52266 : error = xbitmap_set(seen_blocks, blkno, 1);
207 52259 : if (error)
208 0 : goto out_buf;
209 :
210 52259 : *leaf_bpp = bp;
211 52259 : 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 52269 : 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 52269 : struct xfs_attr3_icleaf_hdr leafhdr;
228 52269 : struct xbitmap seen_blocks;
229 52269 : struct xfs_mount *mp = sc->mp;
230 52269 : struct xfs_attr_leafblock *leaf;
231 52269 : struct xfs_buf *leaf_bp;
232 52269 : int error;
233 :
234 52269 : xbitmap_init(&seen_blocks);
235 :
236 52271 : error = xchk_xattr_find_leftmost_leaf(sc, ip, &seen_blocks, &leaf_bp);
237 52262 : if (error)
238 0 : goto out_bitmap;
239 :
240 1115943 : for (;;) {
241 1168205 : uint64_t len;
242 :
243 1168205 : error = xchk_xattr_walk_leaf_entries(sc, ip, attr_fn, leaf_bp,
244 : priv);
245 1168217 : if (error)
246 19 : goto out_leaf;
247 :
248 : /* Find the right sibling of this leaf block. */
249 1168198 : leaf = leaf_bp->b_addr;
250 1168198 : xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
251 1168202 : if (leafhdr.forw == 0)
252 52255 : goto out_leaf;
253 :
254 1115947 : xfs_trans_brelse(sc->tp, leaf_bp);
255 :
256 1115957 : if (leaf_fn) {
257 2975 : error = leaf_fn(sc, priv);
258 2975 : if (error)
259 0 : goto out_bitmap;
260 : }
261 :
262 : /* Make sure we haven't seen this new leaf already. */
263 1115957 : len = 1;
264 1115957 : if (xbitmap_test(&seen_blocks, leafhdr.forw, &len))
265 0 : goto out_bitmap;
266 :
267 1115955 : error = xfs_attr3_leaf_read(sc->tp, ip, ip->i_ino,
268 : leafhdr.forw, &leaf_bp);
269 1115932 : if (error)
270 0 : goto out_bitmap;
271 :
272 : /* Remember that we've seen this new leaf. */
273 1115932 : error = xbitmap_set(&seen_blocks, leafhdr.forw, 1);
274 1115943 : if (error)
275 0 : goto out_leaf;
276 : }
277 :
278 : out_leaf:
279 52274 : xfs_trans_brelse(sc->tp, leaf_bp);
280 52274 : out_bitmap:
281 52274 : xbitmap_destroy(&seen_blocks);
282 52274 : 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 5339118335 : 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 5339118335 : int error;
300 :
301 5339118335 : ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
302 :
303 5318671629 : if (!xfs_inode_hasattr(ip))
304 : return 0;
305 :
306 5319189223 : if (ip->i_af.if_format == XFS_DINODE_FMT_LOCAL)
307 5191720689 : return xchk_xattr_walk_sf(sc, ip, attr_fn, priv);
308 :
309 : /* attr functions require that the attr fork is loaded */
310 127468534 : error = xfs_iread_extents(sc->tp, ip, XFS_ATTR_FORK);
311 127460853 : if (error)
312 : return error;
313 :
314 127464926 : if (xfs_attr_is_leaf(ip))
315 127440152 : return xchk_xattr_walk_leaf(sc, ip, attr_fn, priv);
316 :
317 52271 : 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 7062856027 : 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 7062856027 : struct xchk_pptr_walk *pw = priv;
338 7062856027 : const struct xfs_parent_name_rec *rec = (const void *)name;
339 :
340 : /* Ignore anything that isn't a parent pointer. */
341 7062856027 : if (!(attr_flags & XFS_ATTR_PARENT))
342 : return 0;
343 :
344 : /* Does the ondisk parent pointer structure make sense? */
345 10371910322 : if (!xfs_parent_namecheck(sc->mp, rec, namelen, attr_flags) ||
346 5185770410 : !xfs_parent_valuecheck(sc->mp, value, valuelen))
347 0 : return -EFSCORRUPTED;
348 :
349 5174768305 : xfs_parent_irec_from_disk(pw->pptr_buf, rec, value, valuelen);
350 5184466754 : 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 4990185339 : 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 4990185339 : struct xchk_pptr_walk pw = {
367 : .fn = pptr_fn,
368 : .pptr_buf = pptr_buf,
369 : .priv = priv,
370 : };
371 :
372 4990185339 : ASSERT(xfs_has_parent(sc->mp));
373 :
374 4990185339 : return xchk_xattr_walk(sc, ip, xchk_pptr_walk_attr, NULL, &pw);
375 : }
|