Create `path` with an explicit private security descriptor: owner stamped * to the token user and a protected, inheritable, user-only DACL. A plain * _mkdir takes the token's DEFAULT owner and the parent's inheritable DACL; * under an Administrators-default-owner policy (standard on Windows Server * and GitHub's elevated runners) the directory is then born owned by * BUILTIN\Administrators wi
| 71 | * back to plain _mkdir so degraded environments (Wine) keep working — |
| 72 | * downstream validation still gates security there. */ |
| 73 | static bool win_mkdtemp_private_create(const char *path) { |
| 74 | bool created = false; |
| 75 | HANDLE token = NULL; |
| 76 | TOKEN_USER *user = NULL; |
| 77 | PACL acl = NULL; |
| 78 | DWORD needed = 0; |
| 79 | wchar_t *wide = cbm_path_to_wide(path); |
| 80 | if (wide && OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) && |
| 81 | !GetTokenInformation(token, TokenUser, NULL, 0, &needed) && |
| 82 | GetLastError() == ERROR_INSUFFICIENT_BUFFER && (user = malloc(needed)) != NULL && |
| 83 | GetTokenInformation(token, TokenUser, user, needed, &needed) && user->User.Sid && |
| 84 | IsValidSid(user->User.Sid)) { |
| 85 | EXPLICIT_ACCESSW access; |
| 86 | memset(&access, 0, sizeof(access)); |
| 87 | access.grfAccessPermissions = GENERIC_ALL; |
| 88 | access.grfAccessMode = SET_ACCESS; |
| 89 | access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
| 90 | access.Trustee.TrusteeForm = TRUSTEE_IS_SID; |
| 91 | access.Trustee.TrusteeType = TRUSTEE_IS_USER; |
| 92 | access.Trustee.ptstrName = (LPWSTR)user->User.Sid; |
| 93 | SECURITY_DESCRIPTOR descriptor; |
| 94 | if (SetEntriesInAclW(1, &access, NULL, &acl) == ERROR_SUCCESS && |
| 95 | InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION) && |
| 96 | SetSecurityDescriptorDacl(&descriptor, TRUE, acl, FALSE) && |
| 97 | SetSecurityDescriptorOwner(&descriptor, user->User.Sid, FALSE) && |
| 98 | SetSecurityDescriptorControl(&descriptor, SE_DACL_PROTECTED, SE_DACL_PROTECTED)) { |
| 99 | SECURITY_ATTRIBUTES attributes; |
| 100 | attributes.nLength = sizeof(attributes); |
| 101 | attributes.lpSecurityDescriptor = &descriptor; |
| 102 | attributes.bInheritHandle = FALSE; |
| 103 | created = CreateDirectoryW(wide, &attributes) != 0; |
| 104 | } |
| 105 | } |
| 106 | if (acl) { |
| 107 | (void)LocalFree(acl); |
| 108 | } |
| 109 | free(user); |
| 110 | if (token) { |
| 111 | (void)CloseHandle(token); |
| 112 | } |
| 113 | free(wide); |
| 114 | return created; |
| 115 | } |
| 116 | |
| 117 | char *cbm_mkdtemp(char *tmpl) { |
| 118 | /* Per-call storage is required: daemon sessions invoke mkdtemp concurrently. |
no test coverage detected