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