Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *
0004  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
0005  *
0006  */
0007 
0008 #include <linux/fs.h>
0009 
0010 #include "debug.h"
0011 #include "ntfs.h"
0012 #include "ntfs_fs.h"
0013 
0014 static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
0015                    const __le16 *name, u8 name_len,
0016                    const u16 *upcase)
0017 {
0018     /* First, compare the type codes. */
0019     int diff = le32_to_cpu(left->type) - le32_to_cpu(type);
0020 
0021     if (diff)
0022         return diff;
0023 
0024     /* They have the same type code, so we have to compare the names. */
0025     return ntfs_cmp_names(attr_name(left), left->name_len, name, name_len,
0026                   upcase, true);
0027 }
0028 
0029 /*
0030  * mi_new_attt_id
0031  *
0032  * Return: Unused attribute id that is less than mrec->next_attr_id.
0033  */
0034 static __le16 mi_new_attt_id(struct mft_inode *mi)
0035 {
0036     u16 free_id, max_id, t16;
0037     struct MFT_REC *rec = mi->mrec;
0038     struct ATTRIB *attr;
0039     __le16 id;
0040 
0041     id = rec->next_attr_id;
0042     free_id = le16_to_cpu(id);
0043     if (free_id < 0x7FFF) {
0044         rec->next_attr_id = cpu_to_le16(free_id + 1);
0045         return id;
0046     }
0047 
0048     /* One record can store up to 1024/24 ~= 42 attributes. */
0049     free_id = 0;
0050     max_id = 0;
0051 
0052     attr = NULL;
0053 
0054     for (;;) {
0055         attr = mi_enum_attr(mi, attr);
0056         if (!attr) {
0057             rec->next_attr_id = cpu_to_le16(max_id + 1);
0058             mi->dirty = true;
0059             return cpu_to_le16(free_id);
0060         }
0061 
0062         t16 = le16_to_cpu(attr->id);
0063         if (t16 == free_id) {
0064             free_id += 1;
0065             attr = NULL;
0066         } else if (max_id < t16)
0067             max_id = t16;
0068     }
0069 }
0070 
0071 int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi)
0072 {
0073     int err;
0074     struct mft_inode *m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
0075 
0076     if (!m)
0077         return -ENOMEM;
0078 
0079     err = mi_init(m, sbi, rno);
0080     if (err) {
0081         kfree(m);
0082         return err;
0083     }
0084 
0085     err = mi_read(m, false);
0086     if (err) {
0087         mi_put(m);
0088         return err;
0089     }
0090 
0091     *mi = m;
0092     return 0;
0093 }
0094 
0095 void mi_put(struct mft_inode *mi)
0096 {
0097     mi_clear(mi);
0098     kfree(mi);
0099 }
0100 
0101 int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno)
0102 {
0103     mi->sbi = sbi;
0104     mi->rno = rno;
0105     mi->mrec = kmalloc(sbi->record_size, GFP_NOFS);
0106     if (!mi->mrec)
0107         return -ENOMEM;
0108 
0109     return 0;
0110 }
0111 
0112 /*
0113  * mi_read - Read MFT data.
0114  */
0115 int mi_read(struct mft_inode *mi, bool is_mft)
0116 {
0117     int err;
0118     struct MFT_REC *rec = mi->mrec;
0119     struct ntfs_sb_info *sbi = mi->sbi;
0120     u32 bpr = sbi->record_size;
0121     u64 vbo = (u64)mi->rno << sbi->record_bits;
0122     struct ntfs_inode *mft_ni = sbi->mft.ni;
0123     struct runs_tree *run = mft_ni ? &mft_ni->file.run : NULL;
0124     struct rw_semaphore *rw_lock = NULL;
0125 
0126     if (is_mounted(sbi)) {
0127         if (!is_mft) {
0128             rw_lock = &mft_ni->file.run_lock;
0129             down_read(rw_lock);
0130         }
0131     }
0132 
0133     err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
0134     if (rw_lock)
0135         up_read(rw_lock);
0136     if (!err)
0137         goto ok;
0138 
0139     if (err == -E_NTFS_FIXUP) {
0140         mi->dirty = true;
0141         goto ok;
0142     }
0143 
0144     if (err != -ENOENT)
0145         goto out;
0146 
0147     if (rw_lock) {
0148         ni_lock(mft_ni);
0149         down_write(rw_lock);
0150     }
0151     err = attr_load_runs_vcn(mft_ni, ATTR_DATA, NULL, 0, &mft_ni->file.run,
0152                  vbo >> sbi->cluster_bits);
0153     if (rw_lock) {
0154         up_write(rw_lock);
0155         ni_unlock(mft_ni);
0156     }
0157     if (err)
0158         goto out;
0159 
0160     if (rw_lock)
0161         down_read(rw_lock);
0162     err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
0163     if (rw_lock)
0164         up_read(rw_lock);
0165 
0166     if (err == -E_NTFS_FIXUP) {
0167         mi->dirty = true;
0168         goto ok;
0169     }
0170     if (err)
0171         goto out;
0172 
0173 ok:
0174     /* Check field 'total' only here. */
0175     if (le32_to_cpu(rec->total) != bpr) {
0176         err = -EINVAL;
0177         goto out;
0178     }
0179 
0180     return 0;
0181 
0182 out:
0183     return err;
0184 }
0185 
0186 struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
0187 {
0188     const struct MFT_REC *rec = mi->mrec;
0189     u32 used = le32_to_cpu(rec->used);
0190     u32 t32, off, asize;
0191     u16 t16;
0192 
0193     if (!attr) {
0194         u32 total = le32_to_cpu(rec->total);
0195 
0196         off = le16_to_cpu(rec->attr_off);
0197 
0198         if (used > total)
0199             return NULL;
0200 
0201         if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
0202             !IS_ALIGNED(off, 4)) {
0203             return NULL;
0204         }
0205 
0206         /* Skip non-resident records. */
0207         if (!is_rec_inuse(rec))
0208             return NULL;
0209 
0210         attr = Add2Ptr(rec, off);
0211     } else {
0212         /* Check if input attr inside record. */
0213         off = PtrOffset(rec, attr);
0214         if (off >= used)
0215             return NULL;
0216 
0217         asize = le32_to_cpu(attr->size);
0218         if (asize < SIZEOF_RESIDENT) {
0219             /* Impossible 'cause we should not return such attribute. */
0220             return NULL;
0221         }
0222 
0223         attr = Add2Ptr(attr, asize);
0224         off += asize;
0225     }
0226 
0227     asize = le32_to_cpu(attr->size);
0228 
0229     /* Can we use the first field (attr->type). */
0230     if (off + 8 > used) {
0231         static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
0232         return NULL;
0233     }
0234 
0235     if (attr->type == ATTR_END) {
0236         /* End of enumeration. */
0237         return NULL;
0238     }
0239 
0240     /* 0x100 is last known attribute for now. */
0241     t32 = le32_to_cpu(attr->type);
0242     if ((t32 & 0xf) || (t32 > 0x100))
0243         return NULL;
0244 
0245     /* Check boundary. */
0246     if (off + asize > used)
0247         return NULL;
0248 
0249     /* Check size of attribute. */
0250     if (!attr->non_res) {
0251         if (asize < SIZEOF_RESIDENT)
0252             return NULL;
0253 
0254         t16 = le16_to_cpu(attr->res.data_off);
0255 
0256         if (t16 > asize)
0257             return NULL;
0258 
0259         t32 = le32_to_cpu(attr->res.data_size);
0260         if (t16 + t32 > asize)
0261             return NULL;
0262 
0263         return attr;
0264     }
0265 
0266     /* Check some nonresident fields. */
0267     if (attr->name_len &&
0268         le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
0269             le16_to_cpu(attr->nres.run_off)) {
0270         return NULL;
0271     }
0272 
0273     if (attr->nres.svcn || !is_attr_ext(attr)) {
0274         if (asize + 8 < SIZEOF_NONRESIDENT)
0275             return NULL;
0276 
0277         if (attr->nres.c_unit)
0278             return NULL;
0279     } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
0280         return NULL;
0281 
0282     return attr;
0283 }
0284 
0285 /*
0286  * mi_find_attr - Find the attribute by type and name and id.
0287  */
0288 struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
0289                 enum ATTR_TYPE type, const __le16 *name,
0290                 size_t name_len, const __le16 *id)
0291 {
0292     u32 type_in = le32_to_cpu(type);
0293     u32 atype;
0294 
0295 next_attr:
0296     attr = mi_enum_attr(mi, attr);
0297     if (!attr)
0298         return NULL;
0299 
0300     atype = le32_to_cpu(attr->type);
0301     if (atype > type_in)
0302         return NULL;
0303 
0304     if (atype < type_in)
0305         goto next_attr;
0306 
0307     if (attr->name_len != name_len)
0308         goto next_attr;
0309 
0310     if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
0311         goto next_attr;
0312 
0313     if (id && *id != attr->id)
0314         goto next_attr;
0315 
0316     return attr;
0317 }
0318 
0319 int mi_write(struct mft_inode *mi, int wait)
0320 {
0321     struct MFT_REC *rec;
0322     int err;
0323     struct ntfs_sb_info *sbi;
0324 
0325     if (!mi->dirty)
0326         return 0;
0327 
0328     sbi = mi->sbi;
0329     rec = mi->mrec;
0330 
0331     err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
0332     if (err)
0333         return err;
0334 
0335     if (mi->rno < sbi->mft.recs_mirr)
0336         sbi->flags |= NTFS_FLAGS_MFTMIRR;
0337 
0338     mi->dirty = false;
0339 
0340     return 0;
0341 }
0342 
0343 int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
0344           __le16 flags, bool is_mft)
0345 {
0346     int err;
0347     u16 seq = 1;
0348     struct MFT_REC *rec;
0349     u64 vbo = (u64)rno << sbi->record_bits;
0350 
0351     err = mi_init(mi, sbi, rno);
0352     if (err)
0353         return err;
0354 
0355     rec = mi->mrec;
0356 
0357     if (rno == MFT_REC_MFT) {
0358         ;
0359     } else if (rno < MFT_REC_FREE) {
0360         seq = rno;
0361     } else if (rno >= sbi->mft.used) {
0362         ;
0363     } else if (mi_read(mi, is_mft)) {
0364         ;
0365     } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
0366         /* Record is reused. Update its sequence number. */
0367         seq = le16_to_cpu(rec->seq) + 1;
0368         if (!seq)
0369             seq = 1;
0370     }
0371 
0372     memcpy(rec, sbi->new_rec, sbi->record_size);
0373 
0374     rec->seq = cpu_to_le16(seq);
0375     rec->flags = RECORD_FLAG_IN_USE | flags;
0376 
0377     mi->dirty = true;
0378 
0379     if (!mi->nb.nbufs) {
0380         struct ntfs_inode *ni = sbi->mft.ni;
0381         bool lock = false;
0382 
0383         if (is_mounted(sbi) && !is_mft) {
0384             down_read(&ni->file.run_lock);
0385             lock = true;
0386         }
0387 
0388         err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
0389                   &mi->nb);
0390         if (lock)
0391             up_read(&ni->file.run_lock);
0392     }
0393 
0394     return err;
0395 }
0396 
0397 /*
0398  * mi_insert_attr - Reserve space for new attribute.
0399  *
0400  * Return: Not full constructed attribute or NULL if not possible to create.
0401  */
0402 struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
0403                   const __le16 *name, u8 name_len, u32 asize,
0404                   u16 name_off)
0405 {
0406     size_t tail;
0407     struct ATTRIB *attr;
0408     __le16 id;
0409     struct MFT_REC *rec = mi->mrec;
0410     struct ntfs_sb_info *sbi = mi->sbi;
0411     u32 used = le32_to_cpu(rec->used);
0412     const u16 *upcase = sbi->upcase;
0413     int diff;
0414 
0415     /* Can we insert mi attribute? */
0416     if (used + asize > mi->sbi->record_size)
0417         return NULL;
0418 
0419     /*
0420      * Scan through the list of attributes to find the point
0421      * at which we should insert it.
0422      */
0423     attr = NULL;
0424     while ((attr = mi_enum_attr(mi, attr))) {
0425         diff = compare_attr(attr, type, name, name_len, upcase);
0426 
0427         if (diff < 0)
0428             continue;
0429 
0430         if (!diff && !is_attr_indexed(attr))
0431             return NULL;
0432         break;
0433     }
0434 
0435     if (!attr) {
0436         tail = 8; /* Not used, just to suppress warning. */
0437         attr = Add2Ptr(rec, used - 8);
0438     } else {
0439         tail = used - PtrOffset(rec, attr);
0440     }
0441 
0442     id = mi_new_attt_id(mi);
0443 
0444     memmove(Add2Ptr(attr, asize), attr, tail);
0445     memset(attr, 0, asize);
0446 
0447     attr->type = type;
0448     attr->size = cpu_to_le32(asize);
0449     attr->name_len = name_len;
0450     attr->name_off = cpu_to_le16(name_off);
0451     attr->id = id;
0452 
0453     memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
0454     rec->used = cpu_to_le32(used + asize);
0455 
0456     mi->dirty = true;
0457 
0458     return attr;
0459 }
0460 
0461 /*
0462  * mi_remove_attr - Remove the attribute from record.
0463  *
0464  * NOTE: The source attr will point to next attribute.
0465  */
0466 bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
0467             struct ATTRIB *attr)
0468 {
0469     struct MFT_REC *rec = mi->mrec;
0470     u32 aoff = PtrOffset(rec, attr);
0471     u32 used = le32_to_cpu(rec->used);
0472     u32 asize = le32_to_cpu(attr->size);
0473 
0474     if (aoff + asize > used)
0475         return false;
0476 
0477     if (ni && is_attr_indexed(attr)) {
0478         le16_add_cpu(&ni->mi.mrec->hard_links, -1);
0479         ni->mi.dirty = true;
0480     }
0481 
0482     used -= asize;
0483     memmove(attr, Add2Ptr(attr, asize), used - aoff);
0484     rec->used = cpu_to_le32(used);
0485     mi->dirty = true;
0486 
0487     return true;
0488 }
0489 
0490 /* bytes = "new attribute size" - "old attribute size" */
0491 bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
0492 {
0493     struct MFT_REC *rec = mi->mrec;
0494     u32 aoff = PtrOffset(rec, attr);
0495     u32 total, used = le32_to_cpu(rec->used);
0496     u32 nsize, asize = le32_to_cpu(attr->size);
0497     u32 rsize = le32_to_cpu(attr->res.data_size);
0498     int tail = (int)(used - aoff - asize);
0499     int dsize;
0500     char *next;
0501 
0502     if (tail < 0 || aoff >= used)
0503         return false;
0504 
0505     if (!bytes)
0506         return true;
0507 
0508     total = le32_to_cpu(rec->total);
0509     next = Add2Ptr(attr, asize);
0510 
0511     if (bytes > 0) {
0512         dsize = ALIGN(bytes, 8);
0513         if (used + dsize > total)
0514             return false;
0515         nsize = asize + dsize;
0516         /* Move tail */
0517         memmove(next + dsize, next, tail);
0518         memset(next, 0, dsize);
0519         used += dsize;
0520         rsize += dsize;
0521     } else {
0522         dsize = ALIGN(-bytes, 8);
0523         if (dsize > asize)
0524             return false;
0525         nsize = asize - dsize;
0526         memmove(next - dsize, next, tail);
0527         used -= dsize;
0528         rsize -= dsize;
0529     }
0530 
0531     rec->used = cpu_to_le32(used);
0532     attr->size = cpu_to_le32(nsize);
0533     if (!attr->non_res)
0534         attr->res.data_size = cpu_to_le32(rsize);
0535     mi->dirty = true;
0536 
0537     return true;
0538 }
0539 
0540 int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
0541          struct runs_tree *run, CLST len)
0542 {
0543     int err = 0;
0544     struct ntfs_sb_info *sbi = mi->sbi;
0545     u32 new_run_size;
0546     CLST plen;
0547     struct MFT_REC *rec = mi->mrec;
0548     CLST svcn = le64_to_cpu(attr->nres.svcn);
0549     u32 used = le32_to_cpu(rec->used);
0550     u32 aoff = PtrOffset(rec, attr);
0551     u32 asize = le32_to_cpu(attr->size);
0552     char *next = Add2Ptr(attr, asize);
0553     u16 run_off = le16_to_cpu(attr->nres.run_off);
0554     u32 run_size = asize - run_off;
0555     u32 tail = used - aoff - asize;
0556     u32 dsize = sbi->record_size - used;
0557 
0558     /* Make a maximum gap in current record. */
0559     memmove(next + dsize, next, tail);
0560 
0561     /* Pack as much as possible. */
0562     err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
0563                &plen);
0564     if (err < 0) {
0565         memmove(next, next + dsize, tail);
0566         return err;
0567     }
0568 
0569     new_run_size = ALIGN(err, 8);
0570 
0571     memmove(next + new_run_size - run_size, next + dsize, tail);
0572 
0573     attr->size = cpu_to_le32(asize + new_run_size - run_size);
0574     attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
0575     rec->used = cpu_to_le32(used + new_run_size - run_size);
0576     mi->dirty = true;
0577 
0578     return 0;
0579 }