index.c (14375B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * index.c - NTFS kernel index handling. Part of the Linux-NTFS project. 4 * 5 * Copyright (c) 2004-2005 Anton Altaparmakov 6 */ 7 8#include <linux/slab.h> 9 10#include "aops.h" 11#include "collate.h" 12#include "debug.h" 13#include "index.h" 14#include "ntfs.h" 15 16/** 17 * ntfs_index_ctx_get - allocate and initialize a new index context 18 * @idx_ni: ntfs index inode with which to initialize the context 19 * 20 * Allocate a new index context, initialize it with @idx_ni and return it. 21 * Return NULL if allocation failed. 22 * 23 * Locking: Caller must hold i_mutex on the index inode. 24 */ 25ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *idx_ni) 26{ 27 ntfs_index_context *ictx; 28 29 ictx = kmem_cache_alloc(ntfs_index_ctx_cache, GFP_NOFS); 30 if (ictx) 31 *ictx = (ntfs_index_context){ .idx_ni = idx_ni }; 32 return ictx; 33} 34 35/** 36 * ntfs_index_ctx_put - release an index context 37 * @ictx: index context to free 38 * 39 * Release the index context @ictx, releasing all associated resources. 40 * 41 * Locking: Caller must hold i_mutex on the index inode. 42 */ 43void ntfs_index_ctx_put(ntfs_index_context *ictx) 44{ 45 if (ictx->entry) { 46 if (ictx->is_in_root) { 47 if (ictx->actx) 48 ntfs_attr_put_search_ctx(ictx->actx); 49 if (ictx->base_ni) 50 unmap_mft_record(ictx->base_ni); 51 } else { 52 struct page *page = ictx->page; 53 if (page) { 54 BUG_ON(!PageLocked(page)); 55 unlock_page(page); 56 ntfs_unmap_page(page); 57 } 58 } 59 } 60 kmem_cache_free(ntfs_index_ctx_cache, ictx); 61 return; 62} 63 64/** 65 * ntfs_index_lookup - find a key in an index and return its index entry 66 * @key: [IN] key for which to search in the index 67 * @key_len: [IN] length of @key in bytes 68 * @ictx: [IN/OUT] context describing the index and the returned entry 69 * 70 * Before calling ntfs_index_lookup(), @ictx must have been obtained from a 71 * call to ntfs_index_ctx_get(). 72 * 73 * Look for the @key in the index specified by the index lookup context @ictx. 74 * ntfs_index_lookup() walks the contents of the index looking for the @key. 75 * 76 * If the @key is found in the index, 0 is returned and @ictx is setup to 77 * describe the index entry containing the matching @key. @ictx->entry is the 78 * index entry and @ictx->data and @ictx->data_len are the index entry data and 79 * its length in bytes, respectively. 80 * 81 * If the @key is not found in the index, -ENOENT is returned and @ictx is 82 * setup to describe the index entry whose key collates immediately after the 83 * search @key, i.e. this is the position in the index at which an index entry 84 * with a key of @key would need to be inserted. 85 * 86 * If an error occurs return the negative error code and @ictx is left 87 * untouched. 88 * 89 * When finished with the entry and its data, call ntfs_index_ctx_put() to free 90 * the context and other associated resources. 91 * 92 * If the index entry was modified, call flush_dcache_index_entry_page() 93 * immediately after the modification and either ntfs_index_entry_mark_dirty() 94 * or ntfs_index_entry_write() before the call to ntfs_index_ctx_put() to 95 * ensure that the changes are written to disk. 96 * 97 * Locking: - Caller must hold i_mutex on the index inode. 98 * - Each page cache page in the index allocation mapping must be 99 * locked whilst being accessed otherwise we may find a corrupt 100 * page due to it being under ->writepage at the moment which 101 * applies the mst protection fixups before writing out and then 102 * removes them again after the write is complete after which it 103 * unlocks the page. 104 */ 105int ntfs_index_lookup(const void *key, const int key_len, 106 ntfs_index_context *ictx) 107{ 108 VCN vcn, old_vcn; 109 ntfs_inode *idx_ni = ictx->idx_ni; 110 ntfs_volume *vol = idx_ni->vol; 111 struct super_block *sb = vol->sb; 112 ntfs_inode *base_ni = idx_ni->ext.base_ntfs_ino; 113 MFT_RECORD *m; 114 INDEX_ROOT *ir; 115 INDEX_ENTRY *ie; 116 INDEX_ALLOCATION *ia; 117 u8 *index_end, *kaddr; 118 ntfs_attr_search_ctx *actx; 119 struct address_space *ia_mapping; 120 struct page *page; 121 int rc, err = 0; 122 123 ntfs_debug("Entering."); 124 BUG_ON(!NInoAttr(idx_ni)); 125 BUG_ON(idx_ni->type != AT_INDEX_ALLOCATION); 126 BUG_ON(idx_ni->nr_extents != -1); 127 BUG_ON(!base_ni); 128 BUG_ON(!key); 129 BUG_ON(key_len <= 0); 130 if (!ntfs_is_collation_rule_supported( 131 idx_ni->itype.index.collation_rule)) { 132 ntfs_error(sb, "Index uses unsupported collation rule 0x%x. " 133 "Aborting lookup.", le32_to_cpu( 134 idx_ni->itype.index.collation_rule)); 135 return -EOPNOTSUPP; 136 } 137 /* Get hold of the mft record for the index inode. */ 138 m = map_mft_record(base_ni); 139 if (IS_ERR(m)) { 140 ntfs_error(sb, "map_mft_record() failed with error code %ld.", 141 -PTR_ERR(m)); 142 return PTR_ERR(m); 143 } 144 actx = ntfs_attr_get_search_ctx(base_ni, m); 145 if (unlikely(!actx)) { 146 err = -ENOMEM; 147 goto err_out; 148 } 149 /* Find the index root attribute in the mft record. */ 150 err = ntfs_attr_lookup(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len, 151 CASE_SENSITIVE, 0, NULL, 0, actx); 152 if (unlikely(err)) { 153 if (err == -ENOENT) { 154 ntfs_error(sb, "Index root attribute missing in inode " 155 "0x%lx.", idx_ni->mft_no); 156 err = -EIO; 157 } 158 goto err_out; 159 } 160 /* Get to the index root value (it has been verified in read_inode). */ 161 ir = (INDEX_ROOT*)((u8*)actx->attr + 162 le16_to_cpu(actx->attr->data.resident.value_offset)); 163 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); 164 /* The first index entry. */ 165 ie = (INDEX_ENTRY*)((u8*)&ir->index + 166 le32_to_cpu(ir->index.entries_offset)); 167 /* 168 * Loop until we exceed valid memory (corruption case) or until we 169 * reach the last entry. 170 */ 171 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 172 /* Bounds checks. */ 173 if ((u8*)ie < (u8*)actx->mrec || (u8*)ie + 174 sizeof(INDEX_ENTRY_HEADER) > index_end || 175 (u8*)ie + le16_to_cpu(ie->length) > index_end) 176 goto idx_err_out; 177 /* 178 * The last entry cannot contain a key. It can however contain 179 * a pointer to a child node in the B+tree so we just break out. 180 */ 181 if (ie->flags & INDEX_ENTRY_END) 182 break; 183 /* Further bounds checks. */ 184 if ((u32)sizeof(INDEX_ENTRY_HEADER) + 185 le16_to_cpu(ie->key_length) > 186 le16_to_cpu(ie->data.vi.data_offset) || 187 (u32)le16_to_cpu(ie->data.vi.data_offset) + 188 le16_to_cpu(ie->data.vi.data_length) > 189 le16_to_cpu(ie->length)) 190 goto idx_err_out; 191 /* If the keys match perfectly, we setup @ictx and return 0. */ 192 if ((key_len == le16_to_cpu(ie->key_length)) && !memcmp(key, 193 &ie->key, key_len)) { 194ir_done: 195 ictx->is_in_root = true; 196 ictx->ir = ir; 197 ictx->actx = actx; 198 ictx->base_ni = base_ni; 199 ictx->ia = NULL; 200 ictx->page = NULL; 201done: 202 ictx->entry = ie; 203 ictx->data = (u8*)ie + 204 le16_to_cpu(ie->data.vi.data_offset); 205 ictx->data_len = le16_to_cpu(ie->data.vi.data_length); 206 ntfs_debug("Done."); 207 return err; 208 } 209 /* 210 * Not a perfect match, need to do full blown collation so we 211 * know which way in the B+tree we have to go. 212 */ 213 rc = ntfs_collate(vol, idx_ni->itype.index.collation_rule, key, 214 key_len, &ie->key, le16_to_cpu(ie->key_length)); 215 /* 216 * If @key collates before the key of the current entry, there 217 * is definitely no such key in this index but we might need to 218 * descend into the B+tree so we just break out of the loop. 219 */ 220 if (rc == -1) 221 break; 222 /* 223 * A match should never happen as the memcmp() call should have 224 * cought it, but we still treat it correctly. 225 */ 226 if (!rc) 227 goto ir_done; 228 /* The keys are not equal, continue the search. */ 229 } 230 /* 231 * We have finished with this index without success. Check for the 232 * presence of a child node and if not present setup @ictx and return 233 * -ENOENT. 234 */ 235 if (!(ie->flags & INDEX_ENTRY_NODE)) { 236 ntfs_debug("Entry not found."); 237 err = -ENOENT; 238 goto ir_done; 239 } /* Child node present, descend into it. */ 240 /* Consistency check: Verify that an index allocation exists. */ 241 if (!NInoIndexAllocPresent(idx_ni)) { 242 ntfs_error(sb, "No index allocation attribute but index entry " 243 "requires one. Inode 0x%lx is corrupt or " 244 "driver bug.", idx_ni->mft_no); 245 goto err_out; 246 } 247 /* Get the starting vcn of the index_block holding the child node. */ 248 vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8)); 249 ia_mapping = VFS_I(idx_ni)->i_mapping; 250 /* 251 * We are done with the index root and the mft record. Release them, 252 * otherwise we deadlock with ntfs_map_page(). 253 */ 254 ntfs_attr_put_search_ctx(actx); 255 unmap_mft_record(base_ni); 256 m = NULL; 257 actx = NULL; 258descend_into_child_node: 259 /* 260 * Convert vcn to index into the index allocation attribute in units 261 * of PAGE_SIZE and map the page cache page, reading it from 262 * disk if necessary. 263 */ 264 page = ntfs_map_page(ia_mapping, vcn << 265 idx_ni->itype.index.vcn_size_bits >> PAGE_SHIFT); 266 if (IS_ERR(page)) { 267 ntfs_error(sb, "Failed to map index page, error %ld.", 268 -PTR_ERR(page)); 269 err = PTR_ERR(page); 270 goto err_out; 271 } 272 lock_page(page); 273 kaddr = (u8*)page_address(page); 274fast_descend_into_child_node: 275 /* Get to the index allocation block. */ 276 ia = (INDEX_ALLOCATION*)(kaddr + ((vcn << 277 idx_ni->itype.index.vcn_size_bits) & ~PAGE_MASK)); 278 /* Bounds checks. */ 279 if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_SIZE) { 280 ntfs_error(sb, "Out of bounds check failed. Corrupt inode " 281 "0x%lx or driver bug.", idx_ni->mft_no); 282 goto unm_err_out; 283 } 284 /* Catch multi sector transfer fixup errors. */ 285 if (unlikely(!ntfs_is_indx_record(ia->magic))) { 286 ntfs_error(sb, "Index record with vcn 0x%llx is corrupt. " 287 "Corrupt inode 0x%lx. Run chkdsk.", 288 (long long)vcn, idx_ni->mft_no); 289 goto unm_err_out; 290 } 291 if (sle64_to_cpu(ia->index_block_vcn) != vcn) { 292 ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " 293 "different from expected VCN (0x%llx). Inode " 294 "0x%lx is corrupt or driver bug.", 295 (unsigned long long) 296 sle64_to_cpu(ia->index_block_vcn), 297 (unsigned long long)vcn, idx_ni->mft_no); 298 goto unm_err_out; 299 } 300 if (le32_to_cpu(ia->index.allocated_size) + 0x18 != 301 idx_ni->itype.index.block_size) { 302 ntfs_error(sb, "Index buffer (VCN 0x%llx) of inode 0x%lx has " 303 "a size (%u) differing from the index " 304 "specified size (%u). Inode is corrupt or " 305 "driver bug.", (unsigned long long)vcn, 306 idx_ni->mft_no, 307 le32_to_cpu(ia->index.allocated_size) + 0x18, 308 idx_ni->itype.index.block_size); 309 goto unm_err_out; 310 } 311 index_end = (u8*)ia + idx_ni->itype.index.block_size; 312 if (index_end > kaddr + PAGE_SIZE) { 313 ntfs_error(sb, "Index buffer (VCN 0x%llx) of inode 0x%lx " 314 "crosses page boundary. Impossible! Cannot " 315 "access! This is probably a bug in the " 316 "driver.", (unsigned long long)vcn, 317 idx_ni->mft_no); 318 goto unm_err_out; 319 } 320 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); 321 if (index_end > (u8*)ia + idx_ni->itype.index.block_size) { 322 ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of inode " 323 "0x%lx exceeds maximum size.", 324 (unsigned long long)vcn, idx_ni->mft_no); 325 goto unm_err_out; 326 } 327 /* The first index entry. */ 328 ie = (INDEX_ENTRY*)((u8*)&ia->index + 329 le32_to_cpu(ia->index.entries_offset)); 330 /* 331 * Iterate similar to above big loop but applied to index buffer, thus 332 * loop until we exceed valid memory (corruption case) or until we 333 * reach the last entry. 334 */ 335 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 336 /* Bounds checks. */ 337 if ((u8*)ie < (u8*)ia || (u8*)ie + 338 sizeof(INDEX_ENTRY_HEADER) > index_end || 339 (u8*)ie + le16_to_cpu(ie->length) > index_end) { 340 ntfs_error(sb, "Index entry out of bounds in inode " 341 "0x%lx.", idx_ni->mft_no); 342 goto unm_err_out; 343 } 344 /* 345 * The last entry cannot contain a key. It can however contain 346 * a pointer to a child node in the B+tree so we just break out. 347 */ 348 if (ie->flags & INDEX_ENTRY_END) 349 break; 350 /* Further bounds checks. */ 351 if ((u32)sizeof(INDEX_ENTRY_HEADER) + 352 le16_to_cpu(ie->key_length) > 353 le16_to_cpu(ie->data.vi.data_offset) || 354 (u32)le16_to_cpu(ie->data.vi.data_offset) + 355 le16_to_cpu(ie->data.vi.data_length) > 356 le16_to_cpu(ie->length)) { 357 ntfs_error(sb, "Index entry out of bounds in inode " 358 "0x%lx.", idx_ni->mft_no); 359 goto unm_err_out; 360 } 361 /* If the keys match perfectly, we setup @ictx and return 0. */ 362 if ((key_len == le16_to_cpu(ie->key_length)) && !memcmp(key, 363 &ie->key, key_len)) { 364ia_done: 365 ictx->is_in_root = false; 366 ictx->actx = NULL; 367 ictx->base_ni = NULL; 368 ictx->ia = ia; 369 ictx->page = page; 370 goto done; 371 } 372 /* 373 * Not a perfect match, need to do full blown collation so we 374 * know which way in the B+tree we have to go. 375 */ 376 rc = ntfs_collate(vol, idx_ni->itype.index.collation_rule, key, 377 key_len, &ie->key, le16_to_cpu(ie->key_length)); 378 /* 379 * If @key collates before the key of the current entry, there 380 * is definitely no such key in this index but we might need to 381 * descend into the B+tree so we just break out of the loop. 382 */ 383 if (rc == -1) 384 break; 385 /* 386 * A match should never happen as the memcmp() call should have 387 * cought it, but we still treat it correctly. 388 */ 389 if (!rc) 390 goto ia_done; 391 /* The keys are not equal, continue the search. */ 392 } 393 /* 394 * We have finished with this index buffer without success. Check for 395 * the presence of a child node and if not present return -ENOENT. 396 */ 397 if (!(ie->flags & INDEX_ENTRY_NODE)) { 398 ntfs_debug("Entry not found."); 399 err = -ENOENT; 400 goto ia_done; 401 } 402 if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { 403 ntfs_error(sb, "Index entry with child node found in a leaf " 404 "node in inode 0x%lx.", idx_ni->mft_no); 405 goto unm_err_out; 406 } 407 /* Child node present, descend into it. */ 408 old_vcn = vcn; 409 vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8)); 410 if (vcn >= 0) { 411 /* 412 * If vcn is in the same page cache page as old_vcn we recycle 413 * the mapped page. 414 */ 415 if (old_vcn << vol->cluster_size_bits >> 416 PAGE_SHIFT == vcn << 417 vol->cluster_size_bits >> 418 PAGE_SHIFT) 419 goto fast_descend_into_child_node; 420 unlock_page(page); 421 ntfs_unmap_page(page); 422 goto descend_into_child_node; 423 } 424 ntfs_error(sb, "Negative child node vcn in inode 0x%lx.", 425 idx_ni->mft_no); 426unm_err_out: 427 unlock_page(page); 428 ntfs_unmap_page(page); 429err_out: 430 if (!err) 431 err = -EIO; 432 if (actx) 433 ntfs_attr_put_search_ctx(actx); 434 if (m) 435 unmap_mft_record(base_ni); 436 return err; 437idx_err_out: 438 ntfs_error(sb, "Corrupt index. Aborting lookup."); 439 goto err_out; 440}