1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Pocessing of object ids 4 * 5 * Part of this file is based on code from the NTFS-3G. 6 * 7 * Copyright (c) 2009-2019 Jean-Pierre Andre 8 * Copyright (c) 2026 LG Electronics Co., Ltd. 9 */ 10 11 #include "ntfs.h" 12 #include "index.h" 13 #include "object_id.h" 14 15 struct object_id_index_key { 16 union { 17 u32 alignment; 18 struct guid guid; 19 } object_id; 20 } __packed; 21 22 struct object_id_index_data { 23 __le64 file_id; 24 struct guid birth_volume_id; 25 struct guid birth_object_id; 26 struct guid domain_id; 27 } __packed; 28 29 /* Index entry in $Extend/$ObjId */ 30 struct object_id_index { 31 struct index_entry_header header; 32 struct object_id_index_key key; 33 struct object_id_index_data data; 34 } __packed; 35 36 __le16 objid_index_name[] = {cpu_to_le16('$'), cpu_to_le16('O'), 0}; 37 38 /* 39 * open_object_id_index - Open the $Extend/$ObjId file and its index 40 * @vol: NTFS volume structure 41 * 42 * Opens the $ObjId system file and retrieves its index context. 43 * 44 * Return: The index context if opened successfully, or NULL if an error 45 * occurred. 46 */ 47 static struct ntfs_index_context *open_object_id_index(struct ntfs_volume *vol) 48 { 49 struct inode *dir_vi, *vi; 50 struct ntfs_inode *dir_ni; 51 struct ntfs_index_context *xo = NULL; 52 struct ntfs_name *name = NULL; 53 u64 mref; 54 int uname_len; 55 __le16 *uname; 56 57 uname_len = ntfs_nlstoucs(vol, "$ObjId", 6, &uname, 58 NTFS_MAX_NAME_LEN); 59 if (uname_len < 0) 60 return NULL; 61 62 /* do not use path_name_to inode - could reopen root */ 63 dir_vi = ntfs_iget(vol->sb, FILE_Extend); 64 if (IS_ERR(dir_vi)) { 65 kmem_cache_free(ntfs_name_cache, uname); 66 return NULL; 67 } 68 dir_ni = NTFS_I(dir_vi); 69 70 mutex_lock_nested(&dir_ni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); 71 mref = ntfs_lookup_inode_by_name(dir_ni, uname, uname_len, &name); 72 mutex_unlock(&dir_ni->mrec_lock); 73 kfree(name); 74 kmem_cache_free(ntfs_name_cache, uname); 75 if (IS_ERR_MREF(mref)) 76 goto put_dir_vi; 77 78 vi = ntfs_iget(vol->sb, MREF(mref)); 79 if (IS_ERR(vi)) 80 goto put_dir_vi; 81 82 xo = ntfs_index_ctx_get(NTFS_I(vi), objid_index_name, 2); 83 if (!xo) 84 iput(vi); 85 put_dir_vi: 86 iput(dir_vi); 87 return xo; 88 } 89 90 91 /* 92 * remove_object_id_index - Remove an object id index entry if attribute present 93 * @ni: NTFS inode structure containing the attribute 94 * @xo: Index context for the object id index 95 * 96 * Reads the existing object ID attribute and removes it from the index. 97 * 98 * Return: 0 on success, or a negative error code on failure. 99 */ 100 static int remove_object_id_index(struct ntfs_inode *ni, struct ntfs_index_context *xo) 101 { 102 struct object_id_index_key key = {0}; 103 s64 size; 104 105 if (ni->data_size == 0) 106 return -ENODATA; 107 108 /* read the existing object id attribute */ 109 size = ntfs_inode_attr_pread(VFS_I(ni), 0, sizeof(struct guid), 110 (char *)&key); 111 if (size != sizeof(struct guid)) 112 return -ENODATA; 113 114 if (!ntfs_index_lookup(&key, sizeof(struct object_id_index_key), xo)) 115 return ntfs_index_rm(xo); 116 117 return 0; 118 } 119 120 /* 121 * ntfs_delete_object_id_index - Delete an object_id index entry 122 * @ni: NTFS inode structure 123 * 124 * Opens the object ID index and removes the entry corresponding to the inode. 125 * 126 * Return: 0 on success, or a negative error code on failure. 127 */ 128 int ntfs_delete_object_id_index(struct ntfs_inode *ni) 129 { 130 struct ntfs_index_context *xo; 131 struct ntfs_inode *xoni; 132 struct inode *attr_vi; 133 int ret = 0; 134 135 attr_vi = ntfs_attr_iget(VFS_I(ni), AT_OBJECT_ID, AT_UNNAMED, 0); 136 if (IS_ERR(attr_vi)) 137 return PTR_ERR(attr_vi); 138 139 /* 140 * read the existing object id and un-index it 141 */ 142 xo = open_object_id_index(ni->vol); 143 if (xo) { 144 xoni = xo->idx_ni; 145 mutex_lock_nested(&xoni->mrec_lock, NTFS_EXTEND_MUTEX_PARENT); 146 ret = remove_object_id_index(NTFS_I(attr_vi), xo); 147 if (!ret) { 148 ntfs_index_entry_mark_dirty(xo); 149 mark_mft_record_dirty(xoni); 150 } 151 ntfs_index_ctx_put(xo); 152 mutex_unlock(&xoni->mrec_lock); 153 iput(VFS_I(xoni)); 154 } 155 156 iput(attr_vi); 157 return ret; 158 } 159