adding arguments check functions to mrx functions

moving input argument checks into check_nfs41_X () functions
This commit is contained in:
Olga Kornievskaia 2012-03-29 14:41:28 -04:00 committed by unknown
parent 60e1d87a86
commit dc9377ce58
2 changed files with 377 additions and 189 deletions

View file

@ -223,7 +223,7 @@ void print_ea_info(int on, PFILE_FULL_EA_INFORMATION info)
void print_get_ea(int on, PFILE_GET_EA_INFORMATION info) void print_get_ea(int on, PFILE_GET_EA_INFORMATION info)
{ {
if (!on) return; if (!on || !info) return;
DbgP("GET_EA_INFO: NextOffset=%d EaNameLength=%d EaName=%s\n", DbgP("GET_EA_INFO: NextOffset=%d EaNameLength=%d EaName=%s\n",
info->NextEntryOffset, info->EaNameLength, info->EaName); info->NextEntryOffset, info->EaNameLength, info->EaName);
} }

View file

@ -3384,16 +3384,11 @@ DWORD map_disposition_to_create_retval(
} }
} }
NTSTATUS nfs41_Create( NTSTATUS check_nfs41_create_args(
IN OUT PRX_CONTEXT RxContext) IN PRX_CONTEXT RxContext)
{ {
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; NTSTATUS status = STATUS_SUCCESS;
nfs41_updowncall_entry *entry = NULL;
FCB_INIT_PACKET InitPacket;
RX_FILE_TYPE StorageType = 0;
NT_CREATE_PARAMETERS params = RxContext->Create.NtCreateParameters; NT_CREATE_PARAMETERS params = RxContext->Create.NtCreateParameters;
PFILE_FULL_EA_INFORMATION eainfo = NULL;
nfs3_attrs *attrs = NULL;
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext = __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot); NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
@ -3401,22 +3396,6 @@ NTSTATUS nfs41_Create(
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot); NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
__notnull PMRX_FCB Fcb = RxContext->pFcb; __notnull PMRX_FCB Fcb = RxContext->pFcb;
__notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context; __notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
PNFS41_FOBX nfs41_fobx = NULL;
BOOLEAN oldDeletePending = nfs41_fcb->StandardInfo.DeletePending;
#ifdef ENABLE_TIMINGS
LARGE_INTEGER t1, t2;
t1 = KeQueryPerformanceCounter(NULL);
#endif
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
#ifdef DEBUG_OPEN
DbgEn();
print_debug_header(RxContext);
print_nt_create_params(1, RxContext->Create.NtCreateParameters);
if (RxContext->CurrentIrp->AssociatedIrp.SystemBuffer)
print_ea_info(0, RxContext->CurrentIrp->AssociatedIrp.SystemBuffer);
#endif
if (Fcb->pNetRoot->Type != NET_ROOT_DISK && if (Fcb->pNetRoot->Type != NET_ROOT_DISK &&
Fcb->pNetRoot->Type != NET_ROOT_WILD) { Fcb->pNetRoot->Type != NET_ROOT_WILD) {
@ -3434,6 +3413,7 @@ NTSTATUS nfs41_Create(
if (!pNetRootContext->mounts_init) { if (!pNetRootContext->mounts_init) {
print_error("nfs41_Create: No valid session established\n"); print_error("nfs41_Create: No valid session established\n");
status = STATUS_INSUFFICIENT_RESOURCES;
goto out; goto out;
} }
@ -3498,6 +3478,47 @@ NTSTATUS nfs41_Create(
goto out; goto out;
} }
out:
return status;
}
NTSTATUS nfs41_Create(
IN OUT PRX_CONTEXT RxContext)
{
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
nfs41_updowncall_entry *entry = NULL;
FCB_INIT_PACKET InitPacket;
RX_FILE_TYPE StorageType = 0;
NT_CREATE_PARAMETERS params = RxContext->Create.NtCreateParameters;
PFILE_FULL_EA_INFORMATION eainfo = NULL;
nfs3_attrs *attrs = NULL;
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
__notnull PMRX_FCB Fcb = RxContext->pFcb;
__notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
PNFS41_FOBX nfs41_fobx = NULL;
BOOLEAN oldDeletePending = nfs41_fcb->StandardInfo.DeletePending;
#ifdef ENABLE_TIMINGS
LARGE_INTEGER t1, t2;
t1 = KeQueryPerformanceCounter(NULL);
#endif
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
#ifdef DEBUG_OPEN
DbgEn();
print_debug_header(RxContext);
print_nt_create_params(1, RxContext->Create.NtCreateParameters);
if (RxContext->CurrentIrp->AssociatedIrp.SystemBuffer)
print_ea_info(0, RxContext->CurrentIrp->AssociatedIrp.SystemBuffer);
#endif
status = check_nfs41_create_args(RxContext);
if (status) goto out;
#if defined(STORE_MOUNT_SEC_CONTEXT) && defined (USE_MOUNT_SEC_CONTEXT) #if defined(STORE_MOUNT_SEC_CONTEXT) && defined (USE_MOUNT_SEC_CONTEXT)
status = nfs41_UpcallCreate(NFS41_OPEN, &pVNetRootContext->mount_sec_ctx, status = nfs41_UpcallCreate(NFS41_OPEN, &pVNetRootContext->mount_sec_ctx,
#else #else
@ -3994,6 +4015,14 @@ NTSTATUS map_querydir_errors(
} }
} }
NTSTATUS check_nfs41_dirquery_args(
IN PRX_CONTEXT RxContext)
{
if (RxContext->Info.Buffer == NULL)
return STATUS_INVALID_USER_BUFFER;
return STATUS_SUCCESS;
}
NTSTATUS nfs41_QueryDirectory( NTSTATUS nfs41_QueryDirectory(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -4017,6 +4046,9 @@ NTSTATUS nfs41_QueryDirectory(
print_querydir_args(RxContext); print_querydir_args(RxContext);
#endif #endif
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
switch (InfoClass) { switch (InfoClass) {
/* classes handled in readdir_copy_entry() and readdir_size_for_entry() */ /* classes handled in readdir_copy_entry() and readdir_size_for_entry() */
case FileNamesInformation: case FileNamesInformation:
@ -4156,6 +4188,9 @@ NTSTATUS nfs41_QueryVolumeInformation(
print_queryvolume_args(RxContext); print_queryvolume_args(RxContext);
#endif #endif
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
switch (InfoClass) { switch (InfoClass) {
case FileFsVolumeInformation: case FileFsVolumeInformation:
if ((ULONG)RxContext->Info.LengthRemaining >= DevExt->VolAttrsLen) { if ((ULONG)RxContext->Info.LengthRemaining >= DevExt->VolAttrsLen) {
@ -4374,6 +4409,26 @@ NTSTATUS map_setea_error(
} }
} }
NTSTATUS check_nfs41_setea_args(
IN PRX_CONTEXT RxContext)
{
NTSTATUS status;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
if (pVNetRootContext->read_only) {
print_error("check_nfs41_setattr_args: Read-only mount\n");
status = STATUS_ACCESS_DENIED;
goto out;
}
out:
return status;
}
NTSTATUS nfs41_SetEaInformation( NTSTATUS nfs41_SetEaInformation(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -4402,11 +4457,8 @@ NTSTATUS nfs41_SetEaInformation(
print_ea_info(1, eainfo); print_ea_info(1, eainfo);
#endif #endif
if (pVNetRootContext->read_only) { status = check_nfs41_setea_args(RxContext);
DbgP("Read-only mount\n"); if (status) goto out;
status = STATUS_ACCESS_DENIED;
goto out;
}
status = nfs41_UpcallCreate(NFS41_EA_SET, &nfs41_fobx->sec_ctx, status = nfs41_UpcallCreate(NFS41_EA_SET, &nfs41_fobx->sec_ctx,
pVNetRootContext->session, nfs41_fobx->nfs41_open_state, pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
@ -4465,6 +4517,22 @@ out:
return status; return status;
} }
NTSTATUS check_nfs41_queryea_args(
IN PRX_CONTEXT RxContext)
{
NTSTATUS status;
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
/* XXX windows can query for all eas in which case the list can be empty */
if (RxContext->CurrentIrpSp->Parameters.QueryEa.EaList == NULL)
status = STATUS_INVALID_PARAMETER;
out:
return status;
}
NTSTATUS nfs41_QueryEaInformation( NTSTATUS nfs41_QueryEaInformation(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -4491,13 +4559,10 @@ NTSTATUS nfs41_QueryEaInformation(
#ifdef DEBUG_EA_QUERY #ifdef DEBUG_EA_QUERY
DbgEn(); DbgEn();
print_debug_header(RxContext); print_debug_header(RxContext);
#endif
if (RxContext->CurrentIrpSp->Parameters.QueryEa.EaList == NULL)
goto out;
#ifdef DEBUG_EA_QUERY
print_get_ea(1, query); print_get_ea(1, query);
#endif #endif
status = check_nfs41_queryea_args(RxContext);
if (status) goto out;
if (AnsiStrEq(&NfsV3Attributes, query->EaName, query->EaNameLength)) { if (AnsiStrEq(&NfsV3Attributes, query->EaName, query->EaNameLength)) {
nfs3_attrs attrs; nfs3_attrs attrs;
@ -4613,6 +4678,25 @@ NTSTATUS map_query_acl_error(
} }
} }
NTSTATUS check_nfs41_getacl_args(
PRX_CONTEXT RxContext)
{
NTSTATUS status = STATUS_SUCCESS;
SECURITY_INFORMATION info_class =
RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
/* we don't support sacls */
if (info_class == SACL_SECURITY_INFORMATION ||
info_class == LABEL_SECURITY_INFORMATION) {
status = STATUS_NOT_SUPPORTED;
goto out;
}
if (RxContext->CurrentIrp->UserBuffer == NULL)
status = STATUS_INVALID_USER_BUFFER;
out:
return status;
}
NTSTATUS nfs41_QuerySecurityInformation( NTSTATUS nfs41_QuerySecurityInformation(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -4637,10 +4721,8 @@ NTSTATUS nfs41_QuerySecurityInformation(
print_acl_args(info_class); print_acl_args(info_class);
#endif #endif
/* we don't support sacls */ status = check_nfs41_getacl_args(RxContext);
if (info_class == SACL_SECURITY_INFORMATION || if (status) goto out;
info_class == LABEL_SECURITY_INFORMATION)
goto out;
if (nfs41_fobx->acl && nfs41_fobx->acl_len) { if (nfs41_fobx->acl && nfs41_fobx->acl_len) {
LARGE_INTEGER current_time; LARGE_INTEGER current_time;
@ -4660,7 +4742,7 @@ NTSTATUS nfs41_QuerySecurityInformation(
InterlockedIncrement(&getacl.sops); InterlockedIncrement(&getacl.sops);
InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len); InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len);
#endif #endif
} } else status = 1;
RxFreePool(nfs41_fobx->acl); RxFreePool(nfs41_fobx->acl);
nfs41_fobx->acl = NULL; nfs41_fobx->acl = NULL;
nfs41_fobx->acl_len = 0; nfs41_fobx->acl_len = 0;
@ -4733,6 +4815,32 @@ out:
return status; return status;
} }
NTSTATUS check_nfs41_setacl_args(
PRX_CONTEXT RxContext)
{
NTSTATUS status = STATUS_SUCCESS;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
SECURITY_INFORMATION info_class =
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
if (pVNetRootContext->read_only) {
print_error("check_nfs41_setacl_args: Read-only mount\n");
status = STATUS_ACCESS_DENIED;
goto out;
}
/* we don't support sacls */
if (info_class == SACL_SECURITY_INFORMATION ||
info_class == LABEL_SECURITY_INFORMATION) {
status = STATUS_NOT_SUPPORTED;
goto out;
}
if (RxContext->CurrentIrp->UserBuffer == NULL)
status = STATUS_INVALID_USER_BUFFER;
out:
return status;
}
NTSTATUS nfs41_SetSecurityInformation( NTSTATUS nfs41_SetSecurityInformation(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -4760,11 +4868,8 @@ NTSTATUS nfs41_SetSecurityInformation(
print_acl_args(info_class); print_acl_args(info_class);
#endif #endif
if (pVNetRootContext->read_only) { status = check_nfs41_setacl_args(RxContext);
DbgP("Read-only mount\n"); if (status) goto out;
status = STATUS_ACCESS_DENIED;
goto out;
}
/* check that ACL is present */ /* check that ACL is present */
if (info_class & DACL_SECURITY_INFORMATION) { if (info_class & DACL_SECURITY_INFORMATION) {
@ -4782,11 +4887,6 @@ NTSTATUS nfs41_SetSecurityInformation(
} }
} }
/* we don't support sacls */
if (info_class == SACL_SECURITY_INFORMATION ||
info_class == LABEL_SECURITY_INFORMATION)
goto out;
status = nfs41_UpcallCreate(NFS41_ACL_SET, &nfs41_fobx->sec_ctx, status = nfs41_UpcallCreate(NFS41_ACL_SET, &nfs41_fobx->sec_ctx,
pVNetRootContext->session, nfs41_fobx->nfs41_open_state, pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry); pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
@ -4864,6 +4964,10 @@ NTSTATUS nfs41_QueryFileInformation(
DbgEn(); DbgEn();
print_debug_filedirquery_header(RxContext); print_debug_filedirquery_header(RxContext);
#endif #endif
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
switch (InfoClass) { switch (InfoClass) {
case FileEaInformation: case FileEaInformation:
{ {
@ -5000,6 +5104,98 @@ NTSTATUS map_setfile_error(
} }
} }
NTSTATUS check_nfs41_setattr_args(
IN PRX_CONTEXT RxContext)
{
NTSTATUS status = STATUS_SUCCESS;
FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
if (pVNetRootContext->read_only) {
print_error("check_nfs41_setattr_args: Read-only mount\n");
status = STATUS_ACCESS_DENIED;
goto out;
}
/* http://msdn.microsoft.com/en-us/library/ff469355(v=PROT.10).aspx
* http://msdn.microsoft.com/en-us/library/ff469424(v=PROT.10).aspx
* If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation
* MUST be failed with STATUS_ACCESS_DENIED.
*/
if (InfoClass == FileAllocationInformation ||
InfoClass == FileEndOfFileInformation) {
if (!(RxContext->pRelevantSrvOpen->DesiredAccess & FILE_WRITE_DATA)) {
status = STATUS_ACCESS_DENIED;
goto out;
}
}
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
switch (InfoClass) {
case FileRenameInformation:
{
PFILE_RENAME_INFORMATION rinfo =
(PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
UNICODE_STRING dst = { (USHORT)rinfo->FileNameLength,
(USHORT)rinfo->FileNameLength, rinfo->FileName };
#ifdef DEBUG_FILE_SET
DbgP("Attempting to rename to '%wZ'\n", &dst);
#endif
if (isFilenameTooLong(&dst, pVNetRootContext)) {
status = STATUS_OBJECT_NAME_INVALID;
goto out;
}
if (rinfo->RootDirectory) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
break;
}
case FileLinkInformation:
{
PFILE_LINK_INFORMATION linfo =
(PFILE_LINK_INFORMATION)RxContext->Info.Buffer;
UNICODE_STRING dst = { (USHORT)linfo->FileNameLength,
(USHORT)linfo->FileNameLength, linfo->FileName };
#ifdef DEBUG_FILE_SET
DbgP("Attempting to add link as '%wZ'\n", &dst);
#endif
if (isFilenameTooLong(&dst, pVNetRootContext)) {
status = STATUS_OBJECT_NAME_INVALID;
goto out;
}
if (linfo->RootDirectory) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
break;
}
case FileDispositionInformation:
{
PFILE_DISPOSITION_INFORMATION dinfo =
(PFILE_DISPOSITION_INFORMATION)RxContext->Info.Buffer;
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
if (dinfo->DeleteFile && nfs41_fcb->DeletePending) {
status = STATUS_DELETE_PENDING;
goto out;
}
break;
}
case FileBasicInformation:
case FileAllocationInformation:
case FileEndOfFileInformation:
break;
default:
print_error("nfs41_SetFileInformation: unhandled class %d\n", InfoClass);
status = STATUS_NOT_SUPPORTED;
}
out:
return status;
}
NTSTATUS nfs41_SetFileInformation( NTSTATUS nfs41_SetFileInformation(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -5025,115 +5221,49 @@ NTSTATUS nfs41_SetFileInformation(
print_debug_filedirquery_header(RxContext); print_debug_filedirquery_header(RxContext);
#endif #endif
if (pVNetRootContext->read_only) { status = check_nfs41_setattr_args(RxContext);
DbgP("Read-only mount\n"); if (status) goto out;
status = STATUS_ACCESS_DENIED;
goto out;
}
/* http://msdn.microsoft.com/en-us/library/ff469355(v=PROT.10).aspx
* http://msdn.microsoft.com/en-us/library/ff469424(v=PROT.10).aspx
* If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation
* MUST be failed with STATUS_ACCESS_DENIED.
*/
if (InfoClass == FileAllocationInformation ||
InfoClass == FileEndOfFileInformation) {
if (!(SrvOpen->DesiredAccess & FILE_WRITE_DATA)) {
status = STATUS_ACCESS_DENIED;
goto out;
}
}
switch (InfoClass) { switch (InfoClass) {
case FileRenameInformation:
{
PFILE_RENAME_INFORMATION rinfo =
(PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
UNICODE_STRING dst = { (USHORT)rinfo->FileNameLength,
(USHORT)rinfo->FileNameLength, rinfo->FileName };
#ifdef DEBUG_FILE_SET
DbgP("Attempting to rename to '%wZ'\n", &dst);
#endif
if (isFilenameTooLong(&dst, pVNetRootContext)) {
status = STATUS_OBJECT_NAME_INVALID;
goto out;
}
if (rinfo->RootDirectory) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
}
break;
case FileLinkInformation:
{
PFILE_LINK_INFORMATION linfo =
(PFILE_LINK_INFORMATION)RxContext->Info.Buffer;
UNICODE_STRING dst = { (USHORT)linfo->FileNameLength,
(USHORT)linfo->FileNameLength, linfo->FileName };
#ifdef DEBUG_FILE_SET
DbgP("Attempting to add link as '%wZ'\n", &dst);
#endif
if (isFilenameTooLong(&dst, pVNetRootContext)) {
status = STATUS_OBJECT_NAME_INVALID;
goto out;
}
if (linfo->RootDirectory) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
}
break;
case FileDispositionInformation: case FileDispositionInformation:
{ {
PFILE_DISPOSITION_INFORMATION dinfo = PFILE_DISPOSITION_INFORMATION dinfo =
(PFILE_DISPOSITION_INFORMATION)RxContext->Info.Buffer; (PFILE_DISPOSITION_INFORMATION)RxContext->Info.Buffer;
if (dinfo->DeleteFile) { if (dinfo->DeleteFile) {
if (nfs41_fcb->DeletePending) { nfs41_fcb->DeletePending = TRUE;
status = STATUS_DELETE_PENDING; // we can delete directories right away
goto out; if (nfs41_fcb->StandardInfo.Directory)
} break;
nfs41_fcb->StandardInfo.DeletePending = TRUE;
nfs41_fcb->DeletePending = TRUE; if (RxContext->pFcb->OpenCount > 1) {
// we can delete directories right away rinfo.ReplaceIfExists = 0;
if (nfs41_fcb->StandardInfo.Directory) rinfo.RootDirectory = INVALID_HANDLE_VALUE;
break; rinfo.FileNameLength = 0;
nfs41_fcb->StandardInfo.DeletePending = TRUE; rinfo.FileName[0] = L'\0';
if (RxContext->pFcb->OpenCount > 1) { InfoClass = FileRenameInformation;
rinfo.ReplaceIfExists = 0; nfs41_fcb->Renamed = TRUE;
rinfo.RootDirectory = INVALID_HANDLE_VALUE; break;
rinfo.FileNameLength = 0; }
rinfo.FileName[0] = L'\0'; } else {
InfoClass = FileRenameInformation; /* section 4.3.3 of [FSBO]
nfs41_fcb->Renamed = TRUE; * "file system behavior in the microsoft windows environment"
break; */
} if (nfs41_fcb->DeletePending) {
} else { nfs41_fcb->DeletePending = 0;
/* section 4.3.3 of [FSBO] nfs41_fcb->StandardInfo.DeletePending = 0;
* "file system behavior in the microsoft windows environment" }
*/
if (nfs41_fcb->DeletePending) {
nfs41_fcb->DeletePending = 0;
nfs41_fcb->StandardInfo.DeletePending = 0;
} }
status = STATUS_SUCCESS;
goto out;
} }
status = STATUS_SUCCESS;
goto out;
}
case FileBasicInformation:
case FileAllocationInformation:
break;
case FileEndOfFileInformation: case FileEndOfFileInformation:
{ {
PFILE_END_OF_FILE_INFORMATION info = PFILE_END_OF_FILE_INFORMATION info =
(PFILE_END_OF_FILE_INFORMATION)RxContext->Info.Buffer; (PFILE_END_OF_FILE_INFORMATION)RxContext->Info.Buffer;
nfs41_fcb->StandardInfo.AllocationSize = nfs41_fcb->StandardInfo.AllocationSize =
nfs41_fcb->StandardInfo.EndOfFile = info->EndOfFile; nfs41_fcb->StandardInfo.EndOfFile = info->EndOfFile;
break; break;
} }
default:
print_error("nfs41_SetFileInformation: unhandled class %d\n", InfoClass);
status = STATUS_NOT_SUPPORTED;
goto out;
} }
status = nfs41_UpcallCreate(NFS41_FILE_SET, &nfs41_fobx->sec_ctx, status = nfs41_UpcallCreate(NFS41_FILE_SET, &nfs41_fobx->sec_ctx,
@ -5349,6 +5479,14 @@ NTSTATUS map_readwrite_errors(
} }
} }
NTSTATUS check_nfs41_read_args(
IN PRX_CONTEXT RxContext)
{
if (!RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer)
return STATUS_INVALID_USER_BUFFER;
return STATUS_SUCCESS;
}
NTSTATUS nfs41_Read( NTSTATUS nfs41_Read(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -5373,6 +5511,8 @@ NTSTATUS nfs41_Read(
DbgEn(); DbgEn();
print_readwrite_args(RxContext); print_readwrite_args(RxContext);
#endif #endif
status = check_nfs41_read_args(RxContext);
if (status) goto out;
status = nfs41_UpcallCreate(NFS41_READ, &nfs41_fobx->sec_ctx, status = nfs41_UpcallCreate(NFS41_READ, &nfs41_fobx->sec_ctx,
pVNetRootContext->session, nfs41_fobx->nfs41_open_state, pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
@ -5441,6 +5581,27 @@ out:
return status; return status;
} }
NTSTATUS check_nfs41_write_args(
IN PRX_CONTEXT RxContext)
{
NTSTATUS status = STATUS_SUCCESS;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
if (!RxContext->LowIoContext.ParamsFor.ReadWrite.Buffer) {
status = STATUS_INVALID_USER_BUFFER;
goto out;
}
if (pVNetRootContext->read_only) {
print_error("check_nfs41_write_args: Read-only mount\n");
status = STATUS_ACCESS_DENIED;
goto out;
}
out:
return status;
}
NTSTATUS nfs41_Write( NTSTATUS nfs41_Write(
IN OUT PRX_CONTEXT RxContext) IN OUT PRX_CONTEXT RxContext)
{ {
@ -5466,11 +5627,8 @@ NTSTATUS nfs41_Write(
print_readwrite_args(RxContext); print_readwrite_args(RxContext);
#endif #endif
if (pVNetRootContext->read_only) { status = check_nfs41_write_args(RxContext);
DbgP("Read-only mount\n"); if (status) goto out;
status = STATUS_ACCESS_DENIED;
goto out;
}
status = nfs41_UpcallCreate(NFS41_WRITE, &nfs41_fobx->sec_ctx, status = nfs41_UpcallCreate(NFS41_WRITE, &nfs41_fobx->sec_ctx,
pVNetRootContext->session, nfs41_fobx->nfs41_open_state, pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
@ -5845,28 +6003,18 @@ void print_reparse_buffer(
DbgP("PrintName: %wZ\n", &name); DbgP("PrintName: %wZ\n", &name);
} }
NTSTATUS nfs41_SetReparsePoint( NTSTATUS check_nfs41_setreparse_args(
IN OUT PRX_CONTEXT RxContext) IN PRX_CONTEXT RxContext)
{ {
NTSTATUS status; NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING TargetName;
__notnull XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl; __notnull XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
__notnull PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer; __notnull PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer;
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PV_NET_ROOT VNetRoot = (PV_NET_ROOT)SrvOpen->pVNetRoot;
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext = __notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot); NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext = __notnull PV_NET_ROOT VNetRoot = (PV_NET_ROOT)SrvOpen->pVNetRoot;
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
const ULONG HeaderLen = REPARSE_DATA_BUFFER_HEADER_SIZE; const ULONG HeaderLen = REPARSE_DATA_BUFFER_HEADER_SIZE;
nfs41_updowncall_entry *entry;
#ifdef DEBUG_SYMLINK
DbgEn();
print_debug_header(RxContext);
print_reparse_buffer(Reparse);
#endif
/* access checks */ /* access checks */
if (VNetRootContext->read_only) { if (VNetRootContext->read_only) {
status = STATUS_MEDIA_WRITE_PROTECTED; status = STATUS_MEDIA_WRITE_PROTECTED;
@ -5914,6 +6062,32 @@ NTSTATUS nfs41_SetReparsePoint(
status = STATUS_IO_REPARSE_TAG_MISMATCH; status = STATUS_IO_REPARSE_TAG_MISMATCH;
goto out; goto out;
} }
out:
return status;
}
NTSTATUS nfs41_SetReparsePoint(
IN OUT PRX_CONTEXT RxContext)
{
NTSTATUS status;
UNICODE_STRING TargetName;
__notnull XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
__notnull PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer;
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
nfs41_updowncall_entry *entry;
#ifdef DEBUG_SYMLINK
DbgEn();
print_debug_header(RxContext);
print_reparse_buffer(Reparse);
#endif
status = check_nfs41_setreparse_args(RxContext);
if (status) goto out;
TargetName.MaximumLength = TargetName.Length = TargetName.MaximumLength = TargetName.Length =
Reparse->SymbolicLinkReparseBuffer.PrintNameLength; Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
@ -5941,27 +6115,16 @@ out:
return status; return status;
} }
NTSTATUS nfs41_GetReparsePoint( NTSTATUS check_nfs41_getreparse_args(
IN OUT PRX_CONTEXT RxContext) PRX_CONTEXT RxContext)
{ {
NTSTATUS status; NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING TargetName;
XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl; XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx); __notnull PV_NET_ROOT VNetRoot =
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; (PV_NET_ROOT)RxContext->pRelevantSrvOpen->pVNetRoot;
__notnull PV_NET_ROOT VNetRoot = (PV_NET_ROOT)SrvOpen->pVNetRoot;
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
nfs41_updowncall_entry *entry;
const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER, const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
SymbolicLinkReparseBuffer.PathBuffer); SymbolicLinkReparseBuffer.PathBuffer);
#ifdef DEBUG_SYMLINK
DbgEn();
#endif
/* must have a filename longer than vnetroot name, /* must have a filename longer than vnetroot name,
* or it's trying to operate on the volume itself */ * or it's trying to operate on the volume itself */
if (RxContext->CurrentIrpSp->FileObject->FileName.Length <= if (RxContext->CurrentIrpSp->FileObject->FileName.Length <=
@ -5978,7 +6141,7 @@ NTSTATUS nfs41_GetReparsePoint(
goto out; goto out;
} }
if (!BooleanFlagOn(RxContext->pFcb->Attributes, if (!BooleanFlagOn(RxContext->pFcb->Attributes,
FILE_ATTRIBUTE_REPARSE_POINT)) { FILE_ATTRIBUTE_REPARSE_POINT)) {
status = STATUS_NOT_A_REPARSE_POINT; status = STATUS_NOT_A_REPARSE_POINT;
DbgP("FILE_ATTRIBUTE_REPARSE_POINT is not set!\n"); DbgP("FILE_ATTRIBUTE_REPARSE_POINT is not set!\n");
goto out; goto out;
@ -5989,6 +6152,31 @@ NTSTATUS nfs41_GetReparsePoint(
status = STATUS_BUFFER_TOO_SMALL; status = STATUS_BUFFER_TOO_SMALL;
goto out; goto out;
} }
out:
return status;
}
NTSTATUS nfs41_GetReparsePoint(
IN OUT PRX_CONTEXT RxContext)
{
NTSTATUS status;
UNICODE_STRING TargetName;
XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
nfs41_updowncall_entry *entry;
const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
SymbolicLinkReparseBuffer.PathBuffer);
#ifdef DEBUG_SYMLINK
DbgEn();
#endif
status = check_nfs41_getreparse_args(RxContext);
if (status) goto out;
TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen); TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength - TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength -