root/fs/xfs/scrub/symlink.c

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

DEFINITIONS

This source file includes following definitions.
  1. xchk_setup_symlink
  2. xchk_symlink

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright (C) 2017 Oracle.  All Rights Reserved.
   4  * Author: Darrick J. Wong <darrick.wong@oracle.com>
   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_log_format.h"
  13 #include "xfs_inode.h"
  14 #include "xfs_symlink.h"
  15 #include "scrub/scrub.h"
  16 #include "scrub/common.h"
  17 
  18 /* Set us up to scrub a symbolic link. */
  19 int
  20 xchk_setup_symlink(
  21         struct xfs_scrub        *sc,
  22         struct xfs_inode        *ip)
  23 {
  24         /* Allocate the buffer without the inode lock held. */
  25         sc->buf = kmem_zalloc_large(XFS_SYMLINK_MAXLEN + 1, 0);
  26         if (!sc->buf)
  27                 return -ENOMEM;
  28 
  29         return xchk_setup_inode_contents(sc, ip, 0);
  30 }
  31 
  32 /* Symbolic links. */
  33 
  34 int
  35 xchk_symlink(
  36         struct xfs_scrub        *sc)
  37 {
  38         struct xfs_inode        *ip = sc->ip;
  39         struct xfs_ifork        *ifp;
  40         loff_t                  len;
  41         int                     error = 0;
  42 
  43         if (!S_ISLNK(VFS_I(ip)->i_mode))
  44                 return -ENOENT;
  45         ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
  46         len = ip->i_d.di_size;
  47 
  48         /* Plausible size? */
  49         if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
  50                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  51                 goto out;
  52         }
  53 
  54         /* Inline symlink? */
  55         if (ifp->if_flags & XFS_IFINLINE) {
  56                 if (len > XFS_IFORK_DSIZE(ip) ||
  57                     len > strnlen(ifp->if_u1.if_data, XFS_IFORK_DSIZE(ip)))
  58                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  59                 goto out;
  60         }
  61 
  62         /* Remote symlink; must read the contents. */
  63         error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
  64         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  65                 goto out;
  66         if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
  67                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  68 out:
  69         return error;
  70 }

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