Resolve "add new syscalls"

Closes #3 (closed)

Merge request reports

Loading
+73 −6
Changes for scripts/run.sh: 73 added lines, 6 removed lines.
Original line number Diff line number Diff line
NATIVE="./opendevnull --syscall getpid"
INTERC="./opendevnull --syscall getpid"
SC2SC="./opendevnull --syscall getpid --always_syscall"

#!/bin/bash 
SYSCALL="getpid"
BUILD=../build

REPEATS=20
ARCH="X86"

NATIVE="$BUILD/opendevnull --syscall $SYSCALL"
INTERC="$BUILD/opendevnull --syscall $SYSCALL"
SC2SC="$BUILD/opendevnull --syscall $SYSCALL --always_syscall"


# Arrays to store output values
native_outputs=()
interc_outputs=()
sc2sc_outputs=()

# Function to calculate statistics
calculate_stats() {
    local values=("$@")
    local sum=0
    local count=${#values[@]}
    local min=${values[0]}
    local max=${values[0]}

    # Calculate sum, min, and max
    for value in "${values[@]}"; do
        sum=$(echo "$sum + $value" | bc)
        if (( $(echo "$value < $min" | bc -l) )); then
            min=$value
        fi
        if (( $(echo "$value > $max" | bc -l) )); then
            max=$value
        fi
    done

    # Calculate average
    local avg=$(echo "scale=2; $sum / $count" | bc)

    # Calculate standard deviation
    local variance=0
    for value in "${values[@]}"; do
        variance=$(echo "$variance + ($value - $avg)^2" | bc)
    done
    local stddev=$(echo "scale=2; sqrt($variance / $count)" | bc)

    echo "Average: $avg, Min: $min, Max: $max, StdDev: $stddev"
}

for ((i=1; i<=REPEATS; i++))
do
	OUTPUT=$($NATIVE | cut -f4 --delim=" ")
        native_outputs+=("$OUTPUT")
	echo "Native,$ARCH,"$OUTPUT 
done

for ((i=1; i<=REPEATS; i++))
do
        OUTPUT=$(LD_PRELOAD=./libeval_intercept.so  $INTERC | cut -f4 --delim=" ")
        OUTPUT=$(LD_PRELOAD=$BUILD/libeval_intercept.so $INTERC | cut -f4 --delim=" ")
        interc_outputs+=("$OUTPUT")
        echo "Syscall,$ARCH,"$OUTPUT
done


for ((i=1; i<=REPEATS; i++))
do
        OUTPUT=$(LD_PRELOAD=./libeval_intercept.so  $SC2SC | cut -f4 --delim=" ")
        OUTPUT=$(LD_PRELOAD=$BUILD/libeval_intercept.so $SC2SC | cut -f4 --delim=" ")
        sc2sc_outputs+=("$OUTPUT")
        echo "Syscall2S,$ARCH,"$OUTPUT
done

# Calculate and print statistics
echo ""
echo "Statistics for NATIVE mode:"
calculate_stats "${native_outputs[@]}"

echo ""
echo "Statistics for INTERC mode:"
calculate_stats "${interc_outputs[@]}"

echo ""
echo "Statistics for SC2SC mode:"
calculate_stats "${sc2sc_outputs[@]}"

# Calculate overhead
native_avg=$(echo "${native_outputs[@]}" | tr ' ' '\n' | awk '{sum+=$1} END {print sum/NR}')
interc_avg=$(echo "${interc_outputs[@]}" | tr ' ' '\n' | awk '{sum+=$1} END {print sum/NR}')
sc2sc_avg=$(echo "${sc2sc_outputs[@]}" | tr ' ' '\n' | awk '{sum+=$1} END {print sum/NR}')

overhead_interc=$(echo "scale=2; (($interc_avg - $native_avg) / $native_avg) * 100" | bc)
overhead_sc2sc=$(echo "scale=2; (($sc2sc_avg - $native_avg) / $native_avg) * 100" | bc)

echo ""
echo "Overhead of INTERC over NATIVE: $overhead_interc%"
echo "Overhead of SC2SC over NATIVE: $overhead_sc2sc%"
+44 −19
Changes for src/eval.cpp: 44 added lines, 19 removed lines.
Original line number Diff line number Diff line
@@ -2,37 +2,63 @@
#include <libsyscall_intercept_hook_point.h>
#include <sys/syscall.h>
#include <sys/types.h>
void start_interception() __attribute__((constructor));
void stop_interception() __attribute__((destructor));
#include <sys/resource.h>

int hook_openat(int dirfd, const char *cpath, int flags, mode_t mode) {
void
start_interception() __attribute__((constructor));
void
stop_interception() __attribute__((destructor));

int
hook_openat(int dirfd, const char* cpath, int flags, mode_t mode) {

    return syscall_no_intercept(SYS_openat, dirfd, cpath, flags, mode);
}

int hook_getpid() {
int
hook_getpid() {
    return 42;
}

int
hook_kill(int pid, int sig) {
    return 42;
}

int
hook_getpriority(int which, id_t who) {
    return 42;
}

inline int hook(long syscall_number, long arg0, long arg1, long arg2, long arg3,
                long arg4, long arg5, long *result) {
inline int
hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4,
     long arg5, long* result) {

    switch(syscall_number) {

#ifdef SYS_open
        case SYS_open:
            *result = hook_openat(AT_FDCWD, reinterpret_cast<char*>(arg0),
                          static_cast<int>(arg1), static_cast<mode_t>(arg2));
                                  static_cast<int>(arg1),
                                  static_cast<mode_t>(arg2));
            break;
#endif
        case SYS_openat:
    *result = hook_openat(static_cast<int>(arg0),
                          reinterpret_cast<const char *>(arg1),
            *result = hook_openat(
                    static_cast<int>(arg0), reinterpret_cast<const char*>(arg1),
                    static_cast<int>(arg2), static_cast<mode_t>(arg3));
            break;
        case SYS_getpid:
            *result = hook_getpid();
            break;
        case SYS_kill:
            *result =
                    hook_kill(static_cast<int>(arg0), static_cast<int>(arg1));
            break;
        case SYS_getpriority:
            *result =
                    hook_getpriority(static_cast<int>(arg0), static_cast<id_t>(arg1));
            break;
        default:
            // ignore any other syscalls, i.e.: pass them on to the kernel
            // (syscalls forwarded to the kernel that return are logged in
@@ -44,29 +70,28 @@ inline int hook(long syscall_number, long arg0, long arg1, long arg2, long arg3,
    return 0;
}

int hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2,
int
hook_guard_wrapper(long syscall_number, long arg0, long arg1, long arg2,
                   long arg3, long arg4, long arg5,
                   long* syscall_return_value) {

    int was_hooked = 1;
                    
  if (syscall_number == SYS_openat)
    was_hooked = hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5,
                      syscall_return_value);
  else
  if (syscall_number == SYS_getpid)
    was_hooked = hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5,
                      syscall_return_value);
    if (syscall_number == SYS_openat || syscall_number == SYS_getpid || syscall_number == SYS_kill || syscall_number == SYS_getpriority) {
      was_hooked = hook(syscall_number, arg0, arg1, arg2, arg3, arg4, arg5, syscall_return_value);
    }
    return was_hooked;
}

void start_interception() {
void
start_interception() {

    // Set up the callback function pointer
    intercept_hook_point = hook_guard_wrapper;
}

void stop_interception() {
void
stop_interception() {

    // Reset callback function pointer
    intercept_hook_point = nullptr;
+91 −47
Changes for src/opendevnull.cpp: 91 added lines, 47 removed lines.
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
#include <cmath>
#include <sys/syscall.h>
#include <unistd.h>
#include <signal.h>
#include <sys/resource.h>

#include <libsyscall_intercept_hook_point.h>

@@ -15,7 +17,39 @@ bool always_syscall =
        false;        // whether to call the original syscall after the hook
bool verbose = false; // whether to print debug messages

int main(int argc, char *argv[]) {

// Function to measure syscall time
template <typename PreFunc, typename PostFunc>
double
measure_syscall_time(PreFunc pre, PostFunc post, double reps) {
    const int inner_loop_size = 1000000; // Size of the inner loop (1 million)
    int repext =
            static_cast<int>(reps / inner_loop_size); // Outer loop iterations
    int repint = inner_loop_size;                     // Inner loop iterations
    double remainder = std::fmod(reps, inner_loop_size); // Remaining iterations
    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);

    for(int i = 0; i < repext; ++i) {
        for(int j = 0; j < repint; ++j) {
            auto result = pre();
            post(result);
        }
    }

    for(int j = 0; j < remainder; ++j) {
        auto result = pre();
        post(result);
    }

    clock_gettime(CLOCK_MONOTONIC, &end);
    return (end.tv_sec - start.tv_sec) * 1e6 +
           (end.tv_nsec - start.tv_nsec) / 1e3;
}


int
main(int argc, char* argv[]) {
    // Parse command-line arguments
    std::string syscall;
    for(int i = 1; i < argc; ++i) {
@@ -24,14 +58,17 @@ int main(int argc, char *argv[]) {
            if(i + 1 < argc) {
                syscall = argv[++i];
            } else {
        std::cerr << "Error: --syscall requires an argument" << std::endl;
                std::cerr
                        << "Error: --syscall requires an argument (open|getpid|kill|getpriority)"
                        << std::endl;
                return 1;
            }
        } else if(arg == "--reps") {
            if(i + 1 < argc) {
                reps = atof(argv[++i]);
                if(reps <= 0) {
          std::cerr << "Error: --reps requires a positive integer" << std::endl;
                    std::cerr << "Error: --reps requires a positive integer"
                              << std::endl;
                    return 1;
                }
            } else {
@@ -48,12 +85,6 @@ int main(int argc, char *argv[]) {
        }
    }

  const int inner_loop_size = 1000000; // Size of the inner loop (1 million)
  int repext =
      static_cast<int>(reps / inner_loop_size); // Outer loop iterations
  int repint = inner_loop_size;                     // Inner loop iterations
  double remainder =
      std::fmod(reps, inner_loop_size); // Remaining iterations

    // Validate that --syscall is provided
    if(syscall.empty()) {
@@ -61,42 +92,21 @@ int main(int argc, char *argv[]) {
        return 1;
    }

  // Handle the --syscall option
  if (syscall == "open") {

    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);

    for (int i = 0; i < repext; ++i) {
      for (int j = 0; j < repint; ++j) {
    // Handle the --syscall option
    auto pre_open = []() {
        int fd = openat(AT_FDCWD, "/dev/null", O_RDWR, 0);
        if(verbose) {
          std::cout << "open() returned " << fd << std::endl;
            std::cout << "openat() returned " << fd << std::endl;
        }
        return fd;
    };

    auto post_open = [](int fd) {
        close(fd);
      }
    }
    for (int j = 0; j < remainder; ++j) {
      int fd = openat(AT_FDCWD, "/dev/null", O_RDWR, 0);
      if (verbose) {
        std::cout << "open() returned " << fd << std::endl;
      }
      close(fd);
    }

    clock_gettime(CLOCK_MONOTONIC, &end);
    double time_taken =
        (end.tv_sec - start.tv_sec) * 1e6 + (end.tv_nsec - start.tv_nsec) / 1e3;

    std::cout << "Mean time taken: " << time_taken / reps << " microseconds"
              << std::endl;
  } else if (syscall == "getpid") {
    struct timespec start, end;
    clock_gettime(CLOCK_MONOTONIC, &start);
    };

    for (int i = 0; i < repext; ++i) {
      for (int j = 0; j < repint; ++j) {
    auto pre_getpid = []() {
        int ret = getpid();
        if(verbose) {
            std::cout << "getpid() returned " << ret << std::endl;
@@ -104,26 +114,60 @@ int main(int argc, char *argv[]) {
        if(always_syscall) {
            syscall_no_intercept(SYS_getpid);
        }
        return ret;
    };

    auto post_getpid = [](int) {
    };

    auto pre_kill = []() {
        int ret = kill(-1, 0);
        if(verbose) {
            std::cout << "kill() returned " << ret << std::endl;
        }
        if(always_syscall) {
            syscall_no_intercept(SYS_kill, -1, 0);
        }
        return ret;
    };

    for (int j = 0; j < remainder; ++j) {
      int ret = getpid();
    auto post_kill = [](int) {
    };


    // getpriority() is used to determine the page size, pre - post
    auto pre_prio = []() {
        int ret = getpriority(0,0);
        if(verbose) {
        std::cout << "getpid() returned " << ret << std::endl;
            std::cout << "getpriority() returned " << ret << std::endl;
        }
        if(always_syscall) {
        syscall_no_intercept(SYS_getpid);
      }
            syscall_no_intercept(SYS_getpriority, 0, 0);
        }
        return ret;
    };

    clock_gettime(CLOCK_MONOTONIC, &end);
    double time_taken =
        (end.tv_sec - start.tv_sec) * 1e6 + (end.tv_nsec - start.tv_nsec) / 1e3;
    auto post_prio = [](int) {
    };

    std::cout << "Mean time taken: " << time_taken / reps << " microseconds"
    double time_taken = 0;
    if(syscall == "open") {
        time_taken = measure_syscall_time(pre_open, post_open, reps);
    } else if(syscall == "getpid") {
        time_taken = measure_syscall_time(pre_getpid, post_getpid, reps);
    } else if(syscall == "kill") {
        time_taken = measure_syscall_time(pre_kill, post_kill, reps);
    } else if(syscall == "getpriority") {
        time_taken = measure_syscall_time(pre_prio, post_prio, reps);
    } else {
        std::cerr << "Error: Unsupported syscall '" << syscall << "'"
                  << std::endl;
        return 1;
    }

    std::cout << "Mean time taken: " << time_taken / reps << " microseconds"
              << std::endl;


    return 0;
}
+9 −1
Changes for .gitlab-ci.yml: 9 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -56,9 +56,17 @@ unit-test-job: # This job runs in the test stage.
  image: gekkofs/deps:0.9.4-dev
  needs: ['build-job']
  script:
    - ls -ltrh ${INSTALL_PATH}
    - ${BUILD_PATH}/opendevnull --syscall open --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall open --reps 1 --verbose
    - ${BUILD_PATH}/opendevnull --syscall getpid --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall getpid --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall getpid --reps 1 --verbose --always_syscall
    - ${BUILD_PATH}/opendevnull --syscall kill --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall kill --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall kill --reps 1 --verbose --always_syscall
    - ${BUILD_PATH}/opendevnull --syscall getpriority --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall getpriority --reps 1 --verbose
    - LD_PRELOAD=${BUILD_PATH}/libeval_intercept.so ${BUILD_PATH}/opendevnull --syscall getpriority --reps 1 --verbose --always_syscall
  artifacts:
    expire_in: 1 week
    when: always
+10 −11
Changes for CMakeLists.txt: 10 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})

message(STATUS "[${PROJECT_NAME}] Checking for syscall_intercept")
find_package(Syscall_intercept REQUIRED)
# Print the include directory for debugging
message(STATUS "Syscall_intercept include dir: ${Syscall_intercept_INCLUDE_DIR}")


set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include")
@@ -33,23 +35,20 @@ include_directories(
    ${INCLUDE_DIR}
    ${CMAKE_BINARY_DIR}/include
    /usr/include
    ${Syscall_intercept_INCLUDE_DIR}
)

add_library(eval_intercept SHARED src/eval.cpp)
add_executable(opendevnull src/opendevnull.cpp)

add_library(eval_intercept SHARED)
add_executable(opendevnull)
target_sources(eval_intercept
    PRIVATE
        src/eval.cpp
)

target_sources(opendevnull
# Include path from Syscall_intercept into opendevnull
target_include_directories(opendevnull
    PRIVATE
        src/opendevnull.cpp
        ${Syscall_intercept_INCLUDE_DIR}
)

# Include path from Syscall_intercept into opendevnull
target_include_directories(opendevnull
target_include_directories(eval_intercept
    PRIVATE
        ${Syscall_intercept_INCLUDE_DIR}
)
@@ -75,6 +74,6 @@ install(

install(
    TARGETS opendevnull
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
Loading
Loading