| 4171 | } |
| 4172 | |
| 4173 | static bool win_runtime_directory_secure(const wchar_t *runtime_dir) { |
| 4174 | win_security_t security; |
| 4175 | if (!win_security_init(&security)) { |
| 4176 | return false; |
| 4177 | } |
| 4178 | bool created = CreateDirectoryW(runtime_dir, &security.directory_attributes) != 0; |
| 4179 | if (!created && GetLastError() != ERROR_ALREADY_EXISTS) { |
| 4180 | win_security_destroy(&security); |
| 4181 | return false; |
| 4182 | } |
| 4183 | DWORD attributes = GetFileAttributesW(runtime_dir); |
| 4184 | if (attributes == INVALID_FILE_ATTRIBUTES || (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 || |
| 4185 | (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { |
| 4186 | win_security_destroy(&security); |
| 4187 | return false; |
| 4188 | } |
| 4189 | HANDLE directory = |
| 4190 | CreateFileW(runtime_dir, READ_CONTROL | WRITE_DAC | WRITE_OWNER, |
| 4191 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, |
| 4192 | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| 4193 | bool can_write_owner = directory != INVALID_HANDLE_VALUE; |
| 4194 | if (!can_write_owner) { |
| 4195 | directory = |
| 4196 | CreateFileW(runtime_dir, READ_CONTROL | WRITE_DAC, |
| 4197 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, |
| 4198 | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| 4199 | } |
| 4200 | if (directory == INVALID_HANDLE_VALUE) { |
| 4201 | win_security_destroy(&security); |
| 4202 | return false; |
| 4203 | } |
| 4204 | BY_HANDLE_FILE_INFORMATION file_info; |
| 4205 | bool valid_handle = GetFileInformationByHandle(directory, &file_info) != 0 && |
| 4206 | (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && |
| 4207 | (file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0; |
| 4208 | bool owner_exact = valid_handle && win_file_owner_secure(&security, directory, true); |
| 4209 | /* One-time normalization of the admin-group default-owner artifact: a |
| 4210 | * directory created by plain mkdir under an Administrators-default-owner |
| 4211 | * token (standard policy on Windows Server) is born owned by BUILTIN\ |
| 4212 | * Administrators even though it is this account's own private dir. A |
| 4213 | * TRUSTED owner (the launcher's directory policy: SYSTEM, Administrators, |
| 4214 | * TrustedInstaller) is re-stamped to the exact token user inside the same |
| 4215 | * repair that already re-protects the DACL; any other owner remains |
| 4216 | * refused, and the final validation below still demands the exact user. */ |
| 4217 | bool owner_ok = owner_exact || (valid_handle && can_write_owner && |
| 4218 | win_file_owner_secure(&security, directory, false)); |
| 4219 | DWORD secure_result = ERROR_ACCESS_DENIED; |
| 4220 | if (valid_handle && owner_ok) { |
| 4221 | secure_result = security.set_security_info( |
| 4222 | directory, SE_FILE_OBJECT, |
| 4223 | (owner_exact ? 0U : (DWORD)OWNER_SECURITY_INFORMATION) | DACL_SECURITY_INFORMATION | |
| 4224 | PROTECTED_DACL_SECURITY_INFORMATION, |
| 4225 | owner_exact ? NULL : security.user_sid, NULL, security.directory_acl, NULL); |
| 4226 | } |
| 4227 | if (valid_handle && owner_ok && secure_result != ERROR_SUCCESS) { |
| 4228 | ipc_validation_detail_set("owner/DACL repair failed (status %lu%s)", |
| 4229 | (unsigned long)secure_result, |
| 4230 | can_write_owner ? "" : ", WRITE_OWNER unavailable"); |
no test coverage detected