Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2018-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_trans_resv.h"
11 : #include "xfs_mount.h"
12 : #include "xfs_defer.h"
13 : #include "xfs_btree.h"
14 : #include "xfs_bit.h"
15 : #include "xfs_log_format.h"
16 : #include "xfs_trans.h"
17 : #include "xfs_sb.h"
18 : #include "xfs_inode.h"
19 : #include "xfs_inode_fork.h"
20 : #include "xfs_symlink.h"
21 : #include "xfs_bmap.h"
22 : #include "xfs_quota.h"
23 : #include "xfs_da_format.h"
24 : #include "xfs_da_btree.h"
25 : #include "xfs_bmap_btree.h"
26 : #include "xfs_trans_space.h"
27 : #include "xfs_symlink_remote.h"
28 : #include "xfs_swapext.h"
29 : #include "xfs_xchgrange.h"
30 : #include "scrub/xfs_scrub.h"
31 : #include "scrub/scrub.h"
32 : #include "scrub/common.h"
33 : #include "scrub/trace.h"
34 : #include "scrub/repair.h"
35 : #include "scrub/tempfile.h"
36 : #include "scrub/tempswap.h"
37 : #include "scrub/reap.h"
38 :
39 : /*
40 : * Symbolic Link Repair
41 : * ====================
42 : *
43 : * We repair symbolic links by reading whatever target data we can find, up to
44 : * the first NULL byte. Zero length symlinks are turned into links to the
45 : * current directory. The new target is written into a private hidden
46 : * temporary file, and then an atomic extent swap commits the new symlink
47 : * target to the file being repaired.
48 : */
49 :
50 : /* Set us up to repair the rtsummary file. */
51 : int
52 144613 : xrep_setup_symlink(
53 : struct xfs_scrub *sc,
54 : unsigned int *resblks)
55 : {
56 144613 : struct xfs_mount *mp = sc->mp;
57 144613 : unsigned long long blocks;
58 144613 : int error;
59 :
60 144613 : error = xrep_tempfile_create(sc, S_IFLNK);
61 144691 : if (error)
62 : return error;
63 :
64 : /*
65 : * If we're doing a repair, we reserve enough blocks to write out a
66 : * completely new symlink file, plus twice as many blocks as we would
67 : * need if we can only allocate one block per data fork mapping. This
68 : * should cover the preallocation of the temporary file and swapping
69 : * the extent mappings.
70 : *
71 : * We cannot use xfs_swapext_estimate because we have not yet
72 : * constructed the replacement rtsummary and therefore do not know how
73 : * many extents it will use. By the time we do, we will have a dirty
74 : * transaction (which we cannot drop because we cannot drop the
75 : * rtsummary ILOCK) and cannot ask for more reservation.
76 : */
77 144691 : blocks = xfs_symlink_blocks(sc->mp, XFS_SYMLINK_MAXLEN);
78 144691 : blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
79 144691 : if (blocks > UINT_MAX)
80 : return -EOPNOTSUPP;
81 :
82 144691 : *resblks += blocks;
83 144691 : return 0;
84 : }
85 :
86 : /* Try to salvage the pathname from rmt blocks. */
87 : STATIC int
88 18562 : xrep_symlink_salvage_remote(
89 : struct xfs_scrub *sc)
90 : {
91 18562 : struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
92 18562 : struct xfs_inode *ip = sc->ip;
93 18562 : struct xfs_buf *bp;
94 18562 : char *target_buf = sc->buf;
95 18562 : xfs_failaddr_t fa;
96 18562 : xfs_filblks_t fsblocks;
97 18562 : xfs_daddr_t d;
98 18562 : loff_t len;
99 18562 : loff_t offset;
100 18562 : unsigned int byte_cnt;
101 18562 : bool magic_ok;
102 18562 : bool hdr_ok;
103 18562 : int n;
104 18562 : int nmaps = XFS_SYMLINK_MAPS;
105 18562 : int error;
106 :
107 : /* We'll only read until the buffer is full. */
108 18562 : len = min_t(loff_t, ip->i_disk_size, XFS_SYMLINK_MAXLEN);
109 18562 : fsblocks = xfs_symlink_blocks(sc->mp, len);
110 18562 : error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
111 18562 : if (error)
112 : return error;
113 :
114 : offset = 0;
115 37124 : for (n = 0; n < nmaps; n++) {
116 18562 : struct xfs_dsymlink_hdr *dsl;
117 :
118 18562 : d = XFS_FSB_TO_DADDR(sc->mp, mval[n].br_startblock);
119 :
120 : /* Read the rmt block. We'll run the verifiers manually. */
121 55686 : error = xfs_trans_read_buf(sc->mp, sc->tp, sc->mp->m_ddev_targp,
122 18562 : d, XFS_FSB_TO_BB(sc->mp, mval[n].br_blockcount),
123 : 0, &bp, NULL);
124 18562 : if (error)
125 0 : return error;
126 18562 : bp->b_ops = &xfs_symlink_buf_ops;
127 :
128 : /* How many bytes do we expect to get out of this buffer? */
129 18562 : byte_cnt = XFS_FSB_TO_B(sc->mp, mval[n].br_blockcount);
130 18562 : byte_cnt = XFS_SYMLINK_BUF_SPACE(sc->mp, byte_cnt);
131 18562 : byte_cnt = min_t(unsigned int, byte_cnt, len);
132 :
133 : /*
134 : * See if the verifiers accept this block. We're willing to
135 : * salvage if the if the offset/byte/ino are ok and either the
136 : * verifier passed or the magic is ok. Anything else and we
137 : * stop dead in our tracks.
138 : */
139 18562 : fa = bp->b_ops->verify_struct(bp);
140 18562 : dsl = bp->b_addr;
141 18562 : magic_ok = dsl->sl_magic == cpu_to_be32(XFS_SYMLINK_MAGIC);
142 18562 : hdr_ok = xfs_symlink_hdr_ok(ip->i_ino, offset, byte_cnt, bp);
143 18562 : if (!hdr_ok || (fa != NULL && !magic_ok))
144 : break;
145 :
146 37124 : memcpy(target_buf + offset, dsl + 1, byte_cnt);
147 :
148 18562 : len -= byte_cnt;
149 18562 : offset += byte_cnt;
150 : }
151 :
152 : /* Ensure we have a zero at the end, and /some/ contents. */
153 18562 : if (offset == 0 || target_buf[0] == 0)
154 0 : sprintf(target_buf, ".");
155 : else
156 18562 : target_buf[offset] = 0;
157 : return 0;
158 : }
159 :
160 : /*
161 : * Try to salvage an inline symlink's contents. Empty symlinks become a link
162 : * to the current directory.
163 : */
164 : STATIC void
165 93289 : xrep_symlink_salvage_inline(
166 : struct xfs_scrub *sc)
167 : {
168 93289 : struct xfs_inode *ip = sc->ip;
169 93289 : char *target_buf = sc->buf;
170 93289 : struct xfs_ifork *ifp;
171 :
172 93289 : ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
173 93289 : if (ifp->if_u1.if_data)
174 93289 : strncpy(target_buf, ifp->if_u1.if_data, xfs_inode_data_fork_size(ip));
175 93289 : if (target_buf[0] == 0)
176 0 : sprintf(target_buf, ".");
177 93289 : }
178 :
179 : /* Salvage whatever we can of the target. */
180 : STATIC int
181 111851 : xrep_symlink_salvage(
182 : struct xfs_scrub *sc)
183 : {
184 111851 : if (sc->ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
185 93289 : xrep_symlink_salvage_inline(sc);
186 : } else {
187 18562 : int error = xrep_symlink_salvage_remote(sc);
188 :
189 18562 : if (error)
190 : return error;
191 : }
192 :
193 111851 : trace_xrep_symlink_salvage_target(sc->ip, sc->buf, strlen(sc->buf));
194 111851 : return 0;
195 : }
196 :
197 : STATIC void
198 3139 : xrep_symlink_local_to_remote(
199 : struct xfs_trans *tp,
200 : struct xfs_buf *bp,
201 : struct xfs_inode *ip,
202 : struct xfs_ifork *ifp,
203 : void *priv)
204 : {
205 3139 : struct xfs_scrub *sc = priv;
206 3139 : struct xfs_dsymlink_hdr *dsl = bp->b_addr;
207 :
208 3139 : xfs_symlink_local_to_remote(tp, bp, ip, ifp, NULL);
209 :
210 3139 : if (!xfs_has_crc(sc->mp))
211 : return;
212 :
213 3139 : dsl->sl_owner = cpu_to_be64(sc->ip->i_ino);
214 3139 : xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
215 3139 : ifp->if_bytes - 1);
216 : }
217 :
218 : /*
219 : * Prepare both links' data forks for extent swapping. Promote the tempfile
220 : * from local format to extents format, and if the file being repaired has a
221 : * short format data fork, turn it into an empty extent list.
222 : */
223 : STATIC int
224 18562 : xrep_symlink_swap_prep(
225 : struct xfs_scrub *sc,
226 : bool temp_local,
227 : bool ip_local)
228 : {
229 18562 : int error;
230 :
231 : /*
232 : * If the temp link is in shortform format, convert that to a remote
233 : * target so that we can use the atomic extent swap.
234 : */
235 18562 : if (temp_local) {
236 3139 : int logflags = XFS_ILOG_CORE;
237 :
238 3139 : error = xfs_bmap_local_to_extents(sc->tp, sc->tempip, 1,
239 : &logflags, XFS_DATA_FORK,
240 : xrep_symlink_local_to_remote,
241 : sc);
242 3139 : if (error)
243 0 : return error;
244 :
245 3139 : xfs_trans_log_inode(sc->tp, sc->ip, 0);
246 :
247 3139 : error = xfs_defer_finish(&sc->tp);
248 3139 : if (error)
249 : return error;
250 : }
251 :
252 : /*
253 : * If the file being repaired had a shortform data fork, convert that
254 : * to an empty extent list in preparation for the atomic extent swap.
255 : */
256 18562 : if (ip_local) {
257 0 : struct xfs_ifork *ifp;
258 :
259 0 : ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
260 0 : xfs_idestroy_fork(ifp);
261 0 : ifp->if_format = XFS_DINODE_FMT_EXTENTS;
262 0 : ifp->if_nextents = 0;
263 0 : ifp->if_bytes = 0;
264 0 : ifp->if_u1.if_root = NULL;
265 0 : ifp->if_height = 0;
266 :
267 0 : xfs_trans_log_inode(sc->tp, sc->ip,
268 : XFS_ILOG_CORE | XFS_ILOG_DDATA);
269 : }
270 :
271 : return 0;
272 : }
273 :
274 : /* Swap the temporary link's data fork with the one being repaired. */
275 : STATIC int
276 111851 : xrep_symlink_swap(
277 : struct xfs_scrub *sc)
278 : {
279 111851 : struct xrep_tempswap *tx = sc->buf;
280 111851 : bool ip_local, temp_local;
281 111851 : int error;
282 :
283 : /*
284 : * We're done with the temporary buffer, so we can reuse it for the
285 : * tempfile swap information.
286 : */
287 111851 : error = xrep_tempswap_trans_alloc(sc, XFS_DATA_FORK, tx);
288 111851 : if (error)
289 : return error;
290 :
291 111851 : ip_local = sc->ip->i_df.if_format == XFS_DINODE_FMT_LOCAL;
292 111851 : temp_local = sc->tempip->i_df.if_format == XFS_DINODE_FMT_LOCAL;
293 :
294 : /*
295 : * If the both links have a local format data fork and the rebuilt
296 : * remote data would fit in the repaired file's data fork, copy the
297 : * contents from the tempfile and declare ourselves done.
298 : */
299 111851 : if (ip_local && temp_local &&
300 93289 : sc->tempip->i_disk_size <= xfs_inode_data_fork_size(sc->ip)) {
301 93289 : xrep_tempfile_copyout_local(sc, XFS_DATA_FORK);
302 93289 : return 0;
303 : }
304 :
305 : /* Otherwise, make sure both data forks are in block-mapping mode. */
306 18562 : error = xrep_symlink_swap_prep(sc, temp_local, ip_local);
307 18562 : if (error)
308 : return error;
309 :
310 18562 : return xrep_tempswap_contents(sc, tx);
311 : }
312 :
313 : /*
314 : * Free all the remote blocks and reset the data fork. The caller must join
315 : * the inode to the transaction. This function returns with the inode joined
316 : * to a clean scrub transaction.
317 : */
318 : STATIC int
319 111851 : xrep_symlink_reset_fork(
320 : struct xfs_scrub *sc)
321 : {
322 111851 : struct xfs_ifork *ifp = xfs_ifork_ptr(sc->tempip, XFS_DATA_FORK);
323 111851 : int error;
324 :
325 : /* Unmap all the remote target buffers. */
326 111851 : if (xfs_ifork_has_extents(ifp)) {
327 18562 : error = xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
328 18562 : if (error)
329 : return error;
330 : }
331 :
332 111851 : trace_xrep_symlink_reset_fork(sc->tempip);
333 :
334 : /* Reset the temp link to have the same dummy content. */
335 111851 : xfs_idestroy_fork(ifp);
336 111851 : error = xfs_symlink_write_target(sc->tp, sc->tempip, ".", 1, 0, 0);
337 111851 : if (error)
338 : return error;
339 :
340 111851 : return xrep_tempfile_roll_trans(sc);
341 : }
342 :
343 : /*
344 : * Reinitialize a link target. Caller must ensure the inode is joined to
345 : * the transaction.
346 : */
347 : STATIC int
348 111851 : xrep_symlink_rebuild(
349 : struct xfs_scrub *sc)
350 : {
351 111851 : char *target_buf = sc->buf;
352 111851 : xfs_fsblock_t fs_blocks;
353 111851 : unsigned int target_len;
354 111851 : unsigned int resblks;
355 111851 : int error;
356 :
357 : /* How many blocks do we need? */
358 111851 : target_len = strlen(target_buf);
359 111851 : ASSERT(target_len != 0);
360 111851 : if (target_len == 0 || target_len > XFS_SYMLINK_MAXLEN)
361 : return -EFSCORRUPTED;
362 :
363 111851 : trace_xrep_symlink_rebuild(sc->ip);
364 :
365 : /*
366 : * In preparation to write the new symlink target to the temporary
367 : * file, drop the ILOCK of the file being repaired (it shouldn't be
368 : * joined) and take the ILOCK of the temporary file.
369 : *
370 : * The VFS does not take the IOLOCK while reading a symlink (and new
371 : * symlinks are hidden with INEW until they've been written) so it's
372 : * possible that a readlink() could see the old corrupted contents
373 : * while we're doing this.
374 : */
375 111851 : xchk_iunlock(sc, XFS_ILOCK_EXCL);
376 111851 : xrep_tempfile_ilock(sc);
377 111851 : xfs_trans_ijoin(sc->tp, sc->tempip, 0);
378 :
379 : /*
380 : * Reserve resources to reinitialize the target. We're allowed to
381 : * exceed file quota to repair inconsistent metadata, though this is
382 : * unlikely.
383 : */
384 111851 : fs_blocks = xfs_symlink_blocks(sc->mp, target_len);
385 111851 : resblks = xfs_symlink_space_res(sc->mp, target_len, fs_blocks);
386 111851 : error = xfs_trans_reserve_quota_nblks(sc->tp, sc->tempip, resblks, 0,
387 : true);
388 111851 : if (error)
389 : return error;
390 :
391 : /* Erase the dummy target set up by the tempfile initialization. */
392 111851 : xfs_idestroy_fork(&sc->tempip->i_df);
393 111851 : sc->tempip->i_df.if_bytes = 0;
394 111851 : sc->tempip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
395 :
396 : /* Write the salvaged target to the temporary link. */
397 111851 : error = __xfs_symlink_write_target(sc->tp, sc->tempip, sc->ip->i_ino,
398 : target_buf, target_len, fs_blocks, resblks);
399 111851 : if (error)
400 : return error;
401 :
402 : /*
403 : * Commit the repair transaction so that we can use the atomic extent
404 : * swap helper functions to compute the correct block reservations and
405 : * re-lock the inodes.
406 : */
407 111851 : error = xrep_trans_commit(sc);
408 111851 : if (error)
409 : return error;
410 :
411 : /* Last chance to abort before we start committing fixes. */
412 111851 : if (xchk_should_terminate(sc, &error))
413 0 : return error;
414 :
415 111851 : xrep_tempfile_iunlock(sc);
416 :
417 : /*
418 : * Swap the temp link's data fork with the file being repaired. This
419 : * recreates the transaction and takes the ILOCKs of the file being
420 : * repaired and the temporary file.
421 : */
422 111851 : error = xrep_symlink_swap(sc);
423 111851 : if (error)
424 : return error;
425 :
426 : /*
427 : * Release the old symlink blocks and reset the data fork of the temp
428 : * link to an empty shortform link.
429 : */
430 111851 : return xrep_symlink_reset_fork(sc);
431 : }
432 :
433 : /* Repair a symbolic link. */
434 : int
435 144222 : xrep_symlink(
436 : struct xfs_scrub *sc)
437 : {
438 144222 : int error;
439 :
440 : /* The rmapbt is required to reap the old data fork. */
441 144222 : if (!xfs_has_rmapbt(sc->mp))
442 : return -EOPNOTSUPP;
443 :
444 111851 : ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL);
445 :
446 111851 : error = xrep_symlink_salvage(sc);
447 111851 : if (error)
448 : return error;
449 :
450 : /* Now reset the target. */
451 111851 : return xrep_symlink_rebuild(sc);
452 : }
|