Made sanity checks when setting reparse data of known type

PERMISSION_HANDLING_BRANCH
jpandre 2009-12-15 09:39:29 +00:00
parent 2f8ced2ddd
commit b842a6720e
1 changed files with 59 additions and 2 deletions

View File

@ -393,6 +393,62 @@ static int ntfs_drive_letter(ntfs_volume *vol, ntfschar letter)
return (ret);
}
/*
* Do some sanity checks on reparse data
*
* The only general check is about the size (at least the tag must
* be present)
* If the reparse data looks like a junction point or symbolic
* link, more checks can be done.
*
*/
static BOOL valid_reparse_data(ntfs_inode *ni,
const REPARSE_POINT *reparse_attr, size_t size)
{
BOOL ok;
unsigned int offs;
unsigned int lth;
const struct MOUNT_POINT_REPARSE_DATA *mount_point_data;
const struct SYMLINK_REPARSE_DATA *symlink_data;
ok = ni && reparse_attr
&& (size >= sizeof(REPARSE_POINT))
&& (((size_t)le16_to_cpu(reparse_attr->reparse_data_length)
+ sizeof(REPARSE_POINT)) == size);
if (ok) {
switch (reparse_attr->reparse_tag) {
case IO_REPARSE_TAG_MOUNT_POINT :
mount_point_data = (const struct MOUNT_POINT_REPARSE_DATA*)
reparse_attr->reparse_data;
offs = le16_to_cpu(mount_point_data->subst_name_offset);
lth = le16_to_cpu(mount_point_data->subst_name_length);
/* consistency checks */
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|| ((size_t)((sizeof(REPARSE_POINT)
+ sizeof(struct MOUNT_POINT_REPARSE_DATA)
+ offs + lth)) > size))
ok = FALSE;
break;
case IO_REPARSE_TAG_SYMLINK :
symlink_data = (const struct SYMLINK_REPARSE_DATA*)
reparse_attr->reparse_data;
offs = le16_to_cpu(symlink_data->subst_name_offset);
lth = le16_to_cpu(symlink_data->subst_name_length);
if ((size_t)((sizeof(REPARSE_POINT)
+ sizeof(struct SYMLINK_REPARSE_DATA)
+ offs + lth)) > size)
ok = FALSE;
break;
default :
break;
}
}
if (!ok)
errno = EINVAL;
return (ok);
}
/*
* Check and translate the target of a junction point or
* a full absolute symbolic link.
@ -654,7 +710,8 @@ char *ntfs_make_symlink(ntfs_inode *ni, const char *mnt_point,
vol = ni->vol;
reparse_attr = (REPARSE_POINT*)ntfs_attr_readall(ni,
AT_REPARSE_POINT,(ntfschar*)NULL, 0, &attr_size);
if (reparse_attr && attr_size) {
if (reparse_attr && attr_size
&& valid_reparse_data(ni, reparse_attr, attr_size)) {
switch (reparse_attr->reparse_tag) {
case IO_REPARSE_TAG_MOUNT_POINT :
mount_point_data = (struct MOUNT_POINT_REPARSE_DATA*)
@ -1016,7 +1073,7 @@ int ntfs_set_ntfs_reparse_data(const char *path __attribute__((unused)),
ntfs_index_context *xr;
res = 0;
if (ni && value && (size >= 4)) {
if (ni && valid_reparse_data(ni, (const REPARSE_POINT*)value, size)) {
xr = open_reparse_index(ni->vol);
if (xr) {
if (!ntfs_attr_exist(ni,AT_REPARSE_POINT,