From a1059e4fef704320a80781497e66deaef5d9ea6e Mon Sep 17 00:00:00 2001 From: Navid Malekghaini Date: Sat, 28 Mar 2026 14:12:58 -0700 Subject: [PATCH] Revert "Version support, installer script, and rebranding (#37)" This reverts commit 8899189bb84d4e625290e398eb8e711b84c04173. --- .cppcheck-suppressions | 4 +- .github/copilot-instructions.md | 26 +-- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 208 +++--------------- .gitignore | 3 +- Makefile | 25 +-- README.md | 24 +- docs/RELEASE.md | 6 +- docs/TECHNICAL.md | 34 +-- docs/TESTING.md | 36 +-- e2e/qemu-test.sh | 46 ++-- src/Kbuild | 3 +- src/{proclens_module.c => elf_det.c} | 94 ++++---- src/{proclens_module.h => elf_det.h} | 8 +- ...roclens_module_tests.c => elf_det_tests.c} | 49 ++--- src/{proclens.c => proc_elf_ctrl.c} | 72 +----- src/{proclens.h => proc_elf_ctrl.h} | 6 +- ...proclens_tests.c => proc_elf_ctrl_tests.c} | 62 ++---- 18 files changed, 221 insertions(+), 489 deletions(-) rename src/{proclens_module.c => elf_det.c} (90%) rename src/{proclens_module.h => elf_det.h} (98%) rename src/{proclens_module_tests.c => elf_det_tests.c} (93%) rename src/{proclens.c => proc_elf_ctrl.c} (92%) rename src/{proclens.h => proc_elf_ctrl.h} (68%) rename src/{proclens_tests.c => proc_elf_ctrl_tests.c} (90%) diff --git a/.cppcheck-suppressions b/.cppcheck-suppressions index 524f796..64cd289 100644 --- a/.cppcheck-suppressions +++ b/.cppcheck-suppressions @@ -9,5 +9,5 @@ unmatchedSuppression # Suppress preprocessor errors in kernel headers (configuration issues) preprocessorErrorDirective:*/linux/bitops.h preprocessorErrorDirective:*/linux/*.h -noValidConfiguration:src/proclens_module.c -noValidConfiguration:src/proclens_module.mod.c +noValidConfiguration:src/elf_det.c +noValidConfiguration:src/elf_det.mod.c diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 1a7cffd..5408f02 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,7 +2,7 @@ ## Project Overview -This is a Linux kernel module project that provides process information through `/proc/proclens_module/`. The module displays detailed process information including memory mappings, CPU usage, memory pressure statistics, and ELF binary details. +This is a Linux kernel module project that provides process information through `/proc/elf_det/`. The module displays detailed process information including memory mappings, CPU usage, memory pressure statistics, and ELF binary details. Current output includes memory pressure/layout, brief network stats, open sockets, per-process I/O statistics, and thread information. @@ -48,10 +48,10 @@ The pre-commit hook automatically runs format-check and cppcheck. ### Source Files (`src/`) -- `proclens_module.c` / `proclens_module.h` - Main kernel module and shared helpers -- `proclens_module_tests.c` - Unit tests for proclens_module helpers -- `proclens.c` / `proclens.h` - Control utility and helpers -- `proclens_tests.c` - Unit tests for proclens helpers +- `elf_det.c` / `elf_det.h` - Main kernel module and shared helpers +- `elf_det_tests.c` - Unit tests for elf_det helpers +- `proc_elf_ctrl.c` / `proc_elf_ctrl.h` - Control utility and helpers +- `proc_elf_ctrl_tests.c` - Unit tests for proc_elf_ctrl helpers - `test_multithread.c` - Multi-threaded test application ### Documentation (`docs/`) @@ -87,7 +87,7 @@ The pre-commit hook automatically runs format-check and cppcheck. ### Header Files -- `proclens_module.h` contains helper functions that work in BOTH kernel and userspace +- `elf_det.h` contains helper functions that work in BOTH kernel and userspace - Use `#ifdef __KERNEL__` to separate kernel-only code - Keep helpers pure (no side effects) for testability - Add comprehensive documentation comments for public functions @@ -119,7 +119,7 @@ When adding new helper functions to headers: ### Adding New Statistics -1. Add calculation helper to header file (e.g., `proclens_module.h`) +1. Add calculation helper to header file (e.g., `elf_det.h`) 2. Add unit tests for the helper 3. Call helper in kernel module print function 4. Update `e2e/qemu-test.sh` to validate output @@ -147,10 +147,10 @@ Current implementation includes: `avg_write_bytes_per_syscall`, `io_intensity`) When extending I/O output: -1. Add or update helper functions in `proclens_module.h` +1. Add or update helper functions in `elf_det.h` 2. Keep division-by-zero handling explicit in helper logic 3. Update `e2e/qemu-test.sh` checks for new fields -4. Keep `proclens` view filtering in sync (section key `4` for I/O) +4. Keep `proc_elf_ctrl` view filtering in sync (section key `4` for I/O) ## Build System (Makefile) @@ -234,7 +234,7 @@ Tests validate actual kernel module behavior in isolated environment. ## Key Functions Reference -### Kernel Module (`proclens_module.c`) +### Kernel Module (`elf_det.c`) - `print_memory_pressure()` - Display memory pressure metrics - `print_memory_layout()` - Show heap, stack, code segments @@ -242,10 +242,10 @@ Tests validate actual kernel module behavior in isolated environment. - `print_io_stats()` - Display per-process I/O counters and derived metrics - `print_network_stats()` - Display brief per-process network statistics - `print_sockets()` - Display open sockets and endpoint details -- `proclens_module_show()` - Main process information output handler -- `proclens_module_threads_show()` - Thread listing output handler +- `elfdet_show()` - Main process information output handler +- `elfdet_threads_show()` - Thread listing output handler -### Helpers (`proclens_module.h`) +### Helpers (`elf_det.h`) - `calculate_rss_pages()` - Compute resident set size from mm counters - `pages_to_kb()` - Convert pages to kilobytes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9e3299..1c3c095 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,8 +37,8 @@ jobs: - name: Verify build artifacts run: | ls -la build/ - file build/proclens_module.ko - file build/proclens + file build/elf_det.ko + file build/proc_elf_ctrl echo "Build artifacts verified successfully!" - name: Upload build artifacts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab2f338..22074eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -147,19 +147,17 @@ jobs: printf '\n---\n' printf '**Version**: %s | **Type**: %s\n\n' "$VERSION" "$BUMP_TYPE" printf '## Binary package includes\n\n' - printf -- '- `amd64/proclens_module.ko`\n' - printf -- '- `amd64/proclens`\n' - printf -- '- `arm64/proclens_module.ko`\n' - printf -- '- `arm64/proclens`\n' - printf -- '- `install.sh`\n' - printf -- '- `uninstall.sh`\n' + printf -- '- `amd64/elf_det.ko`\n' + printf -- '- `amd64/proc_elf_ctrl`\n' + printf -- '- `arm64/elf_det.ko`\n' + printf -- '- `arm64/proc_elf_ctrl`\n' printf -- '- `README-QUICKSTART.md`\n\n' printf 'Quick Start summary:\n\n' printf -- '- Supports Linux kernel `%s.x`\n' "${TARGET_KERNEL_BASE}" printf -- '- Includes binaries for `amd64` (`x86_64`) and `arm64` (`aarch64`)\n' - printf -- '- Install or update: `sudo ./install.sh`\n' - printf -- '- Run user tool: `sudo proclens`\n' - printf -- '- Uninstall: `sudo ./uninstall.sh`\n' + printf -- '- Install module: `sudo insmod /elf_det.ko`\n' + printf -- '- Run user tool: `sudo .//proc_elf_ctrl`\n' + printf -- '- Unload module: `sudo rmmod elf_det`\n' } > /tmp/release_notes.md else # Manual workflow dispatch @@ -168,19 +166,17 @@ jobs: printf -- '- Manual release triggered via workflow dispatch.\n\n' printf '**Version**: %s | **Type**: %s\n\n' "$VERSION" "$BUMP_TYPE" printf '## Binary package includes\n\n' - printf -- '- `amd64/proclens_module.ko`\n' - printf -- '- `amd64/proclens`\n' - printf -- '- `arm64/proclens_module.ko`\n' - printf -- '- `arm64/proclens`\n' - printf -- '- `install.sh`\n' - printf -- '- `uninstall.sh`\n' + printf -- '- `amd64/elf_det.ko`\n' + printf -- '- `amd64/proc_elf_ctrl`\n' + printf -- '- `arm64/elf_det.ko`\n' + printf -- '- `arm64/proc_elf_ctrl`\n' printf -- '- `README-QUICKSTART.md`\n\n' printf 'Quick Start summary:\n\n' printf -- '- Supports Linux kernel `%s.x`\n' "${TARGET_KERNEL_BASE}" printf -- '- Includes binaries for `amd64` (`x86_64`) and `arm64` (`aarch64`)\n' - printf -- '- Install or update: `sudo ./install.sh`\n' - printf -- '- Run user tool: `sudo proclens`\n' - printf -- '- Uninstall: `sudo ./uninstall.sh`\n' + printf -- '- Install module: `sudo insmod /elf_det.ko`\n' + printf -- '- Run user tool: `sudo .//proc_elf_ctrl`\n' + printf -- '- Unload module: `sudo rmmod elf_det`\n' } > /tmp/release_notes.md fi @@ -237,8 +233,8 @@ jobs: make user mkdir -p "out/${TARGET_ARCH}" - cp build/proclens_module.ko "out/${TARGET_ARCH}/proclens_module.ko" - cp build/proclens "out/${TARGET_ARCH}/proclens" + cp build/elf_det.ko "out/${TARGET_ARCH}/elf_det.ko" + cp build/proc_elf_ctrl "out/${TARGET_ARCH}/proc_elf_ctrl" - name: Upload architecture binaries uses: actions/upload-artifact@v4 @@ -280,152 +276,18 @@ jobs: run: | set -euo pipefail - PKG_NAME="proclens_module-binaries-${RELEASE_TAG}-linux-${TARGET_KERNEL_BASE}" + PKG_NAME="elf_det-binaries-${RELEASE_TAG}-linux-${TARGET_KERNEL_BASE}" PKG_DIR="dist/${PKG_NAME}" ARCHIVE_PATH="dist/${PKG_NAME}.tar.gz" mkdir -p "$PKG_DIR/amd64" "$PKG_DIR/arm64" - cp dist/artifacts/binaries-amd64/proclens_module.ko "$PKG_DIR/amd64/" - cp dist/artifacts/binaries-amd64/proclens "$PKG_DIR/amd64/" - cp dist/artifacts/binaries-arm64/proclens_module.ko "$PKG_DIR/arm64/" - cp dist/artifacts/binaries-arm64/proclens "$PKG_DIR/arm64/" + cp dist/artifacts/binaries-amd64/elf_det.ko "$PKG_DIR/amd64/" + cp dist/artifacts/binaries-amd64/proc_elf_ctrl "$PKG_DIR/amd64/" + cp dist/artifacts/binaries-arm64/elf_det.ko "$PKG_DIR/arm64/" + cp dist/artifacts/binaries-arm64/proc_elf_ctrl "$PKG_DIR/arm64/" - chmod +x "$PKG_DIR/amd64/proclens" "$PKG_DIR/arm64/proclens" - - cat > "$PKG_DIR/install.sh" << 'EOF' - #!/usr/bin/env bash - set -euo pipefail - - usage() { - cat << 'USAGE' - Usage: sudo ./install.sh [--arch amd64|arm64] - - Installs or updates both components: - - Kernel module: /lib/modules/$(uname -r)/extra/proclens_module.ko - - User binary: /usr/local/bin/proclens - - Behavior: - - Detects architecture automatically (x86_64 -> amd64, aarch64 -> arm64) - - If module is already loaded, unloads it first - - Replaces previously installed binaries (update-in-place) - - Runs depmod and loads module with modprobe (fallback: insmod) - USAGE - } - - if [[ "${EUID}" -ne 0 ]]; then - echo "Please run as root: sudo ./install.sh" - exit 1 - fi - - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - - ARCH="" - if [[ $# -gt 0 ]]; then - case "$1" in - --arch) - ARCH="${2:-}" - shift 2 - ;; - -h|--help) - usage - exit 0 - ;; - *) - echo "Unknown option: $1" - usage - exit 1 - ;; - esac - fi - - if [[ -z "$ARCH" ]]; then - case "$(uname -m)" in - x86_64) - ARCH="amd64" - ;; - aarch64|arm64) - ARCH="arm64" - ;; - *) - echo "Unsupported architecture: $(uname -m)" - echo "Use --arch amd64|arm64" - exit 1 - ;; - esac - fi - - if [[ "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then - echo "Invalid --arch value: $ARCH" - echo "Use amd64 or arm64" - exit 1 - fi - - SRC_MOD="$SCRIPT_DIR/$ARCH/proclens_module.ko" - SRC_BIN="$SCRIPT_DIR/$ARCH/proclens" - - if [[ ! -f "$SRC_MOD" || ! -f "$SRC_BIN" ]]; then - echo "Missing release binaries for arch '$ARCH'" - exit 1 - fi - - KREL="$(uname -r)" - MOD_DIR="/lib/modules/$KREL/extra" - MOD_DST="$MOD_DIR/proclens_module.ko" - BIN_DST="/usr/local/bin/proclens" - - echo "Installing ProcLens binaries for arch: $ARCH" - echo "Kernel release: $KREL" - - if lsmod | grep -q '^proclens_module '; then - echo "Module is currently loaded; unloading old version..." - modprobe -r proclens_module || rmmod proclens_module - fi - - mkdir -p "$MOD_DIR" - install -m 0644 "$SRC_MOD" "$MOD_DST" - install -m 0755 "$SRC_BIN" "$BIN_DST" - - depmod "$KREL" - - if ! modprobe proclens_module; then - echo "modprobe failed; trying insmod directly..." - insmod "$MOD_DST" - fi - - echo "Install/update complete." - echo "User binary: $BIN_DST" - echo "Module file: $MOD_DST" - echo "Check module version: cat /sys/module/proclens_module/version" - echo "Check user version: sudo proclens --version" - EOF - - cat > "$PKG_DIR/uninstall.sh" << 'EOF' - #!/usr/bin/env bash - set -euo pipefail - - if [[ "${EUID}" -ne 0 ]]; then - echo "Please run as root: sudo ./uninstall.sh" - exit 1 - fi - - KREL="$(uname -r)" - MOD_DST="/lib/modules/$KREL/extra/proclens_module.ko" - BIN_DST="/usr/local/bin/proclens" - - if lsmod | grep -q '^proclens_module '; then - echo "Unloading proclens_module module..." - modprobe -r proclens_module || rmmod proclens_module || true - fi - - rm -f "$MOD_DST" - rm -f "$BIN_DST" - depmod "$KREL" - - echo "Uninstall complete." - EOF - - chmod +x "$PKG_DIR/install.sh" "$PKG_DIR/uninstall.sh" + chmod +x "$PKG_DIR/amd64/proc_elf_ctrl" "$PKG_DIR/arm64/proc_elf_ctrl" cat > "$PKG_DIR/README-QUICKSTART.md" << 'EOF' # Quick Start (Linux kernel __TARGET_KERNEL_BASE__.x) @@ -448,24 +310,11 @@ jobs: - `amd64/` for `x86_64` - `arm64/` for `aarch64` - ## 2) Install or update - - ```bash - sudo ./install.sh - ``` - - The installer: - - Installs/updates `proclens` to `/usr/local/bin/proclens` - - Installs/updates `proclens_module.ko` to `/lib/modules/$(uname -r)/extra/proclens_module.ko` - - Unloads an already-loaded `proclens_module` before update - - Runs `depmod` and loads the module - - Optional (override architecture selection): + ## 2) Install kernel module ```bash - sudo ./install.sh --arch amd64 - # or - sudo ./install.sh --arch arm64 + sudo insmod /elf_det.ko + lsmod | grep elf_det ``` If Secure Boot is enabled, module signing may be required. @@ -473,14 +322,13 @@ jobs: ## 3) Run user program ```bash - sudo proclens --version - sudo proclens + sudo .//proc_elf_ctrl ``` - ## 4) Uninstall + ## 4) Unload module ```bash - sudo ./uninstall.sh + sudo rmmod elf_det ``` EOF diff --git a/.gitignore b/.gitignore index e31c6d9..8d84f82 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,8 @@ modules.order *.dSYM/ # Compiled user programs -proclens +proc_elf_ctrl +elf_det_ctrl # Core dumps core diff --git a/Makefile b/Makefile index ea8b526..fa5e6bd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # Kernel Module and User Program Makefile # Kernel module name -obj-m := proclens_module.o +obj-m := elf_det.o # Kernel build directory (allow override via env: KDIR=/path make) KDIR ?= /lib/modules/$(shell uname -r)/build @@ -10,7 +10,7 @@ KDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) # User program -USER_PROG := proclens +USER_PROG := proc_elf_ctrl # Source directory SRC_DIR := src @@ -18,11 +18,6 @@ SRC_DIR := src # Build directory for user program BUILD_DIR := build -# Version: derived from nearest git tag; falls back to "dev" on untagged builds -VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") -CFLAGS_VERSION := -DPROCLENS_VERSION='"$(VERSION)"' -export PROCLENS_VERSION := $(VERSION) - # Static analysis tuning CPPCHECK_JOBS ?= $(shell nproc) CPPCHECK_SRCS := $(filter-out $(SRC_DIR)/%.mod.c, $(wildcard $(SRC_DIR)/*.c)) @@ -44,7 +39,7 @@ module: user: @echo "Building user program..." @mkdir -p $(BUILD_DIR) - gcc -Wall $(CFLAGS_VERSION) -o $(BUILD_DIR)/$(USER_PROG) $(SRC_DIR)/$(USER_PROG).c + gcc -Wall -o $(BUILD_DIR)/$(USER_PROG) $(SRC_DIR)/$(USER_PROG).c @echo "User program built successfully!" # Build multi-threaded test program (for E2E testing) @@ -58,23 +53,23 @@ build-multithread: unit: @echo "Building function-level unit tests..." @mkdir -p $(BUILD_DIR) - gcc -Wall -I$(SRC_DIR) $(CFLAGS_VERSION) -o $(BUILD_DIR)/proclens_module_tests $(SRC_DIR)/proclens_module_tests.c - gcc -Wall -I$(SRC_DIR) $(CFLAGS_VERSION) -o $(BUILD_DIR)/proclens_tests $(SRC_DIR)/proclens_tests.c + gcc -Wall -I$(SRC_DIR) -o $(BUILD_DIR)/elf_det_tests $(SRC_DIR)/elf_det_tests.c + gcc -Wall -I$(SRC_DIR) -o $(BUILD_DIR)/proc_elf_ctrl_tests $(SRC_DIR)/proc_elf_ctrl_tests.c @echo "Running unit tests..." - @$(BUILD_DIR)/proclens_module_tests - @$(BUILD_DIR)/proclens_tests + @$(BUILD_DIR)/elf_det_tests + @$(BUILD_DIR)/proc_elf_ctrl_tests @echo "All function-level unit tests passed!" # Install kernel module (requires root) install: module @echo "Installing kernel module..." - sudo insmod $(BUILD_DIR)/proclens_module.ko - @echo "Module installed. Check with: lsmod | grep proclens_module" + sudo insmod $(BUILD_DIR)/elf_det.ko + @echo "Module installed. Check with: lsmod | grep elf_det" # Uninstall kernel module (requires root) uninstall: @echo "Uninstalling kernel module..." - sudo rmmod proclens_module 2>/dev/null || true + sudo rmmod elf_det 2>/dev/null || true @echo "Module uninstalled." # Test: install module and run user program diff --git a/README.md b/README.md index 59778d0..398caef 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ - **Thread Information**: List all threads with TID, state, CPU usage, priority, and CPU affinity - **CPU Usage Tracking**: Real-time CPU percentage calculation per process and thread - **ELF Section Analysis**: Binary base address and section boundaries -- **Proc Interface**: Easy access through `/proc/proclens_module/` +- **Proc Interface**: Easy access through `/proc/elf_det/` - **Live Dashboard Mode**: No-arg mode refreshes every 1s with switchable Memory, Network, Threads, and I/O sections - **Comprehensive Testing**: Unit tests and QEMU-based E2E testing - **Code Quality**: Pre-configured static analysis (sparse, cppcheck, checkpatch) @@ -62,7 +62,7 @@ ``` 4. Run user program: ```bash - sudo ./build/proclens + ./build/proc_elf_ctrl ``` ### Live Mode (No Parameters) @@ -101,7 +101,6 @@ Running without arguments starts a live dashboard: sudo make uninstall ``` - ## Release Binaries Download prebuilt binaries from GitHub Releases: @@ -115,32 +114,21 @@ Download prebuilt binaries from GitHub Releases: > If your system runs any other kernel version, build from source instead. -After downloading, the preferred installation/update path is to use the bundled installer scripts: +After downloading, install/run with root privileges as needed: ```bash -sudo ./install.sh -sudo proclens --version -sudo proclens -sudo ./uninstall.sh -``` - -Manual install/run is still possible if needed: - -```bash -sudo insmod ./proclens_module.ko -sudo ./proclens +sudo insmod ./elf_det.ko +./proc_elf_ctrl ``` To unload the module: ```bash -sudo rmmod proclens_module +sudo rmmod elf_det ``` More detailed information is bundled with the release packages. - - ## Makefile Targets ```bash diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 7c2e845..95b25ce 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -50,8 +50,8 @@ You can manually trigger a release from the GitHub Actions tab: - For PR releases, notes include a `Changelog` section with PR title/body - Notes include version/type metadata - Notes include a `Binary package includes` section summarizing packaged contents and quick-start commands -3. **Binary Builds**: Builds `proclens_module.ko` and `proclens` for both `amd64` and `arm64` -4. **Packaging**: Produces a bundled archive named `proclens_module-binaries-vX.Y.Z-linux-6.8.0.tar.gz` plus a `.sha256` checksum file +3. **Binary Builds**: Builds `elf_det.ko` and `proc_elf_ctrl` for both `amd64` and `arm64` +4. **Packaging**: Produces a bundled archive named `elf_det-binaries-vX.Y.Z-linux-6.8.0.tar.gz` plus a `.sha256` checksum file 5. **Git Tag Creation**: Creates an annotated git tag (e.g., `v1.4.0`) if it does not already exist 6. **GitHub Release**: Creates a release on GitHub using the generated release notes and uploads the archive + checksum @@ -74,7 +74,7 @@ MAJOR.MINOR.PATCH **Use MAJOR version when:** - Changing kernel module API -- Removing features or fields from /proc/proclens_module/ +- Removing features or fields from /proc/elf_det/ - Incompatible changes to output format **Use MINOR version when:** diff --git a/docs/TECHNICAL.md b/docs/TECHNICAL.md index 553ecd7..53b4d15 100644 --- a/docs/TECHNICAL.md +++ b/docs/TECHNICAL.md @@ -1,19 +1,19 @@ # Technical Details -## Kernel Module (`proclens_module.c`) +## Kernel Module (`elf_det.c`) -The kernel module creates entries in `/proc/proclens_module/`: -- `/proc/proclens_module/pid` - Read/write file to set target PID and read back current buffer value -- `/proc/proclens_module/det` - Read-only file to retrieve process information -- `/proc/proclens_module/threads` - Read-only file to retrieve thread information +The kernel module creates entries in `/proc/elf_det/`: +- `/proc/elf_det/pid` - Read/write file to set target PID and read back current buffer value +- `/proc/elf_det/det` - Read-only file to retrieve process information +- `/proc/elf_det/threads` - Read-only file to retrieve thread information ### Key Functions -- `proclens_module_show()` - Main function to gather and format process information -- `proclens_module_threads_show()` - Gathers thread information for all threads in a process +- `elfdet_show()` - Main function to gather and format process information +- `elfdet_threads_show()` - Gathers thread information for all threads in a process - `find_stack_vma_end()` - Finds stack VMA lower boundary by iterating VMAs - `procfile_write()` - Handles PID input from user space -- `procfile_read()` - Returns formatted `/proc/proclens_module/pid` buffer content +- `procfile_read()` - Returns formatted `/proc/elf_det/pid` buffer content ### Memory Information Extracted @@ -110,13 +110,13 @@ Shows both `start_stack` (top/base) and `stack_end` (current lower boundary). Th - `mm_types.h` - Memory management structures - Maple tree API - Modern VMA iteration (kernel 6.8+) -## User Program (`proclens.c`) +## User Program (`proc_elf_ctrl.c`) Simple C program that supports two modes: ### Live Mode (No Arguments) ```bash -./build/proclens +./build/proc_elf_ctrl ``` Prompts for a PID, then enters a 1-second refresh loop with section filtering. Each refresh prints start/end timestamps in `YY/MM/DD HH:MM:SS`. @@ -158,7 +158,7 @@ Notes: ### Argument Mode ```bash -./build/proclens +./build/proc_elf_ctrl ``` Non-interactive mode - write PID once and print both process and thread information. @@ -167,14 +167,14 @@ Non-interactive mode - write PID once and print both process and thread informat You can override the proc directory for testing: ```bash -PROCLENS_PROC_DIR=/tmp/fakeproc ./build/proclens 12345 +ELF_DET_PROC_DIR=/tmp/fakeproc ./build/proc_elf_ctrl 12345 ``` Internally, path construction is handled via `build_proc_path()`. ## Helper Libraries -### `src/proclens_module.h` +### `src/elf_det.h` Pure functions for CPU usage, BSS range, heap range, thread state, and address range checking: - `compute_usage_permyriad()` - CPU usage calculation - `compute_bss_range()` - BSS boundary validation @@ -183,13 +183,13 @@ Pure functions for CPU usage, BSS range, heap range, thread state, and address r Works in both kernel and user space contexts. -### `src/proclens.h` +### `src/proc_elf_ctrl.h` Path building with environment override: -- `build_proc_path()` - Constructs `/proc/proclens_module/` paths with `PROCLENS_PROC_DIR` support +- `build_proc_path()` - Constructs `/proc/elf_det/` paths with `ELF_DET_PROC_DIR` support ## Output Format -### Process Information (`/proc/proclens_module/det`) +### Process Information (`/proc/elf_det/det`) The output is human-readable and grouped into sections: @@ -200,7 +200,7 @@ The output is human-readable and grouped into sections: - Network stats (brief) - Open sockets (file descriptors, address families, connection states) -### Thread Information (`/proc/proclens_module/threads`) +### Thread Information (`/proc/elf_det/threads`) ``` TID NAME CPU(%) STATE PRIORITY NICE CPU_AFF ``` diff --git a/docs/TESTING.md b/docs/TESTING.md index 37b4fbb..7ad93f3 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -9,8 +9,8 @@ make unit ``` This builds and runs: -- `src/proclens_module_tests.c` – verifies `compute_usage_permyriad()`, `compute_bss_range()`, `compute_heap_range()`, `is_address_in_range()`, `get_thread_state_char()`, `build_cpu_affinity_string()`, and memory-pressure helpers -- `src/proclens_tests.c` – verifies `build_proc_path()`, PID argument bounds, +- `src/elf_det_tests.c` – verifies `compute_usage_permyriad()`, `compute_bss_range()`, `compute_heap_range()`, `is_address_in_range()`, `get_thread_state_char()`, `build_cpu_affinity_string()`, and memory-pressure helpers +- `src/proc_elf_ctrl_tests.c` – verifies `build_proc_path()`, PID argument bounds, process-info print path, cmdline formatting, and section filtering for memory/network/I/O live views Artifacts are created under `build/`. @@ -54,7 +54,7 @@ ssh -p 2222 ubuntu@localhost cd ProcLens make clean && make all sudo make install -./build/proclens +./build/proc_elf_ctrl # Multi-threaded module test make run-multithread @@ -132,27 +132,27 @@ sudo ./e2e/qemu-test.sh ```bash # Ensure module is loaded -lsmod | grep proclens_module +lsmod | grep elf_det # Check proc entries exist (should show det, pid, threads) -ls -la /proc/proclens_module/ +ls -la /proc/elf_det/ ``` ### Testing Thread Information ```bash # Test with single-threaded process -./build/proclens $$ +./build/proc_elf_ctrl $$ # Test with multi-threaded process # Start the bundled multi-threaded test program make build-multithread ./build/test_multithread & -./build/proclens $! +./build/proc_elf_ctrl $! # Manually check thread info -echo "" | sudo tee /proc/proclens_module/pid -sudo cat /proc/proclens_module/threads +echo "" | sudo tee /proc/elf_det/pid +sudo cat /proc/elf_det/threads ``` ### Verify Thread Features @@ -173,12 +173,12 @@ Multi-threaded processes (browsers, IDEs, servers) will show multiple threads. Verify no-argument live mode behavior: ```bash -./build/proclens +./build/proc_elf_ctrl ``` Expected behavior: - Program prints the startup logo once, then validates module/proc readiness -- If `proclens_module` is not loaded, program exits immediately with status `-1` +- If `elf_det` is not loaded, program exits immediately with status `-1` - If required proc files are missing (`pid`, `det`, `threads`), program exits immediately with status `-1` - Screen refreshes every 1 second - Header shows controls (`1` memory, `2` network, `3` threads, `4` I/O, `0` switch PID) @@ -201,7 +201,7 @@ mkdir -p /tmp/fake_proc : > /tmp/fake_proc/pid printf 'Memory Pressure Statistics:\n[network]\nsockets_total: 2\n' > /tmp/fake_proc/det printf 'tid header\nthread line\n' > /tmp/fake_proc/threads -PROCLENS_PROC_DIR=/tmp/fake_proc ./build/proclens +ELF_DET_PROC_DIR=/tmp/fake_proc ./build/proc_elf_ctrl ``` ### Testing Socket Information @@ -209,13 +209,13 @@ To verify socket functionality, test with processes that have open sockets: ```bash # Test with systemd (PID 1) - usually has several sockets -./build/proclens 1 +./build/proc_elf_ctrl 1 # Test with SSH daemon -pgrep sshd | head -1 | xargs ./build/proclens +pgrep sshd | head -1 | xargs ./build/proc_elf_ctrl # Test with current shell (will show SSH connection socket if remote) -./build/proclens $$ +./build/proc_elf_ctrl $$ ``` The socket output should include: @@ -235,7 +235,7 @@ Processes with no open sockets will display "No open sockets". The process output should include a short network section when sockets exist: ```bash -./build/proclens $$ +./build/proc_elf_ctrl $$ ``` Look for: @@ -262,7 +262,7 @@ In the open sockets section: The process output should include an I/O section: ```bash -./build/proclens $$ +./build/proc_elf_ctrl $$ ``` Look for: @@ -277,7 +277,7 @@ the section will show `status: unavailable` instead of per-field counters. ## Test Coverage -### Helper Function Tests (`proclens_module_tests.c`) +### Helper Function Tests (`elf_det_tests.c`) Complete unit test coverage for all pure helper functions: diff --git a/e2e/qemu-test.sh b/e2e/qemu-test.sh index 970d933..4adef08 100755 --- a/e2e/qemu-test.sh +++ b/e2e/qemu-test.sh @@ -70,8 +70,8 @@ echo "" echo "2. Copying files to QEMU VM..." ssh $SSH_OPTS ${SSH_USER}@${SSH_HOST} "mkdir -p ~/ProcLens" ssh $SSH_OPTS ${SSH_USER}@${SSH_HOST} "mkdir -p ~/ProcLens/src" -scp $SCP_OPTS src/proclens_module.c src/proclens_module.h src/proclens_module_tests.c \ - src/proclens.c src/proclens.h src/proclens_tests.c \ +scp $SCP_OPTS src/elf_det.c src/elf_det.h src/elf_det_tests.c \ + src/proc_elf_ctrl.c src/proc_elf_ctrl.h src/proc_elf_ctrl_tests.c \ src/test_multithread.c src/Kbuild ${SSH_USER}@${SSH_HOST}:~/ProcLens/src/ scp $SCP_OPTS Makefile ${SSH_USER}@${SSH_HOST}:~/ProcLens/ @@ -99,23 +99,23 @@ make KDIR=/lib/modules/$(uname -r)/build all make build-multithread echo "Installing kernel module..." -if lsmod | grep -q '^proclens_module'; then +if lsmod | grep -q '^elf_det'; then echo "Module already loaded; unloading first..." - sudo rmmod proclens_module || true + sudo rmmod elf_det || true fi -sudo insmod build/proclens_module.ko +sudo insmod build/elf_det.ko echo "Checking if module is loaded..." -lsmod | grep proclens_module +lsmod | grep elf_det echo "Checking /proc entries..." -ls -la /proc/proclens_module/ +ls -la /proc/elf_det/ echo "Expected files: det, pid, threads" echo "" echo "=== Testing Process Information (PID: $$) ===" -echo "$$" | sudo tee /proc/proclens_module/pid > /dev/null -PROC_OUT=$(sudo cat /proc/proclens_module/det) +echo "$$" | sudo tee /proc/elf_det/pid > /dev/null +PROC_OUT=$(sudo cat /proc/elf_det/det) echo "$PROC_OUT" if ! echo "$PROC_OUT" | grep -q "Memory Pressure Statistics"; then echo "[FAIL] Memory pressure stats missing for PID $$" @@ -167,13 +167,13 @@ fi echo "" echo "=== Testing Thread Information (PID: $$) ===" -sudo cat /proc/proclens_module/threads +sudo cat /proc/elf_det/threads echo "" echo "=== Testing with PID 1 (init/systemd) ===" -echo "1" | sudo tee /proc/proclens_module/pid > /dev/null +echo "1" | sudo tee /proc/elf_det/pid > /dev/null echo "Process info:" -PROC_OUT=$(sudo cat /proc/proclens_module/det) +PROC_OUT=$(sudo cat /proc/elf_det/det) echo "$PROC_OUT" if ! echo "$PROC_OUT" | grep -q "Memory Pressure Statistics"; then echo "[FAIL] Memory pressure stats missing for PID 1" @@ -224,11 +224,11 @@ if ! echo "$PROC_OUT" | grep -q "No open sockets"; then fi echo "" echo "Thread info:" -sudo cat /proc/proclens_module/threads +sudo cat /proc/elf_det/threads echo "" -echo "=== Testing with user program (proclens, PID=1) ===" -sudo ./build/proclens 1 || true +echo "=== Testing with user program (proc_elf_ctrl, PID=1) ===" +sudo ./build/proc_elf_ctrl 1 || true echo "" echo "=== Testing with multi-threaded application ===" @@ -243,10 +243,10 @@ sleep 1 # Test with the multi-threaded process echo "" echo "Testing thread detection with multi-threaded process:" -echo "$MULTITHREAD_PID" | sudo tee /proc/proclens_module/pid > /dev/null +echo "$MULTITHREAD_PID" | sudo tee /proc/elf_det/pid > /dev/null echo "" echo "Process info:" -PROC_OUT=$(sudo cat /proc/proclens_module/det) +PROC_OUT=$(sudo cat /proc/elf_det/det) echo "$PROC_OUT" if ! echo "$PROC_OUT" | grep -q "Memory Pressure Statistics"; then echo "[FAIL] Memory pressure stats missing for PID $MULTITHREAD_PID" @@ -297,14 +297,14 @@ if ! echo "$PROC_OUT" | grep -q "No open sockets"; then fi echo "" echo "Thread info (should show 5 threads: 1 main + 4 workers):" -sudo cat /proc/proclens_module/threads +sudo cat /proc/elf_det/threads sleep 1 # Use the user program to display formatted output echo "" -echo "Using proclens with multi-threaded process:" -sudo ./build/proclens $MULTITHREAD_PID || true +echo "Using proc_elf_ctrl with multi-threaded process:" +sudo ./build/proc_elf_ctrl $MULTITHREAD_PID || true # Wait for multi-threaded program to finish wait $MULTITHREAD_PID @@ -313,7 +313,7 @@ echo "[PASS] Multi-threaded application test completed" echo "" echo "=== Verifying all proc files are accessible ===" -if [ -r /proc/proclens_module/det ] && [ -r /proc/proclens_module/pid ] && [ -r /proc/proclens_module/threads ]; then +if [ -r /proc/elf_det/det ] && [ -r /proc/elf_det/pid ] && [ -r /proc/elf_det/threads ]; then echo "[PASS] All proc files exist and are readable" else echo "[FAIL] Some proc files are missing or not readable" @@ -326,11 +326,11 @@ sudo dmesg | tail -20 echo "" echo "Uninstalling module..." -sudo rmmod proclens_module +sudo rmmod elf_det echo "" echo "Verifying module unloaded..." -lsmod | grep proclens_module || echo "Module successfully unloaded" +lsmod | grep elf_det || echo "Module successfully unloaded" echo "" echo "===================================================" diff --git a/src/Kbuild b/src/Kbuild index 1f53724..1a887e5 100644 --- a/src/Kbuild +++ b/src/Kbuild @@ -1,2 +1 @@ -obj-m := proclens_module.o -ccflags-y += -DPROCLENS_VERSION='"$(PROCLENS_VERSION)"' +obj-m := elf_det.o diff --git a/src/proclens_module.c b/src/elf_det.c similarity index 90% rename from src/proclens_module.c rename to src/elf_det.c index 1ba9513..587c453 100644 --- a/src/proclens_module.c +++ b/src/elf_det.c @@ -22,14 +22,9 @@ #include //for sockaddr_in #include //for sockaddr_in6 #include //for inet_sock -#include "proclens_module.h" - -#ifndef PROCLENS_VERSION -#define PROCLENS_VERSION "dev" -#endif +#include "elf_det.h" MODULE_LICENSE("Dual MIT/GPL"); // module license -MODULE_VERSION(PROCLENS_VERSION); static char buff[20] = "1"; // the common(global) buffer between kernel and user space @@ -37,8 +32,8 @@ static int user_pid; // the desired pid that we get from user static int number_opens; // number of opens(writes) to the pid file // skip these instances (will be described bellow) -static struct proc_dir_entry *proclens_module_dir, *proclens_module_det_entry, - *proclens_module_pid_entry, *proclens_module_threads_entry; +static struct proc_dir_entry *elfdet_dir, *elfdet_det_entry, *elfdet_pid_entry, + *elfdet_threads_entry; static int procfile_open(struct inode *inode, struct file *file); static ssize_t procfile_read(struct file *, char __user *, size_t, loff_t *); @@ -352,9 +347,9 @@ static void print_network_stats(struct seq_file *m, struct task_struct *task) u64 socket_rx_bytes, socket_tx_bytes; u64 drops = 0; int socket_total = 0, tcp_count = 0, udp_count = 0, unix_count = 0; - struct netdev_count netdevs[PROCLENS_MODULE_NETDEV_MAX]; + struct netdev_count netdevs[ELF_DET_NETDEV_MAX]; int netdev_len = 0; - struct top_talker_entry top_talkers[PROCLENS_MODULE_TOP_TALKERS_MAX]; + struct top_talker_entry top_talkers[ELF_DET_TOP_TALKERS_MAX]; int top_talker_len = 0; int ifindex; struct net_device *dev; @@ -411,7 +406,7 @@ static void print_network_stats(struct seq_file *m, struct task_struct *task) unix_count++; try_insert_top_talker(top_talkers, &top_talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, fd, + ELF_DET_TOP_TALKERS_MAX, fd, sk->sk_family, sk->sk_protocol, socket_rx_bytes, socket_tx_bytes); @@ -423,8 +418,7 @@ static void print_network_stats(struct seq_file *m, struct task_struct *task) dev = dev_get_by_index_rcu(sock_net(sk), ifindex); dev_name = dev ? dev->name : "unknown"; add_netdev_count(netdevs, &netdev_len, - PROCLENS_MODULE_NETDEV_MAX, ifindex, - dev_name); + ELF_DET_NETDEV_MAX, ifindex, dev_name); } } @@ -626,7 +620,7 @@ static void print_sockets(struct seq_file *m, struct task_struct *task) } // this function is the base function to gather information from kernel -static int proclens_module_show(struct seq_file *m, void *v) +static int elfdet_show(struct seq_file *m, void *v) { struct task_struct *task; unsigned long bss_start = 0, bss_end = 0; @@ -714,7 +708,7 @@ static int proclens_module_show(struct seq_file *m, void *v) } // this function gathers thread information from kernel -static int proclens_module_threads_show(struct seq_file *m, void *v) +static int elfdet_threads_show(struct seq_file *m, void *v) { struct task_struct *task, *thread; int ret, thread_count = 0; @@ -757,29 +751,28 @@ static int proclens_module_threads_show(struct seq_file *m, void *v) } // runs when opening file -static int proclens_module_open(struct inode *inode, struct file *file) +static int elfdet_open(struct inode *inode, struct file *file) { - return single_open(file, proclens_module_show, - NULL); // calling proclens_module_show + return single_open(file, elfdet_show, NULL); // calling elfdet_show } // runs when opening threads file -static int proclens_module_threads_open(struct inode *inode, struct file *file) +static int elfdet_threads_open(struct inode *inode, struct file *file) { - return single_open(file, proclens_module_threads_show, NULL); + return single_open(file, elfdet_threads_show, NULL); } // file operations of det proc (using proc_ops for kernel 5.6+) -static const struct proc_ops proclens_module_det_ops = { - .proc_open = proclens_module_open, +static const struct proc_ops elfdet_det_ops = { + .proc_open = elfdet_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = single_release, }; // file operations of threads proc -static const struct proc_ops proclens_module_threads_ops = { - .proc_open = proclens_module_threads_open, +static const struct proc_ops elfdet_threads_ops = { + .proc_open = elfdet_threads_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = single_release, @@ -852,49 +845,46 @@ static const struct proc_ops write_pops = { .proc_write = procfile_write, // this is the important part }; -static int proclens_module_init(void) +static int elfdet_init(void) { - proclens_module_dir = proc_mkdir("proclens_module", NULL); - // creating the directory: proclens_module in proc + elfdet_dir = proc_mkdir("elf_det", NULL); + // creating the directory: elf_det in proc - if (!proclens_module_dir) + if (!elfdet_dir) return -ENOMEM; // 0644 means owner read/write, others read-only - proclens_module_det_entry = proc_create( - "det", 0644, proclens_module_dir, &proclens_module_det_ops); - // create proc file det with proclens_module_det_ops - pr_info("det initiated; /proc/proclens_module/det created\n"); - proclens_module_pid_entry = - proc_create("pid", 0644, proclens_module_dir, &write_pops); + elfdet_det_entry = + proc_create("det", 0644, elfdet_dir, &elfdet_det_ops); + // create proc file det with elfdet_det_ops + pr_info("det initiated; /proc/elf_det/det created\n"); + elfdet_pid_entry = proc_create("pid", 0644, elfdet_dir, &write_pops); // create proc file pid with write_pops - pr_info("pid initiated; /proc/proclens_module/pid created\n"); + pr_info("pid initiated; /proc/elf_det/pid created\n"); - proclens_module_threads_entry = - proc_create("threads", 0644, proclens_module_dir, - &proclens_module_threads_ops); - // create proc file threads with proclens_module_threads_ops - pr_info("threads initiated; /proc/proclens_module/threads created\n"); + elfdet_threads_entry = + proc_create("threads", 0644, elfdet_dir, &elfdet_threads_ops); + // create proc file threads with elfdet_threads_ops + pr_info("threads initiated; /proc/elf_det/threads created\n"); - if (!proclens_module_det_entry || !proclens_module_threads_entry) + if (!elfdet_det_entry || !elfdet_threads_entry) return -ENOMEM; return 0; } // the remove operations done by module(cleaning up) -static void proclens_module_exit(void) +static void elfdet_exit(void) { - proc_remove(proclens_module_det_entry); - pr_info("proclens_module exited; /proc/proclens_module/det deleted\n"); - proc_remove(proclens_module_pid_entry); - pr_info("proclens_module exited; /proc/proclens_module/pid deleted\n"); - proc_remove(proclens_module_threads_entry); - pr_info("proclens_module exited; /proc/proclens_module/threads " - "deleted\n"); - proc_remove(proclens_module_dir); + proc_remove(elfdet_det_entry); + pr_info("elf_det exited; /proc/elf_det/det deleted\n"); + proc_remove(elfdet_pid_entry); + pr_info("elf_det exited; /proc/elf_det/pid deleted\n"); + proc_remove(elfdet_threads_entry); + pr_info("elf_det exited; /proc/elf_det/threads deleted\n"); + proc_remove(elfdet_dir); } // macros for init and exit -module_init(proclens_module_init); -module_exit(proclens_module_exit); +module_init(elfdet_init); +module_exit(elfdet_exit); diff --git a/src/proclens_module.h b/src/elf_det.h similarity index 98% rename from src/proclens_module.h rename to src/elf_det.h index b8c724b..9246845 100644 --- a/src/proclens_module.h +++ b/src/elf_det.h @@ -211,14 +211,14 @@ struct memory_region { int exists; /* 1 if region should be displayed, 0 otherwise */ }; -#define PROCLENS_MODULE_NETDEV_MAX 8 -#define PROCLENS_MODULE_NETDEV_NAME_MAX IFNAMSIZ -#define PROCLENS_MODULE_TOP_TALKERS_MAX 3 +#define ELF_DET_NETDEV_MAX 8 +#define ELF_DET_NETDEV_NAME_MAX IFNAMSIZ +#define ELF_DET_TOP_TALKERS_MAX 3 struct netdev_count { int ifindex; int count; - char name[PROCLENS_MODULE_NETDEV_NAME_MAX]; + char name[ELF_DET_NETDEV_NAME_MAX]; }; struct top_talker_entry { diff --git a/src/proclens_module_tests.c b/src/elf_det_tests.c similarity index 93% rename from src/proclens_module_tests.c rename to src/elf_det_tests.c index c7e4af2..6df72dd 100644 --- a/src/proclens_module_tests.c +++ b/src/elf_det_tests.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -#include "proclens_module.h" +#include "elf_det.h" #include #include #include @@ -503,24 +503,21 @@ int main(void) assert(len == 0); /* top talkers ranking tests */ - struct top_talker_entry talkers[PROCLENS_MODULE_TOP_TALKERS_MAX]; + struct top_talker_entry talkers[ELF_DET_TOP_TALKERS_MAX]; int talker_len = 0; memset(talkers, 0, sizeof(talkers)); - try_insert_top_talker(talkers, &talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, 10, 2, 6, 500, - 500); + try_insert_top_talker(talkers, &talker_len, ELF_DET_TOP_TALKERS_MAX, 10, + 2, 6, 500, 500); assert(talker_len == 1); assert(talkers[0].fd == 10); assert(talkers[0].total_bytes == 1000); - try_insert_top_talker(talkers, &talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, 20, 2, 6, 100, - 100); - try_insert_top_talker(talkers, &talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, 30, 1, 17, 700, - 500); + try_insert_top_talker(talkers, &talker_len, ELF_DET_TOP_TALKERS_MAX, 20, + 2, 6, 100, 100); + try_insert_top_talker(talkers, &talker_len, ELF_DET_TOP_TALKERS_MAX, 30, + 1, 17, 700, 500); assert(talker_len == 3); assert(talkers[0].fd == 30); assert(talkers[0].total_bytes == 1200); @@ -528,16 +525,15 @@ int main(void) assert(talkers[2].fd == 20); /* Replaces the current lowest-ranked entry */ - try_insert_top_talker(talkers, &talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, 40, 10, 6, 300, - 300); + try_insert_top_talker(talkers, &talker_len, ELF_DET_TOP_TALKERS_MAX, 40, + 10, 6, 300, 300); assert(talker_len == 3); assert(talkers[2].fd == 40); assert(talkers[2].total_bytes == 600); /* Zero-traffic entries are ignored */ - try_insert_top_talker(talkers, &talker_len, - PROCLENS_MODULE_TOP_TALKERS_MAX, 50, 2, 6, 0, 0); + try_insert_top_talker(talkers, &talker_len, ELF_DET_TOP_TALKERS_MAX, 50, + 2, 6, 0, 0); assert(talker_len == 3); assert(talkers[0].fd == 30); @@ -592,42 +588,41 @@ int main(void) assert(strcmp(state_str, "UNKNOWN") == 0); /* netdev_count tests */ - struct netdev_count devs[PROCLENS_MODULE_NETDEV_MAX]; + struct netdev_count devs[ELF_DET_NETDEV_MAX]; int dev_len = 0; int start_len; int i; memset(devs, 0, sizeof(devs)); - add_netdev_count(devs, &dev_len, PROCLENS_MODULE_NETDEV_MAX, 2, "eth0"); + add_netdev_count(devs, &dev_len, ELF_DET_NETDEV_MAX, 2, "eth0"); assert(dev_len == 1); assert(devs[0].ifindex == 2); assert(devs[0].count == 1); assert(strcmp(devs[0].name, "eth0") == 0); - add_netdev_count(devs, &dev_len, PROCLENS_MODULE_NETDEV_MAX, 2, "eth1"); + add_netdev_count(devs, &dev_len, ELF_DET_NETDEV_MAX, 2, "eth1"); assert(dev_len == 1); assert(devs[0].count == 2); assert(strcmp(devs[0].name, "eth0") == 0); - add_netdev_count(devs, &dev_len, PROCLENS_MODULE_NETDEV_MAX, 1, "lo"); + add_netdev_count(devs, &dev_len, ELF_DET_NETDEV_MAX, 1, "lo"); assert(dev_len == 2); assert(devs[1].ifindex == 1); assert(devs[1].count == 1); assert(strcmp(devs[1].name, "lo") == 0); start_len = dev_len; - for (i = start_len; i < PROCLENS_MODULE_NETDEV_MAX; i++) { + for (i = start_len; i < ELF_DET_NETDEV_MAX; i++) { char name_buf[16]; snprintf(name_buf, sizeof(name_buf), "d%d", i); - add_netdev_count(devs, &dev_len, PROCLENS_MODULE_NETDEV_MAX, - 100 + i, name_buf); + add_netdev_count(devs, &dev_len, ELF_DET_NETDEV_MAX, 100 + i, + name_buf); } - assert(dev_len == PROCLENS_MODULE_NETDEV_MAX); + assert(dev_len == ELF_DET_NETDEV_MAX); - add_netdev_count(devs, &dev_len, PROCLENS_MODULE_NETDEV_MAX, 999, - "extra"); - assert(dev_len == PROCLENS_MODULE_NETDEV_MAX); + add_netdev_count(devs, &dev_len, ELF_DET_NETDEV_MAX, 999, "extra"); + assert(dev_len == ELF_DET_NETDEV_MAX); /* procfile write/read logic tests */ { diff --git a/src/proclens.c b/src/proc_elf_ctrl.c similarity index 92% rename from src/proclens.c rename to src/proc_elf_ctrl.c index 60d7f0e..2c581aa 100644 --- a/src/proclens.c +++ b/src/proc_elf_ctrl.c @@ -7,11 +7,7 @@ #include #include #include -#include "proclens.h" - -#ifndef PROCLENS_VERSION -#define PROCLENS_VERSION "dev" -#endif +#include "proc_elf_ctrl.h" #define C_RESET "\033[0m" #define C_BOLD "\033[1m" @@ -147,7 +143,7 @@ static int ensure_module_loaded(void) { int loaded; - loaded = is_module_loaded("proclens_module"); + loaded = is_module_loaded("elf_det"); if (loaded < 0) { perror("open /proc/modules"); return -1; @@ -155,12 +151,10 @@ static int ensure_module_loaded(void) if (loaded == 0) { fprintf(stderr, - "%serror:%s kernel module 'proclens_module' is not " - "loaded\n", + "%serror:%s kernel module 'elf_det' is not loaded\n", color_code(C_YELLOW), color_code(C_RESET)); - fprintf(stderr, - "hint: run 'sudo insmod ./build/proclens_module.ko' or " - "'sudo make install'\n"); + fprintf(stderr, "hint: run 'sudo insmod ./build/elf_det.ko' or " + "'sudo make install'\n"); return -1; } @@ -188,9 +182,8 @@ static int ensure_proc_files_present(void) "%s\n", color_code(C_YELLOW), color_code(C_RESET), path); - fprintf(stderr, - "hint: confirm /proc/proclens_module is " - "mounted and initialized\n"); + fprintf(stderr, "hint: confirm /proc/elf_det is " + "mounted and initialized\n"); free(path); return -1; } @@ -201,17 +194,6 @@ static int ensure_proc_files_present(void) return 0; } -static int ensure_root_privileges(void) -{ - if (geteuid() == 0) - return 0; - - fprintf(stderr, "%serror:%s proclens requires root privileges\n", - color_code(C_YELLOW), color_code(C_RESET)); - fprintf(stderr, "hint: run with sudo, e.g. 'sudo proclens'\n"); - return -1; -} - static void print_cmdline(const char *pid_str) { char path[64]; @@ -978,49 +960,9 @@ static void run_live_mode(void) restore_terminal(); } -static void print_usage(void) -{ - printf("Usage: proclens [OPTIONS] [PID]\n"); - printf("\n"); - printf("Options:\n"); - printf(" -h, --help Show this help message and exit\n"); - printf(" -v, --version Show version and exit\n"); - printf("\n"); - printf("Arguments:\n"); - printf(" PID Show one-shot process info for the given " - "PID\n"); - printf("\n"); - printf("Live mode (no arguments):\n"); - printf(" Auto-refreshes every 1s. Controls shown in-app:\n"); - printf(" 1 Memory section\n"); - printf(" 2 Network section\n"); - printf(" 3 Threads section\n"); - printf(" 4 I/O section\n"); - printf(" 0 Change PID\n"); - printf(" Up/k Older snapshot Down/j Newer snapshot\n"); - printf(" f Resume live follow\n"); - printf(" Ctrl+C Exit\n"); -} - int main(int argc, char **argv) { init_color_output(); - - if (argc > 1 && - (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) { - print_usage(); - return 0; - } - - if (argc > 1 && - (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0)) { - printf("proclens %s\n", PROCLENS_VERSION); - return 0; - } - - if (ensure_root_privileges() < 0) - return -1; - print_logo_text(); if (ensure_module_loaded() < 0) return -1; diff --git a/src/proclens.h b/src/proc_elf_ctrl.h similarity index 68% rename from src/proclens.h rename to src/proc_elf_ctrl.h index b42a220..4852e70 100644 --- a/src/proclens.h +++ b/src/proc_elf_ctrl.h @@ -5,13 +5,13 @@ #include #include -/* Build path to /proc/proclens_module/ with optional override via env. */ +/* Build path to /proc/elf_det/ with optional override via env. */ static inline char *build_proc_path(const char *name) { - const char *base = getenv("PROCLENS_PROC_DIR"); + const char *base = getenv("ELF_DET_PROC_DIR"); if (!base || !*base) - base = "/proc/proclens_module"; + base = "/proc/elf_det"; size_t len = strlen(base) + 1 + strlen(name) + 1; char *p = (char *)malloc(len); diff --git a/src/proclens_tests.c b/src/proc_elf_ctrl_tests.c similarity index 90% rename from src/proclens_tests.c rename to src/proc_elf_ctrl_tests.c index f3dc33f..c71932f 100644 --- a/src/proclens_tests.c +++ b/src/proc_elf_ctrl_tests.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT #define _GNU_SOURCE -#include "proclens.h" +#include "proc_elf_ctrl.h" #include #include #include @@ -27,7 +27,6 @@ static int module_loaded; static int proc_pid_present; static int proc_det_present; static int proc_threads_present; -static uid_t mock_euid; static void append_output(const char *fmt, ...) { @@ -73,11 +72,10 @@ static void reset_mocks(void) proc_pid_present = 1; proc_det_present = 1; proc_threads_present = 1; - mock_euid = 0; memset(cmdline_content, 0, sizeof(cmdline_content)); cmdline_len = 0; - setenv("PROCLENS_PROC_DIR", "/fake_proc", 1); + setenv("ELF_DET_PROC_DIR", "/fake_proc", 1); } static FILE *mock_fopen(const char *path, const char *mode) @@ -114,10 +112,8 @@ static FILE *mock_fopen(const char *path, const char *mode) if (!strcmp(path, "/proc/modules") && strchr(mode, 'r')) { if (module_loaded) - return fmemopen( - (void *)"proclens_module 0 0 - Live 0x0\n", - strlen("proclens_module 0 0 - Live 0x0\n"), - "r"); + return fmemopen((void *)"elf_det 0 0 - Live 0x0\n", 23, + "r"); return fmemopen((void *)"", 0, "r"); } @@ -166,24 +162,17 @@ static void mock_perror(const char *s) append_output("%s\n", s); } -static uid_t mock_geteuid(void) -{ - return mock_euid; -} - -#define fopen mock_fopen -#define access mock_access -#define geteuid mock_geteuid -#define printf mock_printf -#define puts mock_puts -#define perror mock_perror -#define main proclens_entry -#include "proclens.c" +#define fopen mock_fopen +#define access mock_access +#define printf mock_printf +#define puts mock_puts +#define perror mock_perror +#define main proc_elf_ctrl_entry +#include "proc_elf_ctrl.c" #undef main #undef perror #undef puts #undef printf -#undef geteuid #undef access #undef fopen @@ -192,12 +181,12 @@ static void test_build_proc_path_helper(void) char *p1; char *p2; - unsetenv("PROCLENS_PROC_DIR"); + unsetenv("ELF_DET_PROC_DIR"); p1 = build_proc_path("pid"); - assert(p1 && strcmp(p1, "/proc/proclens_module/pid") == 0); + assert(p1 && strcmp(p1, "/proc/elf_det/pid") == 0); free(p1); - setenv("PROCLENS_PROC_DIR", "/tmp/fakeproc", 1); + setenv("ELF_DET_PROC_DIR", "/tmp/fakeproc", 1); p2 = build_proc_path("det"); assert(p2 && strcmp(p2, "/tmp/fakeproc/det") == 0); free(p2); @@ -260,7 +249,7 @@ static void test_main_argument_pid_is_bounded(void) reset_mocks(); cmdline_len = 0; - rc = proclens_entry(2, (char **)argv); + rc = proc_elf_ctrl_entry(2, (char **)argv); assert(rc == 0); assert(pid_stream_buf); @@ -275,7 +264,7 @@ static void test_main_exits_when_module_not_loaded(void) reset_mocks(); module_loaded = 0; - rc = proclens_entry(2, (char **)argv); + rc = proc_elf_ctrl_entry(2, (char **)argv); assert(rc == -1); assert(!pid_stream_buf); @@ -288,24 +277,10 @@ static void test_main_exits_when_proc_file_missing(void) reset_mocks(); proc_threads_present = 0; - rc = proclens_entry(2, (char **)argv); - - assert(rc == -1); - assert(!pid_stream_buf); -} - -static void test_main_exits_without_root_privileges(void) -{ - static const char *const argv[] = {"prog", "1"}; - int rc; - - reset_mocks(); - mock_euid = 1000; - rc = proclens_entry(2, (char **)argv); + rc = proc_elf_ctrl_entry(2, (char **)argv); assert(rc == -1); assert(!pid_stream_buf); - assert(!strstr(output_buf, "PROCESS INFORMATION")); } static void test_det_preamble_stops_before_sections(void) @@ -481,7 +456,6 @@ int main(void) test_main_argument_pid_is_bounded(); test_main_exits_when_module_not_loaded(); test_main_exits_when_proc_file_missing(); - test_main_exits_without_root_privileges(); test_det_preamble_stops_before_sections(); test_memory_view_filters_network_section(); test_network_view_starts_from_network_section(); @@ -489,7 +463,7 @@ int main(void) test_format_current_time_layout(); test_live_header_and_footer_show_timestamps(); test_snapshot_history_offset_navigation(); - puts("proclens tests passed"); + puts("proc_elf_ctrl tests passed"); reset_mocks(); return 0; }