From dd8d2aa871fc5841c281d1292c39ffb8edf1ebd1 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 4 Apr 2014 16:42:36 -0400 Subject: [PATCH] Windows: Deny writes/truncation to files w RO attr If the readonly file attribute is set on a file, refuse to process writes, truncations or overwrites. The afsd_service will do so and this can lead to data corruption. At the same time, writes from the redirector to afsd_service must not be denied because of the readonly attribute. That check was performed during the CreateFile. Otherwise, a new file can be created with the readonly attribute and then not be writable. Change-Id: I921a11eb8c1a3e642d60c23fc905b3febc0f0761 Reviewed-on: http://gerrit.openafs.org/10985 Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp | 12 ++++++++++++ src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp | 2 +- src/WINNT/afsrdr/user/RDRFunction.c | 11 +++++++++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp b/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp index 4254a7e08..50554821d 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSCreate.cpp @@ -3453,6 +3453,18 @@ AFSProcessOverwriteSupersede( IN PDEVICE_OBJECT DeviceObject, try_return( ntStatus); } + if ( BooleanFlagOn( pObjectInfo->FileAttributes, FILE_ATTRIBUTE_READONLY)) + { + + AFSDbgTrace(( AFS_SUBSYSTEM_FILE_PROCESSING, + AFS_TRACE_LEVEL_WARNING, + "AFSProcessOverwriteSupersede Request failed on %wZ due to read only file attribute\n", + Irp, + &DirectoryCB->NameInformation.FileName)); + + try_return( ntStatus = STATUS_ACCESS_DENIED); + } + // // Be sure we have an Fcb for the object block // diff --git a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp index eb3adaf27..1376d0645 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSWrite.cpp @@ -260,7 +260,7 @@ AFSCommonWrite( IN PDEVICE_OBJECT DeviceObject, "AFSCommonWrite (%p) Request failed due to read only volume\n", Irp)); - try_return( ntStatus = STATUS_ACCESS_DENIED); + try_return( ntStatus = STATUS_MEDIA_WRITE_PROTECTED); } // diff --git a/src/WINNT/afsrdr/user/RDRFunction.c b/src/WINNT/afsrdr/user/RDRFunction.c index 01a334e79..e1193d24f 100644 --- a/src/WINNT/afsrdr/user/RDRFunction.c +++ b/src/WINNT/afsrdr/user/RDRFunction.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2008 Secure Endpoints, Inc. - * Copyright (c) 2009-2013 Your File System, Inc. + * Copyright (c) 2009-2014 Your File System, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -6860,7 +6860,14 @@ RDR_WriteFile( IN cm_user_t *userp, /* Ensure that the caller can access this file */ lock_ObtainWrite(&scp->rw); - code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE, + /* + * Request PRSFS_WRITE | PRSFS_LOCK in order to bypass the unix mode + * check in cm_HaveAccessRights(). By the time RDR_WriteFile is called + * it is already too late to deny the write due to the readonly attribute. + * The Windows cache may have already accepted the data. Only if the + * user does not have real write permission should the write be denied. + */ + code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE | PRSFS_LOCK, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); if (code == CM_ERROR_NOACCESS && scp->creator == userp) { code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT, -- 2.39.5