ea: fail non-cygwin EAs without named attr support

if non-cygwin EAs are given to Create, SetEaInfo, or QueryEaInfo and the server does not support named attributes, fail with STATUS_EAS_NOT_SUPPORTED.  also adds access checks for FILE_READ_EA and FILE_WRITE_EA

Create will accept all 3 cygwin EAs: NfsV3Attributes, NfsActOnLink, and NfsSymlinkTargetName.  it now handles NfsActOnLink by adding FILE_OPEN_REPARSE_POINT to the create options

SetEaInfo will only accept NfsV3Attributes for setting the file mode. the other two will fail with STATUS_INVALID_PARAMETER.  removed handling of NfsActOnLink in setattr.c

QueryEaInfo will accept all 3 cygwin EAs

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2012-04-06 13:42:13 -04:00 committed by unknown
parent b3229d20f6
commit c837631750
2 changed files with 82 additions and 22 deletions

View file

@ -558,10 +558,8 @@ static int handle_setexattr(nfs41_upcall *upcall)
nfs41_open_stateid_arg(state, &stateid);
if ((strncmp("NfsV3Attributes", eainfo->EaName, eainfo->EaNameLength) == 0 &&
strlen("NfsV3Attributes") == eainfo->EaNameLength) ||
(strncmp("NfsActOnLink", eainfo->EaName, eainfo->EaNameLength)== 0 &&
strlen("NfsActOnLink") == eainfo->EaNameLength)) {
if (strncmp("NfsV3Attributes", eainfo->EaName, eainfo->EaNameLength) == 0
&& sizeof("NfsV3Attributes")-1 == eainfo->EaNameLength) {
info.mode = args->mode;
info.attrmask.arr[1] |= FATTR4_WORD1_MODE;
info.attrmask.count = 2;

View file

@ -3392,10 +3392,14 @@ NTSTATUS check_nfs41_create_args(
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
__notnull PFILE_FS_ATTRIBUTE_INFORMATION FsAttrs =
(PFILE_FS_ATTRIBUTE_INFORMATION)pVNetRootContext->FsAttrs;
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
__notnull PMRX_FCB Fcb = RxContext->pFcb;
__notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
PFILE_FULL_EA_INFORMATION ea = (PFILE_FULL_EA_INFORMATION)
RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
if (Fcb->pNetRoot->Type != NET_ROOT_DISK &&
Fcb->pNetRoot->Type != NET_ROOT_WILD) {
@ -3476,6 +3480,25 @@ NTSTATUS check_nfs41_create_args(
goto out;
}
if (ea) {
/* ignore cygwin EAs when checking support and access */
if (!AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength) &&
!AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength) &&
!AnsiStrEq(&NfsSymlinkTargetName, ea->EaName, ea->EaNameLength)) {
if (!(FsAttrs->FileSystemAttributes & FILE_SUPPORTS_EXTENDED_ATTRIBUTES)) {
status = STATUS_EAS_NOT_SUPPORTED;
goto out;
}
if ((params.DesiredAccess & FILE_WRITE_EA) == 0) {
status = STATUS_ACCESS_DENIED;
goto out;
}
}
} else if (RxContext->CurrentIrpSp->Parameters.Create.EaLength) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
out:
return status;
}
@ -3488,8 +3511,8 @@ NTSTATUS nfs41_Create(
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;
PFILE_FULL_EA_INFORMATION ea = (PFILE_FULL_EA_INFORMATION)
RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
@ -3510,8 +3533,7 @@ NTSTATUS nfs41_Create(
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);
if (ea) print_ea_info(0, ea);
#endif
status = check_nfs41_create_args(RxContext);
@ -3535,22 +3557,21 @@ NTSTATUS nfs41_Create(
entry->u.Open.attrs |= FILE_ATTRIBUTE_ARCHIVE;
entry->u.Open.disp = params.Disposition;
entry->u.Open.copts = params.CreateOptions;
/* treat the NfsActOnLink ea as FILE_OPEN_REPARSE_POINT */
if (ea && AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength))
entry->u.Open.copts |= FILE_OPEN_REPARSE_POINT;
entry->u.Open.srv_open = SrvOpen;
if (isDataAccess(params.DesiredAccess) || isOpen2Create(params.Disposition))
entry->u.Open.open_owner_id = InterlockedIncrement(&open_owner_id);
// if we are creating a file check if nfsv3attributes were passed in
if (params.Disposition != FILE_OPEN && params.Disposition != FILE_OVERWRITE) {
if (RxContext->CurrentIrp->AssociatedIrp.SystemBuffer) {
eainfo = (PFILE_FULL_EA_INFORMATION)
RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
if (AnsiStrEq(&NfsV3Attributes, eainfo->EaName, eainfo->EaNameLength)) {
attrs = (nfs3_attrs *)(eainfo->EaName + eainfo->EaNameLength + 1);
if (ea && AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength)) {
nfs3_attrs *attrs = (nfs3_attrs *)(ea->EaName + ea->EaNameLength + 1);
#ifdef DEBUG_OPEN
DbgP("creating file with mode %o\n", attrs->mode);
#endif
entry->u.Open.mode = attrs->mode;
}
}
if (!entry->u.Open.mode)
entry->u.Open.mode = 0777;
if (params.FileAttributes & FILE_ATTRIBUTE_READONLY)
@ -4415,16 +4436,38 @@ NTSTATUS check_nfs41_setea_args(
NTSTATUS status;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
__notnull PFILE_FS_ATTRIBUTE_INFORMATION FsAttrs =
(PFILE_FS_ATTRIBUTE_INFORMATION)pVNetRootContext->FsAttrs;
__notnull PFILE_FULL_EA_INFORMATION ea =
(PFILE_FULL_EA_INFORMATION)RxContext->Info.Buffer;
status = check_nfs41_dirquery_args(RxContext);
if (status) goto out;
if (ea == NULL) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
if (AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength) ||
AnsiStrEq(&NfsSymlinkTargetName, ea->EaName, ea->EaNameLength)) {
status = STATUS_INVALID_PARAMETER; /* only allowed on create */
goto out;
}
/* ignore cygwin EAs when checking support */
if (!(FsAttrs->FileSystemAttributes & FILE_SUPPORTS_EXTENDED_ATTRIBUTES)
&& !AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength)) {
status = STATUS_EAS_NOT_SUPPORTED;
goto out;
}
if ((RxContext->pRelevantSrvOpen->DesiredAccess & FILE_WRITE_EA) == 0) {
status = STATUS_ACCESS_DENIED;
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;
}
@ -4522,14 +4565,33 @@ NTSTATUS check_nfs41_queryea_args(
IN PRX_CONTEXT RxContext)
{
NTSTATUS status;
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(RxContext->pRelevantSrvOpen->pVNetRoot);
__notnull PFILE_FS_ATTRIBUTE_INFORMATION FsAttrs =
(PFILE_FS_ATTRIBUTE_INFORMATION)pVNetRootContext->FsAttrs;
PFILE_GET_EA_INFORMATION ea = (PFILE_GET_EA_INFORMATION)
RxContext->CurrentIrpSp->Parameters.QueryEa.EaList;
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)
if (ea == NULL) {
status = STATUS_INVALID_PARAMETER;
goto out;
}
/* ignore cygwin EAs when checking support */
if (!(FsAttrs->FileSystemAttributes & FILE_SUPPORTS_EXTENDED_ATTRIBUTES)
&& !AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength)
&& !AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength)
&& !AnsiStrEq(&NfsSymlinkTargetName, ea->EaName, ea->EaNameLength)) {
status = STATUS_EAS_NOT_SUPPORTED;
goto out;
}
if ((RxContext->pRelevantSrvOpen->DesiredAccess & FILE_READ_EA) == 0) {
status = STATUS_ACCESS_DENIED;
goto out;
}
out:
return status;
}
@ -4599,7 +4661,7 @@ NTSTATUS nfs41_QueryEaInformation(
query->EaNameLength)) {
const LONG LengthRequired = sizeof(FILE_FULL_EA_INFORMATION) +
NfsActOnLink.Length - sizeof(CHAR);
query->EaNameLength - sizeof(CHAR);
if (LengthRequired > RxContext->Info.LengthRemaining) {
status = STATUS_BUFFER_TOO_SMALL;
RxContext->InformationToReturn = LengthRequired;
@ -4608,9 +4670,9 @@ NTSTATUS nfs41_QueryEaInformation(
info->NextEntryOffset = 0;
info->Flags = 0;
info->EaNameLength = (UCHAR)NfsActOnLink.Length;
info->EaNameLength = query->EaNameLength;
info->EaValueLength = 0;
RtlCopyMemory(info->EaName, NfsActOnLink.Buffer, NfsActOnLink.Length);
RtlCopyMemory(info->EaName, query->EaName, query->EaNameLength);
RxContext->Info.LengthRemaining = LengthRequired;
status = STATUS_SUCCESS;
goto out;