1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 4 * Copyright (C) 2017 Oracle. 5 * All Rights Reserved. 6 */ 7#include "xfs.h" 8#include "xfs_fs.h" 9#include "xfs_format.h" 10#include "xfs_shared.h" 11#include "xfs_trans_resv.h" 12#include "xfs_bit.h" 13#include "xfs_mount.h" 14#include "xfs_ag.h" 15 16 17/* 18 * Verify that an AG block number pointer neither points outside the AG 19 * nor points at static metadata. 20 */ 21static inline bool 22xfs_verify_agno_agbno( 23 struct xfs_mount *mp, 24 xfs_agnumber_t agno, 25 xfs_agblock_t agbno) 26{ 27 xfs_agblock_t eoag; 28 29 eoag = xfs_ag_block_count(mp, agno); 30 if (agbno >= eoag) 31 return false; 32 if (agbno <= XFS_AGFL_BLOCK(mp)) 33 return false; 34 return true; 35} 36 37/* 38 * Verify that an FS block number pointer neither points outside the 39 * filesystem nor points at static AG metadata. 40 */ 41inline bool 42xfs_verify_fsbno( 43 struct xfs_mount *mp, 44 xfs_fsblock_t fsbno) 45{ 46 xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno); 47 48 if (agno >= mp->m_sb.sb_agcount) 49 return false; 50 return xfs_verify_agno_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno)); 51} 52 53/* 54 * Verify that a data device extent is fully contained inside the filesystem, 55 * does not cross an AG boundary, and does not point at static metadata. 56 */ 57bool 58xfs_verify_fsbext( 59 struct xfs_mount *mp, 60 xfs_fsblock_t fsbno, 61 xfs_fsblock_t len) 62{ 63 if (fsbno + len <= fsbno) 64 return false; 65 66 if (!xfs_verify_fsbno(mp, fsbno)) 67 return false; 68 69 if (!xfs_verify_fsbno(mp, fsbno + len - 1)) 70 return false; 71 72 return XFS_FSB_TO_AGNO(mp, fsbno) == 73 XFS_FSB_TO_AGNO(mp, fsbno + len - 1); 74} 75 76/* 77 * Verify that an AG inode number pointer neither points outside the AG 78 * nor points at static metadata. 79 */ 80static inline bool 81xfs_verify_agno_agino( 82 struct xfs_mount *mp, 83 xfs_agnumber_t agno, 84 xfs_agino_t agino) 85{ 86 xfs_agino_t first; 87 xfs_agino_t last; 88 89 xfs_agino_range(mp, agno, &first, &last); 90 return agino >= first && agino <= last; 91} 92 93/* 94 * Verify that an FS inode number pointer neither points outside the 95 * filesystem nor points at static AG metadata. 96 */ 97inline bool 98xfs_verify_ino( 99 struct xfs_mount *mp, 100 xfs_ino_t ino) 101{ 102 xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino); 103 xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); 104 105 if (agno >= mp->m_sb.sb_agcount) 106 return false; 107 if (XFS_AGINO_TO_INO(mp, agno, agino) != ino) 108 return false; 109 return xfs_verify_agno_agino(mp, agno, agino); 110} 111 112/* Is this an internal inode number? */ 113inline bool 114xfs_internal_inum( 115 struct xfs_mount *mp, 116 xfs_ino_t ino) 117{ 118 return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || 119 (xfs_has_quota(mp) && 120 xfs_is_quota_inode(&mp->m_sb, ino)); 121} 122 123/* 124 * Verify that a directory entry's inode number doesn't point at an internal 125 * inode, empty space, or static AG metadata. 126 */ 127bool 128xfs_verify_dir_ino( 129 struct xfs_mount *mp, 130 xfs_ino_t ino) 131{ 132 if (xfs_internal_inum(mp, ino)) 133 return false; 134 return xfs_verify_ino(mp, ino); 135} 136 137/* 138 * Verify that an realtime block number pointer doesn't point off the 139 * end of the realtime device. 140 */ 141inline bool 142xfs_verify_rtbno( 143 struct xfs_mount *mp, 144 xfs_rtblock_t rtbno) 145{ 146 return rtbno < mp->m_sb.sb_rblocks; 147} 148 149/* Verify that a realtime device extent is fully contained inside the volume. */ 150bool 151xfs_verify_rtbext( 152 struct xfs_mount *mp, 153 xfs_rtblock_t rtbno, 154 xfs_filblks_t len) 155{ 156 if (rtbno + len <= rtbno) 157 return false; 158 159 if (!xfs_verify_rtbno(mp, rtbno)) 160 return false; 161 162 return xfs_verify_rtbno(mp, rtbno + len - 1); 163} 164 165/* Calculate the range of valid icount values. */ 166inline void 167xfs_icount_range( 168 struct xfs_mount *mp, 169 unsigned long long *min, 170 unsigned long long *max) 171{ 172 unsigned long long nr_inos = 0; 173 struct xfs_perag *pag; 174 xfs_agnumber_t agno; 175 176 /* root, rtbitmap, rtsum all live in the first chunk */ 177 *min = XFS_INODES_PER_CHUNK; 178 179 for_each_perag(mp, agno, pag) 180 nr_inos += pag->agino_max - pag->agino_min + 1; 181 *max = nr_inos; 182} 183 184/* Sanity-checking of inode counts. */ 185bool 186xfs_verify_icount( 187 struct xfs_mount *mp, 188 unsigned long long icount) 189{ 190 unsigned long long min, max; 191 192 xfs_icount_range(mp, &min, &max); 193 return icount >= min && icount <= max; 194} 195 196/* Sanity-checking of dir/attr block offsets. */ 197bool 198xfs_verify_dablk( 199 struct xfs_mount *mp, 200 xfs_fileoff_t dabno) 201{ 202 xfs_dablk_t max_dablk = -1U; 203 204 return dabno <= max_dablk; 205} 206 207/* Check that a file block offset does not exceed the maximum. */ 208bool 209xfs_verify_fileoff( 210 struct xfs_mount *mp, 211 xfs_fileoff_t off) 212{ 213 return off <= XFS_MAX_FILEOFF; 214} 215 216/* Check that a range of file block offsets do not exceed the maximum. */ 217bool 218xfs_verify_fileext( 219 struct xfs_mount *mp, 220 xfs_fileoff_t off, 221 xfs_fileoff_t len) 222{ 223 if (off + len <= off) 224 return false; 225 226 if (!xfs_verify_fileoff(mp, off)) 227 return false; 228 229 return xfs_verify_fileoff(mp, off + len - 1); 230} 231