Skip to content
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
6 changes: 5 additions & 1 deletion .container/install-ubuntu-dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ sudo apt-get install -y --no-install-recommends \
libxml2-dev \
libzstd1 \
libgtest-dev \
libc6-dev-i386 \
apt-transport-https \
dirmngr \
googletest \
Expand All @@ -47,6 +46,11 @@ sudo apt-get install -y --no-install-recommends \
clang-tools \
libssl-dev

# libc6-dev-i386 is only available/needed on x86_64
if [ "$(uname -m)" = "x86_64" ]; then
sudo apt-get install -y --no-install-recommends libc6-dev-i386
fi

sudo wget https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/openat2.h -O /usr/include/linux/openat2.h

# install debbuild
Expand Down
52 changes: 42 additions & 10 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,37 @@ cmake ..
make
```

## Cross-building for aarch64 (on x86_64)

### Prerequisites
Install cross-compilation toolchain and target-architecture libraries:
```
sudo apt -y install crossbuild-essential-arm64 binutils-aarch64-linux-gnu \
libc6-dev-arm64-cross linux-libc-dev-arm64-cross \
libelf-dev:arm64 libjson-glib-dev:arm64 zlib1g-dev:arm64 libzstd-dev:arm64
```

You may need to enable the arm64 architecture first:
```
sudo dpkg --add-architecture arm64
sudo apt update
```

### Cross-build
```
cd SysinternalsEBPF
mkdir build-arm64
cd build-arm64
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=../cmake/aarch64-linux-gnu.cmake
cmake --build . --parallel
```

### Install (staged)
```
DESTDIR=$(pwd)/staging cmake --install .
```

## (Build from Sysmon ADO internally)
*This is only required when cloning from the Sysmon ADO. Most users can ignore
this.*
Expand Down Expand Up @@ -69,14 +100,15 @@ Or:
sudo make install
sudo ldconfig
```
The shared library will be installed to /lib/x86_64-linux-gnu (Debian) or
/lib64 (Fedora) or /usr/lib (pre multi arch Debian).; the header to /usr/include;
the offsets database and EBPF objects to /opt/sysinternalsEBPF. The libsysinternalsEBPFinstaller
binary will also be installed in /opt/sysinternalsEBPF (which can be copied to another
system and run to install sysinternalsEBPF there). *Note:* 'sudo make install' will use
the binary, include, and lib directories that cmake prefers or you have
overridden, whereas the installer and the packages (see below) use the paths
specified above.
The shared library will be installed to the appropriate multiarch library
directory (e.g. /lib/x86\_64-linux-gnu on Debian x86\_64,
/lib/aarch64-linux-gnu on Debian arm64, or /lib64 on Fedora); the header to
/usr/include; the offsets database and EBPF objects to /opt/sysinternalsEBPF.
The libsysinternalsEBPFinstaller binary will also be installed in
/opt/sysinternalsEBPF (which can be copied to another system and run to install
sysinternalsEBPF there). *Note:* 'sudo make install' will use the binary,
include, and lib directories that cmake prefers or you have overridden, whereas
the installer and the packages (see below) use the paths specified above.

## Make Packages
Packages can be generated with:
Expand All @@ -90,5 +122,5 @@ make rpm
The directories build/deb and build/rpm will be populated with the required
files. If dpkg-deb is available, the build/deb directory will be used to create
a deb package. Similarly if rpmbuild is available, the build/rpm directory will
be used to create an rpm package.

be used to create an rpm package. Package architecture is set automatically
based on the target platform.
90 changes: 74 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,53 @@ if ("${PROJECT_VERSION_TWEAK}" STREQUAL "")
set(PROJECT_VERSION_TWEAK 0)
endif()

configure_file(package/DEBIAN.in/control.in DEBIANcontrol)
configure_file(package/SPECS.in/spec.in SPECS.spec)

#
# enable Debug while pre-release; re-enable it post-release to add symbols to binary
#
#set(CMAKE_BUILD_TYPE Debug)
#option(DEBUG_K "Enter debug mode" On)

#
# external programs used by this build
# external programs used by this build - respect cross-compilation toolchain
#
if(CMAKE_LINKER)
set(LD "${CMAKE_LINKER}")
else()
set(LD "/usr/bin/ld")
endif()

include(GNUInstallDirs)

#
# Architecture detection — reject unsupported targets early
#
set(LD "/usr/bin/ld")
if(NOT DEFINED TARGET_ARCH)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
set(TARGET_ARCH "arm64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
set(TARGET_ARCH "x86")
else()
message(FATAL_ERROR "Unsupported target architecture: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
endif()

message(STATUS "Target architecture: ${TARGET_ARCH}")

# Derive multiarch tuple for system includes
if(TARGET_ARCH STREQUAL "arm64")
set(TARGET_MULTIARCH "aarch64-linux-gnu")
set(DEB_ARCH "arm64")
set(RPM_ARCH "aarch64")
elseif(TARGET_ARCH STREQUAL "x86")
set(TARGET_MULTIARCH "x86_64-linux-gnu")
set(DEB_ARCH "amd64")
set(RPM_ARCH "x86_64")
else()
message(FATAL_ERROR "Unsupported TARGET_ARCH: ${TARGET_ARCH} (expected 'x86' or 'arm64')")
endif()

configure_file(package/DEBIAN.in/control.in DEBIANcontrol)
configure_file(package/SPECS.in/spec.in SPECS.spec)

#
# package name
Expand Down Expand Up @@ -112,13 +146,20 @@ include(ExternalProject)

# Fetch libbpf
# FIX this so that it clones libbpf when the project is cloned
# Build libbpf with the correct compiler for the target architecture
if(CMAKE_CROSSCOMPILING)
set(LIBBPF_BUILD_CMD "CC=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} CFLAGS=\"-g -O2 -Werror -Wall -fPIC\" make")
else()
set(LIBBPF_BUILD_CMD "CFLAGS=\"-g -O2 -Werror -Wall -fPIC\" make")
endif()

ExternalProject_Add(libbpf
GIT_REPOSITORY https://github.com/libbpf/libbpf.git
# GIT_TAG master
GIT_TAG v1.7.0
PREFIX ./libbpf
CONFIGURE_COMMAND ""
BUILD_COMMAND cd ../libbpf/src && bash -c "CFLAGS=\"-g -O2 -Werror -Wall -fPIC\" make"
BUILD_COMMAND cd ../libbpf/src && bash -c "${LIBBPF_BUILD_CMD}"
INSTALL_COMMAND ""
)

Expand Down Expand Up @@ -187,12 +228,12 @@ add_executable(libsysinternalsEBPFinstaller
)

add_custom_target(deb
COMMAND "${CMAKE_SOURCE_DIR}/makePackages.sh" "${CMAKE_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" "${PACKAGE_NAME}" "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" "0" "deb"
COMMAND "${CMAKE_SOURCE_DIR}/makePackages.sh" "${CMAKE_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" "${PACKAGE_NAME}" "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" "0" "deb" "${DEB_ARCH}"
DEPENDS "${CMAKE_SOURCE_DIR}/package" "${PROJECT_BINARY_DIR}/libsysinternalsEBPFinstaller"
)

add_custom_target(rpm
COMMAND "${CMAKE_SOURCE_DIR}/makePackages.sh" "${CMAKE_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" "${PACKAGE_NAME}" "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" "0" "rpm"
COMMAND "${CMAKE_SOURCE_DIR}/makePackages.sh" "${CMAKE_SOURCE_DIR}" "${PROJECT_BINARY_DIR}" "${PACKAGE_NAME}" "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" "0" "rpm" "${RPM_ARCH}"
DEPENDS "${CMAKE_SOURCE_DIR}/package" "${PROJECT_BINARY_DIR}/libsysinternalsEBPFinstaller"
)

Expand Down Expand Up @@ -343,8 +384,8 @@ set_target_properties(sysinternalsEBPF PROPERTIES
)

install(TARGETS sysinternalsEBPF
LIBRARY DESTINATION lib ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION include ${CMAKE_INSTALL_INCLUDEDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
RESOURCE DESTINATION /opt/sysinternalsEBPF/
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
)
Expand Down Expand Up @@ -402,8 +443,21 @@ add_custom_command(OUTPUT unameOffsets.c
#

# set binaries and options for clang and llc
set(CLANG "clang")
set(LLC "llc")
find_program(CLANG clang)
if(NOT CLANG)
message(FATAL_ERROR "clang is required to build eBPF programs")
endif()
find_program(LLC llc)

# Derive the compiler's built-in include directory at configure time
# so we do not backtick the host gcc at build time during cross-compilation.
execute_process(
COMMAND ${CMAKE_C_COMPILER} -print-file-name=include
OUTPUT_VARIABLE GCC_BUILTIN_INCLUDE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "GCC built-in include: ${GCC_BUILTIN_INCLUDE}")

set(CLANG_OPTIONS -Wno-unused-value
-Wno-pointer-sign
-Wno-compare-distinct-pointer-types
Expand All @@ -415,7 +469,7 @@ set(CLANG_OPTIONS -Wno-unused-value
)
set(CLANG_DEFINES -D __KERNEL__
-D __BPF_TRACING__
-D __TARGET_ARCH_x86
-D __TARGET_ARCH_${TARGET_ARCH}
)
if (DEBUG_K)
message("Using DEBUG_K Option...")
Expand All @@ -439,7 +493,13 @@ set(CLANG_INCLUDES
function(build_ebpf ebpfsrc)
add_custom_command(TARGET sysinternalsEBPF
PRE_BUILD
COMMAND "${CLANG}" -nostdinc ${CLANG_INCLUDES} -isystem "/usr/include" -isystem "/usr/include/x86_64-linux-gnu" -isystem `gcc -print-file-name=include` ${CLANG_DEFINES} -O2 ${CLANG_OPTIONS} -target bpf -c "${CMAKE_SOURCE_DIR}/ebpfKern/${ebpfsrc}.c" -o "${ebpfsrc}.o"
COMMAND "${CLANG}" -nostdinc ${CLANG_INCLUDES}
-isystem "/usr/include/${TARGET_MULTIARCH}"
-isystem "/usr/include"
-isystem "${GCC_BUILTIN_INCLUDE}"
${CLANG_DEFINES} -O2 ${CLANG_OPTIONS} -target bpf
-c "${CMAKE_SOURCE_DIR}/ebpfKern/${ebpfsrc}.c"
-o "${ebpfsrc}.o"
COMMENT "Building EBPF object ${ebpfsrc}.o"
DEPENDS ebpfKern/${ebpfsrc}.c ${EBPF_DEPENDS}
)
Expand All @@ -456,5 +516,3 @@ foreach(EBPF_PROG IN LISTS EBPF_PROGS)
# add ebpf programs to clean
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${EBPF_PROG}.o)
endforeach(EBPF_PROG)


19 changes: 19 additions & 0 deletions cmake/aarch64-linux-gnu.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# CMake toolchain file for cross-compiling to aarch64-linux-gnu
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_LINKER aarch64-linux-gnu-ld)
set(CMAKE_AR aarch64-linux-gnu-ar)
set(CMAKE_RANLIB aarch64-linux-gnu-ranlib)
set(CMAKE_STRIP aarch64-linux-gnu-strip)

set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

set(ENV{PKG_CONFIG_LIBDIR}
"/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig")
80 changes: 71 additions & 9 deletions ebpfKern/sysinternalsEBPF_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@
#define PATH_MAX 4096 // Missing def
#endif

#ifndef EBPF_CO_RE
#include <stdint.h>
#endif
#include <bpf_helpers.h>
#include <asm/unistd_64.h>
#include <asm/unistd.h>
#include <sysinternalsEBPFshared.h>

// debug tracing can be found using:
Expand All @@ -62,7 +64,65 @@
#define true 1
#define false 0

// x64 syscall macros
// Architecture-dependent syscall pt_regs access macros.
//
// On arm64 the UAPI header (asm/ptrace.h) only exposes struct user_pt_regs
// (regs[31], sp, pc, pstate) — there is no UAPI struct pt_regs. The kernel-
// internal struct pt_regs starts with user_pt_regs followed by orig_x0
// (the preserved first syscall argument, because the kernel overwrites
// regs[0] with the return value).
//
// CO-RE path – define a pt_regs___arm64 "flavor" struct with
// __attribute__((preserve_access_index)) so CO-RE relocations
// resolve orig_x0 against the target kernel's real pt_regs.
// Non-CO-RE – define struct pt_regs ourselves (arm64 UAPI omits it) so
// the macros compile. Layout must match the kernel.

#if defined(__TARGET_ARCH_arm64)

#ifdef EBPF_CO_RE
// CO-RE flavor type matching the kernel's struct pt_regs on arm64.
// The triple-underscore suffix is the libbpf CO-RE naming convention.
struct pt_regs___arm64 {
unsigned long regs[31];
unsigned long sp;
unsigned long pc;
unsigned long pstate;
unsigned long orig_x0;
} __attribute__((preserve_access_index));

#define SYSCALL_PT_REGS_PARM1(x) (((const struct pt_regs___arm64 *)(x))->orig_x0)
#define SYSCALL_PT_REGS_PARM2(x) (((const struct pt_regs___arm64 *)(x))->regs[1])
#define SYSCALL_PT_REGS_PARM3(x) (((const struct pt_regs___arm64 *)(x))->regs[2])
#define SYSCALL_PT_REGS_PARM4(x) (((const struct pt_regs___arm64 *)(x))->regs[3])
#define SYSCALL_PT_REGS_PARM5(x) (((const struct pt_regs___arm64 *)(x))->regs[4])
#define SYSCALL_PT_REGS_PARM6(x) (((const struct pt_regs___arm64 *)(x))->regs[5])
#define SYSCALL_PT_REGS_RC(x) (((const struct pt_regs___arm64 *)(x))->regs[0])

#else /* non-CO-RE arm64 */

// arm64 UAPI only exposes struct user_pt_regs. Define the kernel-internal
// struct pt_regs layout so the macros below can access orig_x0.
struct pt_regs {
__u64 regs[31];
__u64 sp;
__u64 pc;
__u64 pstate;
__u64 orig_x0;
};

#define SYSCALL_PT_REGS_PARM1(x) ((x)->orig_x0)
#define SYSCALL_PT_REGS_PARM2(x) ((x)->regs[1])
#define SYSCALL_PT_REGS_PARM3(x) ((x)->regs[2])
#define SYSCALL_PT_REGS_PARM4(x) ((x)->regs[3])
#define SYSCALL_PT_REGS_PARM5(x) ((x)->regs[4])
#define SYSCALL_PT_REGS_PARM6(x) ((x)->regs[5])
#define SYSCALL_PT_REGS_RC(x) ((x)->regs[0])

#endif /* EBPF_CO_RE */

#else /* x86_64 */

#ifdef EBPF_CO_RE
#define SYSCALL_PT_REGS_PARM1(x) ((x)->di)
#define SYSCALL_PT_REGS_PARM2(x) ((x)->si)
Expand All @@ -78,6 +138,8 @@
#define SYSCALL_PT_REGS_PARM5(x) ((x)->r8)
#define SYSCALL_PT_REGS_PARM6(x) ((x)->r9)

#endif /* __TARGET_ARCH_arm64 */

#define CMDLINE_MAX_LEN 16384 // must be power of 2
#define MAX_FDS 65535

Expand Down Expand Up @@ -105,18 +167,18 @@ struct bpf_our_raw_tracepoint_args {
// arguments a syscall expects; attempts to do so will cause the verifier
// to reject it.
struct tracepoint__syscalls__sys_enter {
__uint64_t pad;
__uint32_t __syscall_nr;
__uint32_t pad2;
__uint64_t a[6];
__u64 pad;
__u32 __syscall_nr;
__u32 pad2;
__u64 a[6];
};


// all sys_exit arguments are the same for traditional tracepoints.
struct tracepoint__syscalls__sys_exit {
__uint64_t pad;
__uint32_t __syscall_nr;
__uint32_t pad2;
__u64 pad;
__u32 __syscall_nr;
__u32 pad2;
long ret;
};

Expand Down
2 changes: 1 addition & 1 deletion installer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
//
//====================================================================

#include "/usr/include/fcntl.h"
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
Expand Down
Loading