Checked consistency of index entries
Make sure the data and key in indexes do not overflow from index entriesedge.strict_endians^2
parent
32e858a87a
commit
436fe09f87
|
@ -139,6 +139,8 @@ extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni,
|
|||
extern void ntfs_index_ctx_put(ntfs_index_context *ictx);
|
||||
extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx);
|
||||
|
||||
extern int ntfs_index_entry_consistent(const INDEX_ENTRY *ie,
|
||||
COLLATION_RULES collation_rule, u64 inum);
|
||||
extern int ntfs_index_lookup(const void *key, const int key_len,
|
||||
ntfs_index_context *ictx) __attribute_warn_unused_result__;
|
||||
|
||||
|
|
|
@ -328,9 +328,10 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
|
|||
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||
break;
|
||||
|
||||
if (!le16_to_cpu(ie->length)) {
|
||||
ntfs_log_error("Zero length index entry in inode %lld"
|
||||
"\n", (unsigned long long)dir_ni->mft_no);
|
||||
/* The file name must not overflow from the entry */
|
||||
if (ntfs_index_entry_consistent(ie, COLLATION_FILE_NAME,
|
||||
dir_ni->mft_no)) {
|
||||
errno = EIO;
|
||||
goto put_err_out;
|
||||
}
|
||||
/*
|
||||
|
@ -467,10 +468,10 @@ descend_into_child_node:
|
|||
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||
break;
|
||||
|
||||
if (!le16_to_cpu(ie->length)) {
|
||||
/* The file name must not overflow from the entry */
|
||||
if (ntfs_index_entry_consistent(ie, COLLATION_FILE_NAME,
|
||||
dir_ni->mft_no)) {
|
||||
errno = EIO;
|
||||
ntfs_log_error("Zero length index entry in inode %lld"
|
||||
"\n", (unsigned long long)dir_ni->mft_no);
|
||||
goto close_err_out;
|
||||
}
|
||||
/*
|
||||
|
@ -1273,6 +1274,13 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
|||
/* Skip index root entry if continuing previous readdir. */
|
||||
if (ir_pos > (u8*)ie - (u8*)ir)
|
||||
continue;
|
||||
|
||||
/* The file name must not overflow from the entry */
|
||||
if (ntfs_index_entry_consistent(ie, COLLATION_FILE_NAME,
|
||||
dir_ni->mft_no)) {
|
||||
errno = EIO;
|
||||
goto dir_err_out;
|
||||
}
|
||||
/*
|
||||
* Submit the directory entry to ntfs_filldir(), which will
|
||||
* invoke the filldir() callback as appropriate.
|
||||
|
@ -1429,6 +1437,13 @@ find_next_index_buffer:
|
|||
/* Skip index entry if continuing previous readdir. */
|
||||
if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
|
||||
continue;
|
||||
|
||||
/* The file name must not overflow from the entry */
|
||||
if (ntfs_index_entry_consistent(ie, COLLATION_FILE_NAME,
|
||||
dir_ni->mft_no)) {
|
||||
errno = EIO;
|
||||
goto dir_err_out;
|
||||
}
|
||||
/*
|
||||
* Submit the directory entry to ntfs_filldir(), which will
|
||||
* invoke the filldir() callback as appropriate.
|
||||
|
|
|
@ -469,6 +469,57 @@ static INDEX_ROOT *ntfs_ir_lookup2(ntfs_inode *ni, ntfschar *name, u32 len)
|
|||
return ir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the consistency of an index entry
|
||||
*
|
||||
* Make sure data and key do not overflow from entry.
|
||||
* As a side effect, an entry with zero length is rejected.
|
||||
* This entry must be a full one (no INDEX_ENTRY_END flag), and its
|
||||
* length must have been checked beforehand to not overflow from the
|
||||
* index record.
|
||||
*
|
||||
* Returns 0 if no error was found
|
||||
* -1 otherwise (with errno unchanged)
|
||||
*/
|
||||
|
||||
int ntfs_index_entry_consistent(const INDEX_ENTRY *ie,
|
||||
COLLATION_RULES collation_rule, u64 inum)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
if (ie->key_length
|
||||
&& ((le16_to_cpu(ie->key_length) + offsetof(INDEX_ENTRY, key))
|
||||
> le16_to_cpu(ie->length))) {
|
||||
ntfs_log_error("Overflow from index entry in inode %lld\n",
|
||||
(long long)inum);
|
||||
ret = -1;
|
||||
|
||||
} else
|
||||
if (collation_rule == COLLATION_FILE_NAME) {
|
||||
if ((offsetof(INDEX_ENTRY, key.file_name.file_name)
|
||||
+ ie->key.file_name.file_name_length
|
||||
* sizeof(ntfschar))
|
||||
> le16_to_cpu(ie->length)) {
|
||||
ntfs_log_error("File name overflow from index"
|
||||
" entry in inode %lld\n",
|
||||
(long long)inum);
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
if (ie->data_length
|
||||
&& ((le16_to_cpu(ie->data_offset)
|
||||
+ le16_to_cpu(ie->data_length))
|
||||
> le16_to_cpu(ie->length))) {
|
||||
ntfs_log_error("Data overflow from index"
|
||||
" entry in inode %lld\n",
|
||||
(long long)inum);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a key in the index block.
|
||||
*
|
||||
|
@ -521,6 +572,12 @@ static int ntfs_ie_lookup(const void *key, const int key_len,
|
|||
ntfs_log_error("Collation function not defined\n");
|
||||
errno = EOPNOTSUPP;
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
/* Make sure key and data do not overflow from entry */
|
||||
if (ntfs_index_entry_consistent(ie, icx->ir->collation_rule,
|
||||
icx->ni->mft_no)) {
|
||||
errno = EIO;
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
rc = icx->collate(icx->ni->vol, key, key_len,
|
||||
&ie->key, le16_to_cpu(ie->key_length));
|
||||
|
@ -704,6 +761,7 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic
|
|||
else
|
||||
icx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
|
||||
/* get the appropriate collation function */
|
||||
icx->ir = ir;
|
||||
icx->collate = ntfs_get_collate_function(ir->collation_rule);
|
||||
if (!icx->collate) {
|
||||
err = errno = EOPNOTSUPP;
|
||||
|
@ -790,6 +848,10 @@ descend_into_child_node:
|
|||
err_out:
|
||||
icx->bad_index = TRUE; /* Force icx->* to be freed */
|
||||
err_lookup:
|
||||
if (icx->actx) {
|
||||
ntfs_attr_put_search_ctx(icx->actx);
|
||||
icx->actx = NULL;
|
||||
}
|
||||
free(ib);
|
||||
if (!err)
|
||||
err = EIO;
|
||||
|
|
Loading…
Reference in New Issue