Skip to content

Commit c7daf0c

Browse files
committed
Fix close override not applying to CEF
Recent Chromium versions use RTLD_NEXT to find the close() to invoke. This results in libcef.so, which comes *after* zypak's libraries in the resolution order, calling libc's close instead of our close. To fix that, split out close() overrides into their own library, and put libcef in LD_PRELOAD between the other zypak overrides and the close() override. Fixes #34. Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
1 parent 3e1ee34 commit c7daf0c

File tree

7 files changed

+51
-17
lines changed

7 files changed

+51
-17
lines changed

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,20 @@ preload_host_spawn_strategy_DEPS := preload dbus base
8080
preload_host_spawn_strategy_SOURCES := \
8181
bus_safe_fork.cc \
8282
initialize.cc \
83-
no_close_host_fd.cc \
8483
process_override.cc \
8584
spawn_launcher_delegate.cc \
8685
supervisor.cc \
8786

8887
$(call build_shlib,preload_host_spawn_strategy)
8988

89+
preload_host_spawn_strategy_close_SOURCE_DIR := preload/host/spawn_strategy/close
90+
preload_host_spawn_strategy_close_NAME := zypak-preload-host-spawn-strategy-close
91+
preload_host_spawn_strategy_close_DEPS := preload base
92+
preload_host_spawn_strategy_close_SOURCES := \
93+
no_close_host_fd.cc \
94+
95+
$(call build_shlib,preload_host_spawn_strategy_close)
96+
9097
preload_child_SOURCE_DIR := preload/child
9198
preload_child_NAME := zypak-preload-child
9299
preload_child_DEPS := preload base
@@ -150,6 +157,7 @@ install : all
150157
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-host.so
151158
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-host-mimic-strategy.so
152159
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-host-spawn-strategy.so
160+
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-host-spawn-strategy-close.so
153161
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-child.so
154162
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-child-mimic-strategy.so
155163
install -Dm 755 -t $(FLATPAK_DEST)/lib build/libzypak-preload-child-spawn-strategy.so

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ application process. If you need to add your own libraries to `LD_PRELOAD`, plac
8282
`ZYPAK_LD_PRELOAD`, which will result in Zypak adding them to the `LD_PRELOAD` list, in addition to
8383
its own required libraries.
8484

85+
## CEF support
86+
87+
If the application uses CEF, set `ZYPAK_CEF_LIBRARY_PATH` to the absolute path to the `libcef.so`
88+
library.
89+
8590
## Using a different version
8691

8792
If you want to try a different Zypak version for testing, or without using the

src/base/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Env {
3939
static constexpr cstring_view kZypakSettingExposeWidevinePath = "ZYPAK_EXPOSE_WIDEVINE_PATH";
4040
static constexpr cstring_view kZypakSettingLdPreload = "ZYPAK_LD_PRELOAD";
4141
static constexpr cstring_view kZypakSettingSpawnLatestOnReexec = "ZYPAK_SPAWN_LATEST_ON_REEXEC";
42+
static constexpr cstring_view kZypakSettingCefLibraryPath = "ZYPAK_CEF_LIBRARY_PATH";
4243
};
4344

4445
} // namespace zypak

src/helper/main.cc

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,11 @@ bool ApplyFdMapFromArgs(ArgsView::iterator* it, ArgsView::iterator last) {
118118
return true;
119119
}
120120

121-
std::string GetPreload(std::string_view mode, std::string_view libdir) {
122-
std::vector<std::string> preload_names;
123-
124-
preload_names.emplace_back(mode);
125-
if (Env::Test(Env::kZypakZygoteStrategySpawn)) {
126-
preload_names.push_back(std::string(mode) + "-spawn-strategy");
127-
} else {
128-
preload_names.push_back(std::string(mode) + "-mimic-strategy");
129-
}
121+
std::string GetZypakLib(std::string_view libdir, std::string_view name) {
122+
return (fs::path(libdir) / ("libzypak-preload-"s + std::string(name) + ".so")).string();
123+
}
130124

125+
std::string GetPreload(std::string_view mode, std::string_view libdir) {
131126
std::vector<std::string> preload_libs;
132127

133128
// LD_PRELOAD is loaded in left-to-right order, and the last reference to a symbol is used to
@@ -137,9 +132,18 @@ std::string GetPreload(std::string_view mode, std::string_view libdir) {
137132
preload_libs.push_back(std::string(*preload));
138133
}
139134

140-
for (const std::string& name : preload_names) {
141-
fs::path path = fs::path(libdir) / ("libzypak-preload-"s + name + ".so");
142-
preload_libs.push_back(path.string());
135+
preload_libs.push_back(GetZypakLib(libdir, mode));
136+
if (Env::Test(Env::kZypakZygoteStrategySpawn)) {
137+
preload_libs.push_back(GetZypakLib(libdir, std::string(mode) + "-spawn-strategy"));
138+
if (mode == "host") {
139+
if (auto crlib = Env::Get(Env::kZypakSettingCefLibraryPath)) {
140+
preload_libs.emplace_back(*crlib);
141+
}
142+
143+
preload_libs.push_back(GetZypakLib(libdir, "host-spawn-strategy-close"));
144+
}
145+
} else {
146+
preload_libs.push_back(GetZypakLib(libdir, std::string(mode) + "-mimic-strategy"));
143147
}
144148

145149
return Join(preload_libs.begin(), preload_libs.end(), ":");

src/preload/host/spawn_strategy/bus_safe_fork.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "base/debug.h"
1515
#include "dbus/bus.h"
1616
#include "preload/declare_override.h"
17-
#include "preload/host/spawn_strategy/no_close_host_fd.h"
17+
#include "preload/host/spawn_strategy/close/no_close_host_fd.h"
1818

1919
using namespace zypak;
2020

src/preload/host/spawn_strategy/no_close_host_fd.cc renamed to src/preload/host/spawn_strategy/close/no_close_host_fd.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,26 @@
1616

1717
bool zypak::preload::block_supervisor_fd_close = false;
1818

19+
// Overriding close is...tricky.
20+
//
1921
// Chrome 92 introduces its own close override:
20-
// https://chromium-review.googlesource.com/q/I918d79c343c0027ee1ce4353c7acbe7c0e79d1dd This will
21-
// mean that an override of "close" here will not take effect anymore. In order to work around it,
22-
// we can also override glibc's __close instead, which Chromium's close override calls into.
22+
// https://chromium-review.googlesource.com/q/I918d79c343c0027ee1ce4353c7acbe7c0e79d1dd
23+
// This will mean that an override of "close" here will not take effect anymore. In order to work
24+
// around it, we can also override glibc's __close instead, which Chromium's close override calls
25+
// into.
26+
//
27+
// Later versions change it to call the close from dlsym(RTLD_NEXT) instead of hardcoding glibc's
28+
// close:
29+
// https://chromium-review.googlesource.com/c/chromium/src/+/4418528
30+
// But, if close() is being called from a shared library like libcef, then RTLD_NEXT is *not*
31+
// going to point to Zypak, because the resolution order will look like:
32+
//
33+
// LD_PRELOAD(zypak is here) -> libcef.so -> ... -> libc.so
34+
//
35+
// That's why this override is in its own shared library, so it can be added to the LD_PRELOAD list
36+
// after the main overrides & with libcef in-between, resulting in a resolution order like:
37+
38+
// LD_PRELOAD(zypak main preload -> libcef.so -> this preload library w/ close) -> ... -> libc.so
2339

2440
DECLARE_OVERRIDE_THROW(int, __close, int fd) {
2541
if (fd == zypak::sandbox::kZypakSupervisorFd && zypak::preload::block_supervisor_fd_close) {
File renamed without changes.

0 commit comments

Comments
 (0)