Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.9.4.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (c) 2018-2024 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_exchmaps.h"
 29#include "xfs_exchrange.h"
 30#include "xfs_health.h"
 31#include "scrub/xfs_scrub.h"
 32#include "scrub/scrub.h"
 33#include "scrub/common.h"
 34#include "scrub/trace.h"
 35#include "scrub/repair.h"
 36#include "scrub/tempfile.h"
 37#include "scrub/tempexch.h"
 38#include "scrub/reap.h"
 39#include "scrub/health.h"
 40
 41/*
 42 * Symbolic Link Repair
 43 * ====================
 44 *
 45 * We repair symbolic links by reading whatever target data we can find, up to
 46 * the first NULL byte.  If the recovered target strlen matches i_size, then
 47 * we rewrite the target.  In all other cases, we replace the target with an
 48 * overly long string that cannot possibly resolve.  The new target is written
 49 * into a private hidden temporary file, and then a file contents exchange
 50 * commits the new symlink target to the file being repaired.
 51 */
 52
 53/* Set us up to repair the symlink file. */
 54int
 55xrep_setup_symlink(
 56	struct xfs_scrub	*sc,
 57	unsigned int		*resblks)
 58{
 59	struct xfs_mount	*mp = sc->mp;
 60	unsigned long long	blocks;
 61	int			error;
 62
 63	error = xrep_tempfile_create(sc, S_IFLNK);
 64	if (error)
 65		return error;
 66
 67	/*
 68	 * If we're doing a repair, we reserve enough blocks to write out a
 69	 * completely new symlink file, plus twice as many blocks as we would
 70	 * need if we can only allocate one block per data fork mapping.  This
 71	 * should cover the preallocation of the temporary file and exchanging
 72	 * the extent mappings.
 73	 *
 74	 * We cannot use xfs_exchmaps_estimate because we have not yet
 75	 * constructed the replacement symlink and therefore do not know how
 76	 * many extents it will use.  By the time we do, we will have a dirty
 77	 * transaction (which we cannot drop because we cannot drop the
 78	 * symlink ILOCK) and cannot ask for more reservation.
 79	 */
 80	blocks = xfs_symlink_blocks(sc->mp, XFS_SYMLINK_MAXLEN);
 81	blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
 82	if (blocks > UINT_MAX)
 83		return -EOPNOTSUPP;
 84
 85	*resblks += blocks;
 86	return 0;
 87}
 88
 89/*
 90 * Try to salvage the pathname from remote blocks.  Returns the number of bytes
 91 * salvaged or a negative errno.
 92 */
 93STATIC ssize_t
 94xrep_symlink_salvage_remote(
 95	struct xfs_scrub	*sc)
 96{
 97	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
 98	struct xfs_inode	*ip = sc->ip;
 99	struct xfs_buf		*bp;
100	char			*target_buf = sc->buf;
101	xfs_failaddr_t		fa;
102	xfs_filblks_t		fsblocks;
103	xfs_daddr_t		d;
104	loff_t			len;
105	loff_t			offset = 0;
106	unsigned int		byte_cnt;
107	bool			magic_ok;
108	bool			hdr_ok;
109	int			n;
110	int			nmaps = XFS_SYMLINK_MAPS;
111	int			error;
112
113	/* We'll only read until the buffer is full. */
114	len = min_t(loff_t, ip->i_disk_size, XFS_SYMLINK_MAXLEN);
115	fsblocks = xfs_symlink_blocks(sc->mp, len);
116	error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
117	if (error)
118		return error;
119
120	for (n = 0; n < nmaps; n++) {
121		struct xfs_dsymlink_hdr	*dsl;
122
123		d = XFS_FSB_TO_DADDR(sc->mp, mval[n].br_startblock);
124
125		/* Read the rmt block.  We'll run the verifiers manually. */
126		error = xfs_trans_read_buf(sc->mp, sc->tp, sc->mp->m_ddev_targp,
127				d, XFS_FSB_TO_BB(sc->mp, mval[n].br_blockcount),
128				0, &bp, NULL);
129		if (error)
130			return error;
131		bp->b_ops = &xfs_symlink_buf_ops;
132
133		/* How many bytes do we expect to get out of this buffer? */
134		byte_cnt = XFS_FSB_TO_B(sc->mp, mval[n].br_blockcount);
135		byte_cnt = XFS_SYMLINK_BUF_SPACE(sc->mp, byte_cnt);
136		byte_cnt = min_t(unsigned int, byte_cnt, len);
137
138		/*
139		 * See if the verifiers accept this block.  We're willing to
140		 * salvage if the if the offset/byte/ino are ok and either the
141		 * verifier passed or the magic is ok.  Anything else and we
142		 * stop dead in our tracks.
143		 */
144		fa = bp->b_ops->verify_struct(bp);
145		dsl = bp->b_addr;
146		magic_ok = dsl->sl_magic == cpu_to_be32(XFS_SYMLINK_MAGIC);
147		hdr_ok = xfs_symlink_hdr_ok(ip->i_ino, offset, byte_cnt, bp);
148		if (!hdr_ok || (fa != NULL && !magic_ok))
149			break;
150
151		memcpy(target_buf + offset, dsl + 1, byte_cnt);
152
153		len -= byte_cnt;
154		offset += byte_cnt;
155	}
156	return offset;
157}
158
159/*
160 * Try to salvage an inline symlink's contents.  Returns the number of bytes
161 * salvaged or a negative errno.
162 */
163STATIC ssize_t
164xrep_symlink_salvage_inline(
165	struct xfs_scrub	*sc)
166{
167	struct xfs_inode	*ip = sc->ip;
168	char			*target_buf = sc->buf;
169	char			*old_target;
170	struct xfs_ifork	*ifp;
171	unsigned int		nr;
172
173	ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
174	if (!ifp->if_data)
175		return 0;
176
177	/*
178	 * If inode repair zapped the link target, pretend that we didn't find
179	 * any bytes at all so that we can replace the (now totally lost) link
180	 * target with a warning message.
181	 */
182	old_target = ifp->if_data;
183	if (xfs_inode_has_sickness(sc->ip, XFS_SICK_INO_SYMLINK_ZAPPED) &&
184	    sc->ip->i_disk_size == 1 && old_target[0] == '?')
185		return 0;
186
187	nr = min(XFS_SYMLINK_MAXLEN, xfs_inode_data_fork_size(ip));
188	strncpy(target_buf, ifp->if_data, nr);
189	return nr;
190}
191
192#define DUMMY_TARGET \
193	"The target of this symbolic link could not be recovered at all and " \
194	"has been replaced with this explanatory message.  To avoid " \
195	"accidentally pointing to an existing file path, this message is " \
196	"longer than the maximum supported file name length.  That is an " \
197	"acceptable length for a symlink target on XFS but will produce " \
198	"File Name Too Long errors if resolved."
199
200/* Salvage whatever we can of the target. */
201STATIC int
202xrep_symlink_salvage(
203	struct xfs_scrub	*sc)
204{
205	char			*target_buf = sc->buf;
206	ssize_t			buflen = 0;
207
208	BUILD_BUG_ON(sizeof(DUMMY_TARGET) - 1 <= NAME_MAX);
209
210	/*
211	 * Salvage the target if there weren't any corruption problems observed
212	 * while scanning it.
213	 */
214	if (!(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
215		if (sc->ip->i_df.if_format == XFS_DINODE_FMT_LOCAL)
216			buflen = xrep_symlink_salvage_inline(sc);
217		else
218			buflen = xrep_symlink_salvage_remote(sc);
219		if (buflen < 0)
220			return buflen;
221
222		/*
223		 * NULL-terminate the buffer because the ondisk target does not
224		 * do that for us.  If salvage didn't find the exact amount of
225		 * data that we expected to find, don't salvage anything.
226		 */
227		target_buf[buflen] = 0;
228		if (strlen(target_buf) != sc->ip->i_disk_size)
229			buflen = 0;
230	}
231
232	/*
233	 * Change an empty target into a dummy target and clear the symlink
234	 * target zapped flag.
235	 */
236	if (buflen == 0) {
237		xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_SYMLINK_ZAPPED);
238		sprintf(target_buf, DUMMY_TARGET);
239	}
240
241	trace_xrep_symlink_salvage_target(sc->ip, target_buf,
242			strlen(target_buf));
243	return 0;
244}
245
246STATIC void
247xrep_symlink_local_to_remote(
248	struct xfs_trans	*tp,
249	struct xfs_buf		*bp,
250	struct xfs_inode	*ip,
251	struct xfs_ifork	*ifp,
252	void			*priv)
253{
254	struct xfs_scrub	*sc = priv;
255	struct xfs_dsymlink_hdr	*dsl = bp->b_addr;
256
257	xfs_symlink_local_to_remote(tp, bp, ip, ifp, NULL);
258
259	if (!xfs_has_crc(sc->mp))
260		return;
261
262	dsl->sl_owner = cpu_to_be64(sc->ip->i_ino);
263	xfs_trans_log_buf(tp, bp, 0,
264			  sizeof(struct xfs_dsymlink_hdr) + ifp->if_bytes - 1);
265}
266
267/*
268 * Prepare both links' data forks for an exchange.  Promote the tempfile from
269 * local format to extents format, and if the file being repaired has a short
270 * format data fork, turn it into an empty extent list.
271 */
272STATIC int
273xrep_symlink_swap_prep(
274	struct xfs_scrub	*sc,
275	bool			temp_local,
276	bool			ip_local)
277{
278	int			error;
279
280	/*
281	 * If the temp link is in shortform format, convert that to a remote
282	 * target so that we can use the atomic mapping exchange.
283	 */
284	if (temp_local) {
285		int		logflags = XFS_ILOG_CORE;
286
287		error = xfs_bmap_local_to_extents(sc->tp, sc->tempip, 1,
288				&logflags, XFS_DATA_FORK,
289				xrep_symlink_local_to_remote,
290				sc);
291		if (error)
292			return error;
293
294		xfs_trans_log_inode(sc->tp, sc->ip, 0);
295
296		error = xfs_defer_finish(&sc->tp);
297		if (error)
298			return error;
299	}
300
301	/*
302	 * If the file being repaired had a shortform data fork, convert that
303	 * to an empty extent list in preparation for the atomic mapping
304	 * exchange.
305	 */
306	if (ip_local) {
307		struct xfs_ifork	*ifp;
308
309		ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
310		xfs_idestroy_fork(ifp);
311		ifp->if_format = XFS_DINODE_FMT_EXTENTS;
312		ifp->if_nextents = 0;
313		ifp->if_bytes = 0;
314		ifp->if_data = NULL;
315		ifp->if_height = 0;
316
317		xfs_trans_log_inode(sc->tp, sc->ip,
318				XFS_ILOG_CORE | XFS_ILOG_DDATA);
319	}
320
321	return 0;
322}
323
324/* Exchange the temporary symlink's data fork with the one being repaired. */
325STATIC int
326xrep_symlink_swap(
327	struct xfs_scrub	*sc)
328{
329	struct xrep_tempexch	*tx = sc->buf;
330	bool			ip_local, temp_local;
331	int			error;
332
333	ip_local = sc->ip->i_df.if_format == XFS_DINODE_FMT_LOCAL;
334	temp_local = sc->tempip->i_df.if_format == XFS_DINODE_FMT_LOCAL;
335
336	/*
337	 * If the both links have a local format data fork and the rebuilt
338	 * remote data would fit in the repaired file's data fork, copy the
339	 * contents from the tempfile and declare ourselves done.
340	 */
341	if (ip_local && temp_local &&
342	    sc->tempip->i_disk_size <= xfs_inode_data_fork_size(sc->ip)) {
343		xrep_tempfile_copyout_local(sc, XFS_DATA_FORK);
344		return 0;
345	}
346
347	/* Otherwise, make sure both data forks are in block-mapping mode. */
348	error = xrep_symlink_swap_prep(sc, temp_local, ip_local);
349	if (error)
350		return error;
351
352	return xrep_tempexch_contents(sc, tx);
353}
354
355/*
356 * Free all the remote blocks and reset the data fork.  The caller must join
357 * the inode to the transaction.  This function returns with the inode joined
358 * to a clean scrub transaction.
359 */
360STATIC int
361xrep_symlink_reset_fork(
362	struct xfs_scrub	*sc)
363{
364	struct xfs_ifork	*ifp = xfs_ifork_ptr(sc->tempip, XFS_DATA_FORK);
365	int			error;
366
367	/* Unmap all the remote target buffers. */
368	if (xfs_ifork_has_extents(ifp)) {
369		error = xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
370		if (error)
371			return error;
372	}
373
374	trace_xrep_symlink_reset_fork(sc->tempip);
375
376	/* Reset the temp symlink target to dummy content. */
377	xfs_idestroy_fork(ifp);
378	return xfs_symlink_write_target(sc->tp, sc->tempip, sc->tempip->i_ino,
379			"?", 1, 0, 0);
380}
381
382/*
383 * Reinitialize a link target.  Caller must ensure the inode is joined to
384 * the transaction.
385 */
386STATIC int
387xrep_symlink_rebuild(
388	struct xfs_scrub	*sc)
389{
390	struct xrep_tempexch	*tx;
391	char			*target_buf = sc->buf;
392	xfs_fsblock_t		fs_blocks;
393	unsigned int		target_len;
394	unsigned int		resblks;
395	int			error;
396
397	/* How many blocks do we need? */
398	target_len = strlen(target_buf);
399	ASSERT(target_len != 0);
400	if (target_len == 0 || target_len > XFS_SYMLINK_MAXLEN)
401		return -EFSCORRUPTED;
402
403	trace_xrep_symlink_rebuild(sc->ip);
404
405	/*
406	 * In preparation to write the new symlink target to the temporary
407	 * file, drop the ILOCK of the file being repaired (it shouldn't be
408	 * joined) and take the ILOCK of the temporary file.
409	 *
410	 * The VFS does not take the IOLOCK while reading a symlink (and new
411	 * symlinks are hidden with INEW until they've been written) so it's
412	 * possible that a readlink() could see the old corrupted contents
413	 * while we're doing this.
414	 */
415	xchk_iunlock(sc, XFS_ILOCK_EXCL);
416	xrep_tempfile_ilock(sc);
417	xfs_trans_ijoin(sc->tp, sc->tempip, 0);
418
419	/*
420	 * Reserve resources to reinitialize the target.  We're allowed to
421	 * exceed file quota to repair inconsistent metadata, though this is
422	 * unlikely.
423	 */
424	fs_blocks = xfs_symlink_blocks(sc->mp, target_len);
425	resblks = xfs_symlink_space_res(sc->mp, target_len, fs_blocks);
426	error = xfs_trans_reserve_quota_nblks(sc->tp, sc->tempip, resblks, 0,
427			true);
428	if (error)
429		return error;
430
431	/* Erase the dummy target set up by the tempfile initialization. */
432	xfs_idestroy_fork(&sc->tempip->i_df);
433	sc->tempip->i_df.if_bytes = 0;
434	sc->tempip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
435
436	/* Write the salvaged target to the temporary link. */
437	error = xfs_symlink_write_target(sc->tp, sc->tempip, sc->ip->i_ino,
438			target_buf, target_len, fs_blocks, resblks);
439	if (error)
440		return error;
441
442	/*
443	 * Commit the repair transaction so that we can use the atomic mapping
444	 * exchange functions to compute the correct block reservations and
445	 * re-lock the inodes.
446	 */
447	target_buf = NULL;
448	error = xrep_trans_commit(sc);
449	if (error)
450		return error;
451
452	/* Last chance to abort before we start committing fixes. */
453	if (xchk_should_terminate(sc, &error))
454		return error;
455
456	xrep_tempfile_iunlock(sc);
457
458	/*
459	 * We're done with the temporary buffer, so we can reuse it for the
460	 * tempfile contents exchange information.
461	 */
462	tx = sc->buf;
463	error = xrep_tempexch_trans_alloc(sc, XFS_DATA_FORK, tx);
464	if (error)
465		return error;
466
467	/*
468	 * Exchange the temp link's data fork with the file being repaired.
469	 * This recreates the transaction and takes the ILOCKs of the file
470	 * being repaired and the temporary file.
471	 */
472	error = xrep_symlink_swap(sc);
473	if (error)
474		return error;
475
476	/*
477	 * Release the old symlink blocks and reset the data fork of the temp
478	 * link to an empty shortform link.  This is the last repair action we
479	 * perform on the symlink, so we don't need to clean the transaction.
480	 */
481	return xrep_symlink_reset_fork(sc);
482}
483
484/* Repair a symbolic link. */
485int
486xrep_symlink(
487	struct xfs_scrub	*sc)
488{
489	int			error;
490
491	/* The rmapbt is required to reap the old data fork. */
492	if (!xfs_has_rmapbt(sc->mp))
493		return -EOPNOTSUPP;
494	/* We require atomic file exchange range to rebuild anything. */
495	if (!xfs_has_exchange_range(sc->mp))
496		return -EOPNOTSUPP;
497
498	ASSERT(sc->ilock_flags & XFS_ILOCK_EXCL);
499
500	error = xrep_symlink_salvage(sc);
501	if (error)
502		return error;
503
504	/* Now reset the target. */
505	error = xrep_symlink_rebuild(sc);
506	if (error)
507		return error;
508
509	return xrep_trans_commit(sc);
510}