Fix up missing file permissions during installation
This CL addresses the missing file permission issue on machines that
were upgraded from Windows 7 to Windows 8 or later versions.
In order to support sandboxed applications on on Windows 8 and later
OSes, certain Mozc executables need to allow read/execute access for
"ALL APPLICATION PACKAGES" group. This is basically done by default if
Windows 8 or later OS is fresh-installed because "Program Files" already
has such an ACL (Access Control Entry) with inheritable bit.
If the machine was upgraded from Windows 7 or prior, however, already
existing folders such as "Program Files/Google" may not have such an ACE
even after OS upgrade. For those machines, Mozc needs to manually fix
up permissions in the installer. For now following four files need to
be accessible from sandboxed applications.
- GoogleIMEJaTIP32.dll (mozc_tip32.dll)
- GoogleIMEJaTIP64.dll (mozc_tip64.dll)
- GoogleIMEJaConverter.exe (mozc_server.exe)
- GoogleIMEJaRenderer.exe (mozc_renderer.exe)
To be precise, last two files just need to be visible to first two files
running in sandboxed applications to make sure IPC servers are valid (by
using GetNamedPipeServerProcessId API). Note that Windows does not
require the parent directly also needs to be readable. We can basically
care only about those fore files' permission.
There are basically two ways to fix up in our installer. One is to
write such logic by C++ and run as a custom action, and the other is to
let Windows Installer do by using MsiLockPermissionsEx table. The later
idea is actually easier. We can use MsiLockPermissionsEx as follows.
<Component Id='GIMEJaTIP64' Guid='*' Permanent='no'>
<File Id='GoogleIMEJaTIP64.dll'
Name='GoogleIMEJaTIP64.dll'
DiskId='1' Checksum='yes'
Source='$(var.MozcTIP64Path)' Vital='yes'>
<PermissionEx
Sddl="O:SYG:SYD:AI(A;;0x1200a9;;;AC)(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU)(A;ID;0x1200a9;;;AC)">
</File>
</Component>
However, if we use MsiLockPermissionsEx, Windows Installer always
overwrites existing file permissions, which could cause some troubles if
later version of Windows starts adding a new permission to directories
under "Program Files". Therefore, this CL uses a custom action as a
more predictable and reliable way to just fix up a missing permission.
BUG=
TEST=
REF_BUG=31902088
REF_CL=137117790
REF_TIME=2016-10-24T22:02:44-07:00
REF_TIME_RAW=1477371764 -0700
Yohei Yukawa
7 years ago
35 | 35 |
#include <sddl.h>
|
36 | 36 |
#include <strsafe.h>
|
37 | 37 |
|
|
38 |
#include <atlsecurity.h>
|
|
39 |
|
38 | 40 |
#include <memory>
|
39 | 41 |
#include <string>
|
40 | 42 |
|
|
1427 | 1429 |
return true;
|
1428 | 1430 |
}
|
1429 | 1431 |
|
|
1432 |
bool WinSandbox::EnsureAllApplicationPackagesPermisssion(
|
|
1433 |
const wstring &file_name) {
|
|
1434 |
// Get "All Application Packages" group SID.
|
|
1435 |
const ATL::CSid all_application_packages(
|
|
1436 |
Sid(WinBuiltinAnyPackageSid).GetPSID());
|
|
1437 |
|
|
1438 |
// Get current DACL (Discretionary Access Control List) of |file_name|.
|
|
1439 |
ATL::CDacl dacl;
|
|
1440 |
if (!ATL::AtlGetDacl(file_name.c_str(), SE_FILE_OBJECT, &dacl)) {
|
|
1441 |
return false;
|
|
1442 |
}
|
|
1443 |
|
|
1444 |
// As of Windows 10 Anniversary Update, following access masks (==0x1200a9)
|
|
1445 |
// are specified to files under Program Files by default.
|
|
1446 |
const ACCESS_MASK kDesiredMask =
|
|
1447 |
FILE_READ_DATA | FILE_READ_EA | FILE_EXECUTE | READ_CONTROL | SYNCHRONIZE;
|
|
1448 |
|
|
1449 |
// Check if the desired ACE is already specified or not.
|
|
1450 |
for (UINT i = 0; i < dacl.GetAceCount(); ++i) {
|
|
1451 |
CSid ace_sid;
|
|
1452 |
ACCESS_MASK acess_mask = 0;
|
|
1453 |
BYTE ace_type = 0;
|
|
1454 |
dacl.GetAclEntry(i, &ace_sid, &acess_mask, &ace_type);
|
|
1455 |
if (ace_sid == all_application_packages &&
|
|
1456 |
ace_type == ACCESS_ALLOWED_ACE_TYPE &&
|
|
1457 |
(acess_mask & kDesiredMask) == kDesiredMask) {
|
|
1458 |
// This is the desired ACE. There is nothing to do.
|
|
1459 |
return true;
|
|
1460 |
}
|
|
1461 |
}
|
|
1462 |
|
|
1463 |
// We are here because there is no desired ACE. Hence we do add it.
|
|
1464 |
if (!dacl.AddAllowedAce(
|
|
1465 |
all_application_packages, kDesiredMask, ACCESS_ALLOWED_ACE_TYPE)) {
|
|
1466 |
return false;
|
|
1467 |
}
|
|
1468 |
return ATL::AtlSetDacl(file_name.c_str(), SE_FILE_OBJECT, dacl);
|
|
1469 |
}
|
|
1470 |
|
1430 | 1471 |
} // namespace mozc
|
1431 | 1472 |
#endif // OS_WIN
|
183 | 183 |
IntegrityLevel integrity_level,
|
184 | 184 |
ScopedHandle* restricted_token);
|
185 | 185 |
|
|
186 |
// Returns true |file_name| already has or is updated to have an ACE
|
|
187 |
// (Access Control Entry) for "All Application Packages" group to have the
|
|
188 |
// following access masks:
|
|
189 |
// - FILE_READ_DATA
|
|
190 |
// - FILE_READ_EA
|
|
191 |
// - FILE_EXECUTE
|
|
192 |
// - READ_CONTROL
|
|
193 |
// - SYNCHRONIZE
|
|
194 |
static bool EnsureAllApplicationPackagesPermisssion(const wstring &file_name);
|
|
195 |
|
186 | 196 |
protected:
|
187 | 197 |
// Returns SDDL for given |shareble_object_type|.
|
188 | 198 |
// This method is placed here for unit testing.
|
29 | 29 |
|
30 | 30 |
MAJOR=2
|
31 | 31 |
MINOR=19
|
32 | |
BUILD=2654
|
|
32 |
BUILD=2655
|
33 | 33 |
REVISION=102
|
34 | 34 |
# This version represents the version of Mozc IME engine (converter, predictor,
|
35 | 35 |
# etc.). This version info is included both in the Mozc server and in the Mozc
|
46 | 46 |
#include "base/url.h"
|
47 | 47 |
#include "base/util.h"
|
48 | 48 |
#include "base/version.h"
|
|
49 |
#include "base/win_sandbox.h"
|
49 | 50 |
#include "base/win_util.h"
|
50 | 51 |
#include "client/client_interface.h"
|
51 | 52 |
#include "config/stats_config_util.h"
|
|
236 | 237 |
return TRUE;
|
237 | 238 |
}
|
238 | 239 |
|
|
240 |
// [Return='ignore']
|
|
241 |
UINT __stdcall EnsureAllApplicationPackagesPermisssions(MSIHANDLE msi_handle) {
|
|
242 |
DEBUG_BREAK_FOR_DEBUGGER();
|
|
243 |
if (!mozc::WinSandbox::EnsureAllApplicationPackagesPermisssion(
|
|
244 |
GetMozcComponentPath(mozc::kMozcServerName))) {
|
|
245 |
return ERROR_INSTALL_FAILURE;
|
|
246 |
}
|
|
247 |
if (!mozc::WinSandbox::EnsureAllApplicationPackagesPermisssion(
|
|
248 |
GetMozcComponentPath(mozc::kMozcRenderer))) {
|
|
249 |
return ERROR_INSTALL_FAILURE;
|
|
250 |
}
|
|
251 |
if (!mozc::WinSandbox::EnsureAllApplicationPackagesPermisssion(
|
|
252 |
GetMozcComponentPath(mozc::kMozcTIP32))) {
|
|
253 |
return ERROR_INSTALL_FAILURE;
|
|
254 |
}
|
|
255 |
if (mozc::SystemUtil::IsWindowsX64()) {
|
|
256 |
if (!mozc::WinSandbox::EnsureAllApplicationPackagesPermisssion(
|
|
257 |
GetMozcComponentPath(mozc::kMozcTIP64))) {
|
|
258 |
return ERROR_INSTALL_FAILURE;
|
|
259 |
}
|
|
260 |
}
|
|
261 |
return ERROR_SUCCESS;
|
|
262 |
}
|
|
263 |
|
239 | 264 |
UINT __stdcall CallIERefreshElevationPolicy(MSIHANDLE msi_handle) {
|
240 | 265 |
DEBUG_BREAK_FOR_DEBUGGER();
|
241 | 266 |
HRESULT result = ::IERefreshElevationPolicy();
|
0 | 0 |
EXPORTS
|
|
1 |
EnsureAllApplicationPackagesPermisssions
|
1 | 2 |
CallIERefreshElevationPolicy
|
2 | 3 |
InstallIME
|
3 | 4 |
InstallIMERollback
|
33 | 33 |
|
34 | 34 |
#include <windows.h>
|
35 | 35 |
#include <msi.h>
|
|
36 |
|
|
37 |
// Ensures that "ALL APPLICATION PACKAGES" group has read/execute accesses
|
|
38 |
// to server, renderer, and TIP DLL files.
|
|
39 |
UINT __stdcall EnsureAllApplicationPackagesPermisssions(MSIHANDLE msi_handle);
|
36 | 40 |
|
37 | 41 |
// Makes ieuser.exe update the cache of the elevation policies.
|
38 | 42 |
UINT __stdcall CallIERefreshElevationPolicy(MSIHANDLE msi_handle);
|
772 | 772 |
<CustomAction Id='UnregisterTIPRollback32' BinaryKey='CustomActions32'
|
773 | 773 |
DllEntry='UnregisterTIPRollback' Execute='rollback' Impersonate='no'
|
774 | 774 |
Return='ignore' />
|
|
775 |
<CustomAction Id='EnsureAllApplicationPackagesPermisssions'
|
|
776 |
BinaryKey='CustomActions32'
|
|
777 |
DllEntry='EnsureAllApplicationPackagesPermisssions' Execute='deferred'
|
|
778 |
Impersonate='no' Return='ignore' />
|
775 | 779 |
<CustomAction Id='CallIERefreshElevationPolicy' BinaryKey='CustomActions32'
|
776 | 780 |
DllEntry='CallIERefreshElevationPolicy' Execute='commit' Impersonate='no' />
|
777 | 781 |
<CustomAction Id='OpenUninstallSurveyPage' BinaryKey='CustomActions32'
|
|
902 | 906 |
<Custom Action='RegisterTIPRollback32' Before='RegisterTIP32' >
|
903 | 907 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602) AND (NOT UPGRADING)
|
904 | 908 |
</Custom>
|
905 | |
<Custom Action='RegisterTIP32' Before='EnsureIMEIsDisabledForServiceAccountAfterInstall' >
|
|
909 |
<Custom Action='RegisterTIP32'
|
|
910 |
Before='EnsureAllApplicationPackagesPermisssions' >
|
|
911 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602)
|
|
912 |
</Custom>
|
|
913 |
<Custom Action='EnsureAllApplicationPackagesPermisssions'
|
|
914 |
Before='EnsureIMEIsDisabledForServiceAccountAfterInstall' >
|
906 | 915 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602)
|
907 | 916 |
</Custom>
|
908 | 917 |
<Custom Action='EnsureIMEIsDisabledForServiceAccountAfterInstall'
|
861 | 861 |
<CustomAction Id='UnregisterTIPRollback64' BinaryKey='CustomActions64'
|
862 | 862 |
DllEntry='UnregisterTIPRollback' Execute='rollback' Impersonate='no'
|
863 | 863 |
Return='ignore' />
|
|
864 |
<CustomAction Id='EnsureAllApplicationPackagesPermisssions'
|
|
865 |
BinaryKey='CustomActions64'
|
|
866 |
DllEntry='EnsureAllApplicationPackagesPermisssions' Execute='deferred'
|
|
867 |
Impersonate='no' Return='ignore' />
|
864 | 868 |
<CustomAction Id='CallIERefreshElevationPolicy' BinaryKey='CustomActions32'
|
865 | 869 |
DllEntry='CallIERefreshElevationPolicy' Execute='commit' Impersonate='no' />
|
866 | 870 |
<CustomAction Id='OpenUninstallSurveyPage' BinaryKey='CustomActions32'
|
|
1006 | 1010 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602) AND (VersionNT64) AND (NOT UPGRADING)
|
1007 | 1011 |
</Custom>
|
1008 | 1012 |
<Custom Action='RegisterTIP64'
|
|
1013 |
Before='EnsureAllApplicationPackagesPermisssions' >
|
|
1014 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602) AND (VersionNT64)
|
|
1015 |
</Custom>
|
|
1016 |
<Custom Action='EnsureAllApplicationPackagesPermisssions'
|
1009 | 1017 |
Before='EnsureIMEIsDisabledForServiceAccountAfterInstall' >
|
1010 | |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602) AND (VersionNT64)
|
|
1018 |
(NOT (REMOVE="ALL")) AND (VersionNT >= 602)
|
1011 | 1019 |
</Custom>
|
1012 | 1020 |
<Custom Action='EnsureIMEIsDisabledForServiceAccountAfterInstall'
|
1013 | 1021 |
Before='InstallFinalize' >
|