Reviewed-by: Kostiantyn Kostiuk <[email protected]>

On Mon, Sep 7, 2026 at 1:51 PM Marc-André Lureau <
[email protected]> wrote:

> The freeze, thaw and timeout events were created with a NULL DACL,
> granting unrestricted access. Any local process could open and signal
> them, allowing an unprivileged guest process to trigger a filesystem
> freeze or premature thaw.
>
> Replace the NULL DACL with an explicit ACL that grants EVENT_ALL_ACCESS
> only to SYSTEM and the built-in Administrators group, which are the
> accounts under which the VSS service and qemu-ga operate.
>
> Signed-off-by: Marc-André Lureau <[email protected]>
> ---
>  qga/vss-win32/requester.cpp | 52
> ++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 49 insertions(+), 3 deletions(-)
>
> diff --git a/qga/vss-win32/requester.cpp b/qga/vss-win32/requester.cpp
> index d36a90c17d1d..1b0155c691ef 100644
> --- a/qga/vss-win32/requester.cpp
> +++ b/qga/vss-win32/requester.cpp
> @@ -17,6 +17,7 @@
>  #include "install.h"
>  #include <vswriter.h>
>  #include <vsbackup.h>
> +#include <aclapi.h>
>
>  /* Max wait time for frozen event (VSS can only hold writes for 10
> seconds) */
>  #define VSS_TIMEOUT_FREEZE_MSEC 60000
> @@ -298,10 +299,14 @@ void requester_freeze(int *num_vols, void
> *mountpoints, ErrorSet *errset)
>      HRESULT hr;
>      LONG ctx;
>      GUID guidSnapshotSet = GUID_NULL;
> +    SID_IDENTIFIER_AUTHORITY sia_nt = SECURITY_NT_AUTHORITY;
> +    PSID pSidSystem = NULL, pSidAdmins = NULL;
>      SECURITY_DESCRIPTOR sd;
>      SECURITY_ATTRIBUTES sa;
> +    EXPLICIT_ACCESS ea[2];
> +    PACL pAcl = NULL;
>      WCHAR short_volume_name[64], *display_name = short_volume_name;
> -    DWORD wait_status;
> +    DWORD wait_status, aclResult;
>      int num_fixed_drives = 0, i;
>      int num_mount_points = 0;
>      VSS_BACKUP_TYPE vss_bt = get_vss_backup_type();
> @@ -313,9 +318,48 @@ void requester_freeze(int *num_vols, void
> *mountpoints, ErrorSet *errset)
>          return;
>      }
>
> -    /* Allow unrestricted access to events */
> +    /* Grant access to SYSTEM and Administrators only */
> +    if (!AllocateAndInitializeSid(&sia_nt, 1,
> +            SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
> +            &pSidSystem)) {
> +        err_set(errset, GetLastError(), "failed to create SYSTEM SID");
> +        goto out;
> +    }
> +    if (!AllocateAndInitializeSid(&sia_nt, 2,
> +            SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
> +            0, 0, 0, 0, 0, 0, &pSidAdmins)) {
> +        DWORD err = GetLastError();
> +        FreeSid(pSidSystem);
> +        err_set(errset, err, "failed to create Administrators SID");
> +        goto out;
> +    }
> +
> +    ZeroMemory(&ea, sizeof(ea));
> +    ea[0].grfAccessPermissions = EVENT_ALL_ACCESS;
> +    ea[0].grfAccessMode = SET_ACCESS;
> +    ea[0].grfInheritance = NO_INHERITANCE;
> +    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
> +    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
> +    ea[0].Trustee.ptstrName = (LPTSTR)pSidSystem;
> +    ea[1].grfAccessPermissions = EVENT_ALL_ACCESS;
> +    ea[1].grfAccessMode = SET_ACCESS;
> +    ea[1].grfInheritance = NO_INHERITANCE;
> +    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
> +    ea[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
> +    ea[1].Trustee.ptstrName = (LPTSTR)pSidAdmins;
> +
> +    aclResult = SetEntriesInAcl(2, ea, NULL, &pAcl);
> +    if (aclResult != ERROR_SUCCESS) {
> +        FreeSid(pSidSystem);
> +        FreeSid(pSidAdmins);
> +        err_set(errset, aclResult, "failed to create ACL for events");
> +        goto out;
> +    }
> +    FreeSid(pSidSystem);
> +    FreeSid(pSidAdmins);
> +
>      InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
> -    SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
> +    SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE);
>      sa.nLength = sizeof(sa);
>      sa.lpSecurityDescriptor = &sd;
>      sa.bInheritHandle = FALSE;
> @@ -551,6 +595,7 @@ void requester_freeze(int *num_vols, void
> *mountpoints, ErrorSet *errset)
>      }
>
>      qga_debug("end successful");
> +    LocalFree(pAcl);
>      return;
>
>  out:
> @@ -559,6 +604,7 @@ out:
>      }
>
>  out1:
> +    LocalFree(pAcl);
>      requester_cleanup();
>
>      qga_debug_end;
>
> --
> 2.55.0.543.g5ebe2ebe4ea8
>
>

Reply via email to