Skip to content

Commit

Permalink
Revert "Use dlopen on libc instead of RTLD_NEXT"
Browse files Browse the repository at this point in the history
This reverts commit f47125c.

The commit in question directly used the C library instead of RTLD_NEXT
whenever possible, based on some deadlock I didn't specify further in
the commit message.

I could not reproduce a deadlock like this and given that we don't have
a test case that fails with RTLD_NEXT tells me that it doesn't matter.

In addition to just reverting, I also added a small test case that I
used in order to try reproducing the aforementioned issue. Even though I
couldn't reproduce the issue, I'm adding the test anyway since we didn't
have a test case where we use multiple LD_PRELOAD wrappers that operate
on the same set of calls as ip2unix.

Signed-off-by: aszlig <[email protected]>
  • Loading branch information
aszlig committed Aug 15, 2023
1 parent d7b3bde commit e75161b
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 65 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The format is based on [Keep a Changelog], and this project adheres to

### Removed
- Badges (eg. LGTM and build status) in README and Hydra.
- No longer prefer C library path over `RTLD_NEXT`.

## [2.1.4] - 2021-07-10

Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@
in lib.mapAttrs (lib.const (lib.mapAttrs mkProgramTest)) {
mariadb-php-abstract.x86_64-linux =
tests/programs/mariadb-php-abstract.nix;
multiple-preload.x86_64-linux = tests/programs/multiple-preload.nix;
rsession.x86_64-linux = tests/programs/rsession.nix;
};

Expand Down
8 changes: 0 additions & 8 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ project('ip2unix', 'cpp',
default_options: ['cpp_std=c++17', 'warning_level=3'],
meson_version: '>=0.47.0', version: '2.1.4')

script_findlibc = files('scripts/findlibc.py')
script_generrno = files('scripts/generrno.py')
script_genoffsets = files('scripts/genoffsets.py')
script_gensyms = files('scripts/gensyms.py')
Expand Down Expand Up @@ -55,13 +54,6 @@ deps = [
cc.find_library('dl')
]

libcpath = run_command(python, script_findlibc, cc.cmd_array(), check: false)
if libcpath.returncode() == 0
fullpath = libcpath.stdout()
message('Found C library at ' + fullpath)
lib_cflags += ['-DLIBC_PATH="' + fullpath + '"']
endif

systemd_enabled = get_option('systemd-support')

if systemd_enabled
Expand Down
8 changes: 0 additions & 8 deletions scripts/findlibc.py

This file was deleted.

31 changes: 0 additions & 31 deletions src/realcalls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,4 @@
#define IP2UNIX_REALCALL_EXTERN
#include "realcalls.hh"

#include <initializer_list>
#include <memory>
#include <mutex>

std::mutex g_dlsym_mutex;

DlsymHandle dlsym_handle;

DlsymHandle::DlsymHandle() : handle(nullptr)
{
std::scoped_lock<std::mutex> lock(g_dlsym_mutex);

for (const char *libname : {
#ifdef LIBC_PATH
LIBC_PATH,
#endif
"libc.so.6"
}) {
this->handle = dlopen(libname, RTLD_LAZY | RTLD_DEEPBIND);
if (this->handle != nullptr) return;
}

this->handle = RTLD_NEXT;
}

DlsymHandle::~DlsymHandle()
{
std::scoped_lock<std::mutex> lock(g_dlsym_mutex);

if (this->handle != RTLD_NEXT)
dlclose(this->handle);
}
19 changes: 1 addition & 18 deletions src/realcalls.hh
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,7 @@
#define IP2UNIX_REALCALL_EXTERN extern
#endif

struct DlsymHandle
{
DlsymHandle();
~DlsymHandle();

inline void *get(void) const {
return this->handle;
}

private:
DlsymHandle(const DlsymHandle&) = delete;
DlsymHandle &operator=(const DlsymHandle&) = delete;

void *handle;
};

extern std::mutex g_dlsym_mutex;
extern DlsymHandle dlsym_handle;

/* This namespace is here so that we can autogenerate and call wrappers for C
* library functions in a convenient way. For example to call the wrapper for
Expand All @@ -58,7 +41,7 @@ namespace real {
{
g_dlsym_mutex.lock();
if (this->fptr == nullptr) {
void *result = dlsym(dlsym_handle.get(), Self::fname);
void *result = dlsym(RTLD_NEXT, Self::fname);
if (result == nullptr) {
LOG(FATAL) << "Loading of symbol '" << Self::fname
<< "' failed: " << strerror(errno);
Expand Down
44 changes: 44 additions & 0 deletions tests/programs/multiple-preload.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{ pkgs, ip2unix, ... }:

pkgs.runCommand "multiple-preload" {
TSOCKS_DEBUG = 10;
TSOCKS_CONF_FILE = pkgs.writeText "tsocks.conf" ''
server = 127.0.0.2
'';

nativeBuildInputs = [
ip2unix
pkgs.tsocks
pkgs.netcat-openbsd

(pkgs.writeScriptBin "socksd" ''
#!${(pkgs.python3.withPackages (p: [ p.tiny-proxy ])).interpreter}
import anyio
from tiny_proxy import Socks4ProxyHandler
async def main():
handler = Socks4ProxyHandler()
listener = await anyio.create_tcp_listener()
await listener.serve(handler.handle)
anyio.run(main)
'')

(pkgs.writeScriptBin "testprog" ''
#!${pkgs.python3.interpreter}
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect(('1.2.3.4', 1234))
assert sock.recv(3) == b'foo'
'')
];
} ''
echo foo | nc -N -lU foo.sock &
while [ ! -e foo.sock ]; do sleep 1; done
ip2unix -r in,path=bar.sock -r out,path=foo.sock socksd &
while [ ! -e bar.sock ]; do sleep 1; done
ip2unix -vvvvv -r out,addr=127.0.0.2,path=bar.sock tsocks testprog
touch "$out"
''

0 comments on commit e75161b

Please sign in to comment.