mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-11-03 20:48:08 -06:00 
			
		
		
		
	dll: FspFsctlFixServiceSecurity: deny SERVICE_STOP to Everyone
Although the FSD can now be unloaded, this can only be done safely via the new FSP_FSCTL_UNLOAD control code. For this reason we disable the ability to stop the FSD via the Service Manager.
This commit is contained in:
		@@ -617,8 +617,7 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
 | 
				
			|||||||
    PSID WorldSid;
 | 
					    PSID WorldSid;
 | 
				
			||||||
    PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
 | 
					    PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
 | 
				
			||||||
    PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
 | 
					    PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
 | 
				
			||||||
    EXPLICIT_ACCESSW AccessEntry;
 | 
					    EXPLICIT_ACCESSW AccessEntries[2];
 | 
				
			||||||
    ACCESS_MASK AccessRights;
 | 
					 | 
				
			||||||
    PACL Dacl;
 | 
					    PACL Dacl;
 | 
				
			||||||
    BOOL DaclPresent, DaclDefaulted;
 | 
					    BOOL DaclPresent, DaclDefaulted;
 | 
				
			||||||
    DWORD Size;
 | 
					    DWORD Size;
 | 
				
			||||||
@@ -663,41 +662,28 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
 | 
				
			|||||||
        goto exit;
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START right for Everyone */
 | 
					    /* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START rights for Everyone */
 | 
				
			||||||
    AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
 | 
					    AccessEntries[0].grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
 | 
				
			||||||
    AccessEntry.grfAccessMode = GRANT_ACCESS;
 | 
					    AccessEntries[0].grfAccessMode = GRANT_ACCESS;
 | 
				
			||||||
    AccessEntry.grfInheritance = NO_INHERITANCE;
 | 
					    AccessEntries[0].grfInheritance = NO_INHERITANCE;
 | 
				
			||||||
    AccessEntry.Trustee.pMultipleTrustee = 0;
 | 
					    AccessEntries[0].Trustee.pMultipleTrustee = 0;
 | 
				
			||||||
    AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
 | 
					    AccessEntries[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
 | 
				
			||||||
    AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID;
 | 
					    AccessEntries[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
 | 
				
			||||||
    AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
 | 
					    AccessEntries[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
 | 
				
			||||||
    AccessEntry.Trustee.ptstrName = WorldSid;
 | 
					    AccessEntries[0].Trustee.ptstrName = WorldSid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* get the effective rights for Everyone */
 | 
					    /* prepare an EXPLICIT_ACCESS to deny the SERVICE_STOP right to Everyone */
 | 
				
			||||||
    AccessRights = 0;
 | 
					    AccessEntries[1].grfAccessPermissions = SERVICE_STOP;
 | 
				
			||||||
    if (DaclPresent && 0 != Dacl)
 | 
					    AccessEntries[1].grfAccessMode = DENY_ACCESS;
 | 
				
			||||||
    {
 | 
					    AccessEntries[1].grfInheritance = NO_INHERITANCE;
 | 
				
			||||||
        LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
 | 
					    AccessEntries[1].Trustee.pMultipleTrustee = 0;
 | 
				
			||||||
        if (0 != LastError)
 | 
					    AccessEntries[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
 | 
				
			||||||
            /*
 | 
					    AccessEntries[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
 | 
				
			||||||
             * Apparently GetEffectiveRightsFromAclW can fail with ERROR_CIRCULAR_DEPENDENCY
 | 
					    AccessEntries[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
 | 
				
			||||||
             * in some rare circumstances. Calling GetEffectiveRightsFromAclW is not essential
 | 
					    AccessEntries[1].Trustee.ptstrName = WorldSid;
 | 
				
			||||||
             * in this instance. It is only done to check whether the "Everyone/World" SID
 | 
					 | 
				
			||||||
             * already has the access required to start the FSD; if it does not have those
 | 
					 | 
				
			||||||
             * rights already they are added. It is probably safe to just assume that the
 | 
					 | 
				
			||||||
             * required rights are not there if GetEffectiveRightsFromAclW fails; the worst
 | 
					 | 
				
			||||||
             * that can happen is that the rights get added twice (which is benign).
 | 
					 | 
				
			||||||
             *
 | 
					 | 
				
			||||||
             * See https://github.com/winfsp/winfsp/issues/62
 | 
					 | 
				
			||||||
             */
 | 
					 | 
				
			||||||
            AccessRights = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* do we have the required access rights? */
 | 
					 | 
				
			||||||
    if (AccessEntry.grfAccessPermissions != (AccessRights & AccessEntry.grfAccessPermissions))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    /* create a new security descriptor with the new access */
 | 
					    /* create a new security descriptor with the new access */
 | 
				
			||||||
        LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor,
 | 
					    LastError = BuildSecurityDescriptorW(0, 0, 2, AccessEntries, 0, 0, SecurityDescriptor,
 | 
				
			||||||
        &Size, &NewSecurityDescriptor);
 | 
					        &Size, &NewSecurityDescriptor);
 | 
				
			||||||
    if (0 != LastError)
 | 
					    if (0 != LastError)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -711,7 +697,6 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
 | 
				
			|||||||
        Result = FspNtStatusFromWin32(GetLastError());
 | 
					        Result = FspNtStatusFromWin32(GetLastError());
 | 
				
			||||||
        goto exit;
 | 
					        goto exit;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Result = STATUS_SUCCESS;
 | 
					    Result = STATUS_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user