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