Skip to content

Commit 339cb0e

Browse files
committed
Merge pull request #90428 from bruvzg/macos_detect_helper_exes
[macOS export] Detect embedded helper executables using MachO header.
2 parents 1f303e0 + bae2734 commit 339cb0e

File tree

4 files changed

+57
-20
lines changed

4 files changed

+57
-20
lines changed

platform/macos/export/export_plugin.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_pres
909909
return OK;
910910
}
911911

912-
Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) {
912+
Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn, bool p_set_id) {
913913
int codesign_tool = p_preset->get("codesign/codesign");
914914
switch (codesign_tool) {
915915
case 1: { // built-in ad-hoc
@@ -953,6 +953,12 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pre
953953
args.push_back("--code-signature-flags");
954954
args.push_back("runtime");
955955

956+
if (p_set_id) {
957+
String app_id = p_preset->get("application/bundle_identifier");
958+
args.push_back("--binary-identifier");
959+
args.push_back(app_id);
960+
}
961+
956962
args.push_back("-v"); /* provide some more feedback */
957963

958964
args.push_back(p_path);
@@ -1012,6 +1018,12 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pre
10121018
args.push_back(p_preset->get("codesign/identity"));
10131019
}
10141020

1021+
if (p_set_id) {
1022+
String app_id = p_preset->get("application/bundle_identifier");
1023+
args.push_back("-i");
1024+
args.push_back(app_id);
1025+
}
1026+
10151027
args.push_back("-v"); /* provide some more feedback */
10161028
args.push_back("-f");
10171029

@@ -1043,7 +1055,7 @@ Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_pre
10431055
}
10441056

10451057
Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path,
1046-
const String &p_ent_path, bool p_should_error_on_non_code) {
1058+
const String &p_ent_path, const String &p_helper_ent_path, bool p_should_error_on_non_code) {
10471059
static Vector<String> extensions_to_sign;
10481060

10491061
if (extensions_to_sign.is_empty()) {
@@ -1070,7 +1082,8 @@ Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPres
10701082
}
10711083

10721084
if (extensions_to_sign.find(current_file.get_extension()) > -1) {
1073-
Error code_sign_error{ _code_sign(p_preset, current_file_path, p_ent_path, false) };
1085+
int ftype = MachO::get_filetype(current_file_path);
1086+
Error code_sign_error{ _code_sign(p_preset, current_file_path, (ftype == 2 || ftype == 5) ? p_helper_ent_path : p_ent_path, false, (ftype == 2 || ftype == 5)) };
10741087
if (code_sign_error != OK) {
10751088
return code_sign_error;
10761089
}
@@ -1079,7 +1092,7 @@ Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPres
10791092
FileAccess::set_unix_permissions(current_file_path, 0755);
10801093
}
10811094
} else if (dir_access->current_is_dir()) {
1082-
Error code_sign_error{ _code_sign_directory(p_preset, current_file_path, p_ent_path, p_should_error_on_non_code) };
1095+
Error code_sign_error{ _code_sign_directory(p_preset, current_file_path, p_ent_path, p_helper_ent_path, p_should_error_on_non_code) };
10831096
if (code_sign_error != OK) {
10841097
return code_sign_error;
10851098
}
@@ -1097,6 +1110,7 @@ Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPres
10971110
Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path,
10981111
const String &p_in_app_path, bool p_sign_enabled,
10991112
const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
1113+
const String &p_helper_ent_path,
11001114
bool p_should_error_on_non_code_sign) {
11011115
static Vector<String> extensions_to_sign;
11021116

@@ -1186,10 +1200,11 @@ Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access
11861200
if (err == OK && p_sign_enabled) {
11871201
if (dir_access->dir_exists(p_src_path) && p_src_path.get_extension().is_empty()) {
11881202
// If it is a directory, find and sign all dynamic libraries.
1189-
err = _code_sign_directory(p_preset, p_in_app_path, p_ent_path, p_should_error_on_non_code_sign);
1203+
err = _code_sign_directory(p_preset, p_in_app_path, p_ent_path, p_helper_ent_path, p_should_error_on_non_code_sign);
11901204
} else {
11911205
if (extensions_to_sign.find(p_in_app_path.get_extension()) > -1) {
1192-
err = _code_sign(p_preset, p_in_app_path, p_ent_path, false);
1206+
int ftype = MachO::get_filetype(p_in_app_path);
1207+
err = _code_sign(p_preset, p_in_app_path, (ftype == 2 || ftype == 5) ? p_helper_ent_path : p_ent_path, false, (ftype == 2 || ftype == 5));
11931208
}
11941209
if (dir_access->file_exists(p_in_app_path) && is_executable(p_in_app_path)) {
11951210
// chmod with 0755 if the file is executable.
@@ -1203,13 +1218,13 @@ Error EditorExportPlatformMacOS::_copy_and_sign_files(Ref<DirAccess> &dir_access
12031218
Error EditorExportPlatformMacOS::_export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin,
12041219
const String &p_app_path_name, Ref<DirAccess> &dir_access,
12051220
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
1206-
const String &p_ent_path) {
1221+
const String &p_ent_path, const String &p_helper_ent_path) {
12071222
Error error{ OK };
12081223
const Vector<String> &macos_plugins{ p_editor_export_plugin->get_macos_plugin_files() };
12091224
for (int i = 0; i < macos_plugins.size(); ++i) {
12101225
String src_path{ ProjectSettings::get_singleton()->globalize_path(macos_plugins[i]) };
12111226
String path_in_app{ p_app_path_name + "/Contents/PlugIns/" + src_path.get_file() };
1212-
error = _copy_and_sign_files(dir_access, src_path, path_in_app, p_sign_enabled, p_preset, p_ent_path, false);
1227+
error = _copy_and_sign_files(dir_access, src_path, path_in_app, p_sign_enabled, p_preset, p_ent_path, p_helper_ent_path, false);
12131228
if (error != OK) {
12141229
break;
12151230
}
@@ -1786,8 +1801,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
17861801
add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("'rcodesign' doesn't support signing applications with embedded dynamic libraries."));
17871802
}
17881803

1804+
bool sandbox = p_preset->get("codesign/entitlements/app_sandbox/enabled");
17891805
String ent_path = p_preset->get("codesign/entitlements/custom_file");
1790-
String hlp_ent_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + "_helper.entitlements");
1806+
String hlp_ent_path = sandbox ? EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + "_helper.entitlements") : ent_path;
17911807
if (sign_enabled && (ent_path.is_empty())) {
17921808
ent_path = EditorPaths::get_singleton()->get_cache_dir().path_join(pkg_name + ".entitlements");
17931809

@@ -1939,7 +1955,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
19391955
err = ERR_CANT_CREATE;
19401956
}
19411957

1942-
if ((err == OK) && helpers.size() > 0) {
1958+
if ((err == OK) && sandbox && (helpers.size() > 0 || shared_objects.size() > 0)) {
19431959
ent_f = FileAccess::open(hlp_ent_path, FileAccess::WRITE);
19441960
if (ent_f.is_valid()) {
19451961
ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
@@ -1965,7 +1981,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
19651981
String hlp_path = helpers[i];
19661982
err = da->copy(hlp_path, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file());
19671983
if (err == OK && sign_enabled) {
1968-
err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path, false);
1984+
err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path, false, true);
19691985
}
19701986
FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755);
19711987
}
@@ -1977,11 +1993,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
19771993
String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
19781994
if (shared_objects[i].target.is_empty()) {
19791995
String path_in_app = tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file();
1980-
err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, true);
1996+
err = _copy_and_sign_files(da, src_path, path_in_app, sign_enabled, p_preset, ent_path, hlp_ent_path, true);
19811997
} else {
19821998
String path_in_app = tmp_app_path_name.path_join(shared_objects[i].target);
19831999
tmp_app_dir->make_dir_recursive(path_in_app);
1984-
err = _copy_and_sign_files(da, src_path, path_in_app.path_join(src_path.get_file()), sign_enabled, p_preset, ent_path, false);
2000+
err = _copy_and_sign_files(da, src_path, path_in_app.path_join(src_path.get_file()), sign_enabled, p_preset, ent_path, hlp_ent_path, false);
19852001
}
19862002
if (err != OK) {
19872003
break;
@@ -1990,7 +2006,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
19902006

19912007
Vector<Ref<EditorExportPlugin>> export_plugins{ EditorExport::get_singleton()->get_export_plugins() };
19922008
for (int i = 0; i < export_plugins.size(); ++i) {
1993-
err = _export_macos_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path);
2009+
err = _export_macos_plugins_for(export_plugins[i], tmp_app_path_name, da, sign_enabled, p_preset, ent_path, hlp_ent_path);
19942010
if (err != OK) {
19952011
break;
19962012
}
@@ -2010,7 +2026,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
20102026
if (ep.step(TTR("Code signing bundle"), 2)) {
20112027
return ERR_SKIP;
20122028
}
2013-
err = _code_sign(p_preset, tmp_app_path_name, ent_path);
2029+
err = _code_sign(p_preset, tmp_app_path_name, ent_path, true, false);
20142030
}
20152031

20162032
String noto_path = p_path;
@@ -2028,7 +2044,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
20282044
if (ep.step(TTR("Code signing DMG"), 3)) {
20292045
return ERR_SKIP;
20302046
}
2031-
err = _code_sign(p_preset, p_path, ent_path, false);
2047+
err = _code_sign(p_preset, p_path, ent_path, false, false);
20322048
}
20332049
} else if (export_format == "pkg") {
20342050
// Create a Installer.

platform/macos/export/export_plugin.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ class EditorExportPlatformMacOS : public EditorExportPlatform {
8989
void _make_icon(const Ref<EditorExportPreset> &p_preset, const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
9090

9191
Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path);
92-
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true);
93-
Error _code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_should_error_on_non_code = true);
92+
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn = true, bool p_set_id = false);
93+
Error _code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, const String &p_helper_ent_path, bool p_should_error_on_non_code = true);
9494
Error _copy_and_sign_files(Ref<DirAccess> &dir_access, const String &p_src_path, const String &p_in_app_path,
95-
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path,
95+
bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset, const String &p_ent_path, const String &p_helper_ent_path,
9696
bool p_should_error_on_non_code_sign);
9797
Error _export_macos_plugins_for(Ref<EditorExportPlugin> p_editor_export_plugin, const String &p_app_path_name,
9898
Ref<DirAccess> &dir_access, bool p_sign_enabled, const Ref<EditorExportPreset> &p_preset,
99-
const String &p_ent_path);
99+
const String &p_ent_path, const String &p_helper_ent_path);
100100
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
101101
Error _create_pkg(const Ref<EditorExportPreset> &p_preset, const String &p_pkg_path, const String &p_app_path_name);
102102
Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);

platform/macos/export/macho.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,26 @@ bool MachO::is_macho(const String &p_path) {
105105
return (magic == 0xcefaedfe || magic == 0xfeedface || magic == 0xcffaedfe || magic == 0xfeedfacf);
106106
}
107107

108+
uint32_t MachO::get_filetype(const String &p_path) {
109+
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::READ);
110+
ERR_FAIL_COND_V_MSG(fa.is_null(), 0, vformat("MachO: Can't open file: \"%s\".", p_path));
111+
uint32_t magic = fa->get_32();
112+
MachHeader mach_header;
113+
114+
// Read MachO header.
115+
if (magic == 0xcefaedfe || magic == 0xfeedface) {
116+
// Thin 32-bit binary.
117+
fa->get_buffer((uint8_t *)&mach_header, sizeof(MachHeader));
118+
} else if (magic == 0xcffaedfe || magic == 0xfeedfacf) {
119+
// Thin 64-bit binary.
120+
fa->get_buffer((uint8_t *)&mach_header, sizeof(MachHeader));
121+
fa->get_32(); // Skip extra reserved field.
122+
} else {
123+
ERR_FAIL_V_MSG(0, vformat("MachO: File is not a valid MachO binary: \"%s\".", p_path));
124+
}
125+
return mach_header.filetype;
126+
}
127+
108128
bool MachO::open_file(const String &p_path) {
109129
fa = FileAccess::open(p_path, FileAccess::READ_WRITE);
110130
ERR_FAIL_COND_V_MSG(fa.is_null(), false, vformat("MachO: Can't open file: \"%s\".", p_path));

platform/macos/export/macho.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class MachO : public RefCounted {
181181

182182
public:
183183
static bool is_macho(const String &p_path);
184+
static uint32_t get_filetype(const String &p_path);
184185

185186
bool open_file(const String &p_path);
186187

0 commit comments

Comments
 (0)