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

Add initial code for syscall redirection, fix path lookup failures. #21

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
25 changes: 14 additions & 11 deletions pathmapping/pathmapping_interf.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,12 @@ void sbox_map_path_at(
res->mres_readonly = 1;
return;
}
if (*virtual_path == '\0') {
goto end;
}

if ((*virtual_path == '/')
if (virtual_path && ((*virtual_path == '/')
#ifdef AT_FDCWD
|| (dirfd == AT_FDCWD)
|| (dirfd == AT_FDCWD)
#endif
) {
)) {
/* same as sbox_map_path() */
fwd_map_path(
(sbox_binary_name ? sbox_binary_name : "UNKNOWN"),
Expand All @@ -273,9 +270,16 @@ void sbox_map_path_at(
/* pathname found */
char *virtual_abs_path_at_fd = NULL;

if (asprintf(&virtual_abs_path_at_fd, "%s/%s", dirfd_path, virtual_path) < 0) {
/* asprintf failed */
abort();
if (!virtual_path || *virtual_path == '\0') {
if (asprintf(&virtual_abs_path_at_fd, "%s", dirfd_path) < 0) {
/* asprintf failed */
abort();
}
} else {
if (asprintf(&virtual_abs_path_at_fd, "%s/%s", dirfd_path, virtual_path) < 0) {
/* asprintf failed */
abort();
}
}
SB_LOG(SB_LOGLEVEL_DEBUG,
"Synthetic path for %s(%d,'%s') => '%s'",
Expand All @@ -290,12 +294,11 @@ void sbox_map_path_at(
return;
}

end:
/* name not found. Can't do much here, log a warning and return
* the original relative path. That will work if we are lucky, but
* not always.. */
SB_LOG(SB_LOGLEVEL_WARNING, "Path not found for FD %d, for %s(%s)",
dirfd, func_name, virtual_path);
dirfd, func_name, virtual_path);
res->mres_result_buf = res->mres_result_path = strdup(virtual_path);
res->mres_readonly = 0;
}
Expand Down
1 change: 1 addition & 0 deletions preload/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ objs := wrappers.o privatewrappers.o \
fdpathdb.o procfs.o mempcpy.o \
union_dirs.o \
system.o \
syscalls.o \
sb2context.o

ifeq ($(shell uname -s),Linux)
Expand Down
2 changes: 2 additions & 0 deletions preload/interface.master
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ GATE: int execve (const char *filename, char *const argv [], char *const envp[])
GATE: int execvp (const char *file, char *const argv [])
GATE: int execvpe(const char *file, char *const argv[], char *const envp[])

GATE: long syscall(long number, ...) : pass_va_list

GATE: int posix_spawn (pid_t *pid, const char *path, \
const posix_spawn_file_actions_t *file_actions, \
const posix_spawnattr_t *attrp, \
Expand Down
100 changes: 100 additions & 0 deletions preload/syscalls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
*
* SPDX-FileCopyrightText: 2023, Jolla Ltd.
* SPDX-License-Identifier: LGPL-2.1
*
* syscallgate -- syscall() GATE for the scratchbox2 preload library
*
* Copyright (C) 2023 Jolla Ltd.
*/

#include <asm-generic/unistd.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "libsb2.h"
#include "exported.h"

#define EXPAND_0(OPERATION)
#define EXPAND_1(OPERATION, X) OPERATION(X)
#define EXPAND_2(OPERATION, X, ...) OPERATION(X)EXPAND_1(OPERATION, __VA_ARGS__)
#define EXPAND_3(OPERATION, X, ...) OPERATION(X)EXPAND_2(OPERATION, __VA_ARGS__)
#define EXPAND_4(OPERATION, X, ...) OPERATION(X)EXPAND_3(OPERATION, __VA_ARGS__)
#define EXPAND_5(OPERATION, X, ...) OPERATION(X)EXPAND_4(OPERATION, __VA_ARGS__)
#define EXPAND_6(OPERATION, X, ...) OPERATION(X)EXPAND_5(OPERATION, __VA_ARGS__)

#define GET_MACRO(_0,_1,_2,_3,_4,_5,_6,NAME,...) NAME
#define FOR_EACH(action,...) \
GET_MACRO(_0,__VA_ARGS__,EXPAND_6,EXPAND_5,EXPAND_4,EXPAND_3,EXPAND_2,EXPAND_1,EXPAND_0)(action,__VA_ARGS__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is brilliant!


#define DEFINE_ARG(arg) long arg = va_arg(args, long);

#define FORWARD_TO_WRAPPER(sysc, ...) \
case SYS_ ## sysc: { \
FOR_EACH(DEFINE_ARG, __VA_ARGS__); \
ret = sysc(__VA_ARGS__); \
} break

extern long syscall_gate(int *result_errno_ptr,
long (*real_syscall_ptr)(long number, ...),
const char *realfnname, long number, va_list args)
{
long ret;
switch (number) {
FORWARD_TO_WRAPPER(execve, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(openat, arg0, arg1, arg2, arg3);
// FORWARD_TO_WRAPPER(open_by_handle_at, ...)
FORWARD_TO_WRAPPER(open, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(renameat, arg0, arg1, arg2, arg3);
FORWARD_TO_WRAPPER(renameat2, arg0, arg1, arg2, arg3, arg4);
FORWARD_TO_WRAPPER(connect, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(sendto, arg0, arg1, arg2, arg3, arg4, arg5);
FORWARD_TO_WRAPPER(sendmsg, arg0, arg1, arg2);
case SYS_recvfrom: {
FOR_EACH(DEFINE_ARG, arg0, arg1, arg2, arg3, arg4, arg5);
// must do a cast...
ret = recvfrom(arg0, arg1, arg2, arg3, (struct sockaddr*)arg4, arg5);
break;
}
FORWARD_TO_WRAPPER(recvmsg, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(accept, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(accept4, arg0, arg1, arg2, arg3);
FORWARD_TO_WRAPPER(utimensat, arg0, arg1, arg2, arg3);
FORWARD_TO_WRAPPER(utime, arg0, arg1);
FORWARD_TO_WRAPPER(utimes, arg0, arg1);
FORWARD_TO_WRAPPER(fcntl, arg0, arg1, arg2);
FORWARD_TO_WRAPPER(futimesat, arg0, arg1, arg2);

#ifdef SYS_wait
FORWARD_TO_WRAPPER(wait, arg0);
#endif
FORWARD_TO_WRAPPER(waitpid, arg0, arg1, arg2);

#ifdef SYS_wait3
case SYS_wait3: {
FOR_EACH(DEFINE_ARG, arg0, arg1, arg2);
// different number of arguments (for now we ignore rusage
// and redirect to waitpid).
ret = waitpid(-1, arg0, arg1);
break;
}
#endif

case SYS_wait4: {
FOR_EACH(DEFINE_ARG, arg0, arg1, arg2, arg3);
// different number of arguments (for now we ignore rusage
// and redirect to waitpid).
ret = waitpid(arg0, arg1, arg2);
break;
}

default: {
FOR_EACH(DEFINE_ARG, arg0, arg1, arg2, arg3, arg4, arg5);
ret = real_syscall_ptr(number, arg0, arg1, arg2, arg3, arg4, arg5);
break;
}
};
if (result_errno_ptr) *result_errno_ptr = errno;
return ret;
}