libredirect: add some missing calls (#472352)

This commit is contained in:
Bjørn Forsman
2026-01-23 19:36:44 +00:00
committed by GitHub
3 changed files with 152 additions and 9 deletions
+104 -8
View File
@@ -1,11 +1,15 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/xattr.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
@@ -107,6 +111,44 @@ static int open_needs_mode(int flags)
it contains only what we needed for programs in Nixpkgs. Just add
more functions as needed. */
WRAPPER(int, bind)(int socket, const struct sockaddr *addr, socklen_t addr_len)
{
int (*bind_real) (int, const struct sockaddr *, socklen_t) = LOOKUP_REAL(bind);
char buf[PATH_MAX];
const struct sockaddr *real_addr = addr;
if (addr->sa_family == AF_UNIX) {
struct sockaddr_un real_addr_un = *(struct sockaddr_un *)addr;
const char *sun_path = rewrite(real_addr_un.sun_path, buf);
if (sun_path != real_addr_un.sun_path) {
strncpy(real_addr_un.sun_path, buf, sizeof(real_addr_un.sun_path) - 1);
real_addr_un.sun_path[sizeof(real_addr_un.sun_path) - 1] = '\0';
real_addr = (struct sockaddr *)&real_addr_un;
addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(real_addr_un.sun_path) + 1;
}
}
return bind_real(socket, real_addr, addr_len);
}
WRAPPER_DEF(bind)
WRAPPER(int, connect)(int socket, const struct sockaddr *addr, socklen_t addr_len)
{
int (*connect_real) (int, const struct sockaddr *, socklen_t) = LOOKUP_REAL(connect);
char buf[PATH_MAX];
const struct sockaddr *real_addr = addr;
if (addr->sa_family == AF_UNIX) {
struct sockaddr_un real_addr_un = *(struct sockaddr_un *)addr;
const char *sun_path = rewrite(real_addr_un.sun_path, buf);
if (sun_path != real_addr_un.sun_path) {
strncpy(real_addr_un.sun_path, buf, sizeof(real_addr_un.sun_path) - 1);
real_addr_un.sun_path[sizeof(real_addr_un.sun_path) - 1] = '\0';
real_addr = (struct sockaddr *)&real_addr_un;
addr_len = offsetof(struct sockaddr_un, sun_path) + strlen(real_addr_un.sun_path) + 1;
}
}
return connect_real(socket, real_addr, addr_len);
}
WRAPPER_DEF(connect)
WRAPPER(int, open)(const char * path, int flags, ...)
{
int (*open_real) (const char *, int, ...) = LOOKUP_REAL(open);
@@ -155,6 +197,24 @@ WRAPPER(int, openat)(int dirfd, const char * path, int flags, ...)
}
WRAPPER_DEF(openat)
// In musl libc, openat64 is simply a macro for openat
#if !defined(__APPLE__) && !defined(openat64)
WRAPPER(int, openat64)(int dirfd, const char * path, int flags, ...)
{
int (*openat64_real) (int, const char *, int, ...) = LOOKUP_REAL(openat64);
mode_t mode = 0;
if (open_needs_mode(flags)) {
va_list ap;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
}
char buf[PATH_MAX];
return openat64_real(dirfd, rewrite(path, buf), flags, mode);
}
WRAPPER_DEF(openat64)
#endif
WRAPPER(FILE *, fopen)(const char * path, const char * mode)
{
FILE * (*fopen_real) (const char *, const char *) = LOOKUP_REAL(fopen);
@@ -300,29 +360,49 @@ WRAPPER_DEF(execv)
WRAPPER(int, execvp)(const char * path, char * const argv[])
{
int (*_execvp) (const char *, char * const argv[]) = LOOKUP_REAL(execvp);
int (*execvp_real) (const char *, char * const argv[]) = LOOKUP_REAL(execvp);
char buf[PATH_MAX];
return _execvp(rewrite(path, buf), argv);
return execvp_real(rewrite(path, buf), argv);
}
WRAPPER_DEF(execvp)
WRAPPER(int, execve)(const char * path, char * const argv[], char * const envp[])
{
int (*_execve) (const char *, char * const argv[], char * const envp[]) = LOOKUP_REAL(execve);
int (*execve_real) (const char *, char * const argv[], char * const envp[]) = LOOKUP_REAL(execve);
char buf[PATH_MAX];
return _execve(rewrite(path, buf), argv, envp);
return execve_real(rewrite(path, buf), argv, envp);
}
WRAPPER_DEF(execve)
WRAPPER(DIR *, opendir)(const char * path)
{
char buf[PATH_MAX];
DIR * (*_opendir) (const char*) = LOOKUP_REAL(opendir);
DIR * (*opendir_real) (const char*) = LOOKUP_REAL(opendir);
return _opendir(rewrite(path, buf));
return opendir_real(rewrite(path, buf));
}
WRAPPER_DEF(opendir)
#if !defined(__APPLE__)
WRAPPER(ssize_t, listxattr)(const char * path, char * list, size_t size)
{
int (*listxattr_real) (const char *, char *, size_t) = LOOKUP_REAL(listxattr);
char buf[PATH_MAX];
return listxattr_real(rewrite(path, buf), list, size);
}
WRAPPER_DEF(listxattr);
#endif
#if !defined(__APPLE__)
WRAPPER(ssize_t, llistxattr)(const char * path, char * list, size_t size)
{
int (*llistxattr_real) (const char *, char *, size_t) = LOOKUP_REAL(llistxattr);
char buf[PATH_MAX];
return llistxattr_real(rewrite(path, buf), list, size);
}
WRAPPER_DEF(llistxattr);
#endif
#define SYSTEM_CMD_MAX 512
static char * replace_substring(char * source, char * buf, char * replace_string, char * start_ptr, char * suffix_ptr) {
@@ -383,11 +463,11 @@ static void rewriteSystemCall(const char * command, char * buf) {
WRAPPER(int, system)(const char *command)
{
int (*_system) (const char*) = LOOKUP_REAL(system);
int (*system_real) (const char*) = LOOKUP_REAL(system);
char newCommand[SYSTEM_CMD_MAX];
rewriteSystemCall(command, newCommand);
return _system(newCommand);
return system_real(newCommand);
}
WRAPPER_DEF(system)
@@ -399,6 +479,14 @@ WRAPPER(int, chdir)(const char *path)
}
WRAPPER_DEF(chdir);
WRAPPER(int, chmod)(const char * path, mode_t mode)
{
int (*chmod_real) (const char *, mode_t) = LOOKUP_REAL(chmod);
char buf[PATH_MAX];
return chmod_real(rewrite(path, buf), mode);
}
WRAPPER_DEF(chmod)
WRAPPER(int, mkdir)(const char *path, mode_t mode)
{
int (*mkdir_real) (const char *path, mode_t mode) = LOOKUP_REAL(mkdir);
@@ -431,6 +519,14 @@ WRAPPER(int, unlinkat)(int dirfd, const char *path, int flags)
}
WRAPPER_DEF(unlinkat)
WRAPPER(int, remove)(const char *path)
{
int (*remove_real) (const char *path) = LOOKUP_REAL(remove);
char buf[PATH_MAX];
return remove_real(rewrite(path, buf));
}
WRAPPER_DEF(remove)
WRAPPER(int, rmdir)(const char *path)
{
int (*rmdir_real) (const char *path) = LOOKUP_REAL(rmdir);
+1 -1
View File
@@ -124,7 +124,7 @@ else
installCheckPhase = ''
(
source "$hook/nix-support/setup-hook"
NIX_REDIRECTS="/foo/bar/test=${coreutils}/bin/true:/bar/baz=$(mktemp -d)" ./test
NIX_REDIRECTS="/foo/bar/test=${coreutils}/bin/true:/bar/baz=$(mktemp -d):/run/sock=$PWD/test.sock" ./test
)
'';
+47
View File
@@ -8,16 +8,61 @@
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#define TESTDIR "/bar/baz"
#define TESTPATH "/foo/bar/test"
#define TESTSOCK "/run/sock"
#define SUBTEST "./test sub"
extern char **environ;
void test_bind(void) {
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
assert(fd != -1);
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = TESTSOCK,
};
unlink(TESTSOCK);
int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
assert(ret == 0);
close(fd);
}
void test_connect(void) {
// server
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
assert(server_fd != -1);
struct sockaddr_un server_addr = {
.sun_family = AF_UNIX,
.sun_path = TESTSOCK,
};
unlink(TESTSOCK);
int bind_ret = bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
assert(bind_ret == 0);
int listen_ret = listen(server_fd, 5);
assert(listen_ret == 0);
// client
int client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
assert(client_fd != -1);
struct sockaddr_un client_addr = {
.sun_family = AF_UNIX,
.sun_path = TESTSOCK,
};
int connect_ret = connect(client_fd, (struct sockaddr *)&client_addr, sizeof(client_addr));
assert(connect_ret == 0);
// clean up
close(server_fd);
close(client_fd);
}
void test_spawn(void) {
pid_t pid;
int ret;
@@ -160,6 +205,8 @@ int main(int argc, char *argv[])
assert(mktemp(buf) == buf);
assert_mktemp_path(TESTDIR "/temp", "", buf);
test_bind();
test_connect();
test_spawn();
test_system();
test_stat_with_null_path();