- FASTFAT: when querying file name information, fill in the whole buffer provided by the caller, even if filename does not fully fit (driver by Microsoft(R) does the same). Also, return the actual amount of data written in IoSb.Information, even in case of buffer overflow result.

- CDFS: Fix a guaranteed buffer overwrite when zero-terminating a filename. Also apply the same fixes described above.

svn path=/trunk/; revision=37393
This commit is contained in:
Aleksey Bragin 2008-11-17 11:25:36 +00:00
parent bc5c507d54
commit 4983dabf35
2 changed files with 59 additions and 26 deletions

View file

@ -145,23 +145,38 @@ CdfsGetNameInformation(PFILE_OBJECT FileObject,
PULONG BufferLength)
{
ULONG NameLength;
ULONG BytesToCopy;
DPRINT("CdfsGetNameInformation() called\n");
ASSERT(NameInfo != NULL);
ASSERT(Fcb != NULL);
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
NameInfo->FileNameLength = NameLength;
if (*BufferLength < (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + NameLength))
/* If buffer can't hold at least the file name length, bail out */
if (*BufferLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
return STATUS_BUFFER_OVERFLOW;
RtlCopyMemory(NameInfo->FileName,
Fcb->PathName,
NameLength + sizeof(WCHAR));
/* Calculate file name length in bytes */
NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
NameInfo->FileNameLength = NameLength;
*BufferLength -=
(FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + NameLength);
/* Calculate amount of bytes to copy not to overflow the buffer */
BytesToCopy = min(NameLength,
*BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
/* Fill in the bytes */
RtlCopyMemory(NameInfo->FileName, Fcb->PathName, BytesToCopy);
/* Check if we could write more but are not able to */
if (*BufferLength < NameLength + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
{
/* Return number of bytes written */
*BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
return STATUS_BUFFER_OVERFLOW;
}
/* We filled up as many bytes, as needed */
*BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + NameLength);
return STATUS_SUCCESS;
}
@ -395,7 +410,7 @@ CdfsQueryInformation(PDEVICE_OBJECT DeviceObject,
}
Irp->IoStatus.Status = Status;
if (NT_SUCCESS(Status))
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
Irp->IoStatus.Information =
Stack->Parameters.QueryFile.Length - BufferLength;
else

View file

@ -338,15 +338,33 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
* FUNCTION: Retrieve the file name information
*/
{
ULONG BytesToCopy;
ASSERT(NameInfo != NULL);
ASSERT(FCB != NULL);
NameInfo->FileNameLength = FCB->PathNameU.Length;
if (*BufferLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length)
/* If buffer can't hold at least the file name length, bail out */
if (*BufferLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
return STATUS_BUFFER_OVERFLOW;
RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
/* Save file name length, and as much file len, as buffer length allows */
NameInfo->FileNameLength = FCB->PathNameU.Length;
/* Calculate amount of bytes to copy not to overflow the buffer */
BytesToCopy = min(FCB->PathNameU.Length,
*BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
/* Fill in the bytes */
RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, BytesToCopy);
/* Check if we could write more but are not able to */
if (*BufferLength < FCB->PathNameU.Length + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
{
/* Return number of bytes written */
*BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
return STATUS_BUFFER_OVERFLOW;
}
/* We filled up as many bytes, as needed */
*BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length);
return STATUS_SUCCESS;
@ -749,7 +767,7 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
FILE_INFORMATION_CLASS FileInformationClass;
PVFATFCB FCB = NULL;
NTSTATUS RC = STATUS_SUCCESS;
NTSTATUS Status = STATUS_SUCCESS;
PVOID SystemBuffer;
ULONG BufferLength;
@ -780,44 +798,44 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
switch (FileInformationClass)
{
case FileStandardInformation:
RC = VfatGetStandardInformation(FCB,
Status = VfatGetStandardInformation(FCB,
SystemBuffer,
&BufferLength);
break;
case FilePositionInformation:
RC = VfatGetPositionInformation(IrpContext->FileObject,
Status = VfatGetPositionInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileBasicInformation:
RC = VfatGetBasicInformation(IrpContext->FileObject,
Status = VfatGetBasicInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileNameInformation:
RC = VfatGetNameInformation(IrpContext->FileObject,
Status = VfatGetNameInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
case FileInternalInformation:
RC = VfatGetInternalInformation(FCB,
Status = VfatGetInternalInformation(FCB,
SystemBuffer,
&BufferLength);
break;
case FileNetworkOpenInformation:
RC = VfatGetNetworkOpenInformation(FCB,
Status = VfatGetNetworkOpenInformation(FCB,
IrpContext->DeviceExt,
SystemBuffer,
&BufferLength);
break;
case FileAllInformation:
RC = VfatGetAllInformation(IrpContext->FileObject,
Status = VfatGetAllInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
@ -825,7 +843,7 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
break;
case FileEaInformation:
RC = VfatGetEaInformation(IrpContext->FileObject,
Status = VfatGetEaInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
@ -833,18 +851,18 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
break;
case FileAlternateNameInformation:
RC = STATUS_NOT_IMPLEMENTED;
Status = STATUS_NOT_IMPLEMENTED;
break;
default:
RC = STATUS_INVALID_PARAMETER;
Status = STATUS_INVALID_PARAMETER;
}
if (!(FCB->Flags & FCB_IS_PAGE_FILE))
{
ExReleaseResourceLite(&FCB->MainResource);
}
IrpContext->Irp->IoStatus.Status = RC;
if (NT_SUCCESS(RC))
IrpContext->Irp->IoStatus.Status = Status;
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
IrpContext->Irp->IoStatus.Information =
IrpContext->Stack->Parameters.QueryFile.Length - BufferLength;
else
@ -852,7 +870,7 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
return RC;
return Status;
}
NTSTATUS VfatSetInformation(PVFAT_IRP_CONTEXT IrpContext)