root/fs/xfs/libxfs/xfs_symlink_remote.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xfs_symlink_blocks
  2. xfs_symlink_hdr_set
  3. xfs_symlink_hdr_ok
  4. xfs_symlink_verify
  5. xfs_symlink_read_verify
  6. xfs_symlink_write_verify
  7. xfs_symlink_local_to_remote
  8. xfs_symlink_shortform_verify

   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 
  20 
  21 /*
  22  * Each contiguous block has a header, so it is not just a simple pathlen
  23  * to FSB conversion.
  24  */
  25 int
  26 xfs_symlink_blocks(
  27         struct xfs_mount *mp,
  28         int             pathlen)
  29 {
  30         int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
  31 
  32         return (pathlen + buflen - 1) / buflen;
  33 }
  34 
  35 int
  36 xfs_symlink_hdr_set(
  37         struct xfs_mount        *mp,
  38         xfs_ino_t               ino,
  39         uint32_t                offset,
  40         uint32_t                size,
  41         struct xfs_buf          *bp)
  42 {
  43         struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  44 
  45         if (!xfs_sb_version_hascrc(&mp->m_sb))
  46                 return 0;
  47 
  48         memset(dsl, 0, sizeof(struct xfs_dsymlink_hdr));
  49         dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC);
  50         dsl->sl_offset = cpu_to_be32(offset);
  51         dsl->sl_bytes = cpu_to_be32(size);
  52         uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid);
  53         dsl->sl_owner = cpu_to_be64(ino);
  54         dsl->sl_blkno = cpu_to_be64(bp->b_bn);
  55         bp->b_ops = &xfs_symlink_buf_ops;
  56 
  57         return sizeof(struct xfs_dsymlink_hdr);
  58 }
  59 
  60 /*
  61  * Checking of the symlink header is split into two parts. the verifier does
  62  * CRC, location and bounds checking, the unpacking function checks the path
  63  * parameters and owner.
  64  */
  65 bool
  66 xfs_symlink_hdr_ok(
  67         xfs_ino_t               ino,
  68         uint32_t                offset,
  69         uint32_t                size,
  70         struct xfs_buf          *bp)
  71 {
  72         struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  73 
  74         if (offset != be32_to_cpu(dsl->sl_offset))
  75                 return false;
  76         if (size != be32_to_cpu(dsl->sl_bytes))
  77                 return false;
  78         if (ino != be64_to_cpu(dsl->sl_owner))
  79                 return false;
  80 
  81         /* ok */
  82         return true;
  83 }
  84 
  85 static xfs_failaddr_t
  86 xfs_symlink_verify(
  87         struct xfs_buf          *bp)
  88 {
  89         struct xfs_mount        *mp = bp->b_mount;
  90         struct xfs_dsymlink_hdr *dsl = bp->b_addr;
  91 
  92         if (!xfs_sb_version_hascrc(&mp->m_sb))
  93                 return __this_address;
  94         if (!xfs_verify_magic(bp, dsl->sl_magic))
  95                 return __this_address;
  96         if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
  97                 return __this_address;
  98         if (bp->b_bn != be64_to_cpu(dsl->sl_blkno))
  99                 return __this_address;
 100         if (be32_to_cpu(dsl->sl_offset) +
 101                                 be32_to_cpu(dsl->sl_bytes) >= XFS_SYMLINK_MAXLEN)
 102                 return __this_address;
 103         if (dsl->sl_owner == 0)
 104                 return __this_address;
 105         if (!xfs_log_check_lsn(mp, be64_to_cpu(dsl->sl_lsn)))
 106                 return __this_address;
 107 
 108         return NULL;
 109 }
 110 
 111 static void
 112 xfs_symlink_read_verify(
 113         struct xfs_buf  *bp)
 114 {
 115         struct xfs_mount *mp = bp->b_mount;
 116         xfs_failaddr_t  fa;
 117 
 118         /* no verification of non-crc buffers */
 119         if (!xfs_sb_version_hascrc(&mp->m_sb))
 120                 return;
 121 
 122         if (!xfs_buf_verify_cksum(bp, XFS_SYMLINK_CRC_OFF))
 123                 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
 124         else {
 125                 fa = xfs_symlink_verify(bp);
 126                 if (fa)
 127                         xfs_verifier_error(bp, -EFSCORRUPTED, fa);
 128         }
 129 }
 130 
 131 static void
 132 xfs_symlink_write_verify(
 133         struct xfs_buf  *bp)
 134 {
 135         struct xfs_mount *mp = bp->b_mount;
 136         struct xfs_buf_log_item *bip = bp->b_log_item;
 137         xfs_failaddr_t          fa;
 138 
 139         /* no verification of non-crc buffers */
 140         if (!xfs_sb_version_hascrc(&mp->m_sb))
 141                 return;
 142 
 143         fa = xfs_symlink_verify(bp);
 144         if (fa) {
 145                 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
 146                 return;
 147         }
 148 
 149         if (bip) {
 150                 struct xfs_dsymlink_hdr *dsl = bp->b_addr;
 151                 dsl->sl_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 152         }
 153         xfs_buf_update_cksum(bp, XFS_SYMLINK_CRC_OFF);
 154 }
 155 
 156 const struct xfs_buf_ops xfs_symlink_buf_ops = {
 157         .name = "xfs_symlink",
 158         .magic = { 0, cpu_to_be32(XFS_SYMLINK_MAGIC) },
 159         .verify_read = xfs_symlink_read_verify,
 160         .verify_write = xfs_symlink_write_verify,
 161         .verify_struct = xfs_symlink_verify,
 162 };
 163 
 164 void
 165 xfs_symlink_local_to_remote(
 166         struct xfs_trans        *tp,
 167         struct xfs_buf          *bp,
 168         struct xfs_inode        *ip,
 169         struct xfs_ifork        *ifp)
 170 {
 171         struct xfs_mount        *mp = ip->i_mount;
 172         char                    *buf;
 173 
 174         xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
 175 
 176         if (!xfs_sb_version_hascrc(&mp->m_sb)) {
 177                 bp->b_ops = NULL;
 178                 memcpy(bp->b_addr, ifp->if_u1.if_data, ifp->if_bytes);
 179                 xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
 180                 return;
 181         }
 182 
 183         /*
 184          * As this symlink fits in an inode literal area, it must also fit in
 185          * the smallest buffer the filesystem supports.
 186          */
 187         ASSERT(BBTOB(bp->b_length) >=
 188                         ifp->if_bytes + sizeof(struct xfs_dsymlink_hdr));
 189 
 190         bp->b_ops = &xfs_symlink_buf_ops;
 191 
 192         buf = bp->b_addr;
 193         buf += xfs_symlink_hdr_set(mp, ip->i_ino, 0, ifp->if_bytes, bp);
 194         memcpy(buf, ifp->if_u1.if_data, ifp->if_bytes);
 195         xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsymlink_hdr) +
 196                                         ifp->if_bytes - 1);
 197 }
 198 
 199 /*
 200  * Verify the in-memory consistency of an inline symlink data fork. This
 201  * does not do on-disk format checks.
 202  */
 203 xfs_failaddr_t
 204 xfs_symlink_shortform_verify(
 205         struct xfs_inode        *ip)
 206 {
 207         char                    *sfp;
 208         char                    *endp;
 209         struct xfs_ifork        *ifp;
 210         int                     size;
 211 
 212         ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL);
 213         ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 214         sfp = (char *)ifp->if_u1.if_data;
 215         size = ifp->if_bytes;
 216         endp = sfp + size;
 217 
 218         /*
 219          * Zero length symlinks should never occur in memory as they are
 220          * never alllowed to exist on disk.
 221          */
 222         if (!size)
 223                 return __this_address;
 224 
 225         /* No negative sizes or overly long symlink targets. */
 226         if (size < 0 || size > XFS_SYMLINK_MAXLEN)
 227                 return __this_address;
 228 
 229         /* No NULLs in the target either. */
 230         if (memchr(sfp, 0, size - 1))
 231                 return __this_address;
 232 
 233         /* We /did/ null-terminate the buffer, right? */
 234         if (*endp != 0)
 235                 return __this_address;
 236         return NULL;
 237 }

/* [<][>][^][v][top][bottom][index][help] */