tests: mock __open_2()

As of commit [1] glibc may overwrite a call to open() with call
to __open_2() (if only two arguments are provided and the code is
compiled with clang). But since we are not mocking the latter our
test suite is broken as tests try to access paths outside of our
repo.

1: https://sourceware.org/git/?p=glibc.git;a=commit;h=86889e22db329abac618c6a41f86c84657a15324
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
Michal Privoznik 2024-03-13 17:25:35 +01:00
parent ce5efefecd
commit b7e6513a01
9 changed files with 175 additions and 11 deletions

View File

@ -604,6 +604,12 @@ stat_functions = [
functions += stat_functions
open_functions = [
'__open_2',
]
functions += open_functions
foreach function : functions
if cc.has_function(function)
conf.set('WITH_@0@'.format(function.to_upper()), 1)
@ -618,6 +624,13 @@ foreach function : stat_functions
endforeach
foreach function : open_functions
if cc.has_header_symbol('fcntl.h', function)
conf.set('WITH_@0@_DECL'.format(function.to_upper()), 1)
endif
endforeach
# various header checks
headers = [

View File

@ -29,6 +29,9 @@
# include "configmake.h"
static int (*real_open)(const char *path, int flags, ...);
# if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
# endif
static DIR * (*real_opendir)(const char *name);
static int (*real_access)(const char *path, int mode);
@ -44,6 +47,9 @@ init_syms(void)
return;
VIR_MOCK_REAL_INIT(open);
# if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
# endif
VIR_MOCK_REAL_INIT(opendir);
VIR_MOCK_REAL_INIT(access);
}
@ -90,6 +96,26 @@ open(const char *path, int flags, ...)
return ret;
}
# if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
int ret;
char *newpath = NULL;
init_syms();
if (STRPREFIX(path, LEASEDIR) &&
getrealpath(&newpath, path) < 0)
return -1;
ret = real___open_2(newpath ? newpath : path, flags);
free(newpath);
return ret;
}
# endif
DIR *
opendir(const char *path)
{

View File

@ -58,6 +58,9 @@
static int (*real_chown)(const char *path, uid_t uid, gid_t gid);
static int (*real_open)(const char *path, int flags, ...);
#if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
#endif
static int (*real_close)(int fd);
#ifdef WITH_SELINUX
static int (*real_setfilecon_raw)(const char *path, const char *context);
@ -112,6 +115,9 @@ init_syms(void)
VIR_MOCK_REAL_INIT(chown);
VIR_MOCK_REAL_INIT(open);
#if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
#endif
VIR_MOCK_REAL_INIT(close);
#ifdef WITH_SELINUX
VIR_MOCK_REAL_INIT(setfilecon_raw);
@ -324,6 +330,24 @@ open(const char *path, int flags, ...)
}
#if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
int ret;
init_syms();
if (getenv(ENVVAR)) {
ret = 42; /* Some dummy FD */
} else {
ret = real___open_2(path, flags);
}
return ret;
}
#endif
int
close(int fd)
{

View File

@ -30,6 +30,9 @@
# include "vircgroupv2devices.h"
static int (*real_open)(const char *path, int flags, ...);
# if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
# endif
static FILE *(*real_fopen)(const char *path, const char *mode);
static int (*real_access)(const char *path, int mode);
static int (*real_mkdir)(const char *path, mode_t mode);
@ -302,6 +305,9 @@ static void init_syms(void)
VIR_MOCK_REAL_INIT(access);
VIR_MOCK_REAL_INIT(mkdir);
VIR_MOCK_REAL_INIT(open);
# if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
# endif
}
@ -589,6 +595,42 @@ int open(const char *path, int flags, ...)
return ret;
}
# if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
int ret;
char *newpath = NULL;
init_syms();
if (STREQ(path, SYSFS_CPU_PRESENT)) {
init_sysfs();
if (asprintf(&newpath, "%s/%s",
fakesysfscgroupdir,
SYSFS_CPU_PRESENT_MOCKED) < 0) {
errno = ENOMEM;
return -1;
}
}
if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
init_sysfs();
if (asprintf(&newpath, "%s%s",
fakesysfscgroupdir,
path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
errno = ENOMEM;
return -1;
}
}
ret = real___open_2(newpath ? newpath : path, flags);
free(newpath);
return ret;
}
# endif
bool
virCgroupV2DevicesAvailable(virCgroup *group G_GNUC_UNUSED)
{

View File

@ -38,6 +38,9 @@ static const char **prefixes;
/* TODO: callbacks */
static int (*real_open)(const char *path, int flags, ...);
# if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
# endif
static FILE *(*real_fopen)(const char *path, const char *mode);
static int (*real_access)(const char *path, int mode);
static int (*real_mkdir)(const char *path, mode_t mode);
@ -54,6 +57,9 @@ static void init_syms(void)
VIR_MOCK_REAL_INIT(access);
VIR_MOCK_REAL_INIT(mkdir);
VIR_MOCK_REAL_INIT(open);
# if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
# endif
# if defined(__APPLE__) && defined(__x86_64__)
VIR_MOCK_REAL_INIT_ALIASED(opendir, "opendir$INODE64");
# else
@ -176,6 +182,18 @@ int open(const char *path, int flags, ...)
return real_open(newpath ? newpath : path, flags, mode);
}
# if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
g_autofree char *newpath = NULL;
PATH_OVERRIDE(newpath, path);
return real___open_2(newpath ? newpath : path, flags);
}
# endif
DIR *opendir(const char *path)
{
g_autofree char *newpath = NULL;

View File

@ -27,6 +27,10 @@
#include "internal.h"
#ifndef WITH___OPEN_2_DECL
int __open_2 (const char *__path, int __oflag);
#endif
#define VIR_MOCK_COUNT_ARGS(...) VIR_MOCK_ARG27(__VA_ARGS__, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define VIR_MOCK_ARG27(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, ...) _27
#define VIR_MOCK_ARG_PASTE(a, b, ...) a##b(__VA_ARGS__)

View File

@ -36,9 +36,9 @@
static int (*real_access)(const char *path, int mode);
static int (*real_open)(const char *path, int flags, ...);
# ifdef __GLIBC__
# if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
# endif /* ! __GLIBC__ */
# endif /* ! WITH___OPEN_2 */
static int (*real_close)(int fd);
static DIR * (*real_opendir)(const char *name);
static char *(*real_virFileCanonicalizePath)(const char *path);
@ -945,9 +945,9 @@ init_syms(void)
VIR_MOCK_REAL_INIT(access);
VIR_MOCK_REAL_INIT(open);
# ifdef __GLIBC__
# if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
# endif /* ! __GLIBC__ */
# endif /* WITH___OPEN_2 */
VIR_MOCK_REAL_INIT(close);
# if defined(__APPLE__) && defined(__x86_64__)
VIR_MOCK_REAL_INIT_ALIASED(opendir, "opendir$INODE64");
@ -1110,12 +1110,7 @@ open(const char *path, int flags, ...)
}
# ifdef __GLIBC__
/* in some cases this function may not be present in headers, so we need
* a declaration to silence the compiler */
int
__open_2(const char *path, int flags);
# if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
@ -1139,7 +1134,7 @@ __open_2(const char *path, int flags)
return ret;
}
# endif /* ! __GLIBC__ */
# endif /* WITH___OPEN_2 */
DIR *
opendir(const char *path)

View File

@ -29,6 +29,9 @@
#include "virfile.h"
static int (*real_open)(const char *path, int flags, ...);
#if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
#endif
static FILE *(*real_fopen)(const char *path, const char *mode);
static int (*real_access)(const char *path, int mode);
static int (*real_connect)(int fd, const struct sockaddr *addr, socklen_t addrlen);
@ -44,6 +47,9 @@ static void init_syms(void)
return;
VIR_MOCK_REAL_INIT(open);
#if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
#endif
VIR_MOCK_REAL_INIT(fopen);
VIR_MOCK_REAL_INIT(access);
VIR_MOCK_REAL_INIT(connect);
@ -153,6 +159,20 @@ int open(const char *path, int flags, ...)
return ret;
}
#if WITH___OPEN_2
int
__open_2(const char *path, int flags)
{
init_syms();
CHECK_PATH(path);
return real___open_2(path, flags);
}
#endif
FILE *fopen(const char *path, const char *mode)
{
init_syms();

View File

@ -30,6 +30,9 @@
#define FAKE_USB_SYSFS "virusbtestdata/sys_bus_usb"
static int (*real_open)(const char *pathname, int flags, ...);
#if WITH___OPEN_2
static int (*real___open_2)(const char *path, int flags);
#endif
static DIR *(*real_opendir)(const char *name);
static void init_syms(void)
@ -38,6 +41,9 @@ static void init_syms(void)
return;
VIR_MOCK_REAL_INIT(open);
#if WITH___OPEN_2
VIR_MOCK_REAL_INIT(__open_2);
#endif
VIR_MOCK_REAL_INIT(opendir);
}
@ -90,3 +96,19 @@ int open(const char *pathname, int flags, ...)
ret = real_open(path, flags, mode);
return ret;
}
#if WITH___OPEN_2
int
__open_2(const char *pathname, int flags)
{
g_autofree char *path = NULL;
init_syms();
path = get_fake_path(pathname);
if (!path)
return -1;
return real_open(path, flags);
}
#endif