Lab 03: strace — System Call Tracing

Time: 40 minutes | Level: Advanced | Docker: docker run -it --rm --privileged ubuntu:22.04 bash


Overview

Every interaction between a program and the Linux kernel goes through system calls (syscalls). strace intercepts and logs these calls in real-time, making it invaluable for debugging, security analysis, and understanding program behavior. This lab covers filtering, counting, following forks, and tracing real programs.


Step 1: Install strace

apt-get update -qq && apt-get install -y strace
strace --version | head -1

📸 Verified Output:

strace -- version 5.16

💡 strace works by using the ptrace() syscall to intercept system calls of the target process. This is why it requires root or matching UID. It has a performance overhead (2–10x slowdown) — use it for debugging only.


Step 2: Basic Tracing — Understand the Output Format

Trace a simple command and observe the output format:

strace ls /tmp 2>&1 | head -15

📸 Verified Output:

Output format anatomy:

  • = followed by positive number: success (often a file descriptor)

  • = -1 ENOENT: failure with error code

  • = 0: success (no meaningful return)

  • +++ exited with 0 +++: process exit status


Step 3: Filter Syscalls with -e trace=

Focus on specific syscalls to reduce noise:

📸 Verified Output:

Syscall categories:

Category
Syscalls included

file

All file-related: open, read, stat, etc.

network

socket, connect, bind, send, recv, etc.

process

execve, fork, clone, wait, exit

memory

mmap, brk, mprotect

signal

kill, sigaction, pause

💡 Combine filters: strace -e trace=openat,read,write — multiple syscalls comma-separated.


Step 4: Timestamp Output with -tt

Add precise timestamps to understand timing:

📸 Verified Output:

Output includes <N.NNNNNN> — time in seconds for each call:

💡 -tt shows wall-clock time of each call (for sequencing). -T shows duration of each call (for identifying slow operations). Use both together with -ttT.


Step 5: Count Syscalls with -c

Get a statistical summary of all syscall activity:

📸 Verified Output:

💡 The errors column is gold — it shows failed syscall counts. 2 access errors above = the access() calls for /etc/ld.so.preload (doesn't exist but checked anyway).


Step 6: Follow Forks with -f

Trace child processes spawned via fork() or clone():

📸 Verified Output:

With -f, output prefixes show which PID made each call:

💡 Use -ff -o /tmp/trace to write each process's trace to a separate file (/tmp/trace.PID). Essential for debugging multi-process applications.


Step 7: Write Output to File with -o

For long traces, redirect to a file:

📸 Verified Output:

💡 Attaching with -p doesn't restart the program — it observes an already-running process. The process continues normally; only syscall logging is added.


Step 8: Capstone — Debug a "File Not Found" Error

Scenario: A program fails silently. Use strace to find what file it's trying to open.

📸 Verified Output:

📸 Verified Output:

Debug summary: strace revealed exactly which two files were missing, their full paths, and the error code — without needing source code or verbose logging.


Summary

Flag
Purpose

strace <cmd>

Trace all syscalls of a command

-e trace=openat,read

Filter to specific syscalls

-e trace=file

Filter by syscall category

-c

Count/summarize syscalls (statistics)

-tt

Add wall-clock timestamps

-T

Show time spent in each syscall

-f

Follow child processes (fork/clone)

-ff -o file

Write per-PID traces to separate files

-o file

Write trace to file instead of stderr

-p PID

Attach to running process

grep ENOENT

Find failed file operations

Last updated