Example #1
0
NTSTATUS
PvfsQuerySecurityFile(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_NOT_SUPPORTED;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pReturnSecDesc = NULL;
    ULONG SecDescLength = 0;
    SECURITY_INFORMATION SecInfo = 0;
    IRP_ARGS_QUERY_SET_SECURITY Args = pIrpContext->pIrp->Args.QuerySetSecurity;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_CREATE_COMPLETE))
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    BAIL_ON_INVALID_PTR(Args.SecurityDescriptor, ntError);

    ntError = PvfsAccessCheckFileHandle(pCcb, READ_CONTROL);
    BAIL_ON_NT_STATUS(ntError);

    pReturnSecDesc = Args.SecurityDescriptor;
    SecDescLength = Args.Length;
    SecInfo  = Args.SecurityInformation;

    /* Real work starts here */

    ntError = PvfsGetSecurityDescriptorFile(pCcb,
                                            SecInfo,
                                            pReturnSecDesc,
                                            &SecDescLength);
    BAIL_ON_NT_STATUS(ntError);

    pIrp->IoStatusBlock.BytesTransferred = SecDescLength;
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
Example #2
0
NTSTATUS
PvfsReadDirectoryChange(
    PPVFS_IRP_CONTEXT  pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    IRP_ARGS_READ_DIRECTORY_CHANGE Args = pIrp->Args.ReadDirectoryChange;
    PPVFS_CCB pCcb = NULL;
    PULONG pMaxBufferSize = Args.MaxBufferSize;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_CREATE_COMPLETE))
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    if (!PVFS_IS_DIR(pCcb))
    {
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsAccessCheckFileHandle(pCcb, FILE_LIST_DIRECTORY);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.Buffer, ntError);
    BAIL_ON_ZERO_LENGTH(Args.Length, ntError);

    /* If we have something in the buffer, return that immediately.  Else
       register a notification filter */

    LWIO_ASSERT(pCcb->pScb->pOwnerFcb);
    ntError = PvfsNotifyReportBufferedChanges(
                  pCcb,
                  pCcb->pScb->pOwnerFcb,
                  pIrpContext);
    if (ntError == STATUS_NOT_FOUND)
    {
        PvfsIrpMarkPending(pIrpContext, PvfsQueueCancelIrp, pIrpContext);

        LWIO_ASSERT(pCcb->pScb->pOwnerFcb);
        ntError = PvfsNotifyAddFilter(
                      pCcb->pScb->pOwnerFcb,
                      pIrpContext,
                      pCcb,
                      Args.NotifyFilter,
                      Args.WatchTree,
                      pMaxBufferSize);
        if (ntError == STATUS_SUCCESS)
        {
            pIrpContext->QueueType = PVFS_QUEUE_TYPE_NOTIFY;

            if (!pIrpContext->pScb)
            {
                pIrpContext->pScb = PvfsReferenceSCB(pCcb->pScb);
            }

            /* Allow the call to be cancelled while in the queue */

            PvfsIrpContextClearFlag(pIrpContext, PVFS_IRP_CTX_FLAG_ACTIVE);

            ntError = STATUS_PENDING;
            goto cleanup;
        }
    }
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    if (pCcb)
    {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    if (PvfsIrpContextCheckFlag(pIrpContext, PVFS_IRP_CTX_FLAG_PENDED))
    {
        pIrpContext->pIrp->IoStatusBlock.Status = ntError;
        PvfsCompleteIrpContext(pIrpContext);
    }

    goto cleanup;
}
Example #3
0
static
NTSTATUS
PvfsQueryFileFsAttribInfo(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PFILE_FS_ATTRIBUTE_INFORMATION pFileInfo = NULL;
    IRP_ARGS_QUERY_SET_VOLUME_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetVolumeInformation;
    PWSTR pwszFsName = NULL;
    size_t FsNameLenBytes = RtlCStringNumChars(PVFS_FS_NAME) * sizeof(WCHAR);
    PVFS_STATFS StatFs = {0};
    ULONG FsAttributeSet = PVFS_FILE_SYSTEM_ATTRIBUTES;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    /* not sure exact access rights to check for here */

    ntError = PvfsAccessCheckFileHandle(pCcb, FILE_READ_ATTRIBUTES);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.FsInformation, ntError);

    if (Args.Length < sizeof(*pFileInfo) + FsNameLenBytes)
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    pFileInfo = (PFILE_FS_ATTRIBUTE_INFORMATION)Args.FsInformation;

    /* Real work starts here */

    ntError = PvfsSysFstatFs(pCcb, &StatFs);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RtlWC16StringAllocateFromCString(&pwszFsName, PVFS_FS_NAME);
    BAIL_ON_NT_STATUS(ntError);

    pFileInfo->FileSystemAttributes = FsAttributeSet;
    pFileInfo->MaximumComponentNameLength = StatFs.MaximumNameLength;
    pFileInfo->FileSystemNameLength = FsNameLenBytes;
    memcpy(pFileInfo->FileSystemName, pwszFsName, FsNameLenBytes);

    pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo);
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    PVFS_FREE(&pwszFsName);

    return ntError;

error:
    goto cleanup;
}
static NTSTATUS
PvfsQueryFileIdFullDirInfo(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PFILE_ID_FULL_DIR_INFORMATION pFileInfo = NULL;
    PFILE_ID_FULL_DIR_INFORMATION pPrevFileInfo = NULL;
    IRP_ARGS_QUERY_DIRECTORY Args = pIrpContext->pIrp->Args.QueryDirectory;
    PVOID pBuffer = NULL;
    DWORD dwBufLen = 0;
    DWORD dwOffset = 0;
    DWORD dwConsumed = 0;
    BOOLEAN bLocked = FALSE;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!PVFS_IS_DIR(pCcb))
    {
        ntError = STATUS_NOT_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsAccessCheckFileHandle(pCcb,  FILE_LIST_DIRECTORY);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.FileInformation, ntError);

    if (Args.Length < sizeof(*pFileInfo))
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)Args.FileInformation;

    /* Scen the first time through */

    ntError = STATUS_SUCCESS;

    /* Critical region to prevent inteleaving directory
       enumeration */

    LWIO_LOCK_MUTEX(bLocked, &pCcb->FileMutex);

    if (!pCcb->pDirContext->bScanned) {
        ntError = PvfsEnumerateDirectory(
                      pCcb,
                      pIrp->Args.QueryDirectory.FileSpec,
                      -1,
                      FALSE);
    }

    LWIO_UNLOCK_MUTEX(bLocked, &pCcb->FileMutex);

    BAIL_ON_NT_STATUS(ntError);

    /* Check for ending condition */

    if (pCcb->pDirContext->dwIndex == pCcb->pDirContext->dwNumEntries)
    {
        ntError = STATUS_NO_MORE_MATCHES;
        BAIL_ON_NT_STATUS(ntError);
    }


    /* Fill in the buffer */

    pBuffer = Args.FileInformation;
    dwBufLen = Args.Length;
    dwOffset = 0;
    pFileInfo = NULL;
    pPrevFileInfo = NULL;

    do
    {
        PPVFS_DIRECTORY_ENTRY pEntry = NULL;
        DWORD dwIndex;

        pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)(pBuffer + dwOffset);
        pFileInfo->NextEntryOffset = 0;

        dwIndex = pCcb->pDirContext->dwIndex;
        pEntry  = &pCcb->pDirContext->pDirEntries[dwIndex];
        ntError = FillFileIdFullDirInfoBuffer(
                      pFileInfo,
                      dwBufLen - dwOffset,
                      pCcb->pszFilename,
                      pEntry,
                      &dwConsumed);

        /* If we ran out of buffer space, reset pointer to previous
           entry and break out of loop */

        if (ntError == STATUS_BUFFER_TOO_SMALL) {
            pFileInfo = pPrevFileInfo;
            break;
        }

        /* OBJECT_NAME_NOT_FOUND - This deals with a possible race
           where the directory contents was read but the file was
           removed before we could stat() it.

           INSUFFICIENT_RESOURCES - Invalid UTF-8 name.

           ACCESS_DENIED - Special cases like $HOME/.gvfs that can't
           be read by root.  Possibly just an Ubuntu bug but don't
           fail on it.
           https://bugs.launchpad.net/ubuntu/+source/gvfs/+bug/227724

           Just skip the file and move on. */

        if (ntError == STATUS_OBJECT_NAME_NOT_FOUND ||
            ntError == STATUS_INSUFFICIENT_RESOURCES ||
            ntError == STATUS_ACCESS_DENIED)
        {
            pFileInfo = pPrevFileInfo;
            pCcb->pDirContext->dwIndex++;
            continue;
        }

        /* Catch any other errors and bail */

        BAIL_ON_NT_STATUS(ntError);

        pFileInfo->NextEntryOffset = dwConsumed;

        dwOffset += dwConsumed;
        pCcb->pDirContext->dwIndex++;

        pPrevFileInfo = pFileInfo;

        if (Args.ReturnSingleEntry) {
            break;
        }
    }
    /* Exit loop when we are out of buffer or out of entries.  The
       filling function can also break us out of the loop. */
    while (((dwBufLen - dwOffset) > sizeof(FILE_ID_FULL_DIR_INFORMATION)) &&
             (pCcb->pDirContext->dwIndex < pCcb->pDirContext->dwNumEntries));

    /* Update final offset */

    if (pFileInfo) {
        pFileInfo->NextEntryOffset = 0;
    }

    pIrp->IoStatusBlock.BytesTransferred = dwOffset;
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
static NTSTATUS
PvfsSetFileAllocationInfo(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    IRP_ARGS_QUERY_SET_INFORMATION Args = {0};
    PPVFS_PENDING_SET_ALLOCATION pSetAllocationCtx = NULL;
    PFILE_ALLOCATION_INFORMATION pFileInfo = NULL;

    Args = pIrpContext->pIrp->Args.QuerySetInformation;
    pFileInfo = (PFILE_ALLOCATION_INFORMATION)Args.FileInformation;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.FileInformation, ntError);

    if (Args.Length < sizeof(*pFileInfo))
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = PvfsAccessCheckFileHandle(pCcb, FILE_WRITE_DATA);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateSetAllocationContext(
                  &pSetAllocationCtx,
                  pIrpContext,
                  pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsOplockBreakIfLocked(pIrpContext, pCcb, pCcb->pFcb);

    switch (ntError)
    {
    case STATUS_SUCCESS:
        ntError = PvfsSetAllocationWithContext(pSetAllocationCtx);
        break;

    case STATUS_OPLOCK_BREAK_IN_PROGRESS:
        ntError = PvfsPendOplockBreakTest(
                      pSetAllocationCtx->pCcb->pFcb,
                      pIrpContext,
                      pSetAllocationCtx->pCcb,
                      PvfsSetAllocationWithContext,
                      PvfsFreeSetAllocationContext,
                      (PVOID)pSetAllocationCtx);
        if (ntError == STATUS_SUCCESS) {
            pSetAllocationCtx = NULL;
            ntError = STATUS_PENDING;
        }
        break;

    case STATUS_PENDING:
        ntError = PvfsAddItemPendingOplockBreakAck(
                      pSetAllocationCtx->pCcb->pFcb,
                      pIrpContext,
                      PvfsSetAllocationWithContext,
                      PvfsFreeSetAllocationContext,
                      (PVOID)pSetAllocationCtx);
        if (ntError == STATUS_SUCCESS) {
            pSetAllocationCtx = NULL;
            ntError = STATUS_PENDING;
        }
        break;
    }
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    PvfsFreeSetAllocationContext((PVOID*)&pSetAllocationCtx);

    if (pCcb)
    {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
Example #6
0
NTSTATUS
PvfsSetSecurityFile(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_ACCESS_DENIED;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL;
    ULONG SecDescLength = 0;
    SECURITY_INFORMATION SecInfo = 0;
    IRP_ARGS_QUERY_SET_SECURITY Args = pIrpContext->pIrp->Args.QuerySetSecurity;
    ACCESS_MASK RequiredMask = 0;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (!IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_CREATE_COMPLETE))
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    BAIL_ON_INVALID_PTR(Args.SecurityDescriptor, ntError);

    pSecDesc = Args.SecurityDescriptor;
    SecDescLength = Args.Length;
    SecInfo  = Args.SecurityInformation;

    if (SecInfo & OWNER_SECURITY_INFORMATION) {
        RequiredMask |= WRITE_OWNER;
    }
    if (SecInfo & GROUP_SECURITY_INFORMATION) {
        RequiredMask |= WRITE_OWNER;
    }
    if (SecInfo & DACL_SECURITY_INFORMATION) {
        RequiredMask |= WRITE_DAC;
    }
    if (SecInfo & SACL_SECURITY_INFORMATION) {
        RequiredMask |= ACCESS_SYSTEM_SECURITY;
    }

    ntError = PvfsAccessCheckFileHandle(pCcb, RequiredMask);
    BAIL_ON_NT_STATUS(ntError);


    /* Real work starts here */

    ntError = PvfsSetSecurityDescriptorFile(pCcb,
                                             SecInfo,
                                             pSecDesc,
                                             SecDescLength);
    BAIL_ON_NT_STATUS(ntError);

    pIrp->IoStatusBlock.BytesTransferred = 0;
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}
Example #7
0
static
NTSTATUS
PvfsQueryFileFsVolInfo(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PFILE_FS_VOLUME_INFORMATION pFileInfo = NULL;
    IRP_ARGS_QUERY_SET_VOLUME_INFORMATION Args = pIrpContext->pIrp->Args.QuerySetVolumeInformation;
    PWSTR pwszVolumeName = NULL;
    PCSTR pszVolName = "LIKEWISE";
    size_t VolNameLenBytes = RtlCStringNumChars(pszVolName) * sizeof(WCHAR);
    PVFS_STAT stat = { 0 };

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    /* not sure exact access rights to check for here */

    ntError = PvfsAccessCheckFileHandle(pCcb, FILE_READ_ATTRIBUTES);
    BAIL_ON_NT_STATUS(ntError);

    BAIL_ON_INVALID_PTR(Args.FsInformation, ntError);

    if (Args.Length < sizeof(*pFileInfo) + VolNameLenBytes)
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    pFileInfo = (PFILE_FS_VOLUME_INFORMATION)Args.FsInformation;

    /* Real work starts here */

    ntError = PvfsSysFstat(pCcb->fd, &stat);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsUnixToWinTime(&pFileInfo->VolumeCreationTime, stat.s_crtime);
    BAIL_ON_NT_STATUS(ntError);

    pFileInfo->VolumeSerialNumber = 0x009a9a03;
    pFileInfo->SupportsObjects = FALSE;

    ntError = RtlWC16StringAllocateFromCString(&pwszVolumeName, pszVolName);
    BAIL_ON_NT_STATUS(ntError);

    pFileInfo->VolumeLabelLength = VolNameLenBytes;
    memcpy(pFileInfo->VolumeLabel, pwszVolumeName, VolNameLenBytes);

    pIrp->IoStatusBlock.BytesTransferred = sizeof(*pFileInfo);
    ntError = STATUS_SUCCESS;

cleanup:
    if (pCcb) {
        PvfsReleaseCCB(pCcb);
    }

    PVFS_FREE(&pwszVolumeName);

    return ntError;

error:
    goto cleanup;
}
Example #8
0
static
NTSTATUS
PvfsReadInternal(
    PPVFS_IRP_CONTEXT pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PIRP pIrp = pIrpContext->pIrp;
    PPVFS_CCB pCcb = NULL;
    PPVFS_PENDING_READ pReadCtx = NULL;

    /* Sanity checks */

    ntError =  PvfsAcquireCCB(pIrp->FileHandle, &pCcb);
    BAIL_ON_NT_STATUS(ntError);

    if (PVFS_IS_DIR(pCcb)) {
        ntError = STATUS_FILE_IS_A_DIRECTORY;
        BAIL_ON_NT_STATUS(ntError);
    }

#if 0xFFFFFFFF > SSIZE_MAX
    if ((size_t)pIrp->Args.ReadWrite.Length > (size_t) SSIZE_MAX) {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }
#endif

    /* Check the right permissions based on the PagingIo flag */

    if (pIrp->Args.ReadWrite.IsPagingIo)
    {
        ntError = PvfsAccessCheckAnyFileHandle(
                      pCcb,
                      FILE_READ_DATA|FILE_EXECUTE);
    }
    else
    {
        ntError = PvfsAccessCheckFileHandle(
                      pCcb,
                      FILE_READ_DATA);
    }
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsCreateReadContext(&pReadCtx, pIrpContext, pCcb);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsOplockBreakIfLocked(pIrpContext, pCcb, pCcb->pScb);

    switch (ntError)
    {
    case STATUS_SUCCESS:
        ntError = PvfsReadFileWithContext(pReadCtx);
        break;

    case STATUS_OPLOCK_BREAK_IN_PROGRESS:
        ntError = PvfsPendOplockBreakTest(
                      pReadCtx->pCcb->pScb,
                      pIrpContext,
                      pReadCtx->pCcb,
                      PvfsReadFileWithContext,
                      PvfsFreeReadContext,
                      (PVOID)pReadCtx);
        if (ntError == STATUS_PENDING)
        {
            pReadCtx = NULL;
        }
        break;

    case STATUS_PENDING:
        ntError = PvfsAddItemPendingOplockBreakAck(
                      pReadCtx->pCcb->pScb,
                      pIrpContext,
                      PvfsReadFileWithContext,
                      PvfsFreeReadContext,
                      (PVOID)pReadCtx);
        if (ntError == STATUS_PENDING)
        {
            pReadCtx = NULL;
        }
        break;
    }
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    PvfsFreeReadContext(OUT_PPVOID(&pReadCtx));

    if (pCcb)
    {
        PvfsReleaseCCB(pCcb);
    }

    return ntError;

error:
    goto cleanup;
}