blob: d48a5e6c5045c5f154f3c1aba4108f458e9676b0 [file] [log] [blame]
Konstantin Komarov43423062021-08-13 17:21:29 +03001// SPDX-License-Identifier: GPL-2.0
2/*
3 *
4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
5 *
6 */
7
8#include <linux/blkdev.h>
9#include <linux/buffer_head.h>
10#include <linux/fs.h>
11#include <linux/nls.h>
12
13#include "debug.h"
14#include "ntfs.h"
15#include "ntfs_fs.h"
16
17static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
18 const __le16 *name, u8 name_len,
19 const u16 *upcase)
20{
Kari Argillandere8b8e972021-08-03 14:57:09 +030021 /* First, compare the type codes. */
Konstantin Komarov43423062021-08-13 17:21:29 +030022 int diff = le32_to_cpu(left->type) - le32_to_cpu(type);
23
24 if (diff)
25 return diff;
26
Kari Argillandere8b8e972021-08-03 14:57:09 +030027 /* They have the same type code, so we have to compare the names. */
Konstantin Komarov43423062021-08-13 17:21:29 +030028 return ntfs_cmp_names(attr_name(left), left->name_len, name, name_len,
29 upcase, true);
30}
31
32/*
33 * mi_new_attt_id
34 *
Kari Argillandere8b8e972021-08-03 14:57:09 +030035 * Return: Unused attribute id that is less than mrec->next_attr_id.
Konstantin Komarov43423062021-08-13 17:21:29 +030036 */
37static __le16 mi_new_attt_id(struct mft_inode *mi)
38{
39 u16 free_id, max_id, t16;
40 struct MFT_REC *rec = mi->mrec;
41 struct ATTRIB *attr;
42 __le16 id;
43
44 id = rec->next_attr_id;
45 free_id = le16_to_cpu(id);
46 if (free_id < 0x7FFF) {
47 rec->next_attr_id = cpu_to_le16(free_id + 1);
48 return id;
49 }
50
Kari Argillandere8b8e972021-08-03 14:57:09 +030051 /* One record can store up to 1024/24 ~= 42 attributes. */
Konstantin Komarov43423062021-08-13 17:21:29 +030052 free_id = 0;
53 max_id = 0;
54
55 attr = NULL;
56
57 for (;;) {
58 attr = mi_enum_attr(mi, attr);
59 if (!attr) {
60 rec->next_attr_id = cpu_to_le16(max_id + 1);
61 mi->dirty = true;
62 return cpu_to_le16(free_id);
63 }
64
65 t16 = le16_to_cpu(attr->id);
66 if (t16 == free_id) {
67 free_id += 1;
68 attr = NULL;
69 } else if (max_id < t16)
70 max_id = t16;
71 }
72}
73
74int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi)
75{
76 int err;
Kari Argillander195c52b2021-08-24 21:37:07 +030077 struct mft_inode *m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
Konstantin Komarov43423062021-08-13 17:21:29 +030078
79 if (!m)
80 return -ENOMEM;
81
82 err = mi_init(m, sbi, rno);
83 if (err) {
Kari Argillander195c52b2021-08-24 21:37:07 +030084 kfree(m);
Konstantin Komarov43423062021-08-13 17:21:29 +030085 return err;
86 }
87
88 err = mi_read(m, false);
89 if (err) {
90 mi_put(m);
91 return err;
92 }
93
94 *mi = m;
95 return 0;
96}
97
98void mi_put(struct mft_inode *mi)
99{
100 mi_clear(mi);
Kari Argillander195c52b2021-08-24 21:37:07 +0300101 kfree(mi);
Konstantin Komarov43423062021-08-13 17:21:29 +0300102}
103
104int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno)
105{
106 mi->sbi = sbi;
107 mi->rno = rno;
Kari Argillander195c52b2021-08-24 21:37:07 +0300108 mi->mrec = kmalloc(sbi->record_size, GFP_NOFS);
Konstantin Komarov43423062021-08-13 17:21:29 +0300109 if (!mi->mrec)
110 return -ENOMEM;
111
112 return 0;
113}
114
115/*
Kari Argillandere8b8e972021-08-03 14:57:09 +0300116 * mi_read - Read MFT data.
Konstantin Komarov43423062021-08-13 17:21:29 +0300117 */
118int mi_read(struct mft_inode *mi, bool is_mft)
119{
120 int err;
121 struct MFT_REC *rec = mi->mrec;
122 struct ntfs_sb_info *sbi = mi->sbi;
123 u32 bpr = sbi->record_size;
124 u64 vbo = (u64)mi->rno << sbi->record_bits;
125 struct ntfs_inode *mft_ni = sbi->mft.ni;
126 struct runs_tree *run = mft_ni ? &mft_ni->file.run : NULL;
127 struct rw_semaphore *rw_lock = NULL;
128
129 if (is_mounted(sbi)) {
130 if (!is_mft) {
131 rw_lock = &mft_ni->file.run_lock;
132 down_read(rw_lock);
133 }
134 }
135
136 err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
137 if (rw_lock)
138 up_read(rw_lock);
139 if (!err)
140 goto ok;
141
142 if (err == -E_NTFS_FIXUP) {
143 mi->dirty = true;
144 goto ok;
145 }
146
147 if (err != -ENOENT)
148 goto out;
149
150 if (rw_lock) {
151 ni_lock(mft_ni);
152 down_write(rw_lock);
153 }
154 err = attr_load_runs_vcn(mft_ni, ATTR_DATA, NULL, 0, &mft_ni->file.run,
155 vbo >> sbi->cluster_bits);
156 if (rw_lock) {
157 up_write(rw_lock);
158 ni_unlock(mft_ni);
159 }
160 if (err)
161 goto out;
162
163 if (rw_lock)
164 down_read(rw_lock);
165 err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
166 if (rw_lock)
167 up_read(rw_lock);
168
169 if (err == -E_NTFS_FIXUP) {
170 mi->dirty = true;
171 goto ok;
172 }
173 if (err)
174 goto out;
175
176ok:
Kari Argillandere8b8e972021-08-03 14:57:09 +0300177 /* Check field 'total' only here. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300178 if (le32_to_cpu(rec->total) != bpr) {
179 err = -EINVAL;
180 goto out;
181 }
182
183 return 0;
184
185out:
186 return err;
187}
188
189struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
190{
191 const struct MFT_REC *rec = mi->mrec;
192 u32 used = le32_to_cpu(rec->used);
193 u32 t32, off, asize;
194 u16 t16;
195
196 if (!attr) {
197 u32 total = le32_to_cpu(rec->total);
198
199 off = le16_to_cpu(rec->attr_off);
200
201 if (used > total)
202 return NULL;
203
204 if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
Kari Argillanderfa3cacf2021-08-26 11:56:29 +0300205 !IS_ALIGNED(off, 4)) {
Konstantin Komarov43423062021-08-13 17:21:29 +0300206 return NULL;
207 }
208
Kari Argillandere8b8e972021-08-03 14:57:09 +0300209 /* Skip non-resident records. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300210 if (!is_rec_inuse(rec))
211 return NULL;
212
213 attr = Add2Ptr(rec, off);
214 } else {
Kari Argillandere8b8e972021-08-03 14:57:09 +0300215 /* Check if input attr inside record. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300216 off = PtrOffset(rec, attr);
217 if (off >= used)
218 return NULL;
219
220 asize = le32_to_cpu(attr->size);
221 if (asize < SIZEOF_RESIDENT) {
222 /* Impossible 'cause we should not return such attribute */
223 return NULL;
224 }
225
226 attr = Add2Ptr(attr, asize);
227 off += asize;
228 }
229
230 asize = le32_to_cpu(attr->size);
231
Kari Argillandere8b8e972021-08-03 14:57:09 +0300232 /* Can we use the first field (attr->type). */
Konstantin Komarov43423062021-08-13 17:21:29 +0300233 if (off + 8 > used) {
Kari Argillanderfa3cacf2021-08-26 11:56:29 +0300234 static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
Konstantin Komarov43423062021-08-13 17:21:29 +0300235 return NULL;
236 }
237
238 if (attr->type == ATTR_END) {
Kari Argillandere8b8e972021-08-03 14:57:09 +0300239 /* End of enumeration. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300240 return NULL;
241 }
242
Kari Argillandere8b8e972021-08-03 14:57:09 +0300243 /* 0x100 is last known attribute for now. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300244 t32 = le32_to_cpu(attr->type);
245 if ((t32 & 0xf) || (t32 > 0x100))
246 return NULL;
247
Kari Argillandere8b8e972021-08-03 14:57:09 +0300248 /* Check boundary. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300249 if (off + asize > used)
250 return NULL;
251
Kari Argillandere8b8e972021-08-03 14:57:09 +0300252 /* Check size of attribute. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300253 if (!attr->non_res) {
254 if (asize < SIZEOF_RESIDENT)
255 return NULL;
256
257 t16 = le16_to_cpu(attr->res.data_off);
258
259 if (t16 > asize)
260 return NULL;
261
262 t32 = le32_to_cpu(attr->res.data_size);
263 if (t16 + t32 > asize)
264 return NULL;
265
266 return attr;
267 }
268
Kari Argillandere8b8e972021-08-03 14:57:09 +0300269 /* Check some nonresident fields. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300270 if (attr->name_len &&
271 le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
272 le16_to_cpu(attr->nres.run_off)) {
273 return NULL;
274 }
275
276 if (attr->nres.svcn || !is_attr_ext(attr)) {
277 if (asize + 8 < SIZEOF_NONRESIDENT)
278 return NULL;
279
280 if (attr->nres.c_unit)
281 return NULL;
282 } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
283 return NULL;
284
285 return attr;
286}
287
288/*
Kari Argillandere8b8e972021-08-03 14:57:09 +0300289 * mi_find_attr - Find the attribute by type and name and id.
Konstantin Komarov43423062021-08-13 17:21:29 +0300290 */
291struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
292 enum ATTR_TYPE type, const __le16 *name,
293 size_t name_len, const __le16 *id)
294{
295 u32 type_in = le32_to_cpu(type);
296 u32 atype;
297
298next_attr:
299 attr = mi_enum_attr(mi, attr);
300 if (!attr)
301 return NULL;
302
303 atype = le32_to_cpu(attr->type);
304 if (atype > type_in)
305 return NULL;
306
307 if (atype < type_in)
308 goto next_attr;
309
310 if (attr->name_len != name_len)
311 goto next_attr;
312
313 if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
314 goto next_attr;
315
316 if (id && *id != attr->id)
317 goto next_attr;
318
319 return attr;
320}
321
322int mi_write(struct mft_inode *mi, int wait)
323{
324 struct MFT_REC *rec;
325 int err;
326 struct ntfs_sb_info *sbi;
327
328 if (!mi->dirty)
329 return 0;
330
331 sbi = mi->sbi;
332 rec = mi->mrec;
333
334 err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
335 if (err)
336 return err;
337
338 if (mi->rno < sbi->mft.recs_mirr)
339 sbi->flags |= NTFS_FLAGS_MFTMIRR;
340
341 mi->dirty = false;
342
343 return 0;
344}
345
346int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
347 __le16 flags, bool is_mft)
348{
349 int err;
350 u16 seq = 1;
351 struct MFT_REC *rec;
352 u64 vbo = (u64)rno << sbi->record_bits;
353
354 err = mi_init(mi, sbi, rno);
355 if (err)
356 return err;
357
358 rec = mi->mrec;
359
360 if (rno == MFT_REC_MFT) {
361 ;
362 } else if (rno < MFT_REC_FREE) {
363 seq = rno;
364 } else if (rno >= sbi->mft.used) {
365 ;
366 } else if (mi_read(mi, is_mft)) {
367 ;
368 } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
Kari Argillandere8b8e972021-08-03 14:57:09 +0300369 /* Record is reused. Update its sequence number. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300370 seq = le16_to_cpu(rec->seq) + 1;
371 if (!seq)
372 seq = 1;
373 }
374
375 memcpy(rec, sbi->new_rec, sbi->record_size);
376
377 rec->seq = cpu_to_le16(seq);
378 rec->flags = RECORD_FLAG_IN_USE | flags;
379
380 mi->dirty = true;
381
382 if (!mi->nb.nbufs) {
383 struct ntfs_inode *ni = sbi->mft.ni;
384 bool lock = false;
385
386 if (is_mounted(sbi) && !is_mft) {
387 down_read(&ni->file.run_lock);
388 lock = true;
389 }
390
391 err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
392 &mi->nb);
393 if (lock)
394 up_read(&ni->file.run_lock);
395 }
396
397 return err;
398}
399
400/*
Kari Argillandere8b8e972021-08-03 14:57:09 +0300401 * mi_mark_free - Mark record as unused and marks it as free in bitmap.
Konstantin Komarov43423062021-08-13 17:21:29 +0300402 */
403void mi_mark_free(struct mft_inode *mi)
404{
405 CLST rno = mi->rno;
406 struct ntfs_sb_info *sbi = mi->sbi;
407
408 if (rno >= MFT_REC_RESERVED && rno < MFT_REC_FREE) {
409 ntfs_clear_mft_tail(sbi, rno, rno + 1);
410 mi->dirty = false;
411 return;
412 }
413
414 if (mi->mrec) {
415 clear_rec_inuse(mi->mrec);
416 mi->dirty = true;
417 mi_write(mi, 0);
418 }
419 ntfs_mark_rec_free(sbi, rno);
420}
421
422/*
Kari Argillandere8b8e972021-08-03 14:57:09 +0300423 * mi_insert_attr - Reserve space for new attribute.
Konstantin Komarov43423062021-08-13 17:21:29 +0300424 *
Kari Argillandere8b8e972021-08-03 14:57:09 +0300425 * Return: Not full constructed attribute or NULL if not possible to create.
Konstantin Komarov43423062021-08-13 17:21:29 +0300426 */
427struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
428 const __le16 *name, u8 name_len, u32 asize,
429 u16 name_off)
430{
431 size_t tail;
432 struct ATTRIB *attr;
433 __le16 id;
434 struct MFT_REC *rec = mi->mrec;
435 struct ntfs_sb_info *sbi = mi->sbi;
436 u32 used = le32_to_cpu(rec->used);
437 const u16 *upcase = sbi->upcase;
438 int diff;
439
440 /* Can we insert mi attribute? */
441 if (used + asize > mi->sbi->record_size)
442 return NULL;
443
444 /*
445 * Scan through the list of attributes to find the point
446 * at which we should insert it.
447 */
448 attr = NULL;
449 while ((attr = mi_enum_attr(mi, attr))) {
450 diff = compare_attr(attr, type, name, name_len, upcase);
451 if (diff > 0)
452 break;
453 if (diff < 0)
454 continue;
455
456 if (!is_attr_indexed(attr))
457 return NULL;
458 break;
459 }
460
461 if (!attr) {
Kari Argillandere8b8e972021-08-03 14:57:09 +0300462 tail = 8; /* Not used, just to suppress warning. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300463 attr = Add2Ptr(rec, used - 8);
464 } else {
465 tail = used - PtrOffset(rec, attr);
466 }
467
468 id = mi_new_attt_id(mi);
469
470 memmove(Add2Ptr(attr, asize), attr, tail);
471 memset(attr, 0, asize);
472
473 attr->type = type;
474 attr->size = cpu_to_le32(asize);
475 attr->name_len = name_len;
476 attr->name_off = cpu_to_le16(name_off);
477 attr->id = id;
478
479 memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
480 rec->used = cpu_to_le32(used + asize);
481
482 mi->dirty = true;
483
484 return attr;
485}
486
487/*
Kari Argillandere8b8e972021-08-03 14:57:09 +0300488 * mi_remove_attr - Remove the attribute from record.
Konstantin Komarov43423062021-08-13 17:21:29 +0300489 *
Kari Argillandere8b8e972021-08-03 14:57:09 +0300490 * NOTE: The source attr will point to next attribute.
Konstantin Komarov43423062021-08-13 17:21:29 +0300491 */
492bool mi_remove_attr(struct mft_inode *mi, struct ATTRIB *attr)
493{
494 struct MFT_REC *rec = mi->mrec;
495 u32 aoff = PtrOffset(rec, attr);
496 u32 used = le32_to_cpu(rec->used);
497 u32 asize = le32_to_cpu(attr->size);
498
499 if (aoff + asize > used)
500 return false;
501
502 used -= asize;
503 memmove(attr, Add2Ptr(attr, asize), used - aoff);
504 rec->used = cpu_to_le32(used);
505 mi->dirty = true;
506
507 return true;
508}
509
510/* bytes = "new attribute size" - "old attribute size" */
511bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
512{
513 struct MFT_REC *rec = mi->mrec;
514 u32 aoff = PtrOffset(rec, attr);
515 u32 total, used = le32_to_cpu(rec->used);
516 u32 nsize, asize = le32_to_cpu(attr->size);
517 u32 rsize = le32_to_cpu(attr->res.data_size);
518 int tail = (int)(used - aoff - asize);
519 int dsize;
520 char *next;
521
522 if (tail < 0 || aoff >= used)
523 return false;
524
525 if (!bytes)
526 return true;
527
528 total = le32_to_cpu(rec->total);
529 next = Add2Ptr(attr, asize);
530
531 if (bytes > 0) {
Kari Argillanderfa3cacf2021-08-26 11:56:29 +0300532 dsize = ALIGN(bytes, 8);
Konstantin Komarov43423062021-08-13 17:21:29 +0300533 if (used + dsize > total)
534 return false;
535 nsize = asize + dsize;
Kari Argillandere8b8e972021-08-03 14:57:09 +0300536 /* Move tail */
Konstantin Komarov43423062021-08-13 17:21:29 +0300537 memmove(next + dsize, next, tail);
538 memset(next, 0, dsize);
539 used += dsize;
540 rsize += dsize;
541 } else {
Kari Argillanderfa3cacf2021-08-26 11:56:29 +0300542 dsize = ALIGN(-bytes, 8);
Konstantin Komarov43423062021-08-13 17:21:29 +0300543 if (dsize > asize)
544 return false;
545 nsize = asize - dsize;
546 memmove(next - dsize, next, tail);
547 used -= dsize;
548 rsize -= dsize;
549 }
550
551 rec->used = cpu_to_le32(used);
552 attr->size = cpu_to_le32(nsize);
553 if (!attr->non_res)
554 attr->res.data_size = cpu_to_le32(rsize);
555 mi->dirty = true;
556
557 return true;
558}
559
560int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
561 struct runs_tree *run, CLST len)
562{
563 int err = 0;
564 struct ntfs_sb_info *sbi = mi->sbi;
565 u32 new_run_size;
566 CLST plen;
567 struct MFT_REC *rec = mi->mrec;
568 CLST svcn = le64_to_cpu(attr->nres.svcn);
569 u32 used = le32_to_cpu(rec->used);
570 u32 aoff = PtrOffset(rec, attr);
571 u32 asize = le32_to_cpu(attr->size);
572 char *next = Add2Ptr(attr, asize);
573 u16 run_off = le16_to_cpu(attr->nres.run_off);
574 u32 run_size = asize - run_off;
575 u32 tail = used - aoff - asize;
576 u32 dsize = sbi->record_size - used;
577
Kari Argillandere8b8e972021-08-03 14:57:09 +0300578 /* Make a maximum gap in current record. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300579 memmove(next + dsize, next, tail);
580
Kari Argillandere8b8e972021-08-03 14:57:09 +0300581 /* Pack as much as possible. */
Konstantin Komarov43423062021-08-13 17:21:29 +0300582 err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
583 &plen);
584 if (err < 0) {
585 memmove(next, next + dsize, tail);
586 return err;
587 }
588
Kari Argillanderfa3cacf2021-08-26 11:56:29 +0300589 new_run_size = ALIGN(err, 8);
Konstantin Komarov43423062021-08-13 17:21:29 +0300590
591 memmove(next + new_run_size - run_size, next + dsize, tail);
592
593 attr->size = cpu_to_le32(asize + new_run_size - run_size);
594 attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
595 rec->used = cpu_to_le32(used + new_run_size - run_size);
596 mi->dirty = true;
597
598 return 0;
599}