Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle renameat2 on RHEL 8 and systems with glibc < 2.28 #147

Merged
merged 2 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ LIBCLOCATION=$(shell ldd /bin/sh | awk '/libc\.so\./ { print; }' | cut -d' ' -f3
# also remove -ljson-c from EXT_LIB declaration.
# to work with sr3, change SR_APPNAME=\"sr3\" ... otherwise will be managed by version 2.
# on Power9, -fstack-check causes coredumps, so removed for now.
# On RHEL8, add -DINTERCEPT_SYSCALL to handle cases where mv calls syscall directly, instead of calling renameat2.
# See sarrac issue #145 for more information about syscall/renameat2.

CFLAGS = -DHAVE_JSONC -DSR_APPNAME=\"sr3\" -DFORCE_LIBC_REGEX=\"$(LIBCLOCATION)\" -fPIC -ftest-coverage -std=gnu99 -Wall -g -D_GNU_SOURCE $(RABBIT_INCDIR)

Expand Down
82 changes: 79 additions & 3 deletions libsr3shim.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@

#include "sr_post.h"

/*
See https://github.com/MetPX/sarrac/issues/145.
glibc < 2.28 doesn't provide renameat2.
*/
#if !__GLIBC_PREREQ(2,28)
#define INTERCEPT_SYSCALL
#endif

/*
libsrshim - intercepts calls to libc and kernel to post files for broker.

Expand Down Expand Up @@ -48,6 +56,8 @@ SR_SHIM_CONFIG -- environment variable to set configuration file name
void exit_cleanup_posts();
int exit_cleanup_posts_setup = 0;

void syscall_init();

int mypid = 0;
int pid_seconds_wallclock = 0;
int srshim_debug_level = -1;
Expand Down Expand Up @@ -855,10 +865,16 @@ static int renameat_init_done = 0;
typedef int (*renameat_fn)(int, const char *, int, const char *);
static renameat_fn renameat_fn_ptr = NULL;


static int renameat2_init_done = 0;
typedef int (*renameat2_fn)(int, const char *, int, const char *, unsigned int);
static renameat2_fn renameat2_fn_ptr = NULL;

static int syscall_init_done = 0;
typedef long int (*syscall_fn)(long int, ...);
static syscall_fn syscall_fn_ptr = NULL;


int renameorlink(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath, int flags, int link)
/*
Expand All @@ -879,6 +895,7 @@ int renameorlink(int olddirfd, const char *oldpath, int newdirfd,
renameat2_fn_ptr = (renameat2_fn) dlsym(RTLD_NEXT, "renameat2");
renameat2_init_done = 1;
}

if (!renameat_init_done) {
renameat_fn_ptr = (renameat_fn) dlsym(RTLD_NEXT, "renameat");
renameat_init_done = 1;
Expand All @@ -894,6 +911,10 @@ int renameorlink(int olddirfd, const char *oldpath, int newdirfd,
linkat_init_done = 1;
}

if (!syscall_init_done) {
syscall_init();
}

if (link) {
if (linkat_fn_ptr)
status = linkat_fn_ptr(olddirfd, oldpath, newdirfd, newpath, flags);
Expand All @@ -904,11 +925,15 @@ int renameorlink(int olddirfd, const char *oldpath, int newdirfd,
" renameorlink could not identify real entry point for link\n");
}
} else {
if (renameat2_fn_ptr)
if (renameat2_fn_ptr) {
sr_shimdebug_msg(1, " renameorlink using renameat2\n");
status = renameat2_fn_ptr(olddirfd, oldpath, newdirfd, newpath, flags);
else if (renameat_fn_ptr && !flags)
} else if (renameat_fn_ptr && !flags) {
status = renameat_fn_ptr(olddirfd, oldpath, newdirfd, newpath);
else {
} else if (syscall_fn_ptr) {
sr_shimdebug_msg(1, " renameorlink using renameat2 via syscall(316, ...)\n");
status = syscall_fn_ptr(316, olddirfd, oldpath, newdirfd, newpath, flags);
} else {
sr_log_msg(logctxptr,LOG_ERROR,
" renameorlink could not identify real entry point for renameat\n");
return (-1);
Expand Down Expand Up @@ -1362,6 +1387,57 @@ int renameat2(int olddirfd, const char *oldpath, int newdirfd,
return (renameorlink(olddirfd, oldpath, newdirfd, newpath, flags, 0));
}

void syscall_init()
{
if (!syscall_init_done) {
setup_exit();
syscall_fn_ptr = (syscall_fn) dlsym(RTLD_NEXT, "syscall");
syscall_init_done = 1;
}
}

#ifdef INTERCEPT_SYSCALL
long int syscall(long int __sysno, ...)
{
va_list args;
int status = -1;

int olddirfd = -1;
char *oldpath = NULL;
int newdirfd = -1;
char *newpath = NULL;
int flags = -1;

sr_shimdebug_msg(1, "syscall %ld\n", __sysno);

if (!syscall_init_done) {
syscall_init();
}

// renameat2 is 316
if (__sysno == 316) {
sr_shimdebug_msg(1, "syscall %ld\n --> renameat2, will call renameorlink", __sysno);

va_start(args, __sysno);
olddirfd = va_arg(args, int);
oldpath = va_arg(args, char*);
newdirfd = va_arg(args, int);
newpath = va_arg(args, char*);
flags = va_arg(args, int);
va_end(args);

sr_shimdebug_msg(1, "%d, %s, %d, %s, %d", olddirfd, oldpath, newdirfd, newpath, flags);
status = renameorlink(olddirfd, oldpath, newdirfd, newpath, flags, 0);
}
else {
sr_shimdebug_msg(1, "syscall %ld NOT IMPLEMENTED\n", __sysno);
sr_log_msg(logctxptr,LOG_ERROR, "non-renameat2 syscall (%ld) not implemented\n", __sysno);
status = -1;
}
return status;
}
#endif

static int sendfile_init_done = 0;
typedef ssize_t(*sendfile_fn) (int, int, off_t *, size_t);
static sendfile_fn sendfile_fn_ptr = NULL;
Expand Down
Loading