Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4 : * Copyright (c) 2012-2013 Red Hat, Inc.
5 : * All rights reserved.
6 : */
7 : #include "xfs.h"
8 : #include "xfs_fs.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_shared.h"
12 : #include "xfs_trans_resv.h"
13 : #include "xfs_mount.h"
14 : #include "xfs_inode.h"
15 : #include "xfs_error.h"
16 : #include "xfs_trans.h"
17 : #include "xfs_buf_item.h"
18 : #include "xfs_log.h"
19 : #include "xfs_symlink_remote.h"
20 : #include "xfs_bit.h"
21 : #include "xfs_bmap.h"
22 : #include "xfs_health.h"
23 :
24 : /*
25 : * Each contiguous block has a header, so it is not just a simple pathlen
26 : * to FSB conversion.
27 : */
28 : int
29 276358447 : xfs_symlink_blocks(
30 : struct xfs_mount *mp,
31 : int pathlen)
32 : {
33 276358447 : int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
34 :
35 276358447 : return (pathlen + buflen - 1) / buflen;
36 : }
37 :
38 : int
39 25547448 : xfs_symlink_hdr_set(
40 : struct xfs_mount *mp,
41 : xfs_ino_t ino,
42 : uint32_t offset,
43 : uint32_t size,
44 : struct xfs_buf *bp)
45 : {
46 25547448 : struct xfs_dsymlink_hdr *dsl = bp->b_addr;
47 :
48 25547448 : if (!xfs_has_crc(mp))
49 : return 0;
50 :
51 25547448 : memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr));
52 25547448 : dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
53 25547448 : dsl->sl_offset = cpu_to_be32(offset);
54 25547448 : dsl->sl_bytes = cpu_to_be32(size);
55 25547448 : uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid);
56 25553057 : dsl->sl_owner = cpu_to_be64(ino);
57 25553057 : dsl->sl_blkno = cpu_to_be64(xfs_buf_daddr(bp));
58 25553057 : bp->b_ops = &xfs_symlink_buf_ops;
59 :
60 25553057 : return sizeof(struct xfs_dsymlink_hdr);
61 : }
62 :
63 : /*
64 : * Checking of the symlink header is split into two parts. the verifier does
65 : * CRC, location and bounds checking, the unpacking function checks the path
66 : * parameters and owner.
67 : */
68 : bool
69 244496793 : xfs_symlink_hdr_ok(
70 : xfs_ino_t ino,
71 : uint32_t offset,
72 : uint32_t size,
73 : struct xfs_buf *bp)
74 : {
75 244496793 : struct xfs_dsymlink_hdr *dsl = bp->b_addr;
76 :
77 244496793 : if (offset != be32_to_cpu(dsl->sl_offset))
78 : return false;
79 244787532 : if (size != be32_to_cpu(dsl->sl_bytes))
80 : return false;
81 244789284 : if (ino != be64_to_cpu(dsl->sl_owner))
82 0 : return false;
83 :
84 : /* ok */
85 : return true;
86 : }
87 :
88 : static xfs_failaddr_t
89 4139868 : xfs_symlink_verify(
90 : struct xfs_buf *bp)
91 : {
92 4139868 : struct xfs_mount *mp = bp->b_mount;
93 4139868 : struct xfs_dsymlink_hdr *dsl = bp->b_addr;
94 :
95 4139868 : if (!xfs_has_crc(mp))
96 0 : return __this_address;
97 4139868 : if (!xfs_verify_magic(bp, dsl->sl_magic))
98 0 : return __this_address;
99 4139868 : if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
100 0 : return __this_address;
101 4139868 : if (xfs_buf_daddr(bp) != be64_to_cpu(dsl->sl_blkno))
102 0 : return __this_address;
103 4139868 : if (be32_to_cpu(dsl->sl_offset) +
104 4139868 : be32_to_cpu(dsl->sl_bytes) >= XFS_SYMLINK_MAXLEN)
105 0 : return __this_address;
106 4139868 : if (dsl->sl_owner == 0)
107 0 : return __this_address;
108 4139868 : if (!xfs_log_check_lsn(mp, be64_to_cpu(dsl->sl_lsn)))
109 0 : return __this_address;
110 :
111 : return NULL;
112 : }
113 :
114 : static void
115 138875 : xfs_symlink_read_verify(
116 : struct xfs_buf *bp)
117 : {
118 138875 : struct xfs_mount *mp = bp->b_mount;
119 138875 : xfs_failaddr_t fa;
120 :
121 : /* no verification of non-crc buffers */
122 138875 : if (!xfs_has_crc(mp))
123 : return;
124 :
125 138875 : if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
126 10 : xfs_verifier_error(bp, -EFSBADCRC, __this_address);
127 : else {
128 138865 : fa = xfs_symlink_verify(bp);
129 138865 : if (fa)
130 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
131 : }
132 : }
133 :
134 : static void
135 3982441 : xfs_symlink_write_verify(
136 : struct xfs_buf *bp)
137 : {
138 3982441 : struct xfs_mount *mp = bp->b_mount;
139 3982441 : struct xfs_buf_log_item *bip = bp->b_log_item;
140 3982441 : xfs_failaddr_t fa;
141 :
142 : /* no verification of non-crc buffers */
143 3982441 : if (!xfs_has_crc(mp))
144 : return;
145 :
146 3982441 : fa = xfs_symlink_verify(bp);
147 3982441 : if (fa) {
148 0 : xfs_verifier_error(bp, -EFSCORRUPTED, fa);
149 0 : return;
150 : }
151 :
152 3982441 : if (bip) {
153 3982441 : struct xfs_dsymlink_hdr *dsl = bp->b_addr;
154 3982441 : dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
155 : }
156 3982441 : xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF);
157 : }
158 :
159 : const struct xfs_buf_ops xfs_symlink_buf_ops = {
160 : .name = "xfs_symlink",
161 : .magic = { 0, cpu_to_be32(XFS_SYMLINK_MAGIC) },
162 : .verify_read = xfs_symlink_read_verify,
163 : .verify_write = xfs_symlink_write_verify,
164 : .verify_struct = xfs_symlink_verify,
165 : };
166 :
167 : void
168 3141 : xfs_symlink_local_to_remote(
169 : struct xfs_trans *tp,
170 : struct xfs_buf *bp,
171 : struct xfs_inode *ip,
172 : struct xfs_ifork *ifp,
173 : void *priv)
174 : {
175 3141 : struct xfs_mount *mp = ip->i_mount;
176 3141 : char *buf;
177 :
178 3141 : xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
179 :
180 3141 : if (!xfs_has_crc(mp)) {
181 0 : bp->b_ops = NULL;
182 0 : memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
183 0 : xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
184 0 : return;
185 : }
186 :
187 : /*
188 : * As this symlink fits in an inode literal area, it must also fit in
189 : * the smallest buffer the filesystem supports.
190 : */
191 3141 : ASSERT(BBTOB(bp->b_length) >=
192 : ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr));
193 :
194 3141 : bp->b_ops = &xfs_symlink_buf_ops;
195 :
196 3141 : buf = bp->b_addr;
197 3141 : buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
198 6282 : memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes);
199 3141 : xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
200 3141 : ifp->if_bytes - 1);
201 : }
202 :
203 : /*
204 : * Verify the in-memory consistency of an inline symlink data fork. This
205 : * does not do on-disk format checks.
206 : */
207 : xfs_failaddr_t
208 5740208 : xfs_symlink_sf_verify_struct(
209 : void *sfp,
210 : int64_t size)
211 : {
212 5740208 : char *endp = sfp + size;
213 :
214 : /*
215 : * Zero length symlinks should never occur in memory as they are
216 : * never allowed to exist on disk.
217 : */
218 5740208 : if (!size)
219 0 : return __this_address;
220 :
221 : /* No negative sizes or overly long symlink targets. */
222 5740208 : if (size < 0 || size > XFS_SYMLINK_MAXLEN)
223 0 : return __this_address;
224 :
225 : /* No NULLs in the target either. */
226 11480416 : if (memchr(sfp, 0, size - 1))
227 11 : return __this_address;
228 :
229 : /* We /did/ null-terminate the buffer, right? */
230 5740197 : if (*endp != 0)
231 0 : return __this_address;
232 : return NULL;
233 : }
234 :
235 : xfs_failaddr_t
236 5740209 : xfs_symlink_shortform_verify(
237 : struct xfs_inode *ip)
238 : {
239 5740209 : struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
240 :
241 5740209 : ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
242 :
243 5740209 : return xfs_symlink_sf_verify_struct(ifp->if_u1.if_data, ifp->if_bytes);
244 : }
245 :
246 : /* Read a remote symlink target into the buffer. */
247 : int
248 244742298 : xfs_symlink_remote_read(
249 : struct xfs_inode *ip,
250 : char *link)
251 : {
252 244742298 : struct xfs_mount *mp = ip->i_mount;
253 244742298 : struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
254 244742298 : struct xfs_buf *bp;
255 244742298 : xfs_daddr_t d;
256 244742298 : char *cur_chunk;
257 244742298 : int pathlen = ip->i_disk_size;
258 244742298 : int nmaps = XFS_SYMLINK_MAPS;
259 244742298 : int byte_cnt;
260 244742298 : int n;
261 244742298 : int error = 0;
262 244742298 : int fsblocks = 0;
263 244742298 : int offset;
264 :
265 244742298 : ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
266 :
267 244558505 : fsblocks = xfs_symlink_blocks(mp, pathlen);
268 244547569 : error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
269 244399632 : if (error)
270 0 : goto out;
271 :
272 : offset = 0;
273 489151471 : for (n = 0; n < nmaps; n++) {
274 244392390 : d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
275 244420670 : byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
276 :
277 244480626 : error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
278 : &bp, &xfs_symlink_buf_ops);
279 244743648 : if (xfs_metadata_is_sick(error))
280 10 : xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
281 244743648 : if (error)
282 10 : return error;
283 244743638 : byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
284 244743638 : if (pathlen < byte_cnt)
285 : byte_cnt = pathlen;
286 :
287 244743638 : cur_chunk = bp->b_addr;
288 244743638 : if (xfs_has_crc(mp)) {
289 244746578 : if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
290 : byte_cnt, bp)) {
291 0 : xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
292 0 : error = -EFSCORRUPTED;
293 0 : xfs_alert(mp,
294 : "symlink header does not match required off/len/owner (0x%x/0x%x,0x%llx)",
295 : offset, byte_cnt, ip->i_ino);
296 0 : xfs_buf_relse(bp);
297 0 : goto out;
298 :
299 : }
300 :
301 244746578 : cur_chunk += sizeof(struct xfs_dsymlink_hdr);
302 : }
303 :
304 489487276 : memcpy(link + offset, cur_chunk, byte_cnt);
305 :
306 244743638 : pathlen -= byte_cnt;
307 244743638 : offset += byte_cnt;
308 :
309 244743638 : xfs_buf_relse(bp);
310 : }
311 244759081 : ASSERT(pathlen == 0);
312 :
313 244759081 : link[ip->i_disk_size] = '\0';
314 244759081 : error = 0;
315 :
316 : out:
317 : return error;
318 : }
319 :
320 : /* Write the symlink target into the inode. */
321 : int
322 31992676 : __xfs_symlink_write_target(
323 : struct xfs_trans *tp,
324 : struct xfs_inode *ip,
325 : xfs_ino_t owner,
326 : const char *target_path,
327 : int pathlen,
328 : xfs_fsblock_t fs_blocks,
329 : uint resblks)
330 : {
331 31992676 : struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
332 31992676 : struct xfs_mount *mp = tp->t_mountp;
333 31992676 : const char *cur_chunk;
334 31992676 : struct xfs_buf *bp;
335 31992676 : xfs_daddr_t d;
336 31992676 : int byte_cnt;
337 31992676 : int nmaps;
338 31992676 : int offset = 0;
339 31992676 : int n;
340 31992676 : int error;
341 :
342 : /*
343 : * If the symlink will fit into the inode, write it inline.
344 : */
345 31992676 : if (pathlen <= xfs_inode_data_fork_size(ip)) {
346 6435657 : xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
347 :
348 6438158 : ip->i_disk_size = pathlen;
349 6438158 : ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
350 6438158 : xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
351 6438158 : return 0;
352 : }
353 :
354 25557019 : nmaps = XFS_SYMLINK_MAPS;
355 25557019 : error = xfs_bmapi_write(tp, ip, 0, fs_blocks, XFS_BMAPI_METADATA,
356 : resblks, mval, &nmaps);
357 25583511 : if (error)
358 : return error;
359 :
360 25557142 : ip->i_disk_size = pathlen;
361 25557142 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
362 :
363 25557142 : cur_chunk = target_path;
364 25557142 : offset = 0;
365 76790160 : for (n = 0; n < nmaps; n++) {
366 25627397 : char *buf;
367 :
368 25627397 : d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
369 25571941 : byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
370 25571871 : error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
371 25571871 : BTOBB(byte_cnt), 0, &bp);
372 25592350 : if (error)
373 0 : return error;
374 25592350 : bp->b_ops = &xfs_symlink_buf_ops;
375 :
376 25592350 : byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
377 25592350 : byte_cnt = min(byte_cnt, pathlen);
378 :
379 25592350 : buf = bp->b_addr;
380 25592350 : buf += xfs_symlink_hdr_set(mp, owner, offset, byte_cnt, bp);
381 :
382 51138926 : memcpy(buf, cur_chunk, byte_cnt);
383 :
384 25569463 : cur_chunk += byte_cnt;
385 25569463 : pathlen -= byte_cnt;
386 25569463 : offset += byte_cnt;
387 :
388 25569463 : xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
389 25595879 : xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
390 25595879 : (char *)bp->b_addr);
391 : }
392 25605621 : ASSERT(pathlen == 0);
393 : return 0;
394 : }
395 :
396 : /* Remove all the blocks from a symlink and invalidate buffers. */
397 : int
398 23761697 : xfs_symlink_remote_truncate(
399 : struct xfs_trans *tp,
400 : struct xfs_inode *ip)
401 : {
402 23761697 : struct xfs_bmbt_irec mval[XFS_SYMLINK_MAPS];
403 23761697 : struct xfs_mount *mp = tp->t_mountp;
404 23761697 : struct xfs_buf *bp;
405 23761697 : int nmaps = XFS_SYMLINK_MAPS;
406 23761697 : int done = 0;
407 23761697 : int i;
408 23761697 : int error;
409 :
410 : /* Read mappings and invalidate buffers. */
411 23761697 : error = xfs_bmapi_read(ip, 0, XFS_MAX_FILEOFF, mval, &nmaps, 0);
412 23655094 : if (error)
413 : return error;
414 :
415 47443522 : for (i = 0; i < nmaps; i++) {
416 94875022 : if (!xfs_bmap_is_real_extent(&mval[i]))
417 : break;
418 :
419 118169291 : error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
420 23655093 : XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
421 23645539 : XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
422 : &bp);
423 23759277 : if (error)
424 0 : return error;
425 :
426 23759277 : xfs_trans_binval(tp, bp);
427 : }
428 :
429 : /* Unmap the remote blocks. */
430 23785961 : error = xfs_bunmapi(tp, ip, 0, XFS_MAX_FILEOFF, 0, nmaps, &done);
431 23742083 : if (error)
432 : return error;
433 23742083 : if (!done) {
434 0 : ASSERT(done);
435 0 : xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
436 0 : return -EFSCORRUPTED;
437 : }
438 :
439 23742083 : xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
440 23742083 : return 0;
441 : }
|