Skip to content

Syscall intercept #47

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

Open
wants to merge 1 commit 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ results/
dependencies/jdk-8u221-linux-x64.tar.gz
dependencies/cmake-3.15.2/
dependencies/jdk1.8.0_221/
dependencies/sysint_install/
kernel/kbuild/*
*.o
tpcc-sqlite/database/
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "dependencies/syscall_intercept"]
path = dependencies/syscall_intercept
url = https://github.com/pmem/syscall_intercept.git
25 changes: 24 additions & 1 deletion dependencies/splitfs_deps.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
#!/bin/bash

# install boost
sudo apt-get install libboost-dev
sudo apt-get install libboost-dev libcapstone-dev cmake pandoc clang

# install syscall_intercept
git submodule init
git submodule update
syscall_dir=$PWD/syscall_intercept
install_dir=$PWD/sysint_install

mkdir $install_dir
cd $install_dir
cmake $syscall_dir -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang
if [ "$?" -ne 0 ]; then
echo "Failed to build syscall_intercept"
exit 1
fi

make
if [ "$?" -ne 0 ]; then
echo "Failed to build syscall_intercept"
exit 1
fi

sudo make install
rm -rf $install_dir
1 change: 1 addition & 0 deletions dependencies/syscall_intercept
Submodule syscall_intercept added at 304404
32 changes: 32 additions & 0 deletions splitfs_syscall_intercept/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Object files
*.o
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
#*.a
*.la
*.lo

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Others
*~
21 changes: 21 additions & 0 deletions splitfs_syscall_intercept/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SplitFS implementation using syscall intercept Library
[syscall_intercept](https://google.com) is a library that can be used to intercept the system calls. This works by rewriting the machine code in text area of the loaded program.
The prior implementation intercepts the `libc` calls.
This implementation does not make any changes to the logic of SplitFS itself.

###Currently supported applications
1. PJD Test Suite (Tests run successfully)

###How to use?
All paths (not starting with `/`) are relative to root of repository
1. `cd splitfs_syscall_intercept/src`
2. `make clean && make`
3. A file called `libnvp.so` will be created at `splitfs_syscall_intercept/src` -- this is the library file that needs to be used with `LD_PRELOAD`.
4. Run the application that you want using `LD_PRELOAD=splitfs_syscall_intercept/src/libnvp.so` \<application cmd\>

###How to run the PJD test suite?
All paths (not starting with `/`) are relative to root of repository
1. Set up the pmem file mount at `/mnt/pmem_emul`
2. Make sure the mount point has `write` and `execute` permissions so that all users can delete files. (This is required since some tests use `setuid` to switch to a different user. This user will then not have permission to delete the staging files during exit cleanup)
3. `cd tests`
4. `make all_sysint`
122 changes: 122 additions & 0 deletions splitfs_syscall_intercept/include/debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#ifndef __DEBUG_INCLUDED
#define __DEBUG_INCLUDED

#include "boost/preprocessor/list/for_each.hpp"

// Turns on debugging messages
#ifndef SHOW_DEBUG
#define SHOW_DEBUG 0
#endif

#ifndef PRINT_DEBUG_FILE
#define PRINT_DEBUG_FILE 0
#endif

#ifndef SPIN_ON_ERROR
#define SPIN_ON_ERROR 0
#endif

//#define ENV_GDB_VEC "NVP_GDB_VEC"
/*
#define fopen fopen_orig
#undef fopen
*/
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

extern FILE* _nvp_print_fd;

// use stderr, until we dup it
#define NVP_PRINT_FD ((_nvp_print_fd)?_nvp_print_fd:stderr)

typedef char* charptr;
void xil_printf(FILE* f, const charptr c, ...);
//static inline void _nvp_debug_handoff(void)

/*
#define _nvp_debug_handoff(x) \
{ \
xil_printf(stderr, "Stopping thread and waiting for gdb...\ngdb --pid=%i\n", getpid()); \
fflush(stderr); \
sleep(1); \
volatile int asdf = 1; \
sleep(1); \
while(asdf) {}; \
}
*/

#define _nvp_debug_handoff(x) \
{ \
sleep(1); \
volatile int asdf = 1; \
sleep(1); \
while(asdf) {}; \
}


//void outbyte(char c);

//#define ERROR_NAMES (EPERM) (ENOENT) (ESRCH) (EINTR) (EIO) (ENXIO) (E2BIG) (ENOEXEC) (EBADF) (ECHILD) (EAGAIN) (ENOMEM) (EACCES) (EFAULT) (ENOTBLK) (EBUSY) (EEXIST) (EXDEV) (ENODEV) (ENOTDIR) (EISDIR) (EINVAL) (ENFILE) (EMFILE) (ENOTTY) (ETXTBSY) (EFBIG) (ENOSPC) (ESPIPE) (EROFS) (EMLINK) (EPIPE) (EDOM) (ERANGE) (EDEADLK)
#define ERROR_NAMES_LIST (EPERM, (ENOENT, (ESRCH, (EINTR, (EIO, (ENXIO, (E2BIG, (ENOEXEC, (EBADF, (ECHILD, (EAGAIN, (ENOMEM, (EACCES, (EFAULT, (ENOTBLK, (EBUSY, (EEXIST, (EXDEV, (ENODEV, (ENOTDIR, (EISDIR, (EINVAL, (ENFILE, (EMFILE, (ENOTTY, (ETXTBSY, (EFBIG, (ENOSPC, (ESPIPE, (EROFS, (EMLINK, (EPIPE, (EDOM, (ERANGE, (EDEADLK, BOOST_PP_NIL)))))))))))))))))))))))))))))))))))

#define ERROR_IF_PRINT(r, data, elem) if(data == elem) { DEBUG("errno == %s (%i): %s\n", MK_STR(elem), elem, strerror(elem)); }

// also used in fileops_wrap
//#define PRINTFUNC fprintf
#define PRINTFUNC xil_printf


#if DISABLE_MSG
#define MSG(format, ...) do{}while(0)
#else
#define MSG(format, ...) do{PRINTFUNC(NVP_PRINT_FD, "MSG: "); PRINTFUNC (NVP_PRINT_FD, format, ##__VA_ARGS__); fflush(NVP_PRINT_FD); }while(0)
#endif
#define LOG(format, ...) do{PRINTFUNC(NVP_PRINT_FD, "MSG: "); PRINTFUNC (NVP_PRINT_FD, format, ##__VA_ARGS__); fflush(NVP_PRINT_FD); }while(0)
#define ERROR(format, ...) do{PRINTFUNC(NVP_PRINT_FD, "\033[01;33mNVP_ERROR\e[m (pid %i): " format, getpid(), ##__VA_ARGS__); PRINTFUNC(NVP_PRINT_FD, "ROHAN HERE\n"); if(SPIN_ON_ERROR){ _nvp_debug_handoff(); } }while(0)

extern FILE *debug_fd;
#define DEBUG_FD debug_fd

#if PRINT_DEBUG_FILE
#define DEBUG_FILE(format, ...) do {PRINTFUNC(DEBUG_FD, "\033[01;33mNVP_DEBUG\
\e[m (pid %i): " format, getpid(), ##__VA_ARGS__); }while(0)
#else
#define DEBUG_FILE(format, ...) do{}while(0)
#endif

#if SHOW_DEBUG
#define DEBUG(format, ...) do{char loc; PRINTFUNC(NVP_PRINT_FD, "NVP_DEBUG (PID %i SP %p): " format, getpid(), &loc, ##__VA_ARGS__); fflush(NVP_PRINT_FD); } while(0)
#define WARNING(format, ...) do{PRINTFUNC(NVP_PRINT_FD, "NVP_WARNING (PID %i): " format, getpid(), ##__VA_ARGS__); } while(0)
#define DEBUG_P(format, ...) do{PRINTFUNC(NVP_PRINT_FD, format, ##__VA_ARGS__); } while(0)
#else
#define DEBUG(format, ...) do{}while(0)
#define WARNING(format, ...) do{}while(0)
#define DEBUG_P(format, ...) do{}while(0)
#endif

#define FAIL \
"FFFFFFFFFFFFFFFFFFFFFF AAA IIIIIIIIII LLLLLLLLLLL \n"\
"F::::::::::::::::::::F A:::A I::::::::I L:::::::::L \n"\
"F::::::::::::::::::::F A:::::A I::::::::I L:::::::::L \n"\
"FF::::::FFFFFFFFF::::F A:::::::A II::::::II LL:::::::LL \n"\
" F:::::F FFFFFF A:::::::::A I::::I L:::::L \n"\
" F:::::F A:::::A:::::A I::::I L:::::L \n"\
" F::::::FFFFFFFFFF A:::::A A:::::A I::::I L:::::L \n"\
" F:::::::::::::::F A:::::A A:::::A I::::I L:::::L \n"\
" F:::::::::::::::F A:::::A A:::::A I::::I L:::::L \n"\
" F::::::FFFFFFFFFFA:::::AAAAAAAAA:::::A I::::I L:::::L \n"\
" F:::::F A:::::::::::::::::::::A I::::I L:::::L \n"\
" F:::::F A:::::AAAAAAAAAAAAA:::::A I::::I L:::::L LLLLLL\n"\
"FF:::::::FF A:::::A A:::::A II::::::II LL:::::::LLLLLLLLL:::::L\n"\
"F::::::::FF A:::::A A:::::A I::::::::I L::::::::::::::::::::::L\n"\
"F::::::::FF A:::::A A:::::A I::::::::I L::::::::::::::::::::::L\n"\
"FFFFFFFFFFF AAAAAAA AAAAAAAIIIIIIIIII LLLLLLLLLLLLLLLLLLLLLLLL\n"

#endif

//#define PRINT_ERROR_NAME(errnoin) BOOST_PP_SEQ_FOR_EACH(ERROR_IF_PRINT, errnoin, ERROR_NAMES) // can't use BOOST_PP_SEQ_FOR_EACH within another BOOST_PP_SEQ_FOR_EACH
#define PRINT_ERROR_NAME(errnoin) _nvp_print_error_name(errnoin);
void _nvp_print_error_name(int errnoin);

157 changes: 157 additions & 0 deletions splitfs_syscall_intercept/include/nv_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Header file shared by nvmfileops.c, fileops_compareharness.c
#define _GNU_SOURCE

#ifndef __NV_COMMON_H_
#define __NV_COMMON_H_

#ifndef __cplusplus
#endif

#define _GNU_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <sched.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <sys/uio.h>
#include <dlfcn.h>
#include <limits.h>
#include <stdint.h>
#include <sched.h>
#include <ctype.h>
#include <signal.h>
#include <pthread.h>
#include "debug.h"
#include "boost/preprocessor/seq/for_each.hpp"

#define MIN(X,Y) (((X)<(Y))?(X):(Y))
#define MAX(X,Y) (((X)>(Y))?(X):(Y))

// tell the compiler a branch is/is not likely to be followed
#define LIKELY(x) __builtin_expect((x),1)
#define UNLIKELY(x) __builtin_expect((x),0)

#define assert(x) if(UNLIKELY(!(x))) { printf("ASSERT FAILED ROHAN\n"); fflush(NULL); ERROR("NVP_ASSERT("#x") failed!\n"); exit(100); }

// ----------------- Syscall Intercept Stuff ----------------
#define INTF_SYSCALL long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result
#define RETT_SYSCALL_INTERCEPT int

// Pass thru call to kernel
#define RETT_PASS_KERN 1

// Took over call. Don't pass to kernel.
#define RETT_NO_PASS_KERN 0
// ----------------------------------------------------------

#define DO_ALIGNMENT_CHECKS 0

// places quotation marks around arg (eg, MK_STR(stuff) becomes "stuff")
#define MK_STR(arg) #arg
#define MK_STR2(x) MK_STR(x)
#define MK_STR3(x) MK_STR2(x)

#define MACRO_WRAP(a) a
#define MACRO_CAT(a, b) MACRO_WRAP(a##b)

#ifndef __cplusplus
typedef int bool;
#define false 0
#define true 1
#endif


#define BG_CLOSING 0
#define SEQ_LIST 0
#define RAND_LIST 1

// maximum number of file operations to support simultaneously
#define MAX_FILEOPS 32
#define BUF_SIZE 40

// Every time a function is used, determine whether the module's functions have been resolved.
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>

extern int OPEN_MAX;

#define NOSANITYCHECK 1
#if NOSANITYCHECK
#define SANITYCHECK(x)
#else
#define SANITYCHECK(x) if(UNLIKELY(!(x))) { ERROR("NVP_SANITY("#x") failed!\n"); exit(101); }
#endif

#define ASYNC_CLOSING async_close_enable
volatile int async_close_enable;

// Used to determine contents of flags passed to OPEN
#define FLAGS_INCLUDE(flags, x) ((flags&x)||(x==0))
#define DUMP_FLAGS(flags, x) do{ if(FLAGS_INCLUDE(flags, x)) { DEBUG_P("%s(0x%X) ",#x,x); } }while(0)


#define NVP_CHECK_NVF_VALID(nvf) do{ \
if(UNLIKELY(!nvf->valid)) { \
DEBUG("Invalid file descriptor: %i\n", file); \
errno = 0; \
return -1; \
} \
else \
{ \
DEBUG("this function is operating on node %p\n", nvf->node); \
} \
} while(0)

#define NVP_CHECK_NVF_VALID_WR(nvf) do{ \
if(UNLIKELY(!nvf->valid)) { \
DEBUG("Invalid file descriptor: %i\n", file); \
errno = 0; \
return -1; \
} \
else { \
DEBUG("this function is operating on node %p\n", nvf->node); \
} \
} while(0)

#define IS_ERR(x) ((unsigned long)(x) >= (unsigned long)-4095)

// modifications to support different FSYNC policies
#define NVMM_PATH "/mnt/pmem_emul/"

#define SANITYCHECKNVF(nvf) \
SANITYCHECK(nvf->valid); \
SANITYCHECK(nvf->node != NULL); \
SANITYCHECK(nvf->fd >= 0); \
SANITYCHECK(nvf->fd < OPEN_MAX); \
SANITYCHECK(nvf->offset != NULL); \
SANITYCHECK(*nvf->offset >= 0); \
SANITYCHECK(nvf->node->length >=0); \
SANITYCHECK(nvf->node->maplength >= nvf->node->length); \
SANITYCHECK(nvf->node->data != NULL)


#define SFS_OPS (CLOSE) (DUP) (DUP2) (EXECVE) (FSYNC) (LINK) (MKDIR) (MKDIRAT) (MKNOD) (MKNODAT) (OPEN) (READ) \
(RENAME) (RMDIR) (SEEK) (SYMLINK) (SYMLINKAT) (UNLINK) (UNLINKAT) (WRITE)
#define DECLARE_SFS_FUNCS(FUNCT, prefix) \
RETT_SYSCALL_INTERCEPT prefix##FUNCT(INTF_SYSCALL);
#define DECLARE_SFS_FUNCS_IWRAP(r, data, elem) DECLARE_SFS_FUNCS(elem, data)

BOOST_PP_SEQ_FOR_EACH(DECLARE_SFS_FUNCS_IWRAP, _sfs_, SFS_OPS)

#endif
Loading