mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 11:47:47 +00:00
Merge branch 'master' of https://github.com/Paragon-Software-Group/linux-ntfs3.git
This commit is contained in:
commit
df38b2e678
@ -787,7 +787,8 @@ pack_runs:
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
|
||||
attr = mi_find_attr(ni, mi, NULL, type, name, name_len,
|
||||
&le->id);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
goto bad_inode;
|
||||
@ -1181,7 +1182,7 @@ repack:
|
||||
goto out;
|
||||
}
|
||||
|
||||
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, &le->id);
|
||||
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0, &le->id);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1406,7 +1407,7 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
*/
|
||||
if (!attr->non_res) {
|
||||
if (vbo[1] + bytes_per_off > le32_to_cpu(attr->res.data_size)) {
|
||||
ntfs_inode_err(&ni->vfs_inode, "is corrupted");
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return -EINVAL;
|
||||
}
|
||||
addr = resident_data(attr);
|
||||
@ -1796,7 +1797,7 @@ repack:
|
||||
goto out;
|
||||
}
|
||||
|
||||
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0,
|
||||
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0,
|
||||
&le->id);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
@ -2041,8 +2042,8 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
|
||||
}
|
||||
|
||||
/* Look for required attribute. */
|
||||
attr = mi_find_attr(mi, NULL, ATTR_DATA, NULL,
|
||||
0, &le->id);
|
||||
attr = mi_find_attr(ni, mi, NULL, ATTR_DATA,
|
||||
NULL, 0, &le->id);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -2587,7 +2588,7 @@ int attr_force_nonresident(struct ntfs_inode *ni)
|
||||
|
||||
attr = ni_find_attr(ni, NULL, &le, ATTR_DATA, NULL, 0, NULL, &mi);
|
||||
if (!attr) {
|
||||
ntfs_bad_inode(&ni->vfs_inode, "no data attribute");
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -512,7 +512,7 @@ out:
|
||||
ctx->pos = pos;
|
||||
} else if (err < 0) {
|
||||
if (err == -EINVAL)
|
||||
ntfs_inode_err(dir, "directory corrupted");
|
||||
_ntfs_bad_inode(dir);
|
||||
ctx->pos = eod;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ struct ATTR_STD_INFO *ni_std(struct ntfs_inode *ni)
|
||||
{
|
||||
const struct ATTRIB *attr;
|
||||
|
||||
attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
|
||||
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
|
||||
return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO)) :
|
||||
NULL;
|
||||
}
|
||||
@ -89,7 +89,7 @@ struct ATTR_STD_INFO5 *ni_std5(struct ntfs_inode *ni)
|
||||
{
|
||||
const struct ATTRIB *attr;
|
||||
|
||||
attr = mi_find_attr(&ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
|
||||
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_STD, NULL, 0, NULL);
|
||||
|
||||
return attr ? resident_data_ex(attr, sizeof(struct ATTR_STD_INFO5)) :
|
||||
NULL;
|
||||
@ -148,8 +148,10 @@ int ni_load_mi_ex(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi)
|
||||
goto out;
|
||||
|
||||
err = mi_get(ni->mi.sbi, rno, &r);
|
||||
if (err)
|
||||
if (err) {
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return err;
|
||||
}
|
||||
|
||||
ni_add_mi(ni, r);
|
||||
|
||||
@ -201,7 +203,8 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
*mi = &ni->mi;
|
||||
|
||||
/* Look for required attribute in primary record. */
|
||||
return mi_find_attr(&ni->mi, attr, type, name, name_len, NULL);
|
||||
return mi_find_attr(ni, &ni->mi, attr, type, name, name_len,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* First look for list entry of required type. */
|
||||
@ -217,7 +220,7 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
return NULL;
|
||||
|
||||
/* Look for required attribute. */
|
||||
attr = mi_find_attr(m, NULL, type, name, name_len, &le->id);
|
||||
attr = mi_find_attr(ni, m, NULL, type, name, name_len, &le->id);
|
||||
|
||||
if (!attr)
|
||||
goto out;
|
||||
@ -238,8 +241,7 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
return attr;
|
||||
|
||||
out:
|
||||
ntfs_inode_err(&ni->vfs_inode, "failed to parse mft record");
|
||||
ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -259,7 +261,7 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
if (mi)
|
||||
*mi = &ni->mi;
|
||||
/* Enum attributes in primary record. */
|
||||
return mi_enum_attr(&ni->mi, attr);
|
||||
return mi_enum_attr(ni, &ni->mi, attr);
|
||||
}
|
||||
|
||||
/* Get next list entry. */
|
||||
@ -275,7 +277,7 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
|
||||
*mi = mi2;
|
||||
|
||||
/* Find attribute in loaded record. */
|
||||
return rec_find_attr_le(mi2, le2);
|
||||
return rec_find_attr_le(ni, mi2, le2);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -293,7 +295,8 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
if (!ni->attr_list.size) {
|
||||
if (pmi)
|
||||
*pmi = &ni->mi;
|
||||
return mi_find_attr(&ni->mi, NULL, type, name, name_len, NULL);
|
||||
return mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
|
||||
NULL);
|
||||
}
|
||||
|
||||
le = al_find_ex(ni, NULL, type, name, name_len, NULL);
|
||||
@ -319,7 +322,7 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
if (pmi)
|
||||
*pmi = mi;
|
||||
|
||||
attr = mi_find_attr(mi, NULL, type, name, name_len, &le->id);
|
||||
attr = mi_find_attr(ni, mi, NULL, type, name, name_len, &le->id);
|
||||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
@ -330,6 +333,7 @@ struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
vcn <= le64_to_cpu(attr->nres.evcn))
|
||||
return attr;
|
||||
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -398,7 +402,8 @@ int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
int diff;
|
||||
|
||||
if (base_only || type == ATTR_LIST || !ni->attr_list.size) {
|
||||
attr = mi_find_attr(&ni->mi, NULL, type, name, name_len, id);
|
||||
attr = mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
|
||||
id);
|
||||
if (!attr)
|
||||
return -ENOENT;
|
||||
|
||||
@ -437,7 +442,7 @@ next_le2:
|
||||
|
||||
al_remove_le(ni, le);
|
||||
|
||||
attr = mi_find_attr(mi, NULL, type, name, name_len, id);
|
||||
attr = mi_find_attr(ni, mi, NULL, type, name, name_len, id);
|
||||
if (!attr)
|
||||
return -ENOENT;
|
||||
|
||||
@ -485,7 +490,7 @@ ni_ins_new_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
name = le->name;
|
||||
}
|
||||
|
||||
attr = mi_insert_attr(mi, type, name, name_len, asize, name_off);
|
||||
attr = mi_insert_attr(ni, mi, type, name, name_len, asize, name_off);
|
||||
if (!attr) {
|
||||
if (le_added)
|
||||
al_remove_le(ni, le);
|
||||
@ -673,7 +678,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
attr_list = mi_find_attr(&ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
|
||||
attr_list = mi_find_attr(ni, &ni->mi, NULL, ATTR_LIST, NULL, 0, NULL);
|
||||
if (!attr_list)
|
||||
return 0;
|
||||
|
||||
@ -695,7 +700,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
||||
if (!mi)
|
||||
return 0;
|
||||
|
||||
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
|
||||
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
|
||||
le->name_len, &le->id);
|
||||
if (!attr)
|
||||
return 0;
|
||||
@ -731,7 +736,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
||||
goto out;
|
||||
}
|
||||
|
||||
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
|
||||
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
|
||||
le->name_len, &le->id);
|
||||
if (!attr) {
|
||||
/* Should never happened, 'cause already checked. */
|
||||
@ -740,7 +745,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
||||
asize = le32_to_cpu(attr->size);
|
||||
|
||||
/* Insert into primary record. */
|
||||
attr_ins = mi_insert_attr(&ni->mi, le->type, le_name(le),
|
||||
attr_ins = mi_insert_attr(ni, &ni->mi, le->type, le_name(le),
|
||||
le->name_len, asize,
|
||||
le16_to_cpu(attr->name_off));
|
||||
if (!attr_ins) {
|
||||
@ -768,7 +773,7 @@ static int ni_try_remove_attr_list(struct ntfs_inode *ni)
|
||||
if (!mi)
|
||||
continue;
|
||||
|
||||
attr = mi_find_attr(mi, NULL, le->type, le_name(le),
|
||||
attr = mi_find_attr(ni, mi, NULL, le->type, le_name(le),
|
||||
le->name_len, &le->id);
|
||||
if (!attr)
|
||||
continue;
|
||||
@ -831,7 +836,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
|
||||
free_b = 0;
|
||||
attr = NULL;
|
||||
|
||||
for (; (attr = mi_enum_attr(&ni->mi, attr)); le = Add2Ptr(le, sz)) {
|
||||
for (; (attr = mi_enum_attr(ni, &ni->mi, attr)); le = Add2Ptr(le, sz)) {
|
||||
sz = le_size(attr->name_len);
|
||||
le->type = attr->type;
|
||||
le->size = cpu_to_le16(sz);
|
||||
@ -886,7 +891,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
|
||||
u32 asize = le32_to_cpu(b->size);
|
||||
u16 name_off = le16_to_cpu(b->name_off);
|
||||
|
||||
attr = mi_insert_attr(mi, b->type, Add2Ptr(b, name_off),
|
||||
attr = mi_insert_attr(ni, mi, b->type, Add2Ptr(b, name_off),
|
||||
b->name_len, asize, name_off);
|
||||
if (!attr)
|
||||
goto out;
|
||||
@ -909,7 +914,7 @@ int ni_create_attr_list(struct ntfs_inode *ni)
|
||||
goto out;
|
||||
}
|
||||
|
||||
attr = mi_insert_attr(&ni->mi, ATTR_LIST, NULL, 0,
|
||||
attr = mi_insert_attr(ni, &ni->mi, ATTR_LIST, NULL, 0,
|
||||
lsize + SIZEOF_RESIDENT, SIZEOF_RESIDENT);
|
||||
if (!attr)
|
||||
goto out;
|
||||
@ -993,13 +998,13 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
||||
mi = rb_entry(node, struct mft_inode, node);
|
||||
|
||||
if (is_mft_data &&
|
||||
(mi_enum_attr(mi, NULL) ||
|
||||
(mi_enum_attr(ni, mi, NULL) ||
|
||||
vbo <= ((u64)mi->rno << sbi->record_bits))) {
|
||||
/* We can't accept this record 'cause MFT's bootstrapping. */
|
||||
continue;
|
||||
}
|
||||
if (is_mft &&
|
||||
mi_find_attr(mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
|
||||
mi_find_attr(ni, mi, NULL, ATTR_DATA, NULL, 0, NULL)) {
|
||||
/*
|
||||
* This child record already has a ATTR_DATA.
|
||||
* So it can't accept any other records.
|
||||
@ -1008,7 +1013,7 @@ static int ni_ins_attr_ext(struct ntfs_inode *ni, struct ATTR_LIST_ENTRY *le,
|
||||
}
|
||||
|
||||
if ((type != ATTR_NAME || name_len) &&
|
||||
mi_find_attr(mi, NULL, type, name, name_len, NULL)) {
|
||||
mi_find_attr(ni, mi, NULL, type, name, name_len, NULL)) {
|
||||
/* Only indexed attributes can share same record. */
|
||||
continue;
|
||||
}
|
||||
@ -1157,7 +1162,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
/* Estimate the result of moving all possible attributes away. */
|
||||
attr = NULL;
|
||||
|
||||
while ((attr = mi_enum_attr(&ni->mi, attr))) {
|
||||
while ((attr = mi_enum_attr(ni, &ni->mi, attr))) {
|
||||
if (attr->type == ATTR_STD)
|
||||
continue;
|
||||
if (attr->type == ATTR_LIST)
|
||||
@ -1175,7 +1180,7 @@ static int ni_insert_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
|
||||
attr = NULL;
|
||||
|
||||
for (;;) {
|
||||
attr = mi_enum_attr(&ni->mi, attr);
|
||||
attr = mi_enum_attr(ni, &ni->mi, attr);
|
||||
if (!attr) {
|
||||
/* We should never be here 'cause we have already check this case. */
|
||||
err = -EINVAL;
|
||||
@ -1259,7 +1264,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni)
|
||||
for (node = rb_first(&ni->mi_tree); node; node = rb_next(node)) {
|
||||
mi = rb_entry(node, struct mft_inode, node);
|
||||
|
||||
attr = mi_enum_attr(mi, NULL);
|
||||
attr = mi_enum_attr(ni, mi, NULL);
|
||||
|
||||
if (!attr) {
|
||||
mft_min = mi->rno;
|
||||
@ -1280,7 +1285,7 @@ static int ni_expand_mft_list(struct ntfs_inode *ni)
|
||||
ni_remove_mi(ni, mi_new);
|
||||
}
|
||||
|
||||
attr = mi_find_attr(&ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
|
||||
attr = mi_find_attr(ni, &ni->mi, NULL, ATTR_DATA, NULL, 0, NULL);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1397,7 +1402,7 @@ int ni_expand_list(struct ntfs_inode *ni)
|
||||
continue;
|
||||
|
||||
/* Find attribute in primary record. */
|
||||
attr = rec_find_attr_le(&ni->mi, le);
|
||||
attr = rec_find_attr_le(ni, &ni->mi, le);
|
||||
if (!attr) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1604,8 +1609,8 @@ int ni_delete_all(struct ntfs_inode *ni)
|
||||
roff = le16_to_cpu(attr->nres.run_off);
|
||||
|
||||
if (roff > asize) {
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return -EINVAL;
|
||||
/* ni_enum_attr_ex checks this case. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* run==1 means unpack and deallocate. */
|
||||
@ -2726,9 +2731,10 @@ int ni_write_frame(struct ntfs_inode *ni, struct page **pages,
|
||||
{
|
||||
int err;
|
||||
struct ntfs_sb_info *sbi = ni->mi.sbi;
|
||||
struct folio *folio = page_folio(pages[0]);
|
||||
u8 frame_bits = NTFS_LZNT_CUNIT + sbi->cluster_bits;
|
||||
u32 frame_size = sbi->cluster_size << NTFS_LZNT_CUNIT;
|
||||
u64 frame_vbo = (u64)pages[0]->index << PAGE_SHIFT;
|
||||
u64 frame_vbo = folio_pos(folio);
|
||||
CLST frame = frame_vbo >> frame_bits;
|
||||
char *frame_ondisk = NULL;
|
||||
struct page **pages_disk = NULL;
|
||||
@ -3343,7 +3349,7 @@ int ni_write_inode(struct inode *inode, int sync, const char *hint)
|
||||
if (!mi->dirty)
|
||||
continue;
|
||||
|
||||
is_empty = !mi_enum_attr(mi, NULL);
|
||||
is_empty = !mi_enum_attr(ni, mi, NULL);
|
||||
|
||||
if (is_empty)
|
||||
clear_rec_inuse(mi->mrec);
|
||||
|
@ -908,7 +908,11 @@ void ntfs_bad_inode(struct inode *inode, const char *hint)
|
||||
|
||||
ntfs_inode_err(inode, "%s", hint);
|
||||
make_bad_inode(inode);
|
||||
ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
|
||||
/* Avoid recursion if bad inode is $Volume. */
|
||||
if (inode->i_ino != MFT_REC_VOL &&
|
||||
!(sbi->flags & NTFS_FLAGS_LOG_REPLAYING)) {
|
||||
ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1094,8 +1094,7 @@ int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn,
|
||||
|
||||
ok:
|
||||
if (!index_buf_check(ib, bytes, &vbn)) {
|
||||
ntfs_inode_err(&ni->vfs_inode, "directory corrupted");
|
||||
ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1117,8 +1116,7 @@ ok:
|
||||
|
||||
out:
|
||||
if (err == -E_NTFS_CORRUPT) {
|
||||
ntfs_inode_err(&ni->vfs_inode, "directory corrupted");
|
||||
ntfs_set_state(ni->mi.sbi, NTFS_DIRTY_ERROR);
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -410,6 +410,9 @@ end_enum:
|
||||
if (!std5)
|
||||
goto out;
|
||||
|
||||
if (is_bad_inode(inode))
|
||||
goto out;
|
||||
|
||||
if (!is_match && name) {
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
|
@ -745,23 +745,24 @@ int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi);
|
||||
void mi_put(struct mft_inode *mi);
|
||||
int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno);
|
||||
int mi_read(struct mft_inode *mi, bool is_mft);
|
||||
struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr);
|
||||
// TODO: id?
|
||||
struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
|
||||
enum ATTR_TYPE type, const __le16 *name,
|
||||
u8 name_len, const __le16 *id);
|
||||
static inline struct ATTRIB *rec_find_attr_le(struct mft_inode *rec,
|
||||
struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
struct ATTRIB *attr);
|
||||
struct ATTRIB *mi_find_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
struct ATTRIB *attr, enum ATTR_TYPE type,
|
||||
const __le16 *name, u8 name_len, const __le16 *id);
|
||||
static inline struct ATTRIB *rec_find_attr_le(struct ntfs_inode *ni,
|
||||
struct mft_inode *rec,
|
||||
struct ATTR_LIST_ENTRY *le)
|
||||
{
|
||||
return mi_find_attr(rec, NULL, le->type, le_name(le), le->name_len,
|
||||
return mi_find_attr(ni, rec, NULL, le->type, le_name(le), le->name_len,
|
||||
&le->id);
|
||||
}
|
||||
int mi_write(struct mft_inode *mi, int wait);
|
||||
int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
|
||||
__le16 flags, bool is_mft);
|
||||
struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
||||
const __le16 *name, u8 name_len, u32 asize,
|
||||
u16 name_off);
|
||||
struct ATTRIB *mi_insert_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
enum ATTR_TYPE type, const __le16 *name,
|
||||
u8 name_len, u32 asize, u16 name_off);
|
||||
|
||||
bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
struct ATTRIB *attr);
|
||||
|
@ -31,7 +31,7 @@ static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
|
||||
*
|
||||
* Return: Unused attribute id that is less than mrec->next_attr_id.
|
||||
*/
|
||||
static __le16 mi_new_attt_id(struct mft_inode *mi)
|
||||
static __le16 mi_new_attt_id(struct ntfs_inode *ni, struct mft_inode *mi)
|
||||
{
|
||||
u16 free_id, max_id, t16;
|
||||
struct MFT_REC *rec = mi->mrec;
|
||||
@ -52,7 +52,7 @@ static __le16 mi_new_attt_id(struct mft_inode *mi)
|
||||
attr = NULL;
|
||||
|
||||
for (;;) {
|
||||
attr = mi_enum_attr(mi, attr);
|
||||
attr = mi_enum_attr(ni, mi, attr);
|
||||
if (!attr) {
|
||||
rec->next_attr_id = cpu_to_le16(max_id + 1);
|
||||
mi->dirty = true;
|
||||
@ -195,7 +195,8 @@ out:
|
||||
* NOTE: mi->mrec - memory of size sbi->record_size
|
||||
* here we sure that mi->mrec->total == sbi->record_size (see mi_read)
|
||||
*/
|
||||
struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
struct ATTRIB *mi_enum_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
struct ATTRIB *attr)
|
||||
{
|
||||
const struct MFT_REC *rec = mi->mrec;
|
||||
u32 used = le32_to_cpu(rec->used);
|
||||
@ -209,11 +210,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
off = le16_to_cpu(rec->attr_off);
|
||||
|
||||
if (used > total)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
|
||||
!IS_ALIGNED(off, 8)) {
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Skip non-resident records. */
|
||||
@ -243,7 +244,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
*/
|
||||
if (off + 8 > used) {
|
||||
static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attr->type == ATTR_END) {
|
||||
@ -254,112 +255,116 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
|
||||
/* 0x100 is last known attribute for now. */
|
||||
t32 = le32_to_cpu(attr->type);
|
||||
if (!t32 || (t32 & 0xf) || (t32 > 0x100))
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* attributes in record must be ordered by type */
|
||||
if (t32 < prev_type)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
asize = le32_to_cpu(attr->size);
|
||||
|
||||
if (!IS_ALIGNED(asize, 8))
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* Check overflow and boundary. */
|
||||
if (off + asize < off || off + asize > used)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* Can we use the field attr->non_res. */
|
||||
if (off + 9 > used)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* Check size of attribute. */
|
||||
if (!attr->non_res) {
|
||||
/* Check resident fields. */
|
||||
if (asize < SIZEOF_RESIDENT)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
t16 = le16_to_cpu(attr->res.data_off);
|
||||
if (t16 > asize)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (le32_to_cpu(attr->res.data_size) > asize - t16)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
t32 = sizeof(short) * attr->name_len;
|
||||
if (t32 && le16_to_cpu(attr->name_off) + t32 > t16)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
/* Check nonresident fields. */
|
||||
if (attr->non_res != 1)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* Can we use memory including attr->nres.valid_size? */
|
||||
if (asize < SIZEOF_NONRESIDENT)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
t16 = le16_to_cpu(attr->nres.run_off);
|
||||
if (t16 > asize)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
t32 = sizeof(short) * attr->name_len;
|
||||
if (t32 && le16_to_cpu(attr->name_off) + t32 > t16)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
/* Check start/end vcn. */
|
||||
if (le64_to_cpu(attr->nres.svcn) > le64_to_cpu(attr->nres.evcn) + 1)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
data_size = le64_to_cpu(attr->nres.data_size);
|
||||
if (le64_to_cpu(attr->nres.valid_size) > data_size)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
alloc_size = le64_to_cpu(attr->nres.alloc_size);
|
||||
if (data_size > alloc_size)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
t32 = mi->sbi->cluster_mask;
|
||||
if (alloc_size & t32)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (!attr->nres.svcn && is_attr_ext(attr)) {
|
||||
/* First segment of sparse/compressed attribute */
|
||||
/* Can we use memory including attr->nres.total_size? */
|
||||
if (asize < SIZEOF_NONRESIDENT_EX)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
tot_size = le64_to_cpu(attr->nres.total_size);
|
||||
if (tot_size & t32)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (tot_size > alloc_size)
|
||||
return NULL;
|
||||
goto out;
|
||||
} else {
|
||||
if (attr->nres.c_unit)
|
||||
return NULL;
|
||||
goto out;
|
||||
|
||||
if (alloc_size > mi->sbi->volume.size)
|
||||
return NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return attr;
|
||||
|
||||
out:
|
||||
_ntfs_bad_inode(&ni->vfs_inode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* mi_find_attr - Find the attribute by type and name and id.
|
||||
*/
|
||||
struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
|
||||
enum ATTR_TYPE type, const __le16 *name,
|
||||
u8 name_len, const __le16 *id)
|
||||
struct ATTRIB *mi_find_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
struct ATTRIB *attr, enum ATTR_TYPE type,
|
||||
const __le16 *name, u8 name_len, const __le16 *id)
|
||||
{
|
||||
u32 type_in = le32_to_cpu(type);
|
||||
u32 atype;
|
||||
|
||||
next_attr:
|
||||
attr = mi_enum_attr(mi, attr);
|
||||
attr = mi_enum_attr(ni, mi, attr);
|
||||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
@ -467,9 +472,9 @@ int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
|
||||
*
|
||||
* Return: Not full constructed attribute or NULL if not possible to create.
|
||||
*/
|
||||
struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
||||
const __le16 *name, u8 name_len, u32 asize,
|
||||
u16 name_off)
|
||||
struct ATTRIB *mi_insert_attr(struct ntfs_inode *ni, struct mft_inode *mi,
|
||||
enum ATTR_TYPE type, const __le16 *name,
|
||||
u8 name_len, u32 asize, u16 name_off)
|
||||
{
|
||||
size_t tail;
|
||||
struct ATTRIB *attr;
|
||||
@ -488,7 +493,7 @@ struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
||||
* at which we should insert it.
|
||||
*/
|
||||
attr = NULL;
|
||||
while ((attr = mi_enum_attr(mi, attr))) {
|
||||
while ((attr = mi_enum_attr(ni, mi, attr))) {
|
||||
int diff = compare_attr(attr, type, name, name_len, upcase);
|
||||
|
||||
if (diff < 0)
|
||||
@ -508,7 +513,7 @@ struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
|
||||
tail = used - PtrOffset(rec, attr);
|
||||
}
|
||||
|
||||
id = mi_new_attt_id(mi);
|
||||
id = mi_new_attt_id(ni, mi);
|
||||
|
||||
memmove(Add2Ptr(attr, asize), attr, tail);
|
||||
memset(attr, 0, asize);
|
||||
|
Loading…
x
Reference in New Issue
Block a user