saving security context in fobx

instead of getting security context on every upcall, acquire security context on open and save it in fobx. cache manager does read and write calls in a system csecurity context not in users, thus we need to use the context of the open instead.
This commit is contained in:
Olga Kornievskaia 2011-01-07 14:49:41 -05:00 committed by unknown
parent 089a52906b
commit 4c07c25dbb

View file

@ -118,6 +118,7 @@ typedef struct _updowncall_entry {
DWORD errno; DWORD errno;
BOOLEAN async_op; BOOLEAN async_op;
SECURITY_CLIENT_CONTEXT sec_ctx; SECURITY_CLIENT_CONTEXT sec_ctx;
PSECURITY_CLIENT_CONTEXT psec_ctx;
union { union {
struct { struct {
PUNICODE_STRING srv_name; PUNICODE_STRING srv_name;
@ -341,6 +342,7 @@ typedef struct _NFS41_FOBX {
NODE_BYTE_SIZE NodeByteSize; NODE_BYTE_SIZE NodeByteSize;
HANDLE nfs41_open_state; HANDLE nfs41_open_state;
SECURITY_CLIENT_CONTEXT sec_ctx;
} NFS41_FOBX, *PNFS41_FOBX; } NFS41_FOBX, *PNFS41_FOBX;
#define NFS41GetFileObjectExtension(pFobx) \ #define NFS41GetFileObjectExtension(pFobx) \
(((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context)) (((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context))
@ -1123,7 +1125,7 @@ handle_upcall(
ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength; ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
unsigned char *pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer; unsigned char *pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
status = SeImpersonateClientEx(&entry->sec_ctx, NULL); status = SeImpersonateClientEx(entry->psec_ctx, NULL);
if (status != STATUS_SUCCESS) if (status != STATUS_SUCCESS)
print_error("SeImpersonateClientEx failed %x\n", status); print_error("SeImpersonateClientEx failed %x\n", status);
@ -1188,6 +1190,7 @@ handle_upcall(
NTSTATUS nfs41_UpcallCreate( NTSTATUS nfs41_UpcallCreate(
IN DWORD opcode, IN DWORD opcode,
IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
OUT nfs41_updowncall_entry **entry_out) OUT nfs41_updowncall_entry **entry_out)
{ {
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
@ -1210,6 +1213,7 @@ NTSTATUS nfs41_UpcallCreate(
KeInitializeEvent(&entry->cond, SynchronizationEvent, FALSE); KeInitializeEvent(&entry->cond, SynchronizationEvent, FALSE);
ExInitializeFastMutex(&entry->lock); ExInitializeFastMutex(&entry->lock);
if (clnt_sec_ctx == NULL) {
SeCaptureSubjectContext(&sec_ctx); SeCaptureSubjectContext(&sec_ctx);
sec_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; sec_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
sec_qos.ImpersonationLevel = SecurityImpersonation; sec_qos.ImpersonationLevel = SecurityImpersonation;
@ -1221,7 +1225,10 @@ NTSTATUS nfs41_UpcallCreate(
"failed with %x\n", status); "failed with %x\n", status);
RxFreePool(entry); RxFreePool(entry);
} }
entry->psec_ctx = &entry->sec_ctx;
SeReleaseSubjectContext(&sec_ctx); SeReleaseSubjectContext(&sec_ctx);
} else
entry->psec_ctx = clnt_sec_ctx;
*entry_out = entry; *entry_out = entry;
out: out:
@ -1376,10 +1383,12 @@ nfs41_downcall (
} }
ExAcquireFastMutex(&cur->lock); ExAcquireFastMutex(&cur->lock);
SeStopImpersonatingClient();
if (cur->state == NFS41_NOT_WAITING) { if (cur->state == NFS41_NOT_WAITING) {
print_error("[downcall] Nobody is waiting for this request!!!\n"); print_error("[downcall] Nobody is waiting for this request!!!\n");
ExReleaseFastMutex(&cur->lock); ExReleaseFastMutex(&cur->lock);
nfs41_RemoveEntry(downcallLock, downcall, cur); nfs41_RemoveEntry(downcallLock, downcall, cur);
SeDeleteClientSecurity(cur->psec_ctx);
RxFreePool(cur); RxFreePool(cur);
status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL;
goto out_free; goto out_free;
@ -1486,7 +1495,6 @@ nfs41_downcall (
} }
} }
DbgP("[downcall] About to signal waiting IO thread\n"); DbgP("[downcall] About to signal waiting IO thread\n");
SeDeleteClientSecurity(&cur->sec_ctx);
ExReleaseFastMutex(&cur->lock); ExReleaseFastMutex(&cur->lock);
if (cur->async_op) { if (cur->async_op) {
if (cur->status == STATUS_SUCCESS) { if (cur->status == STATUS_SUCCESS) {
@ -1514,7 +1522,7 @@ NTSTATUS nfs41_shutdown_daemon(DWORD version)
nfs41_updowncall_entry *entry = NULL; nfs41_updowncall_entry *entry = NULL;
DbgEn(); DbgEn();
status = nfs41_UpcallCreate(NFS41_SHUTDOWN, &entry); status = nfs41_UpcallCreate(NFS41_SHUTDOWN, NULL, &entry);
if (status) if (status)
goto out; goto out;
entry->version = version; entry->version = version;
@ -1523,6 +1531,7 @@ NTSTATUS nfs41_shutdown_daemon(DWORD version)
status = STATUS_INTERNAL_ERROR; status = STATUS_INTERNAL_ERROR;
goto out; goto out;
} }
SeDeleteClientSecurity(&entry->sec_ctx);
RxFreePool(entry); RxFreePool(entry);
out: out:
DbgEx(); DbgEx();
@ -1766,7 +1775,7 @@ NTSTATUS nfs41_unmount(HANDLE session, DWORD version)
nfs41_updowncall_entry *entry; nfs41_updowncall_entry *entry;
DbgEn(); DbgEn();
status = nfs41_UpcallCreate(NFS41_UNMOUNT, &entry); status = nfs41_UpcallCreate(NFS41_UNMOUNT, NULL, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Mount.session = session; entry->u.Mount.session = session;
@ -1776,6 +1785,7 @@ NTSTATUS nfs41_unmount(HANDLE session, DWORD version)
status = STATUS_INTERNAL_ERROR; status = STATUS_INTERNAL_ERROR;
goto out; goto out;
} }
SeDeleteClientSecurity(&entry->sec_ctx);
RxFreePool(entry); RxFreePool(entry);
out: out:
DbgEx(); DbgEx();
@ -2119,7 +2129,7 @@ NTSTATUS nfs41_mount(PUNICODE_STRING srv_name, PUNICODE_STRING root,
nfs41_updowncall_entry *entry; nfs41_updowncall_entry *entry;
DbgEn(); DbgEn();
status = nfs41_UpcallCreate(NFS41_MOUNT, &entry); status = nfs41_UpcallCreate(NFS41_MOUNT, NULL, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Mount.srv_name = srv_name; entry->u.Mount.srv_name = srv_name;
@ -2131,6 +2141,7 @@ NTSTATUS nfs41_mount(PUNICODE_STRING srv_name, PUNICODE_STRING root,
status = STATUS_INTERNAL_ERROR; status = STATUS_INTERNAL_ERROR;
goto out; goto out;
} }
SeDeleteClientSecurity(&entry->sec_ctx);
*session = entry->u.Mount.session; *session = entry->u.Mount.session;
/* map windows ERRORs to NTSTATUS */ /* map windows ERRORs to NTSTATUS */
@ -2706,7 +2717,7 @@ NTSTATUS nfs41_Create(
goto out; goto out;
} }
status = nfs41_UpcallCreate(NFS41_OPEN, &entry); status = nfs41_UpcallCreate(NFS41_OPEN, NULL, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Open.filename = SrvOpen->pAlreadyPrefixedName; entry->u.Open.filename = SrvOpen->pAlreadyPrefixedName;
@ -2738,6 +2749,7 @@ NTSTATUS nfs41_Create(
status = STATUS_INTERNAL_ERROR; status = STATUS_INTERNAL_ERROR;
goto out; goto out;
} }
SeDeleteClientSecurity(&entry->sec_ctx);
if (entry->status == NO_ERROR && entry->errno == ERROR_REPARSE) { if (entry->status == NO_ERROR && entry->errno == ERROR_REPARSE) {
/* symbolic link handling. when attempting to open a symlink when the /* symbolic link handling. when attempting to open a symlink when the
@ -2804,6 +2816,23 @@ NTSTATUS nfs41_Create(
print_fobx(1, RxContext->pFobx); print_fobx(1, RxContext->pFobx);
nfs41_fobx = (PNFS41_FOBX)(RxContext->pFobx)->Context; nfs41_fobx = (PNFS41_FOBX)(RxContext->pFobx)->Context;
nfs41_fobx->nfs41_open_state = entry->u.Open.open_state; nfs41_fobx->nfs41_open_state = entry->u.Open.open_state;
{
SECURITY_SUBJECT_CONTEXT sec_ctx;
SECURITY_QUALITY_OF_SERVICE sec_qos;
SeCaptureSubjectContext(&sec_ctx);
sec_qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
sec_qos.ImpersonationLevel = SecurityImpersonation;
sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
sec_qos.EffectiveOnly = 0;
status = SeCreateClientSecurityFromSubjectContext(&sec_ctx, &sec_qos, 1, &nfs41_fobx->sec_ctx);
if (status != STATUS_SUCCESS) {
print_error("SeCreateClientSecurityFromSubjectContext "
"failed with %x\n", status);
RxFreePool(entry);
}
DbgP("Created client security token %p\n", nfs41_fobx->sec_ctx.ClientToken);
SeReleaseSubjectContext(&sec_ctx);
}
// we get attributes only for data access and file (not directories) // we get attributes only for data access and file (not directories)
if (Fcb->OpenCount > 0) if (Fcb->OpenCount > 0)
@ -3022,7 +3051,7 @@ NTSTATUS nfs41_CloseSrvOpen (
DbgEn(); DbgEn();
print_close_args(RxContext); print_close_args(RxContext);
status = nfs41_UpcallCreate(NFS41_CLOSE, &entry); status = nfs41_UpcallCreate(NFS41_CLOSE, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Close.open_state = nfs41_fobx->nfs41_open_state; entry->u.Close.open_state = nfs41_fobx->nfs41_open_state;
@ -3045,6 +3074,7 @@ NTSTATUS nfs41_CloseSrvOpen (
/* map windows ERRORs to NTSTATUS */ /* map windows ERRORs to NTSTATUS */
status = map_close_errors(entry->status); status = map_close_errors(entry->status);
RxFreePool(entry); RxFreePool(entry);
SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
out: out:
DbgEx(); DbgEx();
return status; return status;
@ -3174,7 +3204,7 @@ NTSTATUS nfs41_QueryDirectory (
goto out; goto out;
} }
status = nfs41_UpcallCreate(NFS41_DIR_QUERY, &entry); status = nfs41_UpcallCreate(NFS41_DIR_QUERY, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.QueryFile.open_state = nfs41_fobx->nfs41_open_state; entry->u.QueryFile.open_state = nfs41_fobx->nfs41_open_state;
@ -3247,6 +3277,7 @@ NTSTATUS nfs41_QueryVolumeInformation (
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext = PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot); NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
PNFS41_FOBX nfs41_fobx = (PNFS41_FOBX)(RxContext->pFobx)->Context;
nfs41_updowncall_entry *entry; nfs41_updowncall_entry *entry;
PNFS41_NETROOT_EXTENSION pNetRootContext = PNFS41_NETROOT_EXTENSION pNetRootContext =
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot); NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
@ -3325,7 +3356,7 @@ NTSTATUS nfs41_QueryVolumeInformation (
goto out; goto out;
} }
status = nfs41_UpcallCreate(NFS41_VOLUME_QUERY, &entry); status = nfs41_UpcallCreate(NFS41_VOLUME_QUERY, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Volume.session = pVNetRootContext->session; entry->u.Volume.session = pVNetRootContext->session;
@ -3533,7 +3564,7 @@ NTSTATUS nfs41_SetEaInformation (
} else } else
goto out; goto out;
status = nfs41_UpcallCreate(NFS41_EA_SET, &entry); status = nfs41_UpcallCreate(NFS41_EA_SET, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.SetEa.open_state = nfs41_fobx->nfs41_open_state; entry->u.SetEa.open_state = nfs41_fobx->nfs41_open_state;
@ -3682,7 +3713,7 @@ NTSTATUS nfs41_QueryFileInformation (
} }
print_queryfile_args(RxContext); print_queryfile_args(RxContext);
status = nfs41_UpcallCreate(NFS41_FILE_QUERY, &entry); status = nfs41_UpcallCreate(NFS41_FILE_QUERY, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.QueryFile.open_state = nfs41_fobx->nfs41_open_state; entry->u.QueryFile.open_state = nfs41_fobx->nfs41_open_state;
@ -3874,7 +3905,7 @@ NTSTATUS nfs41_SetFileInformation (
goto out; goto out;
} }
status = nfs41_UpcallCreate(NFS41_FILE_SET, &entry); status = nfs41_UpcallCreate(NFS41_FILE_SET, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.SetFile.open_state = nfs41_fobx->nfs41_open_state; entry->u.SetFile.open_state = nfs41_fobx->nfs41_open_state;
@ -4063,7 +4094,7 @@ NTSTATUS nfs41_Read (
DbgEn(); DbgEn();
print_readwrite_args(RxContext); print_readwrite_args(RxContext);
status = nfs41_UpcallCreate(NFS41_READ, &entry); status = nfs41_UpcallCreate(NFS41_READ, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.ReadWrite.open_state = nfs41_fobx->nfs41_open_state; entry->u.ReadWrite.open_state = nfs41_fobx->nfs41_open_state;
@ -4128,7 +4159,7 @@ NTSTATUS nfs41_Write (
DbgEn(); DbgEn();
print_readwrite_args(RxContext); print_readwrite_args(RxContext);
status = nfs41_UpcallCreate(NFS41_WRITE, &entry); status = nfs41_UpcallCreate(NFS41_WRITE, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.ReadWrite.open_state = nfs41_fobx->nfs41_open_state; entry->u.ReadWrite.open_state = nfs41_fobx->nfs41_open_state;
@ -4268,7 +4299,7 @@ NTSTATUS nfs41_Lock(
/* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb, /* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb,
LowIoContext->ResourceThreadId); */ LowIoContext->ResourceThreadId); */
status = nfs41_UpcallCreate(NFS41_LOCK, &entry); status = nfs41_UpcallCreate(NFS41_LOCK, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Lock.open_state = nfs41_fobx->nfs41_open_state; entry->u.Lock.open_state = nfs41_fobx->nfs41_open_state;
@ -4352,7 +4383,7 @@ NTSTATUS nfs41_Unlock(
/* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb, /* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb,
LowIoContext->ResourceThreadId); */ LowIoContext->ResourceThreadId); */
status = nfs41_UpcallCreate(NFS41_UNLOCK, &entry); status = nfs41_UpcallCreate(NFS41_UNLOCK, &nfs41_fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
entry->u.Unlock.open_state = nfs41_fobx->nfs41_open_state; entry->u.Unlock.open_state = nfs41_fobx->nfs41_open_state;
@ -4455,7 +4486,7 @@ static NTSTATUS nfs41_SetReparsePoint(
TargetName.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[ TargetName.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
Reparse->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)]; Reparse->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
status = nfs41_UpcallCreate(NFS41_SYMLINK, &entry); status = nfs41_UpcallCreate(NFS41_SYMLINK, &Fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;
@ -4510,7 +4541,7 @@ static NTSTATUS nfs41_GetReparsePoint(
TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen); TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength - HeaderLen, 0xFFFF); TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength - HeaderLen, 0xFFFF);
status = nfs41_UpcallCreate(NFS41_SYMLINK, &entry); status = nfs41_UpcallCreate(NFS41_SYMLINK, &Fobx->sec_ctx, &entry);
if (status) if (status)
goto out; goto out;