1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Attribute list attribute handling code. 4 * Part of this file is based on code from the NTFS-3G. 5 * 6 * Copyright (c) 2004-2005 Anton Altaparmakov 7 * Copyright (c) 2004-2005 Yura Pakhuchiy 8 * Copyright (c) 2006 Szabolcs Szakacsits 9 * Copyright (c) 2025 LG Electronics Co., Ltd. 10 */ 11 12 #include "mft.h" 13 #include "attrib.h" 14 #include "attrlist.h" 15 #include "lcnalloc.h" 16 17 #define NTFS_MAX_ATTR_LIST_SIZE (256 * 1024) 18 19 /* 20 * ntfs_attrlist_need - check whether inode need attribute list 21 * @ni: opened ntfs inode for which perform check 22 * 23 * Check whether all are attributes belong to one MFT record, in that case 24 * attribute list is not needed. 25 * 26 * Return 1 if inode need attribute list, 0 if not, or -errno on error. 27 */ 28 int ntfs_attrlist_need(struct ntfs_inode *ni) 29 { 30 struct attr_list_entry *ale; 31 32 if (!ni) { 33 ntfs_debug("Invalid arguments.\n"); 34 return -EINVAL; 35 } 36 ntfs_debug("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 37 38 if (!NInoAttrList(ni)) { 39 ntfs_debug("Inode haven't got attribute list.\n"); 40 return -EINVAL; 41 } 42 43 if (!ni->attr_list) { 44 ntfs_debug("Corrupt in-memory struct.\n"); 45 return -EINVAL; 46 } 47 48 ale = (struct attr_list_entry *)ni->attr_list; 49 while ((u8 *)ale < ni->attr_list + ni->attr_list_size) { 50 if (MREF_LE(ale->mft_reference) != ni->mft_no) 51 return 1; 52 ale = (struct attr_list_entry *)((u8 *)ale + le16_to_cpu(ale->length)); 53 } 54 return 0; 55 } 56 57 /* 58 * Repack the $MFT/$ATTRIBUTE_LIST data into one run. 59 * 60 * The mapping pairs for an $ATTRIBUTE_LIST must remain in the base MFT 61 * record. Once that record has no room left, extending a fragmented list 62 * can require one more mapping-pairs byte than the record can hold. There 63 * is no attribute that can legally be moved out in that state: $STANDARD_ 64 * INFORMATION, $ATTRIBUTE_LIST, and the first $MFT/$DATA extent all have to 65 * stay in the base record. Move the list data to one contiguous run. The 66 * caller supplies the minimum allocation size so a recovery can use the 67 * smallest useful run while normal updates can still request the maximum 68 * legal list size as a reserve. 69 */ 70 static int ntfs_attrlist_repack(struct inode *attr_vi, 71 struct ntfs_inode *attr_ni, s64 min_alloc_size, 72 struct ntfs_inode *locked_ni) 73 { 74 struct ntfs_volume *vol = attr_ni->vol; 75 struct runlist_element *old_rl, *new_rl; 76 u8 *data = NULL; 77 s64 data_size, alloc_size, nr_clusters, written; 78 s64 old_alloc_size; 79 size_t old_rl_count, new_rl_count; 80 unsigned long flags; 81 int err, restore_err; 82 if (attr_ni->mft_no != FILE_MFT || !NInoNonResident(attr_ni) || 83 min_alloc_size < 0) 84 return -EINVAL; 85 /* The buffered I/O below can reacquire the attribute runlist lock. */ 86 if (attr_ni == locked_ni) 87 return -ENOSPC; 88 89 err = ntfs_attr_map_whole_runlist(attr_ni); 90 if (err) 91 return err; 92 93 data_size = attr_ni->data_size; 94 if (data_size < 0) 95 return -EIO; 96 97 if (data_size) { 98 data = kvmalloc(data_size, GFP_NOFS); 99 if (!data) 100 return -ENOMEM; 101 102 written = ntfs_inode_attr_pread(attr_vi, 0, data_size, data); 103 if (written != data_size) { 104 err = written < 0 ? (int)written : -EIO; 105 goto out_free_data; 106 } 107 } 108 109 old_alloc_size = attr_ni->allocated_size; 110 alloc_size = max_t(s64, old_alloc_size, min_alloc_size); 111 nr_clusters = ntfs_bytes_to_cluster(vol, 112 alloc_size + vol->cluster_size - 1); 113 if (nr_clusters <= 0) { 114 err = -EFBIG; 115 goto out_free_data; 116 } 117 118 /* A single run keeps the mapping pairs at the minimum size. */ 119 new_rl = ntfs_cluster_alloc(vol, 0, nr_clusters, -1, DATA_ZONE, 120 true, true, false); 121 if (IS_ERR(new_rl)) { 122 err = PTR_ERR(new_rl); 123 goto out_free_data; 124 } 125 126 new_rl_count = 0; 127 if (new_rl->vcn == 0 && new_rl->length == nr_clusters && 128 !new_rl[1].length) 129 new_rl_count = 2; 130 131 if (new_rl_count != 2) { 132 ntfs_cluster_free_from_rl(vol, new_rl); 133 kvfree(new_rl); 134 err = -ENOSPC; 135 goto out_free_data; 136 } 137 old_rl = attr_ni->runlist.rl; 138 old_rl_count = attr_ni->runlist.count; 139 down_write(&attr_ni->runlist.lock); 140 attr_ni->runlist.rl = new_rl; 141 attr_ni->runlist.count = new_rl_count; 142 up_write(&attr_ni->runlist.lock); 143 144 write_lock_irqsave(&attr_ni->size_lock, flags); 145 attr_ni->allocated_size = ntfs_cluster_to_bytes(vol, nr_clusters); 146 write_unlock_irqrestore(&attr_ni->size_lock, flags); 147 148 /* Populate the replacement extent before publishing its mapping pairs. */ 149 if (data_size) { 150 written = ntfs_inode_attr_pwrite(attr_vi, 0, data_size, data, true); 151 if (written != data_size) { 152 err = written < 0 ? (int)written : -EIO; 153 goto restore_old_runlist; 154 } 155 } 156 157 err = ntfs_attr_update_mapping_pairs_locked(attr_ni, 0, locked_ni); 158 if (err) 159 goto restore_old_runlist; 160 161 /* The new mapping is now authoritative; release the old data runs. */ 162 if (ntfs_cluster_free_from_rl(vol, old_rl)) { 163 ntfs_error(vol->sb, 164 "Failed to free old ATTRIBUTE_LIST extent: inode %#llx", 165 (long long)attr_ni->mft_no); 166 NVolSetErrors(vol); 167 } 168 kvfree(old_rl); 169 kvfree(data); 170 return 0; 171 172 restore_old_runlist: 173 down_write(&attr_ni->runlist.lock); 174 attr_ni->runlist.rl = old_rl; 175 attr_ni->runlist.count = old_rl_count; 176 up_write(&attr_ni->runlist.lock); 177 178 write_lock_irqsave(&attr_ni->size_lock, flags); 179 attr_ni->allocated_size = old_alloc_size; 180 write_unlock_irqrestore(&attr_ni->size_lock, flags); 181 182 restore_err = ntfs_attr_update_mapping_pairs_locked( 183 attr_ni, 0, locked_ni); 184 if (restore_err) { 185 ntfs_error(vol->sb, "Failed to restore ATTRIBUTE_LIST mapping pairs (%d)", 186 restore_err); 187 NVolSetErrors(vol); 188 } 189 190 ntfs_cluster_free_from_rl(vol, new_rl); 191 kvfree(new_rl); 192 err = err ? err : restore_err; 193 194 out_free_data: 195 kvfree(data); 196 return err; 197 } 198 199 int ntfs_attrlist_update_locked(struct ntfs_inode *base_ni, 200 struct ntfs_inode *locked_ni) 201 { 202 struct inode *attr_vi; 203 struct ntfs_inode *attr_ni; 204 s64 written; 205 int err, retry_err; 206 207 /* 208 * generic_shutdown_super() clears SB_ACTIVE before evicting cached 209 * inodes. Do not look up the attribute-list inode after SB_ACTIVE has 210 * been cleared; it may already be I_FREEING, and waiting on it can 211 * self-deadlock. 212 */ 213 if (!(VFS_I(base_ni)->i_sb->s_flags & SB_ACTIVE)) 214 return -EIO; 215 216 attr_vi = ntfs_attr_iget(VFS_I(base_ni), AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); 217 if (IS_ERR(attr_vi)) { 218 err = PTR_ERR(attr_vi); 219 return err; 220 } 221 attr_ni = NTFS_I(attr_vi); 222 /* Truncation and page-cache writes can reacquire this runlist lock. */ 223 if (attr_ni == locked_ni) { 224 iput(attr_vi); 225 return -ENOSPC; 226 } 227 228 err = ntfs_attr_truncate_i_locked( 229 attr_ni, base_ni->attr_list_size, HOLES_NO, locked_ni); 230 if (err == -ENOSPC && attr_ni->mft_no == FILE_MFT && 231 NInoNonResident(attr_ni)) { 232 retry_err = ntfs_attrlist_repack(attr_vi, attr_ni, 233 base_ni->attr_list_size, locked_ni); 234 if (retry_err) { 235 ntfs_error(base_ni->vol->sb, "Failed to repack attribute list"); 236 iput(attr_vi); 237 return retry_err; 238 } 239 240 retry_err = ntfs_attr_truncate_i_locked( 241 attr_ni, base_ni->attr_list_size, 242 HOLES_NO, locked_ni); 243 if (retry_err) { 244 ntfs_error(base_ni->vol->sb, 245 "Failed to resize attribute list after repack"); 246 iput(attr_vi); 247 return retry_err; 248 } 249 } else if (err) { 250 iput(attr_vi); 251 ntfs_error(base_ni->vol->sb, 252 "Failed to truncate attribute list of inode %#llx", 253 (long long)base_ni->mft_no); 254 return err; 255 } 256 257 /* 258 * Reserve the maximum legal list size while the MFT metadata area is 259 * still easy to allocate contiguously. This prevents a later list entry 260 * from needing another mapping-pairs byte in the full base MFT record. 261 * Failure to obtain the optional reserve must not reject the current 262 * metadata update; the repack retry above remains available if needed. 263 */ 264 if (base_ni->mft_no == FILE_MFT && NInoNonResident(attr_ni) && 265 attr_ni->allocated_size < NTFS_MAX_ATTR_LIST_SIZE) { 266 retry_err = ntfs_attr_expand_locked( 267 attr_ni, base_ni->attr_list_size, 268 NTFS_MAX_ATTR_LIST_SIZE, locked_ni); 269 if (retry_err == -ENOSPC) { 270 retry_err = ntfs_attrlist_repack( 271 attr_vi, attr_ni, 272 NTFS_MAX_ATTR_LIST_SIZE, locked_ni); 273 if (retry_err == -ENOSPC) 274 retry_err = 0; 275 } 276 if (retry_err) { 277 ntfs_error(base_ni->vol->sb, 278 "Failed to reserve attribute list space"); 279 iput(attr_vi); 280 return retry_err; 281 } 282 } 283 284 i_size_write(attr_vi, base_ni->attr_list_size); 285 286 if (NInoNonResident(attr_ni) && !NInoAttrListNonResident(base_ni)) 287 NInoSetAttrListNonResident(base_ni); 288 289 written = ntfs_inode_attr_pwrite(attr_vi, 0, base_ni->attr_list_size, 290 base_ni->attr_list, false); 291 if (written != base_ni->attr_list_size) { 292 err = written < 0 ? (int)written : -EIO; 293 iput(attr_vi); 294 ntfs_error(base_ni->vol->sb, 295 "Failed to write attribute list of inode %#llx", 296 (long long)base_ni->mft_no); 297 return err; 298 } 299 300 NInoSetAttrListDirty(base_ni); 301 iput(attr_vi); 302 return 0; 303 } 304 305 int ntfs_attrlist_update(struct ntfs_inode *base_ni) 306 { 307 return ntfs_attrlist_update_locked(base_ni, NULL); 308 } 309 310 /* 311 * ntfs_attrlist_entry_add - add an attribute list attribute entry 312 * @ni: opened ntfs inode, which contains that attribute 313 * @attr: attribute record to add to attribute list 314 * 315 * Return 0 on success and -errno on error. 316 */ 317 int ntfs_attrlist_entry_add(struct ntfs_inode *ni, struct attr_record *attr) 318 { 319 struct attr_list_entry *ale; 320 __le64 mref; 321 struct ntfs_attr_search_ctx *ctx; 322 u8 *new_al; 323 int entry_len, entry_offset, err; 324 struct mft_record *ni_mrec; 325 u8 *old_al; 326 __le64 lowest_vcn; 327 328 if (!ni || !attr) { 329 ntfs_debug("Invalid arguments.\n"); 330 return -EINVAL; 331 } 332 333 ntfs_debug("Entering for inode 0x%llx, attr 0x%x.\n", 334 ni->mft_no, (unsigned int) le32_to_cpu(attr->type)); 335 336 ni_mrec = map_mft_record(ni); 337 if (IS_ERR(ni_mrec)) { 338 ntfs_debug("Invalid arguments.\n"); 339 return -EIO; 340 } 341 342 mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni_mrec->sequence_number)); 343 unmap_mft_record(ni); 344 345 if (ni->nr_extents == -1) 346 ni = ni->ext.base_ntfs_ino; 347 348 if (!NInoAttrList(ni)) { 349 ntfs_debug("Attribute list isn't present.\n"); 350 return -ENOENT; 351 } 352 353 /* Determine size and allocate memory for new attribute list. */ 354 entry_len = (sizeof(struct attr_list_entry) + sizeof(__le16) * 355 attr->name_length + 7) & ~7; 356 new_al = kvzalloc(ni->attr_list_size + entry_len, GFP_NOFS); 357 if (!new_al) 358 return -ENOMEM; 359 360 /* Find place for the new entry. */ 361 ctx = ntfs_attr_get_search_ctx(ni, NULL); 362 if (!ctx) { 363 err = -ENOMEM; 364 ntfs_error(ni->vol->sb, "Failed to get search context"); 365 goto err_out; 366 } 367 if (attr->non_resident) 368 lowest_vcn = attr->data.non_resident.lowest_vcn; 369 else 370 lowest_vcn = 0; 371 372 err = ntfs_attr_lookup(attr->type, (attr->name_length) ? (__le16 *) 373 ((u8 *)attr + le16_to_cpu(attr->name_offset)) : 374 AT_UNNAMED, attr->name_length, CASE_SENSITIVE, 375 le64_to_cpu(lowest_vcn), 376 (attr->non_resident) ? NULL : ((u8 *)attr + 377 le16_to_cpu(attr->data.resident.value_offset)), (attr->non_resident) ? 378 0 : le32_to_cpu(attr->data.resident.value_length), ctx); 379 if (!err) { 380 /* Found some extent, check it to be before new extent. */ 381 if (ctx->al_entry->lowest_vcn == lowest_vcn) { 382 err = -EEXIST; 383 ntfs_debug("Such attribute already present in the attribute list.\n"); 384 ntfs_attr_put_search_ctx(ctx); 385 goto err_out; 386 } 387 /* Add new entry after this extent. */ 388 ale = (struct attr_list_entry *)((u8 *)ctx->al_entry + 389 le16_to_cpu(ctx->al_entry->length)); 390 } else { 391 /* Check for real errors. */ 392 if (err != -ENOENT) { 393 ntfs_debug("Attribute lookup failed.\n"); 394 ntfs_attr_put_search_ctx(ctx); 395 goto err_out; 396 } 397 /* No previous extents found. */ 398 ale = ctx->al_entry; 399 } 400 /* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */ 401 ntfs_attr_put_search_ctx(ctx); 402 403 /* Determine new entry offset. */ 404 entry_offset = ((u8 *)ale - ni->attr_list); 405 /* Set pointer to new entry. */ 406 ale = (struct attr_list_entry *)(new_al + entry_offset); 407 memset(ale, 0, entry_len); 408 /* Form new entry. */ 409 ale->type = attr->type; 410 ale->length = cpu_to_le16(entry_len); 411 ale->name_length = attr->name_length; 412 ale->name_offset = offsetof(struct attr_list_entry, name); 413 if (attr->non_resident) 414 ale->lowest_vcn = attr->data.non_resident.lowest_vcn; 415 else 416 ale->lowest_vcn = 0; 417 ale->mft_reference = mref; 418 ale->instance = attr->instance; 419 memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset), 420 attr->name_length * sizeof(__le16)); 421 422 /* Copy entries from old attribute list to new. */ 423 memcpy(new_al, ni->attr_list, entry_offset); 424 memcpy(new_al + entry_offset + entry_len, ni->attr_list + 425 entry_offset, ni->attr_list_size - entry_offset); 426 427 /* Set new runlist. */ 428 old_al = ni->attr_list; 429 ni->attr_list = new_al; 430 ni->attr_list_size = ni->attr_list_size + entry_len; 431 432 err = ntfs_attrlist_update(ni); 433 if (err) { 434 ni->attr_list = old_al; 435 ni->attr_list_size -= entry_len; 436 goto err_out; 437 } 438 kvfree(old_al); 439 return 0; 440 err_out: 441 kvfree(new_al); 442 return err; 443 } 444 445 /* 446 * ntfs_attrlist_entry_rm - remove an attribute list attribute entry 447 * @ctx: attribute search context describing the attribute list entry 448 * 449 * Remove the attribute list entry @ctx->al_entry from the attribute list. 450 * 451 * Return 0 on success and -errno on error. 452 */ 453 int ntfs_attrlist_entry_rm(struct ntfs_attr_search_ctx *ctx) 454 { 455 u8 *new_al; 456 int new_al_len; 457 struct ntfs_inode *base_ni; 458 struct attr_list_entry *ale; 459 460 if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) { 461 ntfs_debug("Invalid arguments.\n"); 462 return -EINVAL; 463 } 464 465 if (ctx->base_ntfs_ino) 466 base_ni = ctx->base_ntfs_ino; 467 else 468 base_ni = ctx->ntfs_ino; 469 ale = ctx->al_entry; 470 471 ntfs_debug("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n", 472 (long long)ctx->ntfs_ino->mft_no, 473 (unsigned int)le32_to_cpu(ctx->al_entry->type), 474 (long long)le64_to_cpu(ctx->al_entry->lowest_vcn)); 475 476 if (!NInoAttrList(base_ni)) { 477 ntfs_debug("Attribute list isn't present.\n"); 478 return -ENOENT; 479 } 480 481 /* Allocate memory for new attribute list. */ 482 new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length); 483 new_al = kvzalloc(new_al_len, GFP_NOFS); 484 if (!new_al) 485 return -ENOMEM; 486 487 /* Copy entries from old attribute list to new. */ 488 memcpy(new_al, base_ni->attr_list, (u8 *)ale - base_ni->attr_list); 489 memcpy(new_al + ((u8 *)ale - base_ni->attr_list), (u8 *)ale + le16_to_cpu( 490 ale->length), new_al_len - ((u8 *)ale - base_ni->attr_list)); 491 492 /* Set new runlist. */ 493 kvfree(base_ni->attr_list); 494 base_ni->attr_list = new_al; 495 base_ni->attr_list_size = new_al_len; 496 497 return ntfs_attrlist_update(base_ni); 498 } 499